Browse Source

[ADD] Sequence check Digit (#1000)

* [ADD] Sequence check Digit

* Change of License to LGPL

* Code review

* Reviews
pull/1003/head
Enric Tobella 7 years ago
committed by Dave Lasley
parent
commit
e1c514251d
  1. 1
      requirements.txt
  2. 51
      sequence_check_digit/README.rst
  3. 4
      sequence_check_digit/__init__.py
  4. 27
      sequence_check_digit/__manifest__.py
  5. 85
      sequence_check_digit/i18n/es.po
  6. 4
      sequence_check_digit/models/__init__.py
  7. 68
      sequence_check_digit/models/ir_sequence.py
  8. BIN
      sequence_check_digit/static/description/icon.png
  9. 4
      sequence_check_digit/tests/__init__.py
  10. 65
      sequence_check_digit/tests/test_check_digit.py
  11. 12
      sequence_check_digit/views/sequence_views.xml

1
requirements.txt

@ -9,3 +9,4 @@ fdb
sqlalchemy sqlalchemy
raven raven
checksumdir checksumdir
python-stdnum

51
sequence_check_digit/README.rst

@ -0,0 +1,51 @@
.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
:alt: License: LGPL-3
====================
Sequence Check Digit
====================
This module was written to configure check digits on sequences added on the end.
It is useful as a control of the number on visual validation.
It is useful when some manual checks are required or on integrations.
The implemented codes can avoid modification of one character and flip of
two consecutive characters.
Usage
=====
* Access sequences and configurate the model to use.
* The model will check if the format of prefix, suffix and number is valid
* Implemented algorithms
* Luhn: [0-9]*
* Damm: [0-9]*
* Verhoeff: [0-9]*
* ISO 7064 Mod 11, 2: [0-9]*
* ISO 7064 Mod 11, 10: [0-9]*
* ISO 7064 Mod 37, 2: [0-9A-Z]*
* ISO 7064 Mod 37, 36: [0-9A-Z]*
* ISO 7064 Mod 97, 10: [0-9A-Z]*
Credits
=======
Contributors
------------
* Enric Tobella <etobella@creublanca.es>
Maintainer
----------
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
This module is maintained by the OCA.
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
To contribute to this module, please visit https://odoo-community.org.

4
sequence_check_digit/__init__.py

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from . import models

27
sequence_check_digit/__manifest__.py

@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2017 Creu Blanca
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
{
"name": "Check Digit on Sequences",
"version": "10.0.1.0.0",
"category": "Reporting",
"website": "https://github.com/OCA/server-tools",
"author": "Creu Blanca, "
"Odoo Community Association (OCA)",
"license": "LGPL-3",
"installable": True,
"application": False,
"summary": "Adds a check digit on sequences",
"depends": [
"base",
],
"data": [
"views/sequence_views.xml",
],
"external_dependencies": {
"python": [
"stdnum",
],
},
}

85
sequence_check_digit/i18n/es.po

@ -0,0 +1,85 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sequence_check_digit
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-09-28 10:14+0000\n"
"PO-Revision-Date: 2017-09-28 10:14+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: sequence_check_digit
#: model:ir.model.fields,field_description:sequence_check_digit.field_ir_sequence_check_digit_formula
msgid "Check digit formula"
msgstr "Dígito de control"
#. module: sequence_check_digit
#: selection:ir.sequence,check_digit_formula:0
msgid "Damm"
msgstr "Damm"
#. module: sequence_check_digit
#: code:addons/sequence_check_digit/models/ir_sequence.py:39
#: code:addons/sequence_check_digit/models/ir_sequence.py:63
#, python-format
msgid "Format is not accepted"
msgstr "El formato no está aceptado"
#. module: sequence_check_digit
#: code:addons/sequence_check_digit/models/ir_sequence.py:61
#, python-format
msgid "Function not found"
msgstr "Función no encontrada"
#. module: sequence_check_digit
#: selection:ir.sequence,check_digit_formula:0
msgid "ISO 7064 Mod 11, 10"
msgstr "ISO 7064 Mod 11, 10"
#. module: sequence_check_digit
#: selection:ir.sequence,check_digit_formula:0
msgid "ISO 7064 Mod 11, 2"
msgstr "ISO 7064 Mod 11, 2"
#. module: sequence_check_digit
#: selection:ir.sequence,check_digit_formula:0
msgid "ISO 7064 Mod 37, 2"
msgstr "ISO 7064 Mod 37, 2"
#. module: sequence_check_digit
#: selection:ir.sequence,check_digit_formula:0
msgid "ISO 7064 Mod 37, 36"
msgstr "ISO 7064 Mod 37, 36"
#. module: sequence_check_digit
#: selection:ir.sequence,check_digit_formula:0
msgid "ISO 7064 Mod 97, 10"
msgstr "ISO 7064 Mod 97, 10"
#. module: sequence_check_digit
#: selection:ir.sequence,check_digit_formula:0
msgid "Luhn"
msgstr "Luhn"
#. module: sequence_check_digit
#: selection:ir.sequence,check_digit_formula:0
msgid "None"
msgstr "Ninguno"
#. module: sequence_check_digit
#: selection:ir.sequence,check_digit_formula:0
msgid "Verhoeff"
msgstr "Verhoeff"
#. module: sequence_check_digit
#: model:ir.model,name:sequence_check_digit.model_ir_sequence
msgid "ir.sequence"
msgstr "ir.sequence"

4
sequence_check_digit/models/__init__.py

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from . import ir_sequence

68
sequence_check_digit/models/ir_sequence.py

@ -0,0 +1,68 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2017 Creu Blanca
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from odoo import fields, models, api, _
from odoo.exceptions import ValidationError
import logging
try:
from stdnum.iso7064 import mod_97_10
from stdnum.iso7064 import mod_37_2, mod_37_36
from stdnum.iso7064 import mod_11_2, mod_11_10
from stdnum import luhn, damm, verhoeff
except(ImportError, IOError) as err:
logging.info(err)
class IrSequence(models.Model):
_inherit = "ir.sequence"
check_digit_formula = fields.Selection(
selection=[
('none', 'None'),
('luhn', 'Luhn'),
('damm', 'Damm'),
('verhoeff', 'Verhoeff'),
('ISO7064_11_2', 'ISO 7064 Mod 11, 2'),
('ISO7064_11_10', 'ISO 7064 Mod 11, 10'),
('ISO7064_37_2', 'ISO 7064 Mod 37, 2'),
('ISO7064_37_36', 'ISO 7064 Mod 37, 36'),
('ISO7064_97_10', 'ISO 7064 Mod 97, 10'),
], default='none'
)
@api.constrains('check_digit_formula', 'prefix', 'suffix')
def check_check_digit_formula(self):
try:
self.get_next_char(0)
except Exception:
raise ValidationError(_('Format is not accepted'))
def get_check_digit(self, code):
try:
return self.get_formula_map()[self.check_digit_formula](code)
except KeyError:
raise ValidationError(_('%s is not an implemented function'
% self.check_digit_formula))
except Exception:
raise ValidationError(_('Format is not accepted'))
def get_formula_map(self):
return {
'none': lambda _: '',
'luhn': luhn.calc_check_digit,
'damm': damm.calc_check_digit,
'verhoeff': verhoeff.calc_check_digit,
'ISO7064_11_2': mod_11_2.calc_check_digit,
'ISO7064_11_10': mod_11_10.calc_check_digit,
'ISO7064_37_2': mod_37_2.calc_check_digit,
'ISO7064_37_36': mod_37_36.calc_check_digit,
'ISO7064_97_10': mod_97_10.calc_check_digits
}
def get_next_char(self, number_next):
code = super(IrSequence, self).get_next_char(number_next)
if not self.check_digit_formula:
return code
return '%s%s' % (code, self.get_check_digit(code))

BIN
sequence_check_digit/static/description/icon.png

After

Width: 128  |  Height: 128  |  Size: 9.2 KiB

4
sequence_check_digit/tests/__init__.py

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from . import test_check_digit

65
sequence_check_digit/tests/test_check_digit.py

@ -0,0 +1,65 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Creu Blanca <https://creublanca.es/>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
from odoo.tests import common
import logging
from odoo.exceptions import ValidationError
try:
from stdnum.iso7064 import mod_97_10
from stdnum.iso7064 import mod_37_2, mod_37_36
from stdnum.iso7064 import mod_11_2, mod_11_10
from stdnum import luhn, damm, verhoeff
except(ImportError, IOError) as err:
logging.info(err)
class TestSequenceCheckDigit(common.TransactionCase):
def get_sequence(self, method):
return self.env['ir.sequence'].create({
'name': 'Test sequence',
'implementation': 'standard',
'check_digit_formula': method,
'padding': '5'
})
def test_luhn(self):
sequence = self.get_sequence('luhn')
self.assertTrue(luhn.validate(sequence.next_by_id()))
def test_damm(self):
sequence = self.get_sequence('damm')
self.assertTrue(damm.validate(sequence.next_by_id()))
def test_verhoeff(self):
sequence = self.get_sequence('verhoeff')
self.assertTrue(verhoeff.validate(sequence.next_by_id()))
def test_mod_11_2(self):
sequence = self.get_sequence('ISO7064_11_2')
self.assertTrue(mod_11_2.validate(sequence.next_by_id()))
def test_mod11_10(self):
sequence = self.get_sequence('ISO7064_11_10')
self.assertTrue(mod_11_10.validate(sequence.next_by_id()))
def test_validation(self):
sequence = self.get_sequence('ISO7064_11_10')
with self.assertRaises(ValidationError):
sequence.prefix = 'A'
sequence.prefix = ''
def test_mod37_2(self):
sequence = self.get_sequence('ISO7064_37_2')
sequence.prefix = 'A'
self.assertTrue(mod_37_2.validate(sequence.next_by_id()))
def test_mod37_36(self):
sequence = self.get_sequence('ISO7064_37_36')
self.assertTrue(mod_37_36.validate(sequence.next_by_id()))
def test_mod97_10(self):
sequence = self.get_sequence('ISO7064_97_10')
self.assertTrue(mod_97_10.validate(sequence.next_by_id()))

12
sequence_check_digit/views/sequence_views.xml

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="sequence_view" model="ir.ui.view">
<field name="model">ir.sequence</field>
<field name="inherit_id" ref="base.sequence_view"/>
<field name="arch" type="xml">
<field name="implementation" position="after">
<field name="check_digit_formula"/>
</field>
</field>
</record>
</odoo>
Loading…
Cancel
Save