From 61f1a24381a6078a56e2c31bec190a415bb2d0d0 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Tue, 23 Jul 2019 17:40:14 +0200 Subject: [PATCH] template filter for Luhn algorithm (#35013) --- tests/test_templates.py | 22 +++++++++++++++++++++ wcs/qommon/templatetags/qommon.py | 32 +++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/tests/test_templates.py b/tests/test_templates.py index 18f0ea65..e9ca0a3a 100644 --- a/tests/test_templates.py +++ b/tests/test_templates.py @@ -522,3 +522,25 @@ def test_reproj(): lazy_formdata = LazyFormData(MockFormData()) tmpl = Template('{% with form_geoloc_base|reproj:"EPSG:3946" as c %}{{c.0}}/{{c.1}}{% endwith %}') assert tmpl.render(CompatibilityNamesDict({'form': lazy_formdata})) == '1625337.15483/5422836.71627' + +def test_luhn(): + # EO Siret + tmpl = Template('{% if "44317013900036"|is_valid_siret%}yes{% endif %}') + assert tmpl.render() == 'yes' + # with spaces + tmpl = Template('{% if " 443 170\t139 00 036 "|is_valid_siret %}yes{% endif %}') + assert tmpl.render() == 'yes' + for i in range(10): + if i == 6: + continue + tmpl = Template('{% if "4431701390003' + str(i) + '"|is_valid_siret %}yes{% endif %}') + assert tmpl.render() == '' + + # EO Siren + tmpl = Template('{% if "443170139"|is_valid_siren %}yes{% endif %}') + assert tmpl.render() == 'yes' + for i in range(10): + if i == 9: + continue + tmpl = Template('{% if "44317013' + str(i) + '"|is_valid_siren %}yes{% endif %}') + assert tmpl.render() == '' diff --git a/wcs/qommon/templatetags/qommon.py b/wcs/qommon/templatetags/qommon.py index 5178392d..31e0e0b0 100644 --- a/wcs/qommon/templatetags/qommon.py +++ b/wcs/qommon/templatetags/qommon.py @@ -20,6 +20,7 @@ from decimal import InvalidOperation as DecimalInvalidOperation from decimal import DivisionByZero as DecimalDivisionByZero import hashlib import math +import re import string import random @@ -348,3 +349,34 @@ def reproj(coords, projection_name): proj = pyproj.Proj(init='EPSG:4326') target_proj = pyproj.Proj(init=projection_name) return pyproj.transform(proj, target_proj, coords['lon'], coords['lat']) + +def is_valid_luhn(value): + '''Verify Luhn checksum on a string representing a number''' + if not value: + return False + string_value = unicode(value) + string_value = re.sub(r'\s', '', string_value) + if not string_value.isdigit(): + return False + + # take all digits couting from the right, double value for digits pair + # index (counting from 1), if double has 2 digits take their sum + checksum = 0 + for i, x in enumerate(reversed(string_value)): + if i % 2 == 0: + checksum += int(x) + else: + checksum += sum(int(y) for y in str(2 * int(x))) + return checksum % 10 == 0 + +@register.filter +def is_valid_siren(value): + return is_valid_luhn(value) + +@register.filter +def is_valid_siret(value): + return is_valid_luhn(value) + +@register.filter +def is_valid_cb(value): + return is_valid_luhn(value) -- 2.22.0