from odoo.exceptions import ValidationError from odoo.tests import common class TestBarcodeNomenclature(common.TransactionCase): @classmethod def setUpClass(cls): super().setUpClass() # Creates an empty nomenclature (rules will be added in the tests). cls.nomenclature = cls.env['barcode.nomenclature'].create({ 'name': 'Barcode Nomenclature Test', }) def test_barcode_nomenclature_parse_barcode_ean8_01(self): """ Parses some barcodes with a simple EAN-8 barcode rule and checks the result. """ self.env['barcode.rule'].create({ 'name': 'Rule Test #1', 'barcode_nomenclature_id': self.nomenclature.id, 'encoding': 'ean8', 'pattern': '........', }) # Must fail because too short. res = self.nomenclature.parse_barcode('0002') self.assertEqual(res['code'], '0002') self.assertEqual(res['type'], 'error', "Must fail because the barcode is too short") self.assertEqual(res['encoding'], '') self.assertEqual(res['base_code'], '0002') self.assertEqual(res['value'], 0) # Must fail because wrong checksum (last digit). res = self.nomenclature.parse_barcode('12345678') self.assertEqual(res['code'], '12345678') self.assertEqual(res['type'], 'error', "Must fail because the checksum digit is wrong") self.assertEqual(res['encoding'], '') self.assertEqual(res['base_code'], '12345678') self.assertEqual(res['value'], 0) # Must pass (right number of digits, right checksum). res = self.nomenclature.parse_barcode('12345670') self.assertEqual(res['code'], '12345670') self.assertEqual(res['type'], 'product') self.assertEqual(res['encoding'], 'ean8') self.assertEqual(res['base_code'], '12345670') self.assertEqual(res['value'], 0, "No value must be located into the barcode") # Must pass (right number of digits, right checksum). res = self.nomenclature.parse_barcode('02003405') self.assertEqual(res['code'], '02003405') self.assertEqual(res['type'], 'product') self.assertEqual(res['encoding'], 'ean8') self.assertEqual(res['base_code'], '02003405') self.assertEqual(res['value'], 0, "No value must be located into the barcode") def test_barcode_nomenclature_parse_barcode_ean8_02_validation_error(self): """ Try to parse a barcode with a wrong barcode rule. """ barcode_rule = self.env['barcode.rule'].create({ 'name': 'Rule Test #1', 'barcode_nomenclature_id': self.nomenclature.id, 'encoding': 'ean8', }) with self.assertRaises(ValidationError), self.cr.savepoint(): # Must fail because empty braces. barcode_rule.pattern = '......{}..' with self.assertRaises(ValidationError), self.cr.savepoint(): # Must fail because decimal can't be before integer. barcode_rule.pattern = '......{DN}' with self.assertRaises(ValidationError), self.cr.savepoint(): # Must fail because a pattern can't have multiple braces group. barcode_rule.pattern = '....{NN}{DD}' with self.assertRaises(ValidationError), self.cr.savepoint(): # Must fail because '*' isn't accepted (should be '.*' instead). barcode_rule.pattern = '*' with self.assertRaises(ValidationError), self.cr.savepoint(): # Must fail because '**' isn't even a valid regular expression. barcode_rule.pattern = '**>>>{ND}' # Allowed since it leads to a valid regular expression. barcode_rule.pattern = '..>>>{ND}' def test_barcode_nomenclature_parse_barcode_ean8_03_value(self): """ Parses some barcodes with a EAN-8 barcode rule who convert the barcode into value and checks the result. """ self.env['barcode.rule'].create({ 'name': 'Rule Test #2', 'barcode_nomenclature_id': self.nomenclature.id, 'encoding': 'ean8', 'pattern': '{NNNNNNNN}', }) res = self.nomenclature.parse_barcode('0002') self.assertEqual(res['code'], '0002') self.assertEqual(res['type'], 'error', "Must fail because the barcode is too short") self.assertEqual(res['encoding'], '') self.assertEqual(res['base_code'], '0002') self.assertEqual(res['value'], 0) res = self.nomenclature.parse_barcode('12345678') self.assertEqual(res['code'], '12345678') self.assertEqual(res['type'], 'error', "Must fail because the checksum digit is wrong") self.assertEqual(res['encoding'], '') self.assertEqual(res['base_code'], '12345678') self.assertEqual(res['value'], 0) # Must pass (right number of digits, right checksum). res = self.nomenclature.parse_barcode('12345670') self.assertEqual(res['code'], '12345670') self.assertEqual(res['type'], 'product') self.assertEqual(res['encoding'], 'ean8') self.assertEqual(res['base_code'], '00000000', "All the barcode should be consumed into the value") self.assertEqual(res['value'], 12345670.0, "The barcode must be converted into value") # Must pass (right number of digits, right checksum). res = self.nomenclature.parse_barcode('02003405') self.assertEqual(res['code'], '02003405') self.assertEqual(res['type'], 'product') self.assertEqual(res['encoding'], 'ean8') self.assertEqual(res['base_code'], '00000000', "All the barcode should be consumed into the value") self.assertEqual(res['value'], 2003405.0, "The barcode must be converted into value") def test_barcode_nomenclature_parse_barcode_ean8_04_multiple_rules(self): """ Parses some barcodes with a nomenclature containing multiple EAN-8 barcode rule and checks the right one is took depending of the pattern. """ self.env['barcode.rule'].create({ 'name': 'Rule Test #1', 'barcode_nomenclature_id': self.nomenclature.id, 'encoding': 'ean8', 'pattern': '11.....{N}', }) self.env['barcode.rule'].create({ 'name': 'Rule Test #1', 'barcode_nomenclature_id': self.nomenclature.id, 'encoding': 'ean8', 'pattern': '66{NN}....', }) # Only fits the second barcode rule. res = self.nomenclature.parse_barcode('11012344') self.assertEqual(res['code'], '11012344') self.assertEqual(res['type'], 'product') self.assertEqual(res['encoding'], 'ean8') self.assertEqual(res['base_code'], '11012340') self.assertEqual(res['value'], 4) # Only fits the second barcode rule. res = self.nomenclature.parse_barcode('66012344') self.assertEqual(res['code'], '66012344') self.assertEqual(res['type'], 'product') self.assertEqual(res['encoding'], 'ean8') self.assertEqual(res['base_code'], '66002344') self.assertEqual(res['value'], 1) # Doesn't fit any barcode rule. res = self.nomenclature.parse_barcode('16012344') self.assertEqual(res['code'], '16012344') self.assertEqual(res['type'], 'error') self.assertEqual(res['encoding'], '') self.assertEqual(res['base_code'], '16012344') self.assertEqual(res['value'], 0) def test_barcode_nomenclature_parse_barcode_ean13_01(self): """ Parses some barcodes with a EAN-13 barcode rule who contains a value and checks the result. """ self.env['barcode.rule'].create({ 'name': 'Rule Test #3', 'barcode_nomenclature_id': self.nomenclature.id, 'encoding': 'ean13', 'pattern': '1........{NND}.', }) # Must fail because too short. res = self.nomenclature.parse_barcode('0002') self.assertEqual(res['code'], '0002') self.assertEqual(res['type'], 'error', "Must fail because the barcode is too short") self.assertEqual(res['encoding'], '') self.assertEqual(res['base_code'], '0002') self.assertEqual(res['value'], 0) # Must fail because wrong checksum (last digit). res = self.nomenclature.parse_barcode('12345678') self.assertEqual(res['code'], '12345678') self.assertEqual(res['type'], 'error', "Must fail because the checksum digit is wrong") self.assertEqual(res['encoding'], '') self.assertEqual(res['base_code'], '12345678') self.assertEqual(res['value'], 0) # Must pass (right number of digits, right checksum). res = self.nomenclature.parse_barcode('1020034051259') self.assertEqual(res['code'], '1020034051259') self.assertEqual(res['type'], 'product') self.assertEqual(res['encoding'], 'ean13') self.assertEqual(res['base_code'], '1020034050009') self.assertEqual(res['value'], 12.5, "Should taken only the value part (NND)") def test_barcode_nomenclature_parse_barcode_ean13_02_sequence(self): """ Parses some barcodes with a nomenclature containing two EAN-13 barcode rule and checks the good one is took depending of its sequence. """ first_created_rule = self.env['barcode.rule'].create({ 'name': 'Rule Test #1', 'barcode_nomenclature_id': self.nomenclature.id, 'encoding': 'ean13', 'pattern': '.....{NNNDDDD}.', 'sequence': 3, }) self.env['barcode.rule'].create({ 'name': 'Rule Test #2', 'barcode_nomenclature_id': self.nomenclature.id, 'encoding': 'ean13', 'pattern': '22......{NNDD}.', 'sequence': 2, }) # Invalids the cache to reset the nomenclature barcode rules' order. self.nomenclature.invalidate_recordset(['rule_ids']) # Only fits the second barcode rule. res = self.nomenclature.parse_barcode('2012345610255') self.assertEqual(res['code'], '2012345610255') self.assertEqual(res['type'], 'product') self.assertEqual(res['encoding'], 'ean13') self.assertEqual(res['base_code'], '2012300000008') self.assertEqual(res['value'], 456.1025) # Fits the two barcode rules, but should take the second one (lower sequence). res = self.nomenclature.parse_barcode('2212345610259') self.assertEqual(res['code'], '2212345610259') self.assertEqual(res['type'], 'product') self.assertEqual(res['encoding'], 'ean13') self.assertEqual(res['base_code'], '2212345600007') self.assertEqual(res['value'], 10.25) first_created_rule.sequence = 1 # Invalids the cache to reset the nomenclature barcode rules' order. self.nomenclature.invalidate_recordset(['rule_ids']) # Should take the first one now (lower sequence). res = self.nomenclature.parse_barcode('2212345610259') self.assertEqual(res['code'], '2212345610259') self.assertEqual(res['type'], 'product') self.assertEqual(res['encoding'], 'ean13') self.assertEqual(res['base_code'], '2212300000002') self.assertEqual(res['value'], 456.1025) def test_barcode_uri_conversion(self): """ This test ensures URIs are correctly converted into barcode data.""" uri = 'urn:epc:class:lgtin : 4012345.012345.998877' barcode_data = self.nomenclature.parse_barcode(uri) self.assertEqual(len(barcode_data), 2) product_part, lot_part = barcode_data self.assertEqual(product_part['type'], 'product') self.assertEqual(product_part['value'], '04012345123456') self.assertEqual(lot_part['type'], 'lot') self.assertEqual(lot_part['value'], '998877') uri = 'urn:epc:id:sgtin:9521141.012345.4711' barcode_data = self.nomenclature.parse_barcode(uri) self.assertEqual(len(barcode_data), 2) product_part, serial_part = barcode_data self.assertEqual(product_part['type'], 'product') self.assertEqual(product_part['value'], '09521141123454') self.assertEqual(serial_part['type'], 'lot') self.assertEqual(serial_part['value'], '4711') uri = 'urn:epc:tag:sgtin-96 : 1.358378.0728089.620776' barcode_data = self.nomenclature.parse_barcode(uri) self.assertEqual(len(barcode_data), 2) product_part, serial_part = barcode_data self.assertEqual(product_part['type'], 'product') self.assertEqual(product_part['value'], '03583787280898') self.assertEqual(serial_part['type'], 'lot') self.assertEqual(serial_part['value'], '620776') uri = 'urn:epc:id:sscc:952656789012.03456' barcode_data = self.nomenclature.parse_barcode(uri) self.assertEqual(len(barcode_data), 1) self.assertEqual(barcode_data[0]['type'], 'package') self.assertEqual(barcode_data[0]['value'], '095265678901234568')