fix: Taxes aren't discounted on early payment discount
- Deductions in payment entry must be split into income loss and tax loss - Compute total discount in percentage, makes discounting different amounts proportionately easier
This commit is contained in:
parent
310643d215
commit
768c3a4927
@ -1669,7 +1669,7 @@ def get_payment_entry(
|
|||||||
dt, party_account_currency, bank, outstanding_amount, payment_type, bank_amount, doc
|
dt, party_account_currency, bank, outstanding_amount, payment_type, bank_amount, doc
|
||||||
)
|
)
|
||||||
|
|
||||||
paid_amount, received_amount, discount_amount = apply_early_payment_discount(
|
paid_amount, received_amount, discount_amount, valid_discounts = apply_early_payment_discount(
|
||||||
paid_amount, received_amount, doc
|
paid_amount, received_amount, doc
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1769,7 +1769,9 @@ def get_payment_entry(
|
|||||||
if party_account and bank:
|
if party_account and bank:
|
||||||
pe.set_exchange_rate(ref_doc=reference_doc)
|
pe.set_exchange_rate(ref_doc=reference_doc)
|
||||||
pe.set_amounts()
|
pe.set_amounts()
|
||||||
if discount_amount:
|
|
||||||
|
discount_amount = set_early_payment_discount_loss(pe, doc, valid_discounts, discount_amount)
|
||||||
|
if discount_amount > 0:
|
||||||
pe.set_gain_or_loss(
|
pe.set_gain_or_loss(
|
||||||
account_details={
|
account_details={
|
||||||
"account": frappe.get_cached_value("Company", pe.company, "default_discount_account"),
|
"account": frappe.get_cached_value("Company", pe.company, "default_discount_account"),
|
||||||
@ -1891,6 +1893,7 @@ def set_paid_amount_and_received_amount(
|
|||||||
|
|
||||||
def apply_early_payment_discount(paid_amount, received_amount, doc):
|
def apply_early_payment_discount(paid_amount, received_amount, doc):
|
||||||
total_discount = 0
|
total_discount = 0
|
||||||
|
valid_discounts = []
|
||||||
eligible_for_payments = ["Sales Order", "Sales Invoice", "Purchase Order", "Purchase Invoice"]
|
eligible_for_payments = ["Sales Order", "Sales Invoice", "Purchase Order", "Purchase Invoice"]
|
||||||
has_payment_schedule = hasattr(doc, "payment_schedule") and doc.payment_schedule
|
has_payment_schedule = hasattr(doc, "payment_schedule") and doc.payment_schedule
|
||||||
|
|
||||||
@ -1911,13 +1914,96 @@ def apply_early_payment_discount(paid_amount, received_amount, doc):
|
|||||||
received_amount -= discount_amount
|
received_amount -= discount_amount
|
||||||
paid_amount -= discount_amount_in_foreign_currency
|
paid_amount -= discount_amount_in_foreign_currency
|
||||||
|
|
||||||
|
valid_discounts.append({"type": term.discount_type, "discount": term.discount})
|
||||||
total_discount += discount_amount
|
total_discount += discount_amount
|
||||||
|
|
||||||
if total_discount:
|
if total_discount:
|
||||||
money = frappe.utils.fmt_money(total_discount, currency=doc.get("currency"))
|
money = frappe.utils.fmt_money(total_discount, currency=doc.get("currency"))
|
||||||
frappe.msgprint(_("Discount of {} applied as per Payment Term").format(money), alert=1)
|
frappe.msgprint(_("Discount of {} applied as per Payment Term").format(money), alert=1)
|
||||||
|
|
||||||
return paid_amount, received_amount, total_discount
|
return paid_amount, received_amount, total_discount, valid_discounts
|
||||||
|
|
||||||
|
|
||||||
|
def set_early_payment_discount_loss(pe, doc, valid_discounts, discount_amount):
|
||||||
|
"""Split early bird discount deductions into Income Loss & Tax Loss."""
|
||||||
|
if not (discount_amount and valid_discounts):
|
||||||
|
return discount_amount
|
||||||
|
|
||||||
|
total_discount_percent = get_total_discount_percent(doc, valid_discounts)
|
||||||
|
|
||||||
|
if not total_discount_percent:
|
||||||
|
return discount_amount
|
||||||
|
|
||||||
|
loss_on_income = add_income_discount_loss(pe, doc, total_discount_percent)
|
||||||
|
loss_on_taxes = add_tax_discount_loss(pe, doc, total_discount_percent)
|
||||||
|
|
||||||
|
return flt(discount_amount - (loss_on_income + loss_on_taxes))
|
||||||
|
|
||||||
|
|
||||||
|
def get_total_discount_percent(doc, valid_discounts) -> float:
|
||||||
|
"""Get total percentage and amount discount applied as a percentage."""
|
||||||
|
total_discount_percent = (
|
||||||
|
sum(
|
||||||
|
discount.get("discount") for discount in valid_discounts if discount.get("type") == "Percentage"
|
||||||
|
)
|
||||||
|
or 0.0
|
||||||
|
)
|
||||||
|
|
||||||
|
# Operate in percentages only as it makes the income & tax split easier
|
||||||
|
total_discount_amount = (
|
||||||
|
sum(discount.get("discount") for discount in valid_discounts if discount.get("type") == "Amount")
|
||||||
|
or 0.0
|
||||||
|
)
|
||||||
|
|
||||||
|
if total_discount_amount:
|
||||||
|
discount_percentage = (total_discount_amount / doc.get("grand_total")) * 100
|
||||||
|
total_discount_percent += discount_percentage
|
||||||
|
return total_discount_percent
|
||||||
|
|
||||||
|
return total_discount_percent
|
||||||
|
|
||||||
|
|
||||||
|
def add_income_discount_loss(pe, doc, total_discount_percent) -> float:
|
||||||
|
loss_on_income = flt(doc.get("total") * (total_discount_percent / 100), doc.precision("total"))
|
||||||
|
pe.append(
|
||||||
|
"deductions",
|
||||||
|
{
|
||||||
|
"account": frappe.get_cached_value("Company", pe.company, "default_discount_account"),
|
||||||
|
"cost_center": pe.cost_center or frappe.get_cached_value("Company", pe.company, "cost_center"),
|
||||||
|
"amount": loss_on_income,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return loss_on_income
|
||||||
|
|
||||||
|
|
||||||
|
def add_tax_discount_loss(pe, doc, total_discount_percenatage) -> float:
|
||||||
|
tax_discount_loss = {}
|
||||||
|
total_tax_loss = 0
|
||||||
|
precision = doc.precision("tax_amount_after_discount_amount", "taxes")
|
||||||
|
|
||||||
|
# The same account head could be used more than once
|
||||||
|
for tax in doc.get("taxes", []):
|
||||||
|
tax_loss = flt(
|
||||||
|
tax.get("tax_amount_after_discount_amount") * (total_discount_percenatage / 100), precision
|
||||||
|
)
|
||||||
|
account = tax.get("account_head")
|
||||||
|
if not tax_discount_loss.get(account):
|
||||||
|
tax_discount_loss[account] = tax_loss
|
||||||
|
else:
|
||||||
|
tax_discount_loss[account] += tax_loss
|
||||||
|
|
||||||
|
for account, loss in tax_discount_loss.items():
|
||||||
|
total_tax_loss += loss
|
||||||
|
pe.append(
|
||||||
|
"deductions",
|
||||||
|
{
|
||||||
|
"account": account,
|
||||||
|
"cost_center": pe.cost_center or frappe.get_cached_value("Company", pe.company, "cost_center"),
|
||||||
|
"amount": loss,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return total_tax_loss
|
||||||
|
|
||||||
|
|
||||||
def get_reference_as_per_payment_terms(
|
def get_reference_as_per_payment_terms(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user