diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index 290d8eb5d4b..c28a8ff44fc 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -234,8 +234,8 @@ class StatusUpdater(Document): self.global_amount_allowance = None for args in self.status_updater: - if "target_ref_field" not in args: - # if target_ref_field is not specified, the programmer does not want to validate qty / amount + if "target_ref_field" not in args or args.get("validate_qty") is False: + # if target_ref_field is not specified or validate_qty is explicitly set to False, skip validation continue # get unique transactions to update diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 7e9036f51e7..fb6b94a7090 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -185,6 +185,7 @@ class PurchaseReceipt(BuyingController): "target_ref_field": "stock_qty", "source_field": "stock_qty", "percent_join_field": "material_request", + "validate_qty": False, }, { "source_dt": "Purchase Receipt Item", diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index 2070b264f8f..d2e0397a7ce 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -15,6 +15,7 @@ from erpnext.controllers.accounts_controller import InvalidQtyError from erpnext.controllers.buying_controller import QtyMismatchError from erpnext.stock import get_warehouse_account_map from erpnext.stock.doctype.item.test_item import create_item, make_item +from erpnext.stock.doctype.material_request.material_request import make_purchase_order from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice from erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle import ( SerialNoDuplicateError, @@ -33,6 +34,40 @@ class TestPurchaseReceipt(FrappeTestCase): def setUp(self): frappe.db.set_single_value("Buying Settings", "allow_multiple_items", 1) + def test_purchase_receipt_skips_validation(self): + """ + Test that validation is skipped when over delivery receipt allowance is reduced after PO submission + and PR can be submitted with higher qty than MR. + """ + item = create_item("Test item for validation") + mr = frappe.new_doc("Material Request") + mr.material_request_type = "Purchase" + mr.company = "_Test Company" + mr.price_list = "_Test Price List" + mr.append( + "items", + { + "item_code": item.name, + "item_name": item.item_name, + "item_group": item.item_group, + "schedule_date": add_days(today(), 1), + "qty": 100, + "uom": item.stock_uom, + }, + ) + mr.insert() + mr.submit() + frappe.db.set_value("Item", item.name, "over_delivery_receipt_allowance", 200) + po = make_purchase_order(mr.name) + po.supplier = "_Test Supplier" + po.items[0].qty = 300 + po.save() + po.submit() + frappe.db.set_value("Item", item.name, "over_delivery_receipt_allowance", 20) + pr = make_purchase_receipt(qty=300, item_code=item.name, do_not_save=True) + pr.save() + pr.submit() + def test_purchase_receipt_qty(self): pr = make_purchase_receipt(qty=0, rejected_qty=0, do_not_save=True) with self.assertRaises(InvalidQtyError):