diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 62d4c538682..95bf0e4688e 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -190,7 +190,9 @@ class calculate_taxes_and_totals(object): item.net_rate = item.rate - if not item.qty and self.doc.get("is_return"): + if ( + not item.qty and self.doc.get("is_return") and self.doc.get("doctype") != "Purchase Receipt" + ): item.amount = flt(-1 * item.rate, item.precision("amount")) elif not item.qty and self.doc.get("is_debit_note"): item.amount = flt(item.rate, item.precision("amount")) diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index eeb09cb8b0e..70b70c3d284 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -135,7 +135,15 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments { } else { // allow for '0' qty on Credit/Debit notes - let qty = item.qty || (me.frm.doc.is_debit_note ? 1 : -1); + let qty = flt(item.qty); + if (!qty) { + qty = (me.frm.doc.is_debit_note ? 1 : -1); + if (me.frm.doc.doctype !== "Purchase Receipt" && me.frm.doc.is_return === 1) { + // In case of Purchase Receipt, qty can be 0 if all items are rejected + qty = flt(item.qty); + } + } + item.net_amount = item.amount = flt(item.rate * qty, precision("amount", item)); } diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 04eff54c43f..6afa86e34eb 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -956,6 +956,10 @@ def update_billing_percentage(pr_doc, update_modified=True, adjust_incoming_rate total_amount += total_billable_amount total_billed_amount += flt(item.billed_amt) + + if pr_doc.get("is_return") and not total_amount and total_billed_amount: + total_amount = total_billed_amount + if adjust_incoming_rate: adjusted_amt = 0.0 if item.billed_amt and item.amount: diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index b7712ee5ce2..a8ef5e8e488 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -2060,6 +2060,32 @@ class TestPurchaseReceipt(FrappeTestCase): company.enable_provisional_accounting_for_non_stock_items = 0 company.save() + def test_purchase_return_status_with_debit_note(self): + pr = make_purchase_receipt(rejected_qty=10, received_qty=10, rate=100, do_not_save=1) + pr.items[0].qty = 0 + pr.items[0].stock_qty = 0 + pr.submit() + + return_pr = make_purchase_receipt( + is_return=1, + return_against=pr.name, + qty=0, + rejected_qty=10 * -1, + received_qty=10 * -1, + do_not_save=1, + ) + return_pr.items[0].qty = 0.0 + return_pr.items[0].stock_qty = 0.0 + return_pr.submit() + + self.assertEqual(return_pr.status, "To Bill") + + pi = make_purchase_invoice(return_pr.name) + pi.submit() + + return_pr.reload() + self.assertEqual(return_pr.status, "Completed") + def prepare_data_for_internal_transfer(): from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier