From a5138f48998cb77cfa7600a9f81717e255d61628 Mon Sep 17 00:00:00 2001 From: ravibharathi656 Date: Thu, 31 Jul 2025 11:42:41 +0530 Subject: [PATCH 1/3] fix: incorrect pending qty when creating sales invoice from sales order --- .../selling/doctype/sales_order/sales_order.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index b6891930e42..f18b8762c7f 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -1176,6 +1176,17 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False, a target.debit_to = get_party_account("Customer", source.customer, source.company) def update_item(source, target, source_parent): + def get_billed_qty(so_item_name): + from frappe.query_builder.functions import Sum + + table = frappe.qb.DocType("Sales Invoice Item") + query = ( + frappe.qb.from_(table) + .select(Sum(table.qty).as_("qty")) + .where((table.docstatus == 1) & (table.so_detail == so_item_name)) + ) + return query.run(pluck="qty")[0] or 0 + if source_parent.has_unit_price_items: # 0 Amount rows (as seen in Unit Price Items) should be mapped as it is pending_amount = flt(source.amount) - flt(source.billed_amt) @@ -1185,8 +1196,8 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False, a target.base_amount = target.amount * flt(source_parent.conversion_rate) target.qty = ( - target.amount / flt(source.rate) - if (source.rate and source.billed_amt) + source.qty - get_billed_qty(source.name) + if (source.qty and source.billed_amt) else (source.qty if is_unit_price_row(source) else source.qty - source.returned_qty) ) From e5d4b4f0f02f9de83cda794b783791a194db6a44 Mon Sep 17 00:00:00 2001 From: ravibharathi656 Date: Mon, 25 Aug 2025 21:04:51 +0530 Subject: [PATCH 2/3] test: add pending quantity check for invoice creation --- .../doctype/sales_order/test_sales_order.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index 3e53d0e4de9..d3cbc3c18c2 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -2568,6 +2568,31 @@ class TestSalesOrder(AccountsTestMixin, IntegrationTestCase): po.submit() self.assertEqual(po.taxes[0].tax_amount, 2) + def test_pending_quantity_after_update_item_during_invoice_creation(self): + so = make_sales_order(qty=30, rate=100) + + si1 = make_sales_invoice(so.name) + si1.update_stock = 1 + si1.get("items")[0].qty = 10 + si1.insert() + si1.submit() + + first_item_of_so = so.get("items")[0] + trans_item = json.dumps( + [ + { + "item_code": first_item_of_so.item_code, + "rate": 1000, + "qty": first_item_of_so.qty, + "docname": first_item_of_so.name, + }, + ] + ) + update_child_qty_rate("Sales Order", trans_item, so.name) + + si2 = make_sales_invoice(so.name) + self.assertEqual(si2.items[0].qty, 20) + def automatically_fetch_payment_terms(enable=1): accounts_settings = frappe.get_doc("Accounts Settings") From 368dbe3bbf138aa892248a9e269e29dde04e1263 Mon Sep 17 00:00:00 2001 From: ravibharathi656 Date: Mon, 25 Aug 2025 21:23:14 +0530 Subject: [PATCH 3/3] chore: remove update_stock --- erpnext/selling/doctype/sales_order/test_sales_order.py | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index d3cbc3c18c2..f3892b8090b 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -2572,7 +2572,6 @@ class TestSalesOrder(AccountsTestMixin, IntegrationTestCase): so = make_sales_order(qty=30, rate=100) si1 = make_sales_invoice(so.name) - si1.update_stock = 1 si1.get("items")[0].qty = 10 si1.insert() si1.submit()