Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: incorrect status creating PR from PO after creating PI #25109

Merged
merged 4 commits into from Apr 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion erpnext/buying/doctype/purchase_order/purchase_order.py
Expand Up @@ -368,7 +368,6 @@ def update_item(obj, target, source_parent):
"Purchase Order": {
"doctype": "Purchase Receipt",
"field_map": {
"per_billed": "per_billed",
"supplier_warehouse":"supplier_warehouse"
},
"validation": {
Expand Down
1 change: 1 addition & 0 deletions erpnext/patches.txt
Expand Up @@ -763,3 +763,4 @@ erpnext.patches.v13_0.setup_gratuity_rule_for_india_and_uae
erpnext.patches.v13_0.setup_uae_vat_fields
execute:frappe.db.set_value('System Settings', None, 'app_name', 'ERPNext')
erpnext.patches.v13_0.rename_discharge_date_in_ip_record
erpnext.patches.v12_0.purchase_receipt_status
30 changes: 30 additions & 0 deletions erpnext/patches/v12_0/purchase_receipt_status.py
@@ -0,0 +1,30 @@
""" This patch fixes old purchase receipts (PR) where even after submitting
the PR, the `status` remains "Draft". `per_billed` field was copied over from previous
doc (PO), hence it is recalculated for setting new correct status of PR.
"""

import frappe

logger = frappe.logger("patch", allow_site=True, file_count=50)

def execute():
affected_purchase_receipts = frappe.db.sql(
"""select name from `tabPurchase Receipt`
where status = 'Draft' and per_billed = 100 and docstatus = 1"""
)

if not affected_purchase_receipts:
return

logger.info("purchase_receipt_status: begin patch, PR count: {}"
.format(len(affected_purchase_receipts)))


for pr in affected_purchase_receipts:
pr_name = pr[0]
logger.info("purchase_receipt_status: patching PR - {}".format(pr_name))

pr_doc = frappe.get_doc("Purchase Receipt", pr_name)

pr_doc.update_billing_status(update_modified=False)
pr_doc.set_status(update=True, update_modified=False)
Expand Up @@ -176,7 +176,7 @@ def on_submit(self):
if flt(self.per_billed) < 100:
self.update_billing_status()
else:
self.status = "Completed"
self.db_set("status", "Completed")


# Updating stock ledger should always be called after updating prevdoc status,
Expand Down
Expand Up @@ -191,7 +191,7 @@ def test_subcontracting(self):

rm_supp_cost = sum([d.amount for d in pr.get("supplied_items")])
self.assertEqual(pr.get("items")[0].rm_supp_cost, flt(rm_supp_cost, 2))

pr.cancel()

def test_subcontracting_gle_fg_item_rate_zero(self):
Expand Down Expand Up @@ -912,6 +912,57 @@ def test_subcontracted_pr_for_multi_transfer_batches(self):
ste1.cancel()
po.cancel()


def test_po_to_pi_and_po_to_pr_worflow_full(self):
"""Test following behaviour:
- Create PO
- Create PI from PO and submit
- Create PR from PO and submit
"""
from erpnext.buying.doctype.purchase_order import test_purchase_order
from erpnext.buying.doctype.purchase_order import purchase_order

po = test_purchase_order.create_purchase_order()

pi = purchase_order.make_purchase_invoice(po.name)
pi.submit()

pr = purchase_order.make_purchase_receipt(po.name)
pr.submit()

pr.load_from_db()

self.assertEqual(pr.status, "Completed")
self.assertEqual(pr.per_billed, 100)

def test_po_to_pi_and_po_to_pr_worflow_partial(self):
"""Test following behaviour:
- Create PO
- Create partial PI from PO and submit
- Create PR from PO and submit
"""
from erpnext.buying.doctype.purchase_order import test_purchase_order
from erpnext.buying.doctype.purchase_order import purchase_order

po = test_purchase_order.create_purchase_order()

pi = purchase_order.make_purchase_invoice(po.name)
pi.items[0].qty /= 2 # roughly 50%, ^ this function only creates PI with 1 item.
pi.submit()

pr = purchase_order.make_purchase_receipt(po.name)
pr.save()
# per_billed is only updated after submission.
self.assertEqual(flt(pr.per_billed), 0)

pr.submit()

pi.load_from_db()
pr.load_from_db()

self.assertEqual(pr.status, "To Bill")
self.assertAlmostEqual(pr.per_billed, 50.0, places=2)

def get_sl_entries(voucher_type, voucher_no):
return frappe.db.sql(""" select actual_qty, warehouse, stock_value_difference
from `tabStock Ledger Entry` where voucher_type=%s and voucher_no=%s
Expand Down