2
0
mirror of https://github.com/frappe/books.git synced 2025-02-13 09:29:18 +00:00

Merge pull request #1116 from AbleKSaju/fix-invoice-creation

fix: allow invoice creation even when free items are out of stock
This commit is contained in:
Akshay 2025-02-06 09:17:17 +05:30 committed by GitHub
commit 93512d7094
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 29 additions and 44 deletions

View File

@ -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,

View File

@ -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[] | []> {
): 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)

View File

@ -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) {