diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 686e6cb047..c06700a99a 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -358,7 +358,7 @@ class Item(Document): check_list.append(d.item_tax_template) def validate_barcode(self): - from stdnum import ean + import barcodenumber if len(self.barcodes) > 0: for item_barcode in self.barcodes: @@ -376,19 +376,16 @@ class Item(Document): item_barcode.barcode_type = ( "" if item_barcode.barcode_type not in options else item_barcode.barcode_type ) - if item_barcode.barcode_type and item_barcode.barcode_type.upper() in ( - "EAN", - "UPC-A", - "EAN-13", - "EAN-8", - ): - if not ean.is_valid(item_barcode.barcode): - frappe.throw( - _("Barcode {0} is not a valid {1} code").format( - item_barcode.barcode, item_barcode.barcode_type - ), - InvalidBarcode, - ) + if item_barcode.barcode_type: + barcode_type = convert_erpnext_to_barcodenumber(item_barcode.barcode_type.upper()) + if barcode_type in barcodenumber.barcodes(): + if not barcodenumber.check_code(barcode_type, item_barcode.barcode): + frappe.throw( + _("Barcode {0} is not a valid {1} code").format( + item_barcode.barcode, item_barcode.barcode_type + ), + InvalidBarcode, + ) def validate_warehouse_for_reorder(self): """Validate Reorder level table for duplicate and conditional mandatory""" @@ -985,6 +982,22 @@ class Item(Document): ) +def convert_erpnext_to_barcodenumber(erpnext_number): + convert = { + "UPC-A": "UPCA", + "CODE-39": "CODE39", + "EAN": "EAN13", + "EAN-12": "EAN", + "EAN-8": "EAN8", + "ISBN-10": "ISBN10", + "ISBN-13": "ISBN13", + } + if erpnext_number in convert: + return convert[erpnext_number] + else: + return erpnext_number + + def make_item_price(item, price_list_name, item_price): frappe.get_doc( { diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index 53f6b7f8f1..67ed90d4e7 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -579,6 +579,19 @@ class TestItem(FrappeTestCase): { "barcode": "ARBITRARY_TEXT", }, + {"barcode": "72527273070", "barcode_type": "UPC-A"}, + {"barcode": "123456", "barcode_type": "CODE-39"}, + {"barcode": "401268452363", "barcode_type": "EAN-12"}, + {"barcode": "90311017", "barcode_type": "EAN-8"}, + {"barcode": "0123456789012", "barcode_type": "GS1"}, + {"barcode": "2211564566668", "barcode_type": "GTIN"}, + {"barcode": "0256480249", "barcode_type": "ISBN"}, + {"barcode": "0192552570", "barcode_type": "ISBN-10"}, + {"barcode": "9781234567897", "barcode_type": "ISBN-13"}, + {"barcode": "9771234567898", "barcode_type": "ISSN"}, + {"barcode": "4581171967072", "barcode_type": "JAN"}, + {"barcode": "12345678", "barcode_type": "PZN"}, + {"barcode": "725272730706", "barcode_type": "UPC"}, ] create_item(item_code) for barcode_properties in barcode_properties_list: diff --git a/erpnext/stock/doctype/item_barcode/item_barcode.json b/erpnext/stock/doctype/item_barcode/item_barcode.json index bda1218817..d9a8347ca0 100644 --- a/erpnext/stock/doctype/item_barcode/item_barcode.json +++ b/erpnext/stock/doctype/item_barcode/item_barcode.json @@ -25,7 +25,7 @@ "fieldtype": "Select", "in_list_view": 1, "label": "Barcode Type", - "options": "\nEAN\nUPC-A" + "options": "\nEAN\nUPC-A\nCODE-39\nEAN-12\nEAN-8\nGS1\nGTIN\nISBN\nISBN-10\nISBN-13\nISSN\nJAN\nPZN\nUPC" }, { "fieldname": "uom", diff --git a/pyproject.toml b/pyproject.toml index 1b342a5fbb..9993e4b9b6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,6 +12,7 @@ dependencies = [ "pycountry~=20.7.3", "python-stdnum~=1.16", "Unidecode~=1.2.0", + "barcodenumber~=0.5.0", # integration dependencies "gocardless-pro~=1.22.0",