From 89d106947279b07073aa87a9678d9c655e562077 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 29 Dec 2023 20:54:49 +0530 Subject: [PATCH] fix: non stock uom validation for serial and batch (backport #39018) (#39026) fix: non stock uom validation for serial and batch (#39018) * fix: non stock uom validation for serial and batch * test: delivery note for batch with non stock uom (cherry picked from commit 0c6de4ecb299daf5359fcd51041942a26f94693d) Co-authored-by: rohitwaghchaure --- .../doctype/sales_invoice/sales_invoice.py | 2 + .../sales_invoice/test_sales_invoice.py | 5 ++- .../sales_invoice_item.json | 9 ++++- .../doctype/delivery_note/delivery_note.py | 2 + .../delivery_note/test_delivery_note.py | 40 +++++++++++++++++++ .../serial_and_batch_bundle.py | 6 ++- 6 files changed, 60 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 6aba1faa84..5924586e73 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -586,6 +586,8 @@ class SalesInvoice(SellingController): "Serial and Batch Bundle", ) + self.delete_auto_created_batches() + def update_status_updater_args(self): if cint(self.update_stock): self.status_updater.append( diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 450c8effea..98d4ed46cc 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -1414,10 +1414,11 @@ class TestSalesInvoice(FrappeTestCase): def test_serialized_cancel(self): si = self.test_serialized() - si.cancel() - + si.reload() serial_nos = get_serial_nos_from_bundle(si.get("items")[0].serial_and_batch_bundle) + si.cancel() + self.assertEqual( frappe.db.get_value("Serial No", serial_nos[0], "warehouse"), "_Test Warehouse - _TC" ) diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json index a403b14c54..ec9e792d7d 100644 --- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json +++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json @@ -81,6 +81,7 @@ "warehouse", "target_warehouse", "quality_inspection", + "pick_serial_and_batch", "serial_and_batch_bundle", "batch_no", "incoming_rate", @@ -897,12 +898,18 @@ "options": "Serial and Batch Bundle", "print_hide": 1, "search_index": 1 + }, + { + "depends_on": "eval:parent.update_stock === 1", + "fieldname": "pick_serial_and_batch", + "fieldtype": "Button", + "label": "Pick Serial / Batch No" } ], "idx": 1, "istable": 1, "links": [], - "modified": "2023-11-14 18:34:10.479329", + "modified": "2023-12-29 13:03:14.121298", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice Item", diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index 132f8f2e29..7d7b0cd476 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -431,6 +431,8 @@ class DeliveryNote(SellingController): "Serial and Batch Bundle", ) + self.delete_auto_created_batches() + def update_stock_reservation_entries(self) -> None: """Updates Delivered Qty in Stock Reservation Entries.""" diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index 933be53b07..3abd1d9e5e 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -1478,6 +1478,46 @@ class TestDeliveryNote(FrappeTestCase): returned_dn.reload() self.assertAlmostEqual(returned_dn.items[0].incoming_rate, 200.0) + def test_batch_with_non_stock_uom(self): + frappe.db.set_single_value( + "Stock Settings", "auto_create_serial_and_batch_bundle_for_outward", 1 + ) + + item = make_item( + properties={ + "has_batch_no": 1, + "create_new_batch": 1, + "batch_number_series": "TESTBATCH.#####", + "stock_uom": "Nos", + } + ) + if not frappe.db.exists("UOM Conversion Detail", {"parent": item.name, "uom": "Kg"}): + item.append("uoms", {"uom": "Kg", "conversion_factor": 5.0}) + item.save() + + item_code = item.name + + make_stock_entry(item_code=item_code, target="_Test Warehouse - _TC", qty=5, basic_rate=100.0) + dn = create_delivery_note( + item_code=item_code, qty=1, rate=500, warehouse="_Test Warehouse - _TC", do_not_save=True + ) + dn.items[0].uom = "Kg" + dn.items[0].conversion_factor = 5.0 + + dn.save() + dn.submit() + + self.assertEqual(dn.items[0].stock_qty, 5.0) + voucher_detail_no = dn.items[0].name + delivered_batch_qty = frappe.db.get_value( + "Serial and Batch Bundle", {"voucher_detail_no": voucher_detail_no}, "total_qty" + ) + self.assertEqual(abs(delivered_batch_qty), 5.0) + + frappe.db.set_single_value( + "Stock Settings", "auto_create_serial_and_batch_bundle_for_outward", 0 + ) + def create_delivery_note(**args): dn = frappe.new_doc("Delivery Note") 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 a4fb5324ee..774e5c657d 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 @@ -483,7 +483,11 @@ class SerialandBatchBundle(Document): if row.get("doctype") in ["Subcontracting Receipt Supplied Item"]: qty_field = "consumed_qty" - if abs(abs(flt(self.total_qty, precision)) - abs(flt(row.get(qty_field), precision))) > 0.01: + qty = row.get(qty_field) + if qty_field == "qty" and row.get("stock_qty"): + qty = row.get("stock_qty") + + if abs(abs(flt(self.total_qty, precision)) - abs(flt(qty, precision))) > 0.01: self.throw_error_message( f"Total quantity {abs(flt(self.total_qty))} in the Serial and Batch Bundle {bold(self.name)} does not match with the quantity {abs(flt(row.get(qty_field)))} for the Item {bold(self.item_code)} in the {self.voucher_type} # {self.voucher_no}" )