Browse Source

Merge pull request #1102 from acsone/9.0-backport_sequence_check_digit_tbi

[9.0] [BACKPORT] Sequence Check Digit
pull/1138/head
Pedro M. Baeza 7 years ago
committed by GitHub
parent
commit
846b9335ad
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      requirements.txt
  2. 74
      sequence_check_digit/README.rst
  3. 1
      sequence_check_digit/__init__.py
  4. 27
      sequence_check_digit/__openerp__.py
  5. 85
      sequence_check_digit/i18n/es.po
  6. 85
      sequence_check_digit/i18n/fr.po
  7. 1
      sequence_check_digit/models/__init__.py
  8. 68
      sequence_check_digit/models/ir_sequence.py
  9. BIN
      sequence_check_digit/static/description/icon.png
  10. 4
      sequence_check_digit/tests/__init__.py
  11. 65
      sequence_check_digit/tests/test_check_digit.py
  12. 15
      sequence_check_digit/views/sequence_views.xml
  13. 1
      setup/sequence_check_digit/odoo_addons/__init__.py
  14. 1
      setup/sequence_check_digit/odoo_addons/sequence_check_digit
  15. 6
      setup/sequence_check_digit/setup.py

1
requirements.txt

@ -10,3 +10,4 @@ fs==0.5.4
oauthlib
pyjwt
cryptography
python-stdnum

74
sequence_check_digit/README.rst

@ -0,0 +1,74 @@
.. 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.
Configuration
=============
* 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]*
Usage
=====
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/149/9.0
Bug Tracker
===========
Bugs are tracked on `GitHub Issues
<https://github.com/OCA/server-tools/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smash it by providing detailed and welcomed feedback.
Credits
=======
Images
------
* Odoo Community Association: `Icon <https://odoo-community.org/logo.png>`_.
Contributors
------------
* Enric Tobella <etobella@creublanca.es>
* Thomas Binsfeld <thomas.binsfeld@acsone.eu> (https://www.acsone.eu/)
Do not contact contributors directly about support or help with technical issues.
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.

1
sequence_check_digit/__init__.py

@ -0,0 +1 @@
from . import models

27
sequence_check_digit/__openerp__.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": "9.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 9.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"

85
sequence_check_digit/i18n/fr.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 9.0c\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-12-21 11:02+0000\n"
"PO-Revision-Date: 2017-12-21 11:02+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
#: code:addons/sequence_check_digit/models/ir_sequence.py:46
#, python-format
msgid "%s is not an implemented function"
msgstr "%s n'est pas une fonction implémentée"
#. module: sequence_check_digit
#: model:ir.model.fields,field_description:sequence_check_digit.field_ir_sequence_check_digit_formula
msgid "Check digit formula"
msgstr "Formule de chiffre de contrôle"
#. 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:40
#: code:addons/sequence_check_digit/models/ir_sequence.py:49
#, python-format
msgid "Format is not accepted"
msgstr "Le format n'est pas accepté"
#. 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 "Aucun"
#. 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"

1
sequence_check_digit/models/__init__.py

@ -0,0 +1 @@
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 openerp import fields, models, api, _
from openerp.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 openerp.tests import common
import logging
from openerp.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()))

15
sequence_check_digit/views/sequence_views.xml

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2017 Creu Blanca <https://creublanca.es/>
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). -->
<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>

1
setup/sequence_check_digit/odoo_addons/__init__.py

@ -0,0 +1 @@
__import__('pkg_resources').declare_namespace(__name__)

1
setup/sequence_check_digit/odoo_addons/sequence_check_digit

@ -0,0 +1 @@
../../../sequence_check_digit

6
setup/sequence_check_digit/setup.py

@ -0,0 +1,6 @@
import setuptools
setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)
Loading…
Cancel
Save