Merge pull request #1243 from frappe/fix-tax-amount

fix: calculate tax on discounted amount
This commit is contained in:
Able k Saju
2025-06-12 09:27:18 +05:30
committed by GitHub
2 changed files with 94 additions and 26 deletions
+71 -12
View File
@@ -340,23 +340,27 @@ export abstract class Invoice extends Transactional {
let amount = item.amount!;
if (!this.discountAfterTax) {
const itemDiscountAmount = this.getItemDiscountAmount();
let itemDiscountAmount = this.getDiscountAmount(item);
if (this.isReturn && itemDiscountAmount.isNegative()) {
itemDiscountAmount = itemDiscountAmount.abs();
}
if (this.isReturn) {
amount = amount.add(itemDiscountAmount);
} else {
amount = amount.sub(itemDiscountAmount);
}
const taxItem: InvoiceTaxItem = {
details,
exchangeRate: this.exchangeRate ?? 1,
fullAmount: amount,
taxAmount: amount.mul(details.rate / 100),
};
taxItems.push(taxItem);
}
const taxItem: InvoiceTaxItem = {
details,
exchangeRate: this.exchangeRate ?? 1,
fullAmount: amount,
taxAmount: amount.mul(details.rate / 100),
};
taxItems.push(taxItem);
}
}
@@ -427,7 +431,10 @@ export abstract class Invoice extends Transactional {
const itemDiscountAmount = this.getItemDiscountAmount();
const invoiceDiscountAmount = this.getInvoiceDiscountAmount();
if (this.isReturn) {
if (
this.isReturn &&
itemDiscountAmount.add(invoiceDiscountAmount).isPositive()
) {
return itemDiscountAmount.add(invoiceDiscountAmount).neg();
}
@@ -475,6 +482,58 @@ export abstract class Invoice extends Transactional {
return totalItemAmounts.percent(this.discountPercent ?? 0);
}
getDiscountAmount(item: InvoiceItem) {
if (!this.enableDiscounting) {
return this.fyo.pesa(0);
}
if (!this?.items?.length) {
return this.fyo.pesa(0);
}
let discountAmount = this.fyo.pesa(0);
if (item.setItemDiscountAmount) {
discountAmount = discountAmount.add(
(item.itemDiscountAmount ?? this.fyo.pesa(0)).mul(
item.quantity as number
)
);
} else if (!this.discountAfterTax) {
if (this.isReturn) {
discountAmount = discountAmount.add(
(item.amount ?? this.fyo.pesa(0)).mul(
-Math.abs(item.itemDiscountPercent as number) / 100
)
);
} else {
discountAmount = discountAmount.add(
(item.amount ?? this.fyo.pesa(0)).mul(
(item.itemDiscountPercent ?? 0) / 100
)
);
}
} else if (this.discountAfterTax) {
if (this.isReturn) {
discountAmount = discountAmount.add(
(item.itemTaxedTotal ?? this.fyo.pesa(0)).mul(
-Math.abs(item.itemDiscountPercent as number) / 100
)
);
} else {
discountAmount = discountAmount.add(
(item.itemTaxedTotal ?? this.fyo.pesa(0)).mul(
(item.itemDiscountPercent ?? 0) / 100
)
);
}
}
if (this.isReturn) {
return discountAmount.neg();
}
return discountAmount;
}
getItemDiscountAmount() {
if (!this.enableDiscounting) {
return this.fyo.pesa(0);
@@ -496,7 +555,7 @@ export abstract class Invoice extends Transactional {
if (this.isReturn) {
discountAmount = discountAmount.add(
(item.amount ?? this.fyo.pesa(0)).mul(
-Math.abs(item.itemDiscountPercent as number) / 100
Math.abs(item.itemDiscountPercent as number) / 100
)
);
} else {
+23 -14
View File
@@ -19,7 +19,8 @@ import { Item } from '../Item/Item';
import { StockTransfer } from 'models/inventory/StockTransfer';
import { isPesa } from 'fyo/utils';
import { PricingRule } from '../PricingRule/PricingRule';
import { getItemRateFromPriceList } from 'models/helpers';
import { getItemRateFromPriceList, getPricingRule } from 'models/helpers';
import { SalesInvoice } from '../SalesInvoice/SalesInvoice';
export abstract class InvoiceItem extends Doc {
item?: string;
@@ -430,31 +431,39 @@ export abstract class InvoiceItem extends Doc {
setItemDiscountAmount: {
formula: async () => {
if (
!this.fyo.singles.AccountingSettings?.enablePricingRule ||
!this.fyo.singles.AccountingSettings?.enablePricingRule &&
!this.parentdoc?.pricingRuleDetail
) {
return (this.setItemDiscountAmount = false);
}
const pricingRule = this.parentdoc?.pricingRuleDetail?.filter(
(prDetail) => prDetail.referenceItem === this.item
const applicablePricingRules = await getPricingRule(
this.parentdoc as SalesInvoice
);
if (pricingRule && !pricingRule.length) {
return (this.setItemDiscountAmount = false);
}
let pricingRuleDoc;
const pricingRuleDoc = (await this.fyo.doc.getDoc(
ModelNameEnum.PricingRule,
pricingRule[0]?.referenceName
)) as PricingRule;
applicablePricingRules?.map((val) => {
if (val.applyOnItem == this.item) {
pricingRuleDoc = val.pricingRule;
}
});
if (pricingRuleDoc.discountType === 'Product Discount') {
if (!pricingRuleDoc) {
return this.setItemDiscountAmount;
}
if (pricingRuleDoc.priceDiscountType === 'amount') {
await this.set('itemDiscountAmount', pricingRuleDoc.discountAmount);
if (
(pricingRuleDoc as PricingRule).discountType === 'Product Discount'
) {
return this.setItemDiscountAmount;
}
if ((pricingRuleDoc as PricingRule).priceDiscountType === 'amount') {
await this.set(
'itemDiscountAmount',
(pricingRuleDoc as PricingRule).discountAmount
);
return true;
}