From 61d59b392a7c97743a4b07959ea3a0eeb22958b8 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 15 Mar 2024 18:19:56 +0530 Subject: [PATCH] fix: serial and batch for internal transfer (backport #40467) (#40477) fix: serial and batch for internal transfer (#40467) * fix: serial and batch for internal transfer * chore: fix test cases (cherry picked from commit 59222813af2cf1407da5708814795e302ce6be34) Co-authored-by: rohitwaghchaure --- .../sales_invoice/test_sales_invoice.py | 1 - erpnext/controllers/buying_controller.py | 37 ++- .../controllers/sales_and_purchase_return.py | 22 +- erpnext/controllers/selling_controller.py | 33 ++- erpnext/controllers/stock_controller.py | 11 +- .../js/utils/serial_no_batch_selector.js | 4 + .../doctype/delivery_note/delivery_note.py | 1 + .../purchase_receipt/test_purchase_receipt.py | 274 ++++++++++++++++++ .../serial_and_batch_bundle.json | 3 +- .../serial_and_batch_bundle.py | 1 + .../stock/doctype/stock_entry/stock_entry.py | 1 + .../doctype/stock_entry/test_stock_entry.py | 1 + erpnext/stock/serial_batch_bundle.py | 4 + 13 files changed, 374 insertions(+), 19 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 6a01ccf3409..2876ebd4eb3 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -3932,7 +3932,6 @@ def create_internal_supplier(supplier_name, represents_company, allowed_to_inter ) supplier.append("companies", {"company": allowed_to_interact_with}) - supplier.insert() supplier_name = supplier.name else: diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 821185766eb..c5307270156 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -513,6 +513,14 @@ class BuyingController(SubcontractingController): (not cint(self.is_return) and self.docstatus == 1) or (cint(self.is_return) and self.docstatus == 2) ): + serial_and_batch_bundle = d.get("serial_and_batch_bundle") + if self.is_internal_transfer() and self.is_return and self.docstatus == 2: + serial_and_batch_bundle = frappe.db.get_value( + "Stock Ledger Entry", + {"voucher_detail_no": d.name, "warehouse": d.from_warehouse}, + "serial_and_batch_bundle", + ) + from_warehouse_sle = self.get_sl_entries( d, { @@ -521,19 +529,24 @@ class BuyingController(SubcontractingController): "outgoing_rate": d.rate, "recalculate_rate": 1, "dependant_sle_voucher_detail_no": d.name, + "serial_and_batch_bundle": serial_and_batch_bundle, }, ) sl_entries.append(from_warehouse_sle) + type_of_transaction = "Inward" + if self.docstatus == 2: + type_of_transaction = "Outward" + sle = self.get_sl_entries( d, { "actual_qty": flt(pr_qty), "serial_and_batch_bundle": ( d.serial_and_batch_bundle - if not self.is_internal_transfer() - else self.get_package_for_target_warehouse(d) + if not self.is_internal_transfer() or self.is_return + else self.get_package_for_target_warehouse(d, type_of_transaction=type_of_transaction) ), }, ) @@ -570,7 +583,17 @@ class BuyingController(SubcontractingController): or (cint(self.is_return) and self.docstatus == 1) ): from_warehouse_sle = self.get_sl_entries( - d, {"actual_qty": -1 * pr_qty, "warehouse": d.from_warehouse, "recalculate_rate": 1} + d, + { + "actual_qty": -1 * pr_qty, + "warehouse": d.from_warehouse, + "recalculate_rate": 1, + "serial_and_batch_bundle": ( + self.get_package_for_target_warehouse(d, d.from_warehouse, "Inward") + if self.is_internal_transfer() and self.is_return + else None + ), + }, ) sl_entries.append(from_warehouse_sle) @@ -597,13 +620,15 @@ class BuyingController(SubcontractingController): via_landed_cost_voucher=via_landed_cost_voucher, ) - def get_package_for_target_warehouse(self, item) -> str: + def get_package_for_target_warehouse(self, item, warehouse=None, type_of_transaction=None) -> str: if not item.serial_and_batch_bundle: return "" + if not warehouse: + warehouse = item.warehouse + return self.make_package_for_transfer( - item.serial_and_batch_bundle, - item.warehouse, + item.serial_and_batch_bundle, warehouse, type_of_transaction=type_of_transaction ) def update_ordered_and_reserved_qty(self): diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py index de431f3d42d..3ea3bcdfcc8 100644 --- a/erpnext/controllers/sales_and_purchase_return.py +++ b/erpnext/controllers/sales_and_purchase_return.py @@ -423,6 +423,15 @@ def make_return_doc( ]: type_of_transaction = "Outward" + warehouse = source_doc.warehouse if qty_field == "stock_qty" else source_doc.rejected_warehouse + if source_parent.doctype in [ + "Sales Invoice", + "POS Invoice", + "Delivery Note", + ] and source_parent.get("is_internal_customer"): + type_of_transaction = "Outward" + warehouse = source_doc.target_warehouse + cls_obj = SerialBatchCreation( { "type_of_transaction": type_of_transaction, @@ -432,7 +441,7 @@ def make_return_doc( "returned_serial_nos": returned_serial_nos, "voucher_type": source_parent.doctype, "do_not_submit": True, - "warehouse": source_doc.warehouse, + "warehouse": warehouse, "has_serial_no": item_details.has_serial_no, "has_batch_no": item_details.has_batch_no, } @@ -575,11 +584,14 @@ def make_return_doc( if not item_details.has_batch_no and not item_details.has_serial_no: return - for qty_field in ["stock_qty", "rejected_qty"]: - if target_doc.get(qty_field) and not target_doc.get("use_serial_batch_fields"): + if not target_doc.get("use_serial_batch_fields"): + for qty_field in ["stock_qty", "rejected_qty"]: + if not target_doc.get(qty_field): + continue + update_serial_batch_no(source_doc, target_doc, source_parent, item_details, qty_field) - elif target_doc.get(qty_field) and target_doc.get("use_serial_batch_fields"): - update_non_bundled_serial_nos(source_doc, target_doc, source_parent) + elif target_doc.get("use_serial_batch_fields"): + update_non_bundled_serial_nos(source_doc, target_doc, source_parent) def update_non_bundled_serial_nos(source_doc, target_doc, source_parent): from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index ecc28a89fa5..747b4e061b6 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -442,8 +442,10 @@ class SellingController(StockController): # Get incoming rate based on original item cost based on valuation method qty = flt(d.get("stock_qty") or d.get("actual_qty")) - if not d.incoming_rate or ( - get_valuation_method(d.item_code) == "Moving Average" and self.get("is_return") + if ( + not d.incoming_rate + or self.is_internal_transfer() + or (get_valuation_method(d.item_code) == "Moving Average" and self.get("is_return")) ): d.incoming_rate = get_incoming_rate( { @@ -458,6 +460,8 @@ class SellingController(StockController): "voucher_no": self.name, "voucher_detail_no": d.name, "allow_zero_valuation": d.get("allow_zero_valuation"), + "batch_no": d.batch_no, + "serial_no": d.serial_no, }, raise_error_if_no_rate=False, ) @@ -530,13 +534,26 @@ class SellingController(StockController): self.make_sl_entries(sl_entries) def get_sle_for_source_warehouse(self, item_row): + serial_and_batch_bundle = item_row.serial_and_batch_bundle + if serial_and_batch_bundle and self.is_internal_transfer() and self.is_return: + if self.docstatus == 1: + serial_and_batch_bundle = self.make_package_for_transfer( + serial_and_batch_bundle, item_row.warehouse, type_of_transaction="Inward" + ) + else: + serial_and_batch_bundle = frappe.db.get_value( + "Stock Ledger Entry", + {"voucher_detail_no": item_row.name, "warehouse": item_row.warehouse}, + "serial_and_batch_bundle", + ) + sle = self.get_sl_entries( item_row, { "actual_qty": -1 * flt(item_row.qty), "incoming_rate": item_row.incoming_rate, "recalculate_rate": cint(self.is_return), - "serial_and_batch_bundle": item_row.serial_and_batch_bundle, + "serial_and_batch_bundle": serial_and_batch_bundle, }, ) if item_row.target_warehouse and not cint(self.is_return): @@ -557,9 +574,15 @@ class SellingController(StockController): if item_row.warehouse: sle.dependant_sle_voucher_detail_no = item_row.name - if item_row.serial_and_batch_bundle: + if item_row.serial_and_batch_bundle and not cint(self.is_return): + type_of_transaction = "Inward" + if cint(self.is_return): + type_of_transaction = "Outward" + sle["serial_and_batch_bundle"] = self.make_package_for_transfer( - item_row.serial_and_batch_bundle, item_row.target_warehouse + item_row.serial_and_batch_bundle, + item_row.target_warehouse, + type_of_transaction=type_of_transaction, ) return sle diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 688600774cc..2b607eafdf8 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -236,6 +236,14 @@ class StockController(AccountsController): qty = row.get("rejected_qty") warehouse = row.get("rejected_warehouse") + if ( + self.is_internal_transfer() + and self.doctype in ["Sales Invoice", "Delivery Note"] + and self.is_return + ): + warehouse = row.get("target_warehouse") or row.get("warehouse") + type_of_transaction = "Outward" + bundle_details.update( { "qty": qty, @@ -579,7 +587,7 @@ class StockController(AccountsController): bundle_doc.warehouse = warehouse bundle_doc.type_of_transaction = type_of_transaction bundle_doc.voucher_type = self.doctype - bundle_doc.voucher_no = self.name + bundle_doc.voucher_no = "" if self.is_new() or self.docstatus == 2 else self.name bundle_doc.is_cancelled = 0 for row in bundle_doc.entries: @@ -595,6 +603,7 @@ class StockController(AccountsController): bundle_doc.calculate_qty_and_amount() bundle_doc.flags.ignore_permissions = True + bundle_doc.flags.ignore_validate = True bundle_doc.save(ignore_permissions=True) return bundle_doc.name diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index 24133b8cdc3..42d37bf493b 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -542,6 +542,10 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { frappe.throw(__("Please add atleast one Serial No / Batch No")); } + if (!warehouse) { + frappe.throw(__("Please select a Warehouse")); + } + frappe .call({ method: "erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.add_serial_batch_ledgers", diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index fdc9753cfc7..a7fcd04c634 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -333,6 +333,7 @@ class DeliveryNote(SellingController): "type_of_transaction": "Outward", "serial_and_batch_bundle": bundle_id, "item_code": item.get("item_code"), + "warehouse": item.get("warehouse"), } ) diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index 8c3c1f750ab..b4fc464b534 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -2522,6 +2522,280 @@ class TestPurchaseReceipt(FrappeTestCase): self.assertEqual(row.serial_no, "\n".join(serial_nos[:2])) self.assertEqual(row.rejected_serial_no, serial_nos[2]) + def test_internal_transfer_with_serial_batch_items_and_their_valuation(self): + from erpnext.controllers.sales_and_purchase_return import make_return_doc + from erpnext.stock.doctype.delivery_note.delivery_note import make_inter_company_purchase_receipt + from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note + + prepare_data_for_internal_transfer() + + customer = "_Test Internal Customer 2" + company = "_Test Company with perpetual inventory" + + batch_item_doc = make_item( + "_Test Batch Item For Stock Transfer", + {"has_batch_no": 1, "create_new_batch": 1, "batch_number_series": "BT-BIFST-.####"}, + ) + + serial_item_doc = make_item( + "_Test Serial No Item For Stock Transfer", + {"has_serial_no": 1, "serial_no_series": "BT-BIFST-.####"}, + ) + + inward_entry = make_purchase_receipt( + item_code=batch_item_doc.name, + qty=10, + rate=150, + warehouse="Stores - TCP1", + company="_Test Company with perpetual inventory", + use_serial_batch_fields=1, + do_not_submit=1, + ) + + inward_entry.append( + "items", + { + "item_code": serial_item_doc.name, + "qty": 15, + "rate": 250, + "item_name": serial_item_doc.item_name, + "conversion_factor": 1.0, + "uom": serial_item_doc.stock_uom, + "stock_uom": serial_item_doc.stock_uom, + "warehouse": "Stores - TCP1", + "use_serial_batch_fields": 1, + }, + ) + + inward_entry.submit() + inward_entry.reload() + + for row in inward_entry.items: + self.assertTrue(row.serial_and_batch_bundle) + + inter_transfer_dn = create_delivery_note( + item_code=inward_entry.items[0].item_code, + company=company, + customer=customer, + cost_center="Main - TCP1", + expense_account="Cost of Goods Sold - TCP1", + qty=10, + rate=500, + warehouse="Stores - TCP1", + target_warehouse="Work In Progress - TCP1", + batch_no=get_batch_from_bundle(inward_entry.items[0].serial_and_batch_bundle), + use_serial_batch_fields=1, + do_not_submit=1, + ) + + inter_transfer_dn.append( + "items", + { + "item_code": serial_item_doc.name, + "qty": 15, + "rate": 350, + "item_name": serial_item_doc.item_name, + "conversion_factor": 1.0, + "uom": serial_item_doc.stock_uom, + "stock_uom": serial_item_doc.stock_uom, + "warehouse": "Stores - TCP1", + "target_warehouse": "Work In Progress - TCP1", + "serial_no": "\n".join( + get_serial_nos_from_bundle(inward_entry.items[1].serial_and_batch_bundle) + ), + "use_serial_batch_fields": 1, + }, + ) + + inter_transfer_dn.submit() + inter_transfer_dn.reload() + for row in inter_transfer_dn.items: + if row.item_code == batch_item_doc.name: + self.assertEqual(row.rate, 150.0) + else: + self.assertEqual(row.rate, 250.0) + + self.assertTrue(row.serial_and_batch_bundle) + + inter_transfer_pr = make_inter_company_purchase_receipt(inter_transfer_dn.name) + for row in inter_transfer_pr.items: + row.from_warehouse = "Work In Progress - TCP1" + row.warehouse = "Stores - TCP1" + inter_transfer_pr.submit() + + for row in inter_transfer_pr.items: + if row.item_code == batch_item_doc.name: + self.assertEqual(row.rate, 150.0) + else: + self.assertEqual(row.rate, 250.0) + + self.assertTrue(row.serial_and_batch_bundle) + + inter_transfer_pr_return = make_return_doc("Purchase Receipt", inter_transfer_pr.name) + + inter_transfer_pr_return.submit() + inter_transfer_pr_return.reload() + for row in inter_transfer_pr_return.items: + self.assertTrue(row.serial_and_batch_bundle) + if row.item_code == serial_item_doc.name: + self.assertEqual(row.rate, 250.0) + serial_nos = get_serial_nos_from_bundle(row.serial_and_batch_bundle) + for sn in serial_nos: + serial_no_details = frappe.db.get_value("Serial No", sn, ["status", "warehouse"], as_dict=1) + self.assertTrue(serial_no_details.status == "Active") + self.assertEqual(serial_no_details.warehouse, "Work In Progress - TCP1") + + inter_transfer_dn_return = make_return_doc("Delivery Note", inter_transfer_dn.name) + inter_transfer_dn_return.posting_date = today() + inter_transfer_dn_return.posting_time = nowtime() + for row in inter_transfer_dn_return.items: + row.target_warehouse = "Work In Progress - TCP1" + + inter_transfer_dn_return.submit() + inter_transfer_dn_return.reload() + + for row in inter_transfer_dn_return.items: + self.assertTrue(row.serial_and_batch_bundle) + + def test_internal_transfer_with_serial_batch_items_without_user_serial_batch_fields(self): + from erpnext.controllers.sales_and_purchase_return import make_return_doc + from erpnext.stock.doctype.delivery_note.delivery_note import make_inter_company_purchase_receipt + from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note + + frappe.db.set_single_value("Stock Settings", "use_serial_batch_fields", 0) + + prepare_data_for_internal_transfer() + + customer = "_Test Internal Customer 2" + company = "_Test Company with perpetual inventory" + + batch_item_doc = make_item( + "_Test Batch Item For Stock Transfer USE SERIAL BATCH FIELDS", + {"has_batch_no": 1, "create_new_batch": 1, "batch_number_series": "USBF-BT-BIFST-.####"}, + ) + + serial_item_doc = make_item( + "_Test Serial No Item For Stock Transfer USE SERIAL BATCH FIELDS", + {"has_serial_no": 1, "serial_no_series": "USBF-BT-BIFST-.####"}, + ) + + inward_entry = make_purchase_receipt( + item_code=batch_item_doc.name, + qty=10, + rate=150, + warehouse="Stores - TCP1", + company="_Test Company with perpetual inventory", + use_serial_batch_fields=0, + do_not_submit=1, + ) + + inward_entry.append( + "items", + { + "item_code": serial_item_doc.name, + "qty": 15, + "rate": 250, + "item_name": serial_item_doc.item_name, + "conversion_factor": 1.0, + "uom": serial_item_doc.stock_uom, + "stock_uom": serial_item_doc.stock_uom, + "warehouse": "Stores - TCP1", + "use_serial_batch_fields": 0, + }, + ) + + inward_entry.submit() + inward_entry.reload() + + for row in inward_entry.items: + self.assertTrue(row.serial_and_batch_bundle) + + inter_transfer_dn = create_delivery_note( + item_code=inward_entry.items[0].item_code, + company=company, + customer=customer, + cost_center="Main - TCP1", + expense_account="Cost of Goods Sold - TCP1", + qty=10, + rate=500, + warehouse="Stores - TCP1", + target_warehouse="Work In Progress - TCP1", + batch_no=get_batch_from_bundle(inward_entry.items[0].serial_and_batch_bundle), + use_serial_batch_fields=0, + do_not_submit=1, + ) + + inter_transfer_dn.append( + "items", + { + "item_code": serial_item_doc.name, + "qty": 15, + "rate": 350, + "item_name": serial_item_doc.item_name, + "conversion_factor": 1.0, + "uom": serial_item_doc.stock_uom, + "stock_uom": serial_item_doc.stock_uom, + "warehouse": "Stores - TCP1", + "target_warehouse": "Work In Progress - TCP1", + "serial_no": "\n".join( + get_serial_nos_from_bundle(inward_entry.items[1].serial_and_batch_bundle) + ), + "use_serial_batch_fields": 0, + }, + ) + + inter_transfer_dn.submit() + inter_transfer_dn.reload() + for row in inter_transfer_dn.items: + if row.item_code == batch_item_doc.name: + self.assertEqual(row.rate, 150.0) + else: + self.assertEqual(row.rate, 250.0) + + self.assertTrue(row.serial_and_batch_bundle) + + inter_transfer_pr = make_inter_company_purchase_receipt(inter_transfer_dn.name) + for row in inter_transfer_pr.items: + row.from_warehouse = "Work In Progress - TCP1" + row.warehouse = "Stores - TCP1" + inter_transfer_pr.submit() + + for row in inter_transfer_pr.items: + if row.item_code == batch_item_doc.name: + self.assertEqual(row.rate, 150.0) + else: + self.assertEqual(row.rate, 250.0) + + self.assertTrue(row.serial_and_batch_bundle) + + inter_transfer_pr_return = make_return_doc("Purchase Receipt", inter_transfer_pr.name) + + inter_transfer_pr_return.submit() + inter_transfer_pr_return.reload() + for row in inter_transfer_pr_return.items: + self.assertTrue(row.serial_and_batch_bundle) + if row.item_code == serial_item_doc.name: + self.assertEqual(row.rate, 250.0) + serial_nos = get_serial_nos_from_bundle(row.serial_and_batch_bundle) + for sn in serial_nos: + serial_no_details = frappe.db.get_value("Serial No", sn, ["status", "warehouse"], as_dict=1) + self.assertTrue(serial_no_details.status == "Active") + self.assertEqual(serial_no_details.warehouse, "Work In Progress - TCP1") + + inter_transfer_dn_return = make_return_doc("Delivery Note", inter_transfer_dn.name) + inter_transfer_dn_return.posting_date = today() + inter_transfer_dn_return.posting_time = nowtime() + for row in inter_transfer_dn_return.items: + row.target_warehouse = "Work In Progress - TCP1" + + inter_transfer_dn_return.submit() + inter_transfer_dn_return.reload() + + for row in inter_transfer_dn_return.items: + self.assertTrue(row.serial_and_batch_bundle) + + frappe.db.set_single_value("Stock Settings", "use_serial_batch_fields", 1) + def prepare_data_for_internal_transfer(): from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.json b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.json index 7a58462357b..59ef43e31a8 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.json +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.json @@ -113,6 +113,7 @@ { "fieldname": "voucher_no", "fieldtype": "Dynamic Link", + "in_standard_filter": 1, "label": "Voucher No", "no_copy": 1, "options": "voucher_type", @@ -250,7 +251,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2023-12-07 17:56:55.528563", + "modified": "2024-03-15 15:22:24.003486", "modified_by": "Administrator", "module": "Stock", "name": "Serial and Batch Bundle", diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index 08cb3ca3074..9a7395fc667 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -801,6 +801,7 @@ class SerialandBatchBundle(Document): self.set_purchase_document_no() def on_submit(self): + self.validate_batch_inventory() self.validate_serial_nos_inventory() def set_purchase_document_no(self): diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 4421a3e7938..c317a889ec6 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -2606,6 +2606,7 @@ def move_sample_to_retention_warehouse(company, items): "type_of_transaction": "Outward", "serial_and_batch_bundle": item.get("serial_and_batch_bundle"), "item_code": item.get("item_code"), + "warehouse": item.get("t_warehouse"), } ) diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index 902b8ffa90c..ce3c4958cec 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -999,6 +999,7 @@ class TestStockEntry(FrappeTestCase): "type_of_transaction": "Inward", "serial_and_batch_bundle": s2.items[0].serial_and_batch_bundle, "item_code": "_Test Serialized Item", + "warehouse": "_Test Warehouse - _TC", } ) diff --git a/erpnext/stock/serial_batch_bundle.py b/erpnext/stock/serial_batch_bundle.py index 4e87fa022d8..7b42103bdeb 100644 --- a/erpnext/stock/serial_batch_bundle.py +++ b/erpnext/stock/serial_batch_bundle.py @@ -820,6 +820,10 @@ class SerialBatchCreation: self.remove_returned_serial_nos(new_package) new_package.docstatus = 0 + new_package.warehouse = self.warehouse + new_package.voucher_no = "" + new_package.posting_date = today() + new_package.posting_time = nowtime() new_package.type_of_transaction = self.type_of_transaction new_package.returned_against = self.get("returned_against") new_package.save()