Projet

Général

Profil

0001-template-filter-for-Luhn-algorithm-35013.patch

Benjamin Dauvergne, 24 juillet 2019 17:13

Télécharger (4,89 ko)

Voir les différences:

Subject: [PATCH] template filter for Luhn algorithm (#35013)

 tests/test_templates.py           | 48 +++++++++++++++++++++++++++++
 wcs/qommon/templatetags/qommon.py | 50 +++++++++++++++++++++++++++++++
 2 files changed, 98 insertions(+)
tests/test_templates.py
522 522
    lazy_formdata = LazyFormData(MockFormData())
523 523
    tmpl = Template('{% with form_geoloc_base|reproj:"EPSG:3946" as c %}{{c.0}}/{{c.1}}{% endwith %}')
524 524
    assert tmpl.render(CompatibilityNamesDict({'form': lazy_formdata})) == '1625337.15483/5422836.71627'
525

  
526
def test_luhn():
527
    # Failing cases
528
    tmpl = Template('{% if None|is_valid_siret%}yes{% endif %}')
529
    assert tmpl.render() == ''
530
    tmpl = Template('{% if True|is_valid_siret%}yes{% endif %}')
531
    assert tmpl.render() == ''
532
    tmpl = Template('{% if False|is_valid_siret%}yes{% endif %}')
533
    assert tmpl.render() == ''
534

  
535
    # EO Siret
536
    tmpl = Template('{% if "44317013900036"|is_valid_siret%}yes{% endif %}')
537
    assert tmpl.render() == 'yes'
538
    tmpl = Template('{% if 44317013900036|is_valid_siret%}yes{% endif %}')
539
    assert tmpl.render() == 'yes'
540

  
541
    # with spaces
542
    tmpl = Template('{% if  " 443 170\t139 00 036 "|is_valid_siret %}yes{% endif %}')
543
    assert tmpl.render() == 'yes'
544
    tmpl = Template('{{ " 443 170\t139 00 036 "|is_valid_siret }}')
545
    assert tmpl.render() == '44317013900036'
546
    for i in range(10):
547
        if i == 6:
548
            continue
549
        tmpl = Template('{% if  "4431701390003' + str(i) + '"|is_valid_siret %}yes{% endif %}')
550
        assert tmpl.render() == ''
551

  
552
    # EO Siren
553
    tmpl = Template('{% if  "443170139"|is_valid_siren %}yes{% endif %}')
554
    assert tmpl.render() == 'yes'
555
    for i in range(10):
556
        if i == 9:
557
            continue
558
        tmpl = Template('{% if  "44317013' + str(i) + '"|is_valid_siren %}yes{% endif %}')
559
        assert tmpl.render() == ''
560

  
561
    # credit card number
562
    tmpl = Template('{% if  "5555 5555 5555 4444"|is_valid_credit_card_number %}yes{% endif %}')
563
    assert tmpl.render() == 'yes'
564
    tmpl = Template('{{ "5555 5555 5555 4444"|is_valid_credit_card_number }}')
565
    assert tmpl.render() == '5555555555554444'
566

  
567
    # La poste
568
    tmpl = Template('{% if  "356 000 000"|is_valid_siren%}yes{% endif %}')
569
    assert tmpl.render() == 'yes'
570

  
571
    tmpl = Template('{% if  "356 000 000 12345"|is_valid_siret%}yes{% endif %}')
572
    assert tmpl.render() == 'yes'
wcs/qommon/templatetags/qommon.py
20 20
from decimal import DivisionByZero as DecimalDivisionByZero
21 21
import hashlib
22 22
import math
23
import re
23 24
import string
24 25
import random
25 26

  
......
348 349
    proj = pyproj.Proj(init='EPSG:4326')
349 350
    target_proj = pyproj.Proj(init=projection_name)
350 351
    return pyproj.transform(proj, target_proj, coords['lon'], coords['lat'])
352

  
353
def clean_numeric_identifier(value):
354
    if not value:
355
        return u''
356
    string_value = unicode(value)
357
    string_value = re.sub(r'\s', '', string_value)
358
    if not string_value.isdigit():
359
        return u''
360
    return string_value
361

  
362
def is_valid_luhn(value, length=None):
363
    '''Verify Luhn checksum on a string representing a number'''
364
    if not value:
365
        return u''
366
    string_value = unicode(value)
367
    if length is not None and len(string_value) != length:
368
        return u''
369

  
370
    # take all digits couting from the right, double value for digits pair
371
    # index (counting from 1), if double has 2 digits take their sum
372
    checksum = 0
373
    for i, x in enumerate(reversed(string_value)):
374
        if i % 2 == 0:
375
            checksum += int(x)
376
        else:
377
            checksum += sum(int(y) for y in str(2 * int(x)))
378
    if checksum % 10 != 0:
379
        return u''
380
    return string_value
381

  
382
@register.filter
383
def is_valid_siren(value):
384
    string_value = clean_numeric_identifier(value)
385
    # special case : La Poste
386
    if string_value == '356000000':
387
        return string_value
388
    return is_valid_luhn(string_value, length=9)
389

  
390
@register.filter
391
def is_valid_siret(value):
392
    string_value = clean_numeric_identifier(value)
393
    # special case : La Poste
394
    if string_value.startswith('356000000') and len(string_value) == 14:
395
        return string_value
396
    return is_valid_luhn(string_value, length=14)
397

  
398
@register.filter
399
def is_valid_credit_card_number(value):
400
    return is_valid_luhn(clean_numeric_identifier(value), length=16)
351
-