diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index 431bdd742a0..a81eadfefa0 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -123,6 +123,22 @@ class MaterialRequest(BuyingController): def check_if_already_pulled(self): pass + def validate_with_previous_doc(self): + super().validate_with_previous_doc( + { + "Sales Order": { + "ref_dn_field": "sales_order", + "compare_fields": [["company", "="]], + }, + "Sales Order Item": { + "ref_dn_field": "sales_order_item", + "compare_fields": [["item_code", "="], ["uom", "="], ["conversion_factor", "="]], + "is_child_table": True, + "allow_duplicate_prev_row_id": True, + }, + } + ) + def validate_qty_against_so(self): so_items = {} # Format --> {'SO/00001': {'Item/001': 120, 'Item/002': 24}} for d in self.get("items"): @@ -165,6 +181,7 @@ class MaterialRequest(BuyingController): self.validate_schedule_date() self.check_for_on_hold_or_closed_status("Sales Order", "sales_order") + self.validate_with_previous_doc() self.validate_uom_is_integer("uom", "qty") self.validate_material_request_type() diff --git a/erpnext/stock/doctype/material_request/test_material_request.py b/erpnext/stock/doctype/material_request/test_material_request.py index aaa69e9d130..df0ca3ea00f 100644 --- a/erpnext/stock/doctype/material_request/test_material_request.py +++ b/erpnext/stock/doctype/material_request/test_material_request.py @@ -1064,6 +1064,18 @@ class TestMaterialRequest(ERPNextTestSuite): self.assertEqual(mr.items[0].qty, 5) self.assertEqual(mr.items[1].qty, 5) + def test_item_change_on_sales_order_row_is_blocked(self): + from erpnext.selling.doctype.sales_order.mapper import make_material_request + from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order + + other_item = create_item("_Test MR Item Swap").name + so = make_sales_order() + mr = make_material_request(so.name) + mr.material_request_type = "Purchase" + # swapping the fetched item would leave a stale link to the SO row + mr.items[0].item_code = other_item + self.assertRaises(frappe.ValidationError, mr.insert) + def test_pending_qty_in_pick_list(self): """Test for pick list mapped doc qty from partially received Material Request Transfer""" import json