fix: ensure that additional discount amount is not mapped repeatedly

(cherry picked from commit feb62102d9)
This commit is contained in:
Sagar Vora
2025-10-17 15:31:21 +05:30
committed by Mergify
parent 798858bd4f
commit 44539f0944

View File

@@ -39,6 +39,8 @@ from erpnext.accounts.doctype.pricing_rule.utils import (
)
from erpnext.accounts.general_ledger import get_round_off_account_and_cost_center
from erpnext.accounts.party import (
PURCHASE_TRANSACTION_TYPES,
SALES_TRANSACTION_TYPES,
get_party_account,
get_party_account_currency,
get_party_gle_currency,
@@ -2918,6 +2920,83 @@ class AccountsController(TransactionBase):
x["transaction_currency"] = self.currency
x["transaction_exchange_rate"] = self.get("conversion_rate") or 1
def after_mapping(self, source_doc):
self.set_discount_amount_after_mapping(source_doc)
def set_discount_amount_after_mapping(self, source_doc):
"""
Ensures that Additional Discount Amount is not copied repeatedly
for multiple mappings of a single source transaction.
"""
# source and target doctypes should both be buying / selling
for transaction_types in (PURCHASE_TRANSACTION_TYPES, SALES_TRANSACTION_TYPES):
if self.doctype in transaction_types and source_doc.doctype in transaction_types:
break
else:
return
# ensure both doctypes have discount_amount field
if not self.meta.get_field("discount_amount") or not source_doc.meta.get_field("discount_amount"):
return
# ensure discount_amount is set in source doc
if not source_doc.discount_amount:
return
# ensure additional_discount_percentage is not set in the source doc
if source_doc.get("additional_discount_percentage"):
return
item_doctype = self.meta.get_field("items").options
item_meta = frappe.get_meta(item_doctype)
reference_fieldname = next(
(
row.fieldname
for row in item_meta.fields
if row.fieldtype == "Link"
and row.options == source_doc.doctype
and not row.get("is_custom_field")
),
None,
)
if not reference_fieldname:
return
doctype_table = frappe.qb.DocType(self.doctype)
item_table = frappe.qb.DocType(item_doctype)
discount_already_applied = (
frappe.qb.from_(doctype_table)
.where(doctype_table.docstatus == 1)
.where(doctype_table.discount_amount != 0)
.where(
doctype_table.name.isin(
frappe.qb.from_(item_table)
.select(item_table.parent)
.where(item_table[reference_fieldname] == source_doc.name)
.distinct()
)
)
.select(Sum(doctype_table.discount_amount))
).run()
if not discount_already_applied:
return
discount_already_applied = flt(discount_already_applied[0][0], self.precision("discount_amount"))
if (source_doc.discount_amount * (discount_already_applied - source_doc.discount_amount)) >= 0:
# full discount already applied or exceeded
self.discount_amount = 0
else:
self.discount_amount = flt(
self.discount_amount - discount_already_applied, self.precision("discount_amount")
)
self.calculate_taxes_and_totals()
@frappe.whitelist()
def get_tax_rate(account_head):