Projet

Général

Profil

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

Benjamin Dauvergne, 24 juillet 2019 16:59

Télécharger (4,01 ko)

Voir les différences:

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

 tests/test_templates.py           | 45 +++++++++++++++++++++++++++++++
 wcs/qommon/templatetags/qommon.py | 40 +++++++++++++++++++++++++++
 2 files changed, 85 insertions(+)
tests/test_templates.py
534 534
    assert tmpl.render() == ''
535 535
    tmpl = Template('{{ " 1 23 4 "|clean_number }}')
536 536
    assert tmpl.render() == '1234'
537

  
538

  
539
def test_luhn():
540
    # Failing cases
541
    tmpl = Template('{% if None|is_valid_siret%}yes{% endif %}')
542
    assert tmpl.render() == ''
543
    tmpl = Template('{% if True|is_valid_siret%}yes{% endif %}')
544
    assert tmpl.render() == ''
545
    tmpl = Template('{% if False|is_valid_siret%}yes{% endif %}')
546
    assert tmpl.render() == ''
547

  
548
    # EO Siret
549
    tmpl = Template('{% if "44317013900036"|is_valid_siret%}yes{% endif %}')
550
    assert tmpl.render() == 'yes'
551
    tmpl = Template('{% if 44317013900036|is_valid_siret%}yes{% endif %}')
552
    assert tmpl.render() == 'yes'
553

  
554
    # with spaces
555
    tmpl = Template('{% if  " 443 170\t139 00 036 "|clean_number|is_valid_siret %}yes{% endif %}')
556
    assert tmpl.render() == 'yes'
557
    for i in range(10):
558
        if i == 6:
559
            continue
560
        tmpl = Template('{% if  "4431701390003' + str(i) + '"|is_valid_siret %}yes{% endif %}')
561
        assert tmpl.render() == ''
562

  
563
    # EO Siren
564
    tmpl = Template('{% if  "443170139"|is_valid_siren %}yes{% endif %}')
565
    assert tmpl.render() == 'yes'
566
    for i in range(10):
567
        if i == 9:
568
            continue
569
        tmpl = Template('{% if  "44317013' + str(i) + '"|is_valid_siren %}yes{% endif %}')
570
        assert tmpl.render() == ''
571

  
572
    # credit card number
573
    tmpl = Template('{% if  "5555 5555 5555 4444"|clean_number|is_valid_credit_card_number %}yes{% endif %}')
574
    assert tmpl.render() == 'yes'
575

  
576
    # La poste
577
    tmpl = Template('{% if  "356 000 000"|clean_number|is_valid_siren%}yes{% endif %}')
578
    assert tmpl.render() == 'yes'
579

  
580
    tmpl = Template('{% if  "356 000 000 12345"|clean_number|is_valid_siret%}yes{% endif %}')
581
    assert tmpl.render() == 'yes'
wcs/qommon/templatetags/qommon.py
359 359
    if not string_value.isdigit():
360 360
        return u''
361 361
    return string_value
362

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

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

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

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

  
399
@register.filter
400
def is_valid_credit_card_number(value):
401
    return is_valid_luhn(value, length=16)
362
-