Android_Retail/src/Pages/BookingScreen/Components/BSItemCards/ValidateOffer.jsx

134 lines
4.1 KiB
JavaScript

const toNum = (v, fallback = 0) => (v == null ? fallback : Number(v));
export function validateOffers(
item,
OverAllproductBasedOfferDatas,
CartData = [],
TakAwayId,
DineinId
) {
const qty = toNum(item.OrderQty);
const amount = toNum(item.TotalAmt);
const allOffers =
(OverAllproductBasedOfferDatas?.ProdDtl || []).filter(
(offer) =>
offer.OfferType !== "S" &&
offer.ProdId === item?.ProdId &&
(offer.LimitUsage > 0 || offer.LimitUsage == null) &&
(offer.ProdVariantDetails || []).some((variant) =>
(variant.StockDetails || []).some(
(stock) => stock.InwardDtlId === item?.InwardDtlId
)
)
) || [];
// filter by offer applicability
const applicableOffers = allOffers.filter((offer) => {
if (offer.OfferType === "I") {
return amount >= (offer.MinPurchase || 0) || qty >= (offer.MinQty || 0);
}
if (offer.OfferType === "Q") {
return qty >= (offer.FromQty || 0) && qty <= (offer.ToQty || Infinity);
}
if (offer.OfferType === "B") {
const cartQty = CartData?.filter((c) => c.ProdId === item.ProdId).reduce(
(acc, cur) => acc + toNum(cur.OrderQty),
0
);
return cartQty >= (offer.MinQty || 0);
}
return false;
});
// separate B (buy/get) from others
const buyGetOffers = [];
let bestNonB = null;
let bestDiscount = 0;
for (const offer of applicableOffers) {
if (offer.OfferType === "B") buyGetOffers.push(offer);
else {
const discount =
offer.ValueType === "F"
? toNum(offer.OfferAmt)
: (toNum(offer.OfferAmt) * amount) / 100;
if (discount >= bestDiscount) {
bestDiscount = discount;
bestNonB = offer;
}
}
}
// dedupe circular buy/get relationships (keep simpler: remove offers that are circular duplicates)
const dedupedBuyGet = buyGetOffers.filter((o, idx, arr) => {
if (!o.FreeProducts && !o.FreeProductsList) return true;
return !o.FreeProductsList?.some((fp) =>
arr.some(
(other) =>
other !== o &&
other.ProdId === fp.FreeProdId &&
other.FreeProductsList?.some((ofp) => ofp.FreeProdId === o.ProdId)
)
);
});
const results = [];
if (dedupedBuyGet.length > 0) {
for (const o of dedupedBuyGet)
results.push(buildOfferObj(o, o.OfferAmt || 0, item, DineinId, TakAwayId));
} else if (bestNonB) {
results.push(
buildOfferObj(bestNonB, bestDiscount, item, DineinId, TakAwayId)
);
}
return results;
}
function buildOfferObj(offer, discount, item, DineinId, TakAwayId) {
const freeProductsRaw = offer.FreeProducts || offer.FreeProductsList;
const freeProductsArray = freeProductsRaw
? Array.isArray(freeProductsRaw)
? freeProductsRaw
: [freeProductsRaw]
: [];
return {
OfferId: offer.OfferId || "",
OfferAmount: discount || 0,
OfferMode: offer.OfferType, // I/Q/B
AcuvalOfferAmount: offer.OfferAmt,
OfferValue: offer.OfferAmt || 0,
TableName: offer.TableName || "",
TableUniqueName: offer.TableUniqueName || "",
TableUniqueId: offer.TableUniqueId || "",
ActualFreeQty: offer.ActualFreeQty || 0,
OfferType: offer.ValueType || "", // F / P
Detail: offer.Detail || [],
OfferCode: offer.OfferCode || "",
CustId: offer.CustId || "",
UsedCount: offer.UsedCount || 0,
AppliesTo: offer.AppliesTo || "",
BookingType: item.BookingTypeName === "Dine In" ? DineinId : TakAwayId,
FreeProductsList: freeProductsArray.map((fp) => ({
FreeProdId: fp.FreeProdId || "",
FreeQty: fp.FreeQty || 0,
FreeProdName: fp.FreeProdName || "",
ProdVariantDetails: fp.ProdVariantDetails || [],
})),
// product-level fields
ProdId: item?.ProdId || "",
SinglePc: item?.SinglePc || "",
StockAvailable: item?.StockAvailable || "",
ProdVariantName: item?.ProdVariantName || "",
Type: item?.Type || "",
BookingType: item?.BookingType || 0,
InwardDtlId: item?.InwardDtlId || "",
ProdCat: item?.ProdCat || "",
HalfPrice: offer?.HalfPrice,
MinQty: offer?.MinQty,
};
}