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:
parent
beccfb6f22
commit
9345ee5106
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -2,4 +2,5 @@ import { Doc } from 'fyo/model/doc';
|
||||
|
||||
export class PricingRuleDetail extends Doc {
|
||||
referenceName?: string;
|
||||
referenceItem?: string;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user