From ddd367c6deb3273fc099c0ee7faee2d4186e44bf Mon Sep 17 00:00:00 2001 From: Navin-S-R Date: Tue, 30 Dec 2025 14:47:28 +0530 Subject: [PATCH] fix(asset): handle same asset being sold in multiple line items in sales invoice (cherry picked from commit 23b094f151ab606f52142ff2789ad80fb97b574c) --- .../doctype/sales_invoice/sales_invoice.py | 24 ++++++++++---- erpnext/assets/doctype/asset/asset.js | 32 +++++++++++++------ 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 79784c076bc..433bc7f731d 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1205,6 +1205,13 @@ class SalesInvoice(SellingController): def split_asset_based_on_sale_qty(self): asset_qty_map = self.get_asset_qty() for asset, qty in asset_qty_map.items(): + if qty["actual_qty"] < qty["sale_qty"]: + frappe.throw( + _( + "Sell quantity cannot exceed the asset quantity. Asset {0} has only {1} item(s)." + ).format(asset, qty["actual_qty"]) + ) + remaining_qty = qty["actual_qty"] - qty["sale_qty"] if remaining_qty > 0: split_asset(asset, remaining_qty) @@ -1227,13 +1234,16 @@ class SalesInvoice(SellingController): for row in self.items: if row.is_fixed_asset and row.asset: actual_qty = asset_actual_qty.get(row.asset) - asset_qty_map.setdefault( - row.asset, - { - "sale_qty": flt(row.qty), - "actual_qty": flt(actual_qty), - }, - ) + if row.asset in asset_qty_map.keys(): + asset_qty_map[row.asset]["sale_qty"] += flt(row.qty) + else: + asset_qty_map.setdefault( + row.asset, + { + "sale_qty": flt(row.qty), + "actual_qty": flt(actual_qty), + }, + ) return asset_qty_map diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index 2d4a2fb3d3a..46fbdaf4443 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -591,7 +591,7 @@ frappe.ui.form.on("Asset", { }); }; - const dialog = new frappe.ui.Dialog({ + let dialog = new frappe.ui.Dialog({ title: __("Sell Asset"), fields: [ { @@ -606,18 +606,30 @@ frappe.ui.form.on("Asset", { dialog.set_primary_action(__("Sell"), function () { const dialog_data = dialog.get_values(); const sell_qty = cint(dialog_data.sell_qty); + const asset_qty = cint(frm.doc.asset_quantity); - if (sell_qty < cint(frm.doc.asset_quantity)) { - frappe.confirm( - __( - "The sell quantity is less than the total asset quantity. The remaining quantity will be split into a new asset. This action cannot be undone.
Do you want to continue?" - ), - () => make_sales_invoice(sell_qty) - ); - } else { - make_sales_invoice(sell_qty); + if (sell_qty <= 0) { + frappe.throw(__("Sell quantity must be greater than zero")); } + if (sell_qty > asset_qty) { + frappe.throw(__("Sell quantity cannot exceed the asset quantity")); + } + + if (sell_qty < asset_qty) { + frappe.confirm( + __( + "The sell quantity is less than the total asset quantity. The remaining quantity will be split into a new asset. This action cannot be undone.

Do you want to continue?" + ), + () => { + make_sales_invoice(sell_qty); + dialog.hide(); + } + ); + return; + } + + make_sales_invoice(sell_qty); dialog.hide(); });