diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index 643047e982d..813c70806f4 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -22,6 +22,8 @@ "is_paid", "is_return", "return_against", + "update_billed_amount_in_purchase_order", + "update_billed_amount_in_purchase_receipt", "apply_tds", "tax_withholding_category", "amended_from", @@ -410,6 +412,20 @@ "read_only": 1, "search_index": 1 }, + { + "default": "0", + "depends_on": "eval: doc.is_return", + "fieldname": "update_billed_amount_in_purchase_order", + "fieldtype": "Check", + "label": "Update Billed Amount in Purchase Order" + }, + { + "default": "1", + "depends_on": "eval: doc.is_return", + "fieldname": "update_billed_amount_in_purchase_receipt", + "fieldtype": "Check", + "label": "Update Billed Amount in Purchase Receipt" + }, { "fieldname": "section_addresses", "fieldtype": "Section Break", @@ -1594,7 +1610,7 @@ "idx": 204, "is_submittable": 1, "links": [], - "modified": "2023-11-03 15:47:30.319200", + "modified": "2024-02-25 11:20:28.366808", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice", diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 802ac8080a9..f6fcd7e70e0 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -514,6 +514,11 @@ class PurchaseInvoice(BuyingController): super(PurchaseInvoice, self).on_submit() self.check_prev_docstatus() + + if self.is_return and not self.update_billed_amount_in_purchase_order: + # NOTE status updating bypassed for is_return + self.status_updater = [] + self.update_status_updater_args() self.update_prevdoc_status() @@ -1264,6 +1269,10 @@ class PurchaseInvoice(BuyingController): self.check_on_hold_or_closed_status() + if self.is_return and not self.update_billed_amount_in_purchase_order: + # NOTE status updating bypassed for is_return + self.status_updater = [] + self.update_status_updater_args() self.update_prevdoc_status() @@ -1357,6 +1366,9 @@ class PurchaseInvoice(BuyingController): frappe.throw(_("Supplier Invoice No exists in Purchase Invoice {0}").format(pi)) def update_billing_status_in_pr(self, update_modified=True): + if self.is_return and not self.update_billed_amount_in_purchase_receipt: + return + updated_pr = [] po_details = [] diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py index 739a989c79e..3a498ee271b 100644 --- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py @@ -940,6 +940,38 @@ class TestPurchaseOrder(FrappeTestCase): self.assertRaises(frappe.ValidationError, po.save) + def test_po_billed_amount_against_return_entry(self): + from erpnext.accounts.doctype.purchase_invoice.purchase_invoice import make_debit_note + + # Create a Purchase Order and Fully Bill it + po = create_purchase_order() + pi = make_pi_from_po(po.name) + pi.insert() + pi.submit() + + # Debit Note - 50% Qty & enable updating PO billed amount + pi_return = make_debit_note(pi.name) + pi_return.items[0].qty = -5 + pi_return.update_billed_amount_in_purchase_order = 1 + pi_return.submit() + + # Check if the billed amount reduced + po.reload() + self.assertEqual(po.per_billed, 50) + + pi_return.reload() + pi_return.cancel() + + # Debit Note - 50% Qty & disable updating PO billed amount + pi_return = make_debit_note(pi.name) + pi_return.items[0].qty = -5 + pi_return.update_billed_amount_in_purchase_order = 0 + pi_return.submit() + + # Check if the billed amount stayed the same + po.reload() + self.assertEqual(po.per_billed, 100) + 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/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index d8141f93e68..7defbc5bcdf 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -2189,6 +2189,41 @@ class TestPurchaseReceipt(FrappeTestCase): pr.cancel() self.assertTrue(frappe.db.exists("Batch", batch_no)) + def test_pr_billed_amount_against_return_entry(self): + from erpnext.accounts.doctype.purchase_invoice.purchase_invoice import make_debit_note + from erpnext.stock.doctype.purchase_receipt.purchase_receipt import ( + make_purchase_invoice as make_pi_from_pr, + ) + + # Create a Purchase Receipt and Fully Bill it + pr = make_purchase_receipt(qty=10) + pi = make_pi_from_pr(pr.name) + pi.insert() + pi.submit() + + # Debit Note - 50% Qty & enable updating PR billed amount + pi_return = make_debit_note(pi.name) + pi_return.items[0].qty = -5 + pi_return.update_billed_amount_in_purchase_receipt = 1 + pi_return.submit() + + # Check if the billed amount reduced + pr.reload() + self.assertEqual(pr.per_billed, 50) + + pi_return.reload() + pi_return.cancel() + + # Debit Note - 50% Qty & disable updating PR billed amount + pi_return = make_debit_note(pi.name) + pi_return.items[0].qty = -5 + pi_return.update_billed_amount_in_purchase_receipt = 0 + pi_return.submit() + + # Check if the billed amount stayed the same + pr.reload() + self.assertEqual(pr.per_billed, 100) + def prepare_data_for_internal_transfer(): from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier