From 4342b891ebdc80350c9e713c0e0a18e84713955d Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Sat, 13 Apr 2024 15:30:58 +0530 Subject: [PATCH] fix: type of transaction validation for the stock entry (backport #40986) (#40992) * fix: type of transaction validation for the stock entry (cherry picked from commit 8ad0295f1b00f56a345c75751936c398afd101f8) * chore: fix test case --------- Co-authored-by: Rohit Waghchaure --- .../stock/doctype/stock_entry/stock_entry.py | 46 +++++++++++++++++-- .../doctype/stock_entry/test_stock_entry.py | 35 ++++++++++++++ 2 files changed, 78 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 6bcade1acae6..9c94786c8033 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -9,7 +9,17 @@ from frappe import _ from frappe.model.mapper import get_mapped_doc from frappe.query_builder.functions import Sum -from frappe.utils import cint, comma_or, cstr, flt, format_time, formatdate, getdate, nowdate +from frappe.utils import ( + cint, + comma_or, + cstr, + flt, + format_time, + formatdate, + get_link_to_form, + getdate, + nowdate, +) import erpnext from erpnext.accounts.general_ledger import process_gl_map @@ -640,8 +650,8 @@ def check_if_operations_completed(self): ) ) - work_order_link = frappe.utils.get_link_to_form("Work Order", self.work_order) - job_card_link = frappe.utils.get_link_to_form("Job Card", job_card) + work_order_link = get_link_to_form("Work Order", self.work_order) + job_card_link = get_link_to_form("Job Card", job_card) frappe.throw( _( "Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}." @@ -1350,9 +1360,24 @@ def get_finished_item_row(self): return finished_item_row + def validate_serial_batch_bundle_type(self, serial_and_batch_bundle): + if ( + frappe.db.get_value("Serial and Batch Bundle", serial_and_batch_bundle, "type_of_transaction") + != "Outward" + ): + frappe.throw( + _( + "The Serial and Batch Bundle {0} is not valid for this transaction. The 'Type of Transaction' should be 'Outward' instead of 'Inward' in Serial and Batch Bundle {0}" + ).format(get_link_to_form("Serial and Batch Bundle", serial_and_batch_bundle)), + title=_("Invalid Serial and Batch Bundle"), + ) + def get_sle_for_source_warehouse(self, sl_entries, finished_item_row): for d in self.get("items"): if cstr(d.s_warehouse): + if d.serial_and_batch_bundle and self.docstatus == 1: + self.validate_serial_batch_bundle_type(d.serial_and_batch_bundle) + sle = self.get_sl_entries( d, { @@ -1369,6 +1394,21 @@ def get_sle_for_source_warehouse(self, sl_entries, finished_item_row): ): sle.dependant_sle_voucher_detail_no = finished_item_row.name + if sle.serial_and_batch_bundle and self.docstatus == 2: + bundle_id = frappe.get_cached_value( + "Serial and Batch Bundle", + { + "voucher_detail_no": d.name, + "voucher_no": self.name, + "is_cancelled": 0, + "type_of_transaction": "Outward", + }, + "name", + ) + + if bundle_id: + sle.serial_and_batch_bundle = bundle_id + sl_entries.append(sle) def make_serial_and_batch_bundle_for_transfer(self): diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index 6c4c825c072f..a680b7733d3c 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -1745,6 +1745,41 @@ def test_use_serial_and_batch_fields(self): self.assertTrue(frappe.db.exists("Serial No", serial_no)) self.assertEqual(frappe.db.get_value("Serial No", serial_no, "status"), "Delivered") + def test_serial_batch_bundle_type_of_transaction(self): + item = make_item( + "Test Use Serial and Batch Item SN Item", + { + "has_batch_no": 1, + "is_stock_item": 1, + "create_new_batch": 1, + "batch_naming_series": "Test-SBBTYT-NNS.#####", + }, + ).name + + se = make_stock_entry( + item_code=item, + qty=2, + target="_Test Warehouse - _TC", + use_serial_batch_fields=1, + ) + + batch_no = get_batch_from_bundle(se.items[0].serial_and_batch_bundle) + + se = make_stock_entry( + item_code=item, + qty=2, + source="_Test Warehouse - _TC", + target="Stores - _TC", + use_serial_batch_fields=0, + batch_no=batch_no, + do_not_submit=True, + ) + + se.reload() + sbb = se.items[0].serial_and_batch_bundle + frappe.db.set_value("Serial and Batch Bundle", sbb, "type_of_transaction", "Inward") + self.assertRaises(frappe.ValidationError, se.submit) + def make_serialized_item(**args): args = frappe._dict(args)