You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

102 lines
3.7 KiB

8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
  1. # -*- coding: utf-8 -*-
  2. # Copyright (C) 2014 GRAP (http://www.grap.coop)
  3. # Copyright (C) 2016-Today GRAP (http://www.lalouve.net)
  4. # @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
  5. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  6. import barcode
  7. from openerp import models, fields, api, exceptions
  8. class barcode_generate_mixin(models.AbstractModel):
  9. _name = 'barcode.generate.mixin'
  10. # Column Section
  11. barcode_rule_id = fields.Many2one(
  12. string='Barcode Rule', comodel_name='barcode.rule')
  13. barcode_base = fields.Char(string='Barcode Base')
  14. # Constrains Section
  15. @api.multi
  16. @api.constrains('barcode_base')
  17. def _constrains_barcode_base(self):
  18. for item in self:
  19. if item.barcode_base and not item.barcode_base.isdigit():
  20. raise exceptions.Warning(_("Barcode Base should be numeric"))
  21. # View Section
  22. @api.multi
  23. def generate_base(self):
  24. for item in self:
  25. padding = item.barcode_rule_id.pattern.count('.')
  26. generic_code = self._get_custom_barcode(item)
  27. if generic_code:
  28. generic_code = generic_code.replace(
  29. '.' * padding, '_' * padding)
  30. reserved_barcodes = self.search([('barcode', 'ilike', generic_code)]).mapped('barcode')
  31. next_base = str(self._get_next_integer_base(
  32. item, generic_code, reserved_barcodes)).rjust(padding, '0')
  33. item.barcode_base = next_base
  34. @api.multi
  35. def generate_barcode(self):
  36. for item in self:
  37. padding = item.barcode_rule_id.pattern.count('.')
  38. full_base = str(item.barcode_base).rjust(padding, '0')
  39. custom_code = self._get_custom_barcode(item)
  40. if custom_code:
  41. custom_code = custom_code.replace('.' * padding, full_base)
  42. barcode_class = barcode.get_barcode_class(
  43. item.barcode_rule_id.encoding)
  44. item.barcode = barcode_class(custom_code)
  45. @api.multi
  46. def generate_base_barcode(self):
  47. for item in self:
  48. if not item.barcode_base:
  49. item.generate_base()
  50. item.generate_barcode()
  51. # Custom Section
  52. @api.model
  53. def _get_next_integer_base(self, item, generic_code, reserved_barcodes):
  54. """Given a list of reserved_barcodes, This will return the next"
  55. base barcode. By default, return the max barcode base + 1.
  56. Overload / Overwrite this function to provide custom behaviour.
  57. (specially, fill gaps functionnality).
  58. generic_code should have the '_' pattern.
  59. """
  60. if not reserved_barcodes:
  61. return 1
  62. max_barcode = sorted(reserved_barcodes)[len(reserved_barcodes) - 1]
  63. begin = generic_code.find('_')
  64. end = begin + generic_code.count('_')
  65. return int(max_barcode[begin:end]) + 1
  66. @api.model
  67. def _get_custom_barcode(self, item):
  68. """
  69. if the pattern is '23.....{NNNDD}'
  70. this function will return '23.....00000'
  71. """
  72. if not item.barcode_rule_id:
  73. return False
  74. # Define barcode
  75. custom_code = item.barcode_rule_id.pattern
  76. custom_code = custom_code.replace('{', '').replace('}', '')
  77. custom_code = custom_code.replace(
  78. 'D', self._get_replacement_char('D'))
  79. return custom_code.replace(
  80. 'N', self._get_replacement_char('N'))
  81. @api.model
  82. def _get_replacement_char(self, char):
  83. """
  84. Can be overload by inheritance
  85. Define wich character will be used instead of the 'N' or the 'D'
  86. char, present in the pattern of the barcode_rule_id
  87. """
  88. return '0'