diff --git a/barcodes_generate/README.rst b/barcodes_generate/README.rst new file mode 100644 index 00000000..dc627758 --- /dev/null +++ b/barcodes_generate/README.rst @@ -0,0 +1,115 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +============== +{module_title} +============== + +============================================ +Generate Barcodes for Products and Customers +============================================ + +This module expends Odoo functionnality, allowing user to generate barcode +depending on a given barcode rule. + +For exemple, a typical pattern for products is "23.....{NNNDD}" that means +that: +* the EAN13 code will begin by '23' ; +* followed by 5 digits (named Barcode Base in this module, ) ; +* and after 5 others digits to define the variable price ; +* a 13 digit control + +With this module, it is possible to: + +* Affect a pattern (barcode.rule) to a product.product or a res.partner + +* Generate the next Barcode base of a pattern. (to avoid duplicate barcode) +* Generate a barcode, based on a pattern and a barcode base + +Configuration +============= + +To configure this module, you need to: + +* Go to Point Of Sale / Configuration / Barcode Nomenclatures and select +* Select a Nomenclature +* Create or select a rule +.. figure:: barcodes_generate/static/description/barcode_rule_tree.png + +* Check 'Available for Products', or 'Available for Partners' Checkbox. + +.. figure:: barcodes_generate/static/description/barcode_rule_form.png + +Usage +===== + +To use this module, you need to: + +* Go to a Product form (or a Partner Form): +* set a rule to the current object + +.. figure:: barcodes_generate/static/description/product_product_form_empty.png + +* Click on 'Generate Base and Barcode' + +.. figure:: barcodes_generate/static/description/product_product_form_generated.png + +Alternatively you can set manually a barcode base, and click only on Generate barcode. + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/184/9.0 + +Known issues / Roadmap +====================== + +Dependency to point_of_sale is required because barcode field, defined in 'base' +module (in the res.partner model), is defined in a 'point_of_sale' view. +Furthermore, barcode nomenclature menu is available on Point Of Sale submenu. + +It's a relative problem, because product barcodes generation will occures +mostly in a Point of Sale context. + +You could comment 'point_of_sale' dependencies if you want to use this module +without point of sale installed. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smashing it by providing a detailed and welcomed feedback. + +Credits +======= + +Images +------ + +* Odoo Community Association: `Icon `_. + +* Icon of the module is based on the Oxygen Team work and is under LGPL licence: + http://www.iconarchive.com/show/oxygen-icons-by-oxygen-icons.org.html + +Contributors +------------ + +* Sylvain LE GAL (https://twitter.com/legalsylvain) + +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. + diff --git a/barcodes_generate/__openerp__.py b/barcodes_generate/__openerp__.py index cd84ded4..9b131278 100644 --- a/barcodes_generate/__openerp__.py +++ b/barcodes_generate/__openerp__.py @@ -1,51 +1,19 @@ # -*- coding: utf-8 -*- # Copyright (C) 2016-Today GRAP (http://www.grap.coop) +# Copyright (C) 2016-Today GRAP (http://www.lalouve.net) # @author: Sylvain LE GAL (https://twitter.com/legalsylvain) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). { - 'name': 'Barcodes - Generate', - 'summary': 'Generate Barcodes for Products and Customers', + 'name': 'Generate Barcodes', + 'summary': 'Generate Barcodes for Products and Partners', 'version': '1.0', 'category': 'Point Of Sale', - 'description': """ -============================================ -Generate Barcodes for Products and Customers -============================================ - -This module expends Odoo functionnality, allowing user to generate barcode -depending on a given barcode rule. - -For exemple, a typical pattern for products is "23.....{NNNDD}" that means -that the EAN13 code will begin by '23', followed by 5 digits and after 5 others -digits to define the variable price. (EAN13 has a third char for control). - -With this module, it is possible to: - -* Affect a pattern (barcode.rule) to a product.product or a res.partner -* To generate an EAN13 depending on the defined pattern and a custom ID - -Note ----- -Dependency to point_of_sale is required because barcode field, defined in 'base' -module (in the res.partner model), is defined in a 'point_of_sale' view. - -It's a relative problem, because product barcodes generation will occures -mostly in a Point of Sale context. - -You could comment 'point_of_sale' dependency if you want to use this module -without point of sale. - -Copyright Note --------------- -Icon of the module is based on the Oxygen Team work and is under LGPL licence: - -http://www.iconarchive.com/show/oxygen-icons-by-oxygen-icons.org.html - - -""", - 'author': 'GRAP', - 'website': 'http://www.grap.coop', + 'author': + 'GRAP,' + 'La Louve,' + 'Odoo Community Association (OCA)', + 'website': 'http://www.odoo-community.org', 'license': 'AGPL-3', 'depends': [ 'barcodes', @@ -59,6 +27,7 @@ http://www.iconarchive.com/show/oxygen-icons-by-oxygen-icons.org.html ], 'demo': [ 'demo/res_users.xml', + 'demo/barcode_rule.xml', ], 'images': [ 'static/description/barcode_rule.png' diff --git a/barcodes_generate/demo/barcode.rule.xml b/barcodes_generate/demo/barcode.rule.xml new file mode 100644 index 00000000..b37e4458 --- /dev/null +++ b/barcodes_generate/demo/barcode.rule.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + Partner (Generated Barcode) + + client + ean13 + 042......... + 999 + + + + diff --git a/barcodes_generate/demo/barcode_rule.xml b/barcodes_generate/demo/barcode_rule.xml new file mode 100644 index 00000000..f5f152db --- /dev/null +++ b/barcodes_generate/demo/barcode_rule.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + Partner (Generated Barcode) + + + client + ean13 + 042......... + 999 + + + + diff --git a/barcodes_generate/demo/res_users.xml b/barcodes_generate/demo/res_users.xml index bdf035f6..b90eb9d5 100644 --- a/barcodes_generate/demo/res_users.xml +++ b/barcodes_generate/demo/res_users.xml @@ -1,13 +1,19 @@ - + - + - + + diff --git a/barcodes_generate/models/barcode_generate_mixin.py b/barcodes_generate/models/barcode_generate_mixin.py index 10c544bf..266df28e 100644 --- a/barcodes_generate/models/barcode_generate_mixin.py +++ b/barcodes_generate/models/barcode_generate_mixin.py @@ -1,53 +1,99 @@ # -*- coding: utf-8 -*- # Copyright (C) 2014 GRAP (http://www.grap.coop) +# Copyright (C) 2016-Today GRAP (http://www.lalouve.net) # @author: Sylvain LE GAL (https://twitter.com/legalsylvain) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). import barcode -from openerp.osv import fields -from openerp.osv.orm import AbstractModel +from openerp import models, fields, api, exceptions -class barcode_generate_mixin(AbstractModel): +class barcode_generate_mixin(models.AbstractModel): _name = 'barcode.generate.mixin' - _columns = { - 'barcode_rule_id': fields.many2one( - 'barcode.rule', 'Barcode Rule'), - 'barcode_base': fields.integer('Barcode Base'), - } - - def generate_barcode(self, cr, uid, ids, context=None): - vals = self._compute_custom_barcode(cr, uid, ids, context=context) - for id in vals.keys(): - self.write(cr, uid, id, {'ean13': vals[id]}, context=context) - return True - - def _compute_custom_barcode(self, cr, uid, ids, context=None): - res = {} - for item in self.browse(cr, uid, ids, context=context): - if item.barcode_rule_id and item.barcode_base: - pass - barcode_class = barcode.get_barcode_class( - item.barcode_rule_id.encoding) + # Column Section + barcode_rule_id = fields.Many2one( + string='Barcode Rule', comodel_name='barcode.rule') + + barcode_base = fields.Char(string='Barcode Base') + + # Constrains Section + @api.multi + @api.constrains('barcode_base') + def _constrains_barcode_base(self): + for item in self: + if item.barcode_base and not item.barcode_base.isdigit(): + raise exceptions.Warning(_("Barcode Base should be numeric")) + + # View Section + @api.multi + def generate_base(self): + for item in self: + padding = item.barcode_rule_id.pattern.count('.') + generic_code = self._get_custom_barcode(item) + if generic_code: + generic_code = generic_code.replace( + '.' * padding, '_' * padding) + reserved_barcodes = self.search([('barcode', 'ilike', generic_code)]).mapped('barcode') + next_base = str(self._get_next_integer_base( + item, generic_code, reserved_barcodes)).rjust(padding, '0') + item.barcode_base = next_base + + @api.multi + def generate_barcode(self): + for item in self: padding = item.barcode_rule_id.pattern.count('.') full_base = str(item.barcode_base).rjust(padding, '0') + custom_code = self._get_custom_barcode(item) + if custom_code: + custom_code = custom_code.replace('.' * padding, full_base) + barcode_class = barcode.get_barcode_class( + item.barcode_rule_id.encoding) + item.barcode = barcode_class(custom_code) + + @api.multi + def generate_base_barcode(self): + for item in self: + if not item.barcode_base: + item.generate_base() + item.generate_barcode() + + # Custom Section + @api.model + def _get_next_integer_base(self, item, generic_code, reserved_barcodes): + """Given a list of reserved_barcodes, This will return the next" + base barcode. By default, return the max barcode base + 1. + Overload / Overwrite this function to provide custom behaviour. + (specially, fill gaps functionnality). + generic_code should have the '_' pattern. + """ + if not reserved_barcodes: + return 1 + max_barcode = sorted(reserved_barcodes)[len(reserved_barcodes) - 1] + begin = generic_code.find('_') + end = begin + generic_code.count('_') + return int(max_barcode[begin:end]) + 1 + + @api.model + def _get_custom_barcode(self, item): + """ + if the pattern is '23.....{NNNDD}' + this function will return '23.....00000' + """ + if not item.barcode_rule_id: + return False + + # Define barcode + custom_code = item.barcode_rule_id.pattern + custom_code = custom_code.replace('{', '').replace('}', '') + custom_code = custom_code.replace( + 'D', self._get_replacement_char('D')) + return custom_code.replace( + 'N', self._get_replacement_char('N')) - # Define barcode - custom_code = item.barcode_rule_id.pattern - custom_code = custom_code.replace('{', '').replace('}', '') - custom_code = custom_code.replace( - 'D', self._get_barcode_replacement_char( - cr, uid, 'D', context=context)) - custom_code = custom_code.replace( - 'N', self._get_barcode_replacement_char( - cr, uid, 'N', context=context)) - custom_code = custom_code.replace('.' * padding, full_base) - res[item.id] = barcode_class(custom_code) - return res - - def _get_barcode_replacement_char(self, cr, uid, char, context=None): + @api.model + def _get_replacement_char(self, char): """ Can be overload by inheritance Define wich character will be used instead of the 'N' or the 'D' diff --git a/barcodes_generate/models/barcode_rule.py b/barcodes_generate/models/barcode_rule.py index 3a4a63f7..ef57c695 100644 --- a/barcodes_generate/models/barcode_rule.py +++ b/barcodes_generate/models/barcode_rule.py @@ -1,27 +1,21 @@ # -*- coding: utf-8 -*- # Copyright (C) 2014 GRAP (http://www.grap.coop) +# Copyright (C) 2016-Today GRAP (http://www.lalouve.net) # @author: Sylvain LE GAL (https://twitter.com/legalsylvain) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from openerp.osv import fields -from openerp.osv.orm import Model +from openerp import models, fields -class barcode_rule(Model): +class barcode_rule(models.Model): _inherit = 'barcode.rule' - _columns = { - 'is_product_available': fields.boolean( - string='Available for Products', help="If checked, users with" - " specific access right will have the possibility to generate" - " barcodes with this pattern for the products."), - 'is_partner_available': fields.boolean( - string='Available for Partners', help="If checked, users with" - " specific access right will have the possibility to generate" - " barcodes with this pattern for the partners."), - } + is_product_available = fields.Boolean( + string='Available for Products', help="If checked, users with" + " specific access right will have the possibility to generate" + " barcodes with this pattern for the products.") - # TODO set constraint - # is_product_available and is_partner_available: - # - should be possible only for ean13 barcode rule - # - should be possible only if pattern contains at leas one '.' char + is_partner_available = fields.Boolean( + string='Available for Partners', help="If checked, users with" + " specific access right will have the possibility to generate" + " barcodes with this pattern for the partners.") diff --git a/barcodes_generate/models/product_product.py b/barcodes_generate/models/product_product.py index c20f9475..6ec511d0 100644 --- a/barcodes_generate/models/product_product.py +++ b/barcodes_generate/models/product_product.py @@ -1,11 +1,12 @@ # -*- coding: utf-8 -*- # Copyright (C) 2014 GRAP (http://www.grap.coop) +# Copyright (C) 2016-Today GRAP (http://www.lalouve.net) # @author: Sylvain LE GAL (https://twitter.com/legalsylvain) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from openerp.osv.orm import Model +from openerp import models -class product_product(Model): +class ProductProduct(models.Model): _name = 'product.product' _inherit = ['product.product', 'barcode.generate.mixin'] diff --git a/barcodes_generate/models/res_partner.py b/barcodes_generate/models/res_partner.py index 9ae48017..8d3aee6b 100644 --- a/barcodes_generate/models/res_partner.py +++ b/barcodes_generate/models/res_partner.py @@ -3,9 +3,9 @@ # @author: Sylvain LE GAL (https://twitter.com/legalsylvain) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from openerp.osv.orm import Model +from openerp import models -class res_partner(Model): +class ResPartner(models.Model): _name = 'res.partner' _inherit = ['res.partner', 'barcode.generate.mixin'] diff --git a/barcodes_generate/security/res_groups.xml b/barcodes_generate/security/res_groups.xml index 0d81da22..a9522bde 100644 --- a/barcodes_generate/security/res_groups.xml +++ b/barcodes_generate/security/res_groups.xml @@ -1,11 +1,12 @@ - + Generate Barcodes for Products @@ -17,4 +18,4 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - + diff --git a/barcodes_generate/static/description/barcode_rule_form.png b/barcodes_generate/static/description/barcode_rule_form.png new file mode 100644 index 00000000..f90c9bdc Binary files /dev/null and b/barcodes_generate/static/description/barcode_rule_form.png differ diff --git a/barcodes_generate/static/description/barcode_rule.png b/barcodes_generate/static/description/barcode_rule_tree.png similarity index 100% rename from barcodes_generate/static/description/barcode_rule.png rename to barcodes_generate/static/description/barcode_rule_tree.png diff --git a/barcodes_generate/static/description/product_product_form_empty.png b/barcodes_generate/static/description/product_product_form_empty.png new file mode 100644 index 00000000..8ed388be Binary files /dev/null and b/barcodes_generate/static/description/product_product_form_empty.png differ diff --git a/barcodes_generate/static/description/product_product_form_generated.png b/barcodes_generate/static/description/product_product_form_generated.png new file mode 100644 index 00000000..9c3e609d Binary files /dev/null and b/barcodes_generate/static/description/product_product_form_generated.png differ diff --git a/barcodes_generate/views/view_barcode_rule.xml b/barcodes_generate/views/view_barcode_rule.xml index 08b7299d..98e39484 100644 --- a/barcodes_generate/views/view_barcode_rule.xml +++ b/barcodes_generate/views/view_barcode_rule.xml @@ -1,11 +1,12 @@ - + barcode.rule @@ -18,4 +19,4 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - + diff --git a/barcodes_generate/views/view_product_product.xml b/barcodes_generate/views/view_product_product.xml index 77df09cf..b45483e1 100644 --- a/barcodes_generate/views/view_product_product.xml +++ b/barcodes_generate/views/view_product_product.xml @@ -1,28 +1,39 @@ - + product.product - + - + + + +