mirror of
https://github.com/frappe/books.git
synced 2025-02-13 17:39:09 +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:
commit
93512d7094
@ -24,7 +24,6 @@ import {
|
|||||||
getPricingRulesConflicts,
|
getPricingRulesConflicts,
|
||||||
removeLoyaltyPoint,
|
removeLoyaltyPoint,
|
||||||
roundFreeItemQty,
|
roundFreeItemQty,
|
||||||
getItemQtyMap,
|
|
||||||
} from 'models/helpers';
|
} from 'models/helpers';
|
||||||
import { StockTransfer } from 'models/inventory/StockTransfer';
|
import { StockTransfer } from 'models/inventory/StockTransfer';
|
||||||
import { validateBatch } from 'models/inventory/helpers';
|
import { validateBatch } from 'models/inventory/helpers';
|
||||||
@ -1286,19 +1285,11 @@ export abstract class Invoice extends Transactional {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let freeItemQty: number | undefined;
|
|
||||||
|
|
||||||
if (pricingRuleDoc?.freeItem) {
|
|
||||||
const itemQtyMap = await getItemQtyMap(this as SalesInvoice);
|
|
||||||
freeItemQty = itemQtyMap[pricingRuleDoc.freeItem]?.availableQty;
|
|
||||||
}
|
|
||||||
|
|
||||||
const canApplyPRLOnItem = canApplyPricingRule(
|
const canApplyPRLOnItem = canApplyPricingRule(
|
||||||
pricingRuleDoc,
|
pricingRuleDoc,
|
||||||
this.date as Date,
|
this.date as Date,
|
||||||
item.quantity as number,
|
item.quantity as number,
|
||||||
item.amount as Money,
|
item.amount as Money
|
||||||
freeItemQty as number
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!canApplyPRLOnItem) {
|
if (!canApplyPRLOnItem) {
|
||||||
@ -1313,7 +1304,7 @@ export abstract class Invoice extends Transactional {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pricingRuleDoc.roundFreeItemQty) {
|
if (pricingRuleDoc.roundFreeItemQty) {
|
||||||
freeItemQty = roundFreeItemQty(
|
roundFreeItemQty(
|
||||||
roundFreeItemQuantity,
|
roundFreeItemQuantity,
|
||||||
pricingRuleDoc.roundingMethod as 'round' | 'floor' | 'ceil'
|
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,
|
this as SalesInvoice,
|
||||||
pricingRuleDocsForItem,
|
pricingRuleDocsForItem,
|
||||||
item.quantity as number,
|
item.quantity as number,
|
||||||
|
@ -983,7 +983,7 @@ export async function getPricingRule(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const filtered = await filterPricingRules(
|
const filtered = filterPricingRules(
|
||||||
doc as SalesInvoice,
|
doc as SalesInvoice,
|
||||||
pricingRuleDocsForItem,
|
pricingRuleDocsForItem,
|
||||||
item.quantity as number,
|
item.quantity as number,
|
||||||
@ -1046,30 +1046,17 @@ export async function getItemRateFromPriceList(
|
|||||||
return plItem?.rate;
|
return plItem?.rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function filterPricingRules(
|
export function filterPricingRules(
|
||||||
doc: SalesInvoice,
|
doc: SalesInvoice,
|
||||||
pricingRuleDocsForItem: PricingRule[],
|
pricingRuleDocsForItem: PricingRule[],
|
||||||
quantity: number,
|
quantity: number,
|
||||||
amount: Money
|
amount: Money
|
||||||
): Promise<PricingRule[] | []> {
|
): PricingRule[] | [] {
|
||||||
const filteredPricingRules: PricingRule[] = [];
|
const filteredPricingRules: PricingRule[] = [];
|
||||||
|
|
||||||
for (const pricingRuleDoc of pricingRuleDocsForItem) {
|
for (const pricingRuleDoc of pricingRuleDocsForItem) {
|
||||||
let freeItemQty: number | undefined;
|
|
||||||
|
|
||||||
if (pricingRuleDoc?.freeItem) {
|
|
||||||
const itemQtyMap = await getItemQtyMap(doc);
|
|
||||||
freeItemQty = itemQtyMap[pricingRuleDoc.freeItem]?.availableQty;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
canApplyPricingRule(
|
canApplyPricingRule(pricingRuleDoc, doc.date as Date, quantity, amount)
|
||||||
pricingRuleDoc,
|
|
||||||
doc.date as Date,
|
|
||||||
quantity,
|
|
||||||
amount,
|
|
||||||
freeItemQty ?? 0
|
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
filteredPricingRules.push(pricingRuleDoc);
|
filteredPricingRules.push(pricingRuleDoc);
|
||||||
}
|
}
|
||||||
@ -1081,22 +1068,8 @@ export function canApplyPricingRule(
|
|||||||
pricingRuleDoc: PricingRule,
|
pricingRuleDoc: PricingRule,
|
||||||
sinvDate: Date,
|
sinvDate: Date,
|
||||||
quantity: number,
|
quantity: number,
|
||||||
amount: Money,
|
amount: Money
|
||||||
freeItemQty: number
|
|
||||||
): boolean {
|
): 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 (
|
if (
|
||||||
(pricingRuleDoc.minQuantity as number) > 0 &&
|
(pricingRuleDoc.minQuantity as number) > 0 &&
|
||||||
quantity < (pricingRuleDoc.minQuantity as number)
|
quantity < (pricingRuleDoc.minQuantity as number)
|
||||||
|
@ -803,6 +803,27 @@ export default defineComponent({
|
|||||||
|
|
||||||
await this.sinvDoc.appendPricingRuleDetail(hasPricingRules);
|
await this.sinvDoc.appendPricingRuleDetail(hasPricingRules);
|
||||||
await this.sinvDoc.applyProductDiscount();
|
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() {
|
async routeToSinvList() {
|
||||||
if (!this.sinvDoc.items?.length) {
|
if (!this.sinvDoc.items?.length) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user