2
0
mirror of https://github.com/frappe/books.git synced 2024-11-08 14:50:56 +00:00

feat: price discount

This commit is contained in:
akshayitzme 2024-02-01 17:04:39 +05:30
parent beccfb6f22
commit 9345ee5106
2 changed files with 114 additions and 56 deletions

View File

@ -19,9 +19,7 @@ import { Item } from '../Item/Item';
import { StockTransfer } from 'models/inventory/StockTransfer';
import { PriceList } from '../PriceList/PriceList';
import { isPesa } from 'fyo/utils';
import { canApplyPricingRule } from 'models/helpers';
import { PricingRule } from '../PricingRule/PricingRule';
import { SalesInvoiceItem } from '../SalesInvoiceItem/SalesInvoiceItem';
export abstract class InvoiceItem extends Doc {
item?: string;
@ -49,6 +47,8 @@ export abstract class InvoiceItem extends Doc {
itemDiscountedTotal?: Money;
itemTaxedTotal?: Money;
isFreeItem?: boolean;
get isSales() {
return (
this.schemaName === 'SalesInvoiceItem' ||
@ -96,6 +96,10 @@ export abstract class InvoiceItem extends Doc {
return !!this.parentdoc?.isReturn;
}
get pricingRuleDetail() {
return this.parentdoc?.pricingRuleDetail;
}
constructor(schema: Schema, data: DocValueMap, fyo: Fyo) {
super(schema, data, fyo);
this._setGetCurrencies();
@ -172,6 +176,7 @@ export abstract class InvoiceItem extends Doc {
'itemTaxedTotal',
'itemDiscountedTotal',
'setItemDiscountAmount',
'pricingRuleDetail',
],
},
unit: {
@ -407,41 +412,79 @@ export abstract class InvoiceItem extends Doc {
},
dependsOn: ['item', 'quantity'],
},
isPricingRuleAppliedItem: {
setItemDiscountAmount: {
formula: async () => {
if (!this.parentdoc?.pricingRuleDetail) {
return false;
if (
!this.fyo.singles.AccountingSettings?.enablePricingRule ||
!this.parentdoc?.pricingRuleDetail
) {
return this.setItemDiscountAmount;
}
for (const prleDoc of this.parentdoc.pricingRuleDetail) {
const pricingRuleDoc = (await this.fyo.doc.getDoc(
ModelNameEnum.PricingRule,
prleDoc.referenceName
)) as PricingRule;
const pricingRule = this.parentdoc?.pricingRuleDetail?.filter(
(prDetail) => prDetail.referenceItem === this.item
);
if (
!canApplyPricingRule(
pricingRuleDoc,
this.parentdoc.date as Date,
this.quantity as number,
this.amount as Money
)
) {
continue;
}
if (!pricingRule) {
return this.setItemDiscountAmount;
}
const appliedItems = pricingRuleDoc.appliedItems?.map(
(item) => item.item
const pricingRuleDoc = (await this.fyo.doc.getDoc(
ModelNameEnum.PricingRule,
pricingRule[0].referenceName
)) as PricingRule;
if (pricingRuleDoc.discountType === 'Product Discount') {
return this.setItemDiscountAmount;
}
if (pricingRuleDoc.priceDiscountType === 'amount') {
const discountAmount = pricingRuleDoc.discountAmount?.mul(
this.quantity as number
);
if (!appliedItems?.includes(this.item)) {
continue;
}
await applyPricingRuleOnItem(this, pricingRuleDoc);
await this.set('itemDiscountAmount', discountAmount);
return true;
}
return this.setItemDiscountAmount;
},
dependsOn: ['item', 'quantity'],
dependsOn: ['pricingRuleDetail'],
},
itemDiscountPercent: {
formula: async () => {
if (
!this.fyo.singles.AccountingSettings?.enablePricingRule ||
!this.parentdoc?.pricingRuleDetail
) {
return this.itemDiscountPercent;
}
const pricingRule = this.parentdoc?.pricingRuleDetail?.filter(
(prDetail) => prDetail.referenceItem === this.item
);
if (!pricingRule) {
return this.itemDiscountPercent;
}
const pricingRuleDoc = (await this.fyo.doc.getDoc(
ModelNameEnum.PricingRule,
pricingRule[0].referenceName
)) as PricingRule;
if (pricingRuleDoc.discountType === 'Product Discount') {
return this.itemDiscountPercent;
}
if (pricingRuleDoc.priceDiscountType === 'percentage') {
await this.set('setItemDiscountAmount', false);
return pricingRuleDoc.discountPercentage;
}
return this.setItemDiscountAmount;
},
dependsOn: ['pricingRuleDetail'],
},
};
@ -570,7 +613,21 @@ export abstract class InvoiceItem extends Doc {
}
async function getItemRate(doc: InvoiceItem): Promise<Money | undefined> {
if (doc.isFreeItem) {
return doc.rate;
}
let pricingRuleRate: Money | undefined;
if (doc.fyo.singles.AccountingSettings?.enablePricingRule) {
pricingRuleRate = await getItemRateFromPricingRule(doc);
}
if (pricingRuleRate) {
return pricingRuleRate;
}
let priceListRate: Money | undefined;
if (doc.fyo.singles.AccountingSettings?.enablePriceList) {
priceListRate = await getItemRateFromPriceList(doc);
}
@ -591,6 +648,33 @@ async function getItemRate(doc: InvoiceItem): Promise<Money | undefined> {
return;
}
async function getItemRateFromPricingRule(
doc: InvoiceItem
): Promise<Money | undefined> {
const pricingRule = doc.parentdoc?.pricingRuleDetail?.filter(
(prDetail) => prDetail.referenceItem === doc.item
);
if (!pricingRule) {
return;
}
const pricingRuleDoc = (await doc.fyo.doc.getDoc(
ModelNameEnum.PricingRule,
pricingRule[0].referenceName
)) as PricingRule;
if (pricingRuleDoc.discountType !== 'Price Discount') {
return;
}
if (pricingRuleDoc.priceDiscountType !== 'rate') {
return;
}
return pricingRuleDoc.discountRate;
}
async function getItemRateFromPriceList(
doc: InvoiceItem
): Promise<Money | undefined> {
@ -773,30 +857,3 @@ function getRate(
return null;
}
async function applyPricingRuleOnItem(
sinvItemDoc: SalesInvoiceItem,
pricingRuleDoc: PricingRule
) {
switch (pricingRuleDoc.priceDiscountType) {
case 'rate':
await sinvItemDoc.set('rate', pricingRuleDoc.discountRate);
return;
case 'amount':
await sinvItemDoc.set('setItemDiscountAmount', true);
const discountAmount = pricingRuleDoc.discountAmount?.mul(
sinvItemDoc.quantity as number
);
await sinvItemDoc.set('itemDiscountAmount', discountAmount);
return;
case 'percentage':
await sinvItemDoc.set(
'itemDiscountPercent',
pricingRuleDoc.discountPercentage
);
return;
}
}

View File

@ -2,4 +2,5 @@ import { Doc } from 'fyo/model/doc';
export class PricingRuleDetail extends Doc {
referenceName?: string;
referenceItem?: string;
}