mirror of
https://github.com/frappe/erpnext.git
synced 2026-09-16 18:24:10 +00:00
Merge pull request #58045 from mihir-kandoi/codex/repair-underbilled-pr-status
fix(stock): repair existing underbilled purchase receipts
This commit is contained in:
@@ -511,3 +511,4 @@ erpnext.patches.v16_0.set_stock_uom_in_job_card
|
|||||||
erpnext.patches.v16_0.set_work_order_requested_and_picked_qty
|
erpnext.patches.v16_0.set_work_order_requested_and_picked_qty
|
||||||
erpnext.patches.v16_0.rename_italy_customer_name_fields
|
erpnext.patches.v16_0.rename_italy_customer_name_fields
|
||||||
erpnext.patches.v16_0.recalculate_purchase_receipt_billing_status
|
erpnext.patches.v16_0.recalculate_purchase_receipt_billing_status
|
||||||
|
erpnext.patches.v16_0.recalculate_mixed_purchase_receipt_billing_status
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
from erpnext.patches.v16_0.recalculate_purchase_receipt_billing_status import (
|
||||||
|
exclude_purchase_order_items_with_invoice_created_receipts,
|
||||||
|
get_candidate_purchase_order_items,
|
||||||
|
)
|
||||||
|
from erpnext.stock.doctype.purchase_receipt.services.billing_status import (
|
||||||
|
update_billed_amount_based_on_po,
|
||||||
|
update_billing_percentage,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
purchase_order_items = get_candidate_purchase_order_items()
|
||||||
|
if purchase_order_items:
|
||||||
|
purchase_order_items = exclude_purchase_order_items_with_invoice_created_receipts(
|
||||||
|
purchase_order_items
|
||||||
|
)
|
||||||
|
|
||||||
|
if not purchase_order_items:
|
||||||
|
return
|
||||||
|
|
||||||
|
updated_purchase_receipts = update_billed_amount_based_on_po(purchase_order_items)
|
||||||
|
for purchase_receipt in set(updated_purchase_receipts):
|
||||||
|
update_billing_percentage(frappe.get_doc("Purchase Receipt", purchase_receipt))
|
||||||
@@ -950,12 +950,14 @@ class TestPurchaseReceipt(ERPNextTestSuite):
|
|||||||
def test_pr_billing_status_with_mixed_direct_and_po_invoice(self):
|
def test_pr_billing_status_with_mixed_direct_and_po_invoice(self):
|
||||||
"""A receipt with partial direct billing consumes PO-invoiced amount through
|
"""A receipt with partial direct billing consumes PO-invoiced amount through
|
||||||
the amount-capped branch. The consumed qty must shrink along with the amount,
|
the amount-capped branch. The consumed qty must shrink along with the amount,
|
||||||
otherwise the next receipt divides by a stale qty and is under-billed.
|
otherwise the next receipt divides by a stale qty and is under-billed. The
|
||||||
|
repair patch must also recalculate values stored before the fix.
|
||||||
|
|
||||||
Flow:
|
Flow:
|
||||||
1. PO (Qty: 10, Rate: 500) -> PI for Qty 5 (Amount 2500)
|
1. PO (Qty: 10, Rate: 500) -> PI for Qty 5 (Amount 2500)
|
||||||
2. PO -> PR1 (Qty 3), then a direct PI for 500 against PR1
|
2. PO -> PR1 (Qty 3), then a direct PI for 500 against PR1
|
||||||
3. PO -> PR2 (Qty 3) -> reallocation must leave both receipts fully billed
|
3. PO -> PR2 (Qty 3) -> reallocation must leave both receipts fully billed
|
||||||
|
4. Seed the old under-billed values -> the repair patch must restore them
|
||||||
"""
|
"""
|
||||||
from erpnext.buying.doctype.purchase_order.mapper import (
|
from erpnext.buying.doctype.purchase_order.mapper import (
|
||||||
make_purchase_invoice as make_purchase_invoice_from_po,
|
make_purchase_invoice as make_purchase_invoice_from_po,
|
||||||
@@ -996,6 +998,40 @@ class TestPurchaseReceipt(ERPNextTestSuite):
|
|||||||
self.assertEqual(pr2.per_billed, 100)
|
self.assertEqual(pr2.per_billed, 100)
|
||||||
self.assertEqual(pr2.status, "Completed")
|
self.assertEqual(pr2.status, "Completed")
|
||||||
|
|
||||||
|
from erpnext.patches.v16_0 import recalculate_mixed_purchase_receipt_billing_status
|
||||||
|
|
||||||
|
purchase_order_item = po.items[0].name
|
||||||
|
frappe.db.set_value(
|
||||||
|
"Purchase Receipt Item",
|
||||||
|
pr2.items[0].name,
|
||||||
|
"billed_amt",
|
||||||
|
900,
|
||||||
|
update_modified=False,
|
||||||
|
)
|
||||||
|
frappe.db.set_value(
|
||||||
|
"Purchase Receipt",
|
||||||
|
pr2.name,
|
||||||
|
{"per_billed": 60, "status": "Partly Billed"},
|
||||||
|
update_modified=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch.object(
|
||||||
|
recalculate_mixed_purchase_receipt_billing_status,
|
||||||
|
"get_candidate_purchase_order_items",
|
||||||
|
return_value=[purchase_order_item],
|
||||||
|
):
|
||||||
|
recalculate_mixed_purchase_receipt_billing_status.execute()
|
||||||
|
|
||||||
|
pr2.load_from_db()
|
||||||
|
modified_after_repair = pr2.modified
|
||||||
|
recalculate_mixed_purchase_receipt_billing_status.execute()
|
||||||
|
pr2.load_from_db()
|
||||||
|
self.assertEqual(pr2.modified, modified_after_repair)
|
||||||
|
|
||||||
|
self.assertEqual(pr2.get("items")[0].billed_amt, 1500)
|
||||||
|
self.assertEqual(pr2.per_billed, 100)
|
||||||
|
self.assertEqual(pr2.status, "Completed")
|
||||||
|
|
||||||
pr2.cancel()
|
pr2.cancel()
|
||||||
direct_pi.reload()
|
direct_pi.reload()
|
||||||
direct_pi.cancel()
|
direct_pi.cancel()
|
||||||
|
|||||||
Reference in New Issue
Block a user