diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index a0ed1f24290..2b3d3b72a02 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -32,7 +32,7 @@ test_ignore = ["BOM"] test_dependencies = ["Warehouse", "Item Group", "Item Tax Template", "Brand", "Item Attribute"] -def make_item(item_code=None, properties=None, uoms=None): +def make_item(item_code=None, properties=None, uoms=None, barcode=None): if not item_code: item_code = frappe.generate_hash(length=16) @@ -61,6 +61,14 @@ def make_item(item_code=None, properties=None, uoms=None): for uom in uoms: item.append("uoms", uom) + if barcode: + item.append( + "barcodes", + { + "barcode": barcode, + }, + ) + item.insert() return item diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 9bb607cc6f2..238de34cd51 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -30,6 +30,7 @@ from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import ( OpeningEntryAccountError, ) from erpnext.stock.get_item_details import ( + get_barcode_data, get_bin_details, get_conversion_factor, get_default_cost_center, @@ -428,7 +429,14 @@ class StockEntry(StockController): for field in reset_fields: item.set(field, item_details.get(field)) - update_fields = ("uom", "description", "expense_account", "cost_center", "conversion_factor") + update_fields = ( + "uom", + "description", + "expense_account", + "cost_center", + "conversion_factor", + "barcode", + ) for field in update_fields: if not item.get(field): @@ -1634,6 +1642,10 @@ class StockEntry(StockController): if subcontract_items and len(subcontract_items) == 1: ret["subcontracted_item"] = subcontract_items[0].main_item_code + barcode_data = get_barcode_data(item_code=item.name) + if barcode_data and len(barcode_data.get(item.name)) == 1: + ret["barcode"] = barcode_data.get(item.name)[0] + return ret @frappe.whitelist() diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index 9d7e3baa336..34b4ac222e7 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -110,6 +110,12 @@ class TestStockEntry(FrappeTestCase): self._test_auto_material_request("_Test Item") self._test_auto_material_request("_Test Item", material_request_type="Transfer") + def test_barcode_item_stock_entry(self): + item_code = make_item("_Test Item Stock Entry For Barcode", barcode="BDD-1234567890") + + se = make_stock_entry(item_code=item_code, target="_Test Warehouse - _TC", qty=1, basic_rate=100) + self.assertEqual(se.items[0].barcode, "BDD-1234567890") + def test_auto_material_request_for_variant(self): fields = [{"field_name": "reorder_levels"}] set_item_variant_settings(fields) diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js index 4a85360235a..8532b60d59c 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js @@ -81,6 +81,18 @@ frappe.ui.form.on("Stock Reconciliation", { if (frm.doc.company) { frm.trigger("toggle_display_account_head"); } + + frm.events.set_fields_onload_for_line_item(frm); + }, + + set_fields_onload_for_line_item(frm) { + if (frm.is_new() && frm.doc?.items && cint(frappe.user_defaults?.use_serial_batch_fields) === 1) { + frm.doc.items.forEach((item) => { + if (!item.serial_and_batch_bundle) { + frappe.model.set_value(item.doctype, item.name, "use_serial_batch_fields", 1); + } + }); + } }, scan_barcode: function (frm) { @@ -155,6 +167,9 @@ frappe.ui.form.on("Stock Reconciliation", { item.qty = item.qty || 0; item.valuation_rate = item.valuation_rate || 0; + item.use_serial_batch_fields = cint( + frappe.user_defaults?.use_serial_batch_fields + ); }); frm.refresh_field("items"); }, @@ -298,6 +313,10 @@ frappe.ui.form.on("Stock Reconciliation Item", { if (!item.warehouse && frm.doc.set_warehouse) { frappe.model.set_value(cdt, cdn, "warehouse", frm.doc.set_warehouse); } + + if (item.docstatus === 0 && cint(frappe.user_defaults?.use_serial_batch_fields) === 1) { + frappe.model.set_value(item.doctype, item.name, "use_serial_batch_fields", 1); + } }, add_serial_batch_bundle(frm, cdt, cdn) { diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index ee2f9cb6faa..247ab1f7d47 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -490,12 +490,21 @@ def update_barcode_value(out): out["barcode"] = barcode_data.get(out.item_code)[0] -def get_barcode_data(items_list): +def get_barcode_data(items_list=None, item_code=None): # get item-wise batch no data # example: {'LED-GRE': [Batch001, Batch002]} # where LED-GRE is item code, SN0001 is serial no and Pune is warehouse itemwise_barcode = {} + if not items_list and item_code: + _dict_item_code = frappe._dict( + { + "item_code": item_code, + } + ) + + items_list = [frappe._dict(_dict_item_code)] + for item in items_list: barcodes = frappe.db.get_all("Item Barcode", filters={"parent": item.item_code}, fields="barcode")