From 106f5fc10de22a347c3e600e1233e8162a12a637 Mon Sep 17 00:00:00 2001 From: AbleKSaju <126228406+AbleKSaju@users.noreply.github.com> Date: Wed, 5 Feb 2025 14:56:51 +0530 Subject: [PATCH] fix: allow invoice creation even when free items are out of stock --- models/baseModels/Invoice/Invoice.ts | 15 +++-------- models/helpers.ts | 37 ++++------------------------ src/pages/POS/POS.vue | 21 ++++++++++++++++ 3 files changed, 29 insertions(+), 44 deletions(-) diff --git a/models/baseModels/Invoice/Invoice.ts b/models/baseModels/Invoice/Invoice.ts index 808abbe0..367410da 100644 --- a/models/baseModels/Invoice/Invoice.ts +++ b/models/baseModels/Invoice/Invoice.ts @@ -24,7 +24,6 @@ import { getPricingRulesConflicts, removeLoyaltyPoint, roundFreeItemQty, - getItemQtyMap, } from 'models/helpers'; import { StockTransfer } from 'models/inventory/StockTransfer'; import { validateBatch } from 'models/inventory/helpers'; @@ -1286,19 +1285,11 @@ export abstract class Invoice extends Transactional { continue; } - let freeItemQty: number | undefined; - - if (pricingRuleDoc?.freeItem) { - const itemQtyMap = await getItemQtyMap(this as SalesInvoice); - freeItemQty = itemQtyMap[pricingRuleDoc.freeItem]?.availableQty; - } - const canApplyPRLOnItem = canApplyPricingRule( pricingRuleDoc, this.date as Date, item.quantity as number, - item.amount as Money, - freeItemQty as number + item.amount as Money ); if (!canApplyPRLOnItem) { @@ -1313,7 +1304,7 @@ export abstract class Invoice extends Transactional { } if (pricingRuleDoc.roundFreeItemQty) { - freeItemQty = roundFreeItemQty( + roundFreeItemQty( roundFreeItemQuantity, pricingRuleDoc.roundingMethod as 'round' | 'floor' | 'ceil' ); @@ -1467,7 +1458,7 @@ export abstract class Invoice extends Transactional { } } - const filtered = await filterPricingRules( + const filtered = filterPricingRules( this as SalesInvoice, pricingRuleDocsForItem, item.quantity as number, diff --git a/models/helpers.ts b/models/helpers.ts index 9132fb0c..134f535c 100644 --- a/models/helpers.ts +++ b/models/helpers.ts @@ -983,7 +983,7 @@ export async function getPricingRule( continue; } - const filtered = await filterPricingRules( + const filtered = filterPricingRules( doc as SalesInvoice, pricingRuleDocsForItem, item.quantity as number, @@ -1046,30 +1046,17 @@ export async function getItemRateFromPriceList( return plItem?.rate; } -export async function filterPricingRules( +export function filterPricingRules( doc: SalesInvoice, pricingRuleDocsForItem: PricingRule[], quantity: number, amount: Money -): Promise { +): PricingRule[] | [] { const filteredPricingRules: PricingRule[] = []; for (const pricingRuleDoc of pricingRuleDocsForItem) { - let freeItemQty: number | undefined; - - if (pricingRuleDoc?.freeItem) { - const itemQtyMap = await getItemQtyMap(doc); - freeItemQty = itemQtyMap[pricingRuleDoc.freeItem]?.availableQty; - } - if ( - canApplyPricingRule( - pricingRuleDoc, - doc.date as Date, - quantity, - amount, - freeItemQty ?? 0 - ) + canApplyPricingRule(pricingRuleDoc, doc.date as Date, quantity, amount) ) { filteredPricingRules.push(pricingRuleDoc); } @@ -1081,22 +1068,8 @@ export function canApplyPricingRule( pricingRuleDoc: PricingRule, sinvDate: Date, quantity: number, - amount: Money, - freeItemQty: number + amount: Money ): boolean { - const freeItemQuantity = pricingRuleDoc.freeItemQuantity; - - if (pricingRuleDoc.isRecursive) { - freeItemQty = quantity / (pricingRuleDoc.recurseEvery as number); - } - - // Filter by Quantity - if (pricingRuleDoc.freeItem && freeItemQuantity! >= freeItemQty) { - throw new ValidationError( - t`Free item '${pricingRuleDoc.freeItem}' does not have a specified quantity` - ); - } - if ( (pricingRuleDoc.minQuantity as number) > 0 && quantity < (pricingRuleDoc.minQuantity as number) diff --git a/src/pages/POS/POS.vue b/src/pages/POS/POS.vue index 79d677d4..173cb92f 100644 --- a/src/pages/POS/POS.vue +++ b/src/pages/POS/POS.vue @@ -803,6 +803,27 @@ export default defineComponent({ await this.sinvDoc.appendPricingRuleDetail(hasPricingRules); await this.sinvDoc.applyProductDiscount(); + + const outOfStockFreeItems: string[] = []; + const itemQtyMap = await getItemQtyMap(this.sinvDoc as SalesInvoice); + + hasPricingRules.map((pRule) => { + const freeItemQty = + itemQtyMap[pRule.pricingRule.freeItem as string]?.availableQty; + + if (freeItemQty <= 0) { + this.sinvDoc.items = this.sinvDoc.items?.filter( + (val) => !(val.isFreeItem && val.item == pRule.pricingRule.freeItem) + ); + + outOfStockFreeItems.push(pRule.pricingRule.freeItem as string); + } + }); + + showToast({ + type: 'error', + message: t`Free items out of stock: ${outOfStockFreeItems.join(', ')}`, + }); }, async routeToSinvList() { if (!this.sinvDoc.items?.length) {