diff --git a/models/baseModels/Invoice/Invoice.ts b/models/baseModels/Invoice/Invoice.ts index 2aa675f2..1e5133ee 100644 --- a/models/baseModels/Invoice/Invoice.ts +++ b/models/baseModels/Invoice/Invoice.ts @@ -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 { diff --git a/models/baseModels/InvoiceItem/InvoiceItem.ts b/models/baseModels/InvoiceItem/InvoiceItem.ts index b50f7671..4e12e445 100644 --- a/models/baseModels/InvoiceItem/InvoiceItem.ts +++ b/models/baseModels/InvoiceItem/InvoiceItem.ts @@ -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; }