2
0
mirror of https://github.com/frappe/books.git synced 2024-11-09 23:30:56 +00:00

fix: pricing rule not applied in pos

This commit is contained in:
akshayitzme 2024-08-19 13:00:25 +05:30
parent 427b8260e0
commit d4a08d8331
5 changed files with 71 additions and 21 deletions

View File

@ -646,11 +646,12 @@ export abstract class Invoice extends Transactional {
}
const pricingRule = await this.getPricingRule();
if (pricingRule) {
await this.appendPricingRuleDetail(pricingRule);
if (!pricingRule) {
return false;
}
return !!pricingRule?.length;
await this.appendPricingRuleDetail(pricingRule);
return !!pricingRule;
},
dependsOn: ['items'],
},
@ -954,6 +955,8 @@ export abstract class Invoice extends Transactional {
if (this.pricingRuleDetail?.length) {
await this.applyProductDiscount();
} else {
this.clearFreeItems();
}
}
@ -1099,22 +1102,40 @@ export abstract class Invoice extends Transactional {
}
}
clearFreeItems() {
if (this.pricingRuleDetail?.length || !this.items) {
return;
}
for (const item of this.items) {
if (item.isFreeItem) {
this.items = this.items?.filter(
(invoiceItem) => invoiceItem.name !== item.name
);
}
}
}
async applyProductDiscount() {
if (!this.pricingRuleDetail || !this.items) {
if (!this.items) {
return;
}
if (!this.pricingRuleDetail?.length || !this.pricingRuleDetail.length) {
return;
}
this.items = this.items.filter((item) => !item.isFreeItem);
for (const item of this.items) {
if (item.isFreeItem) {
continue;
}
const pricingRuleDetailForItem = this.pricingRuleDetail.filter(
(doc) => doc.referenceItem === item.item
);
if (!pricingRuleDetailForItem.length) {
return;
}
const pricingRuleDoc = (await this.fyo.doc.getDoc(
ModelNameEnum.PricingRule,
pricingRuleDetailForItem[0].referenceName

View File

@ -141,7 +141,7 @@ test('pricing rule is applied when filtered by min and max qty', async (t) => {
);
});
test('pricing rule is not applied when item qty is < min qty ', async (t) => {
test('pricing rule is not applied when item qty is < min qty', async (t) => {
const sinv = fyo.doc.getNewDoc(ModelNameEnum.SalesInvoice, {
date: new Date(),
party: partyMap.partyOne.name,
@ -548,7 +548,6 @@ test('create a product discount, recurse 2', async (t) => {
await sinv.runFormulas();
await sinv.sync();
console.log('freeQty', sinv.items![1].quantity);
t.equal(!!sinv.items![1].isFreeItem, true);
t.equal(sinv.items![1].rate!.float, pricingRuleMap[1].freeItemRate);
t.equal(sinv.items![1].quantity, pricingRuleMap[1].freeItemQuantity);

View File

@ -663,13 +663,13 @@ export async function addItem<M extends ModelsWithItems>(name: string, doc: M) {
export async function getPricingRule(
doc: Invoice
): Promise<ApplicablePricingRules[] | undefined> {
): Promise<ApplicablePricingRules[] | null> {
if (
!doc.fyo.singles.AccountingSettings?.enablePricingRule ||
!doc.isSales ||
!doc.items
) {
return;
return null;
}
const pricingRules: ApplicablePricingRules[] = [];
@ -786,13 +786,15 @@ export function canApplyPricingRule(
// Filter by Validity
if (
pricingRuleDoc.validFrom &&
sinvDate.toISOString() < pricingRuleDoc.validFrom.toISOString()
new Date(sinvDate.setHours(0, 0, 0, 0)).toISOString() <
pricingRuleDoc.validFrom.toISOString()
) {
return false;
}
if (
pricingRuleDoc.validTo &&
sinvDate.toISOString() > pricingRuleDoc.validTo.toISOString()
new Date(sinvDate.setHours(0, 0, 0, 0)).toISOString() >
pricingRuleDoc.validTo.toISOString()
) {
return false;
}

View File

@ -362,6 +362,23 @@ export default defineComponent({
setTransferRefNo(ref: string) {
this.transferRefNo = ref;
},
removeFreeItems() {
if (!this.sinvDoc || !this.sinvDoc.items) {
return;
}
if (!!this.sinvDoc.isPricingRuleApplied) {
return;
}
for (const item of this.sinvDoc.items) {
if (item.isFreeItem) {
this.sinvDoc.items = this.sinvDoc.items?.filter(
(invoiceItem) => invoiceItem.name !== item.name
);
}
}
},
async addItem(item: POSItem | Item | undefined) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
@ -385,17 +402,21 @@ export default defineComponent({
const existingItems =
this.sinvDoc.items?.filter(
(invoiceItem) => invoiceItem.item === item.name
(invoiceItem) =>
invoiceItem.item === item.name && !invoiceItem.isFreeItem
) ?? [];
if (item.hasBatch) {
for (const item of existingItems) {
const itemQty = item.quantity ?? 0;
for (const invItem of existingItems) {
const itemQty = invItem.quantity ?? 0;
const qtyInBatch =
this.itemQtyMap[item.item as string][item.batch as string] ?? 0;
this.itemQtyMap[invItem.item as string][invItem.batch as string] ??
0;
if (itemQty < qtyInBatch) {
item.quantity = (item.quantity as number) + 1;
invItem.quantity = (invItem.quantity as number) + 1;
invItem.rate = item.rate as Money;
return;
}
}
@ -415,8 +436,10 @@ export default defineComponent({
}
if (existingItems.length) {
existingItems[0].rate = item.rate as Money;
existingItems[0].quantity = (existingItems[0].quantity as number) + 1;
await this.applyPricingRule();
await this.sinvDoc.runFormulas();
return;
}
@ -568,7 +591,11 @@ export default defineComponent({
const hasPricingRules = await getPricingRule(
this.sinvDoc as SalesInvoice
);
if (!hasPricingRules) {
if (!hasPricingRules || !hasPricingRules.length) {
this.sinvDoc.pricingRuleDetail = undefined;
this.sinvDoc.isPricingRuleApplied = false;
this.removeFreeItems();
return;
}

View File

@ -21,7 +21,8 @@ import { showToast } from './interactive';
export async function getItemQtyMap(): Promise<ItemQtyMap> {
const itemQtyMap: ItemQtyMap = {};
const valuationMethod =
fyo.singles.InventorySettings?.valuationMethod ?? ValuationMethod.FIFO;
(fyo.singles.InventorySettings?.valuationMethod as ValuationMethod) ??
ValuationMethod.FIFO;
const rawSLEs = await getRawStockLedgerEntries(fyo);
const rawData = getStockLedgerEntries(rawSLEs, valuationMethod);