diff --git a/apply_guidance.ts b/apply_guidance.ts index a329708..2401ba8 100644 --- a/apply_guidance.ts +++ b/apply_guidance.ts @@ -1,17 +1,38 @@ export function apply_guidance(doc: any) { +/*----------------------------------------------------------------------------------------------------------------------------------------------------- + price optimization lookup table +-----------------------------------------------------------------------------------------------------------------------------------------------------*/ + + function getAdjValue(number) { + const data = [ + {f: 2.001, t: 1000, snap: 3, adj: 0 }, + {f: 1.001, t: 2, snap: 2, adj: 0 }, + {f: 0.1, t: 1, snap: 1, adj: 0 }, + {f: 0, t: 0.1, snap: 0, adj: 0 }, + {f: -1, t: -0.00001, snap: -1, adj: 0.05}, + {f: -2, t: -0.999999, snap: -2, adj: 0.05}, + {f: -1000, t: -2.001, snap: -3, adj: 0.10}, + ]; + const match = data.find(row => number >= row.f && number <= row.t); + return match ? match.adj : null; + } + const targetPrice = doc.pricing?.v1tp ?? doc.pricing?.v0tp; - const earlyPrice = doc.hist?.cust?.early_price; + const bridgePremium = doc.pricing?.bridgePremium ; + const earlyPriceOrig = doc.hist?.cust?.early_price; + const earlyPrice = doc.hist?.cust?.early_price * bridgePremium; + const earlyMarketPrice = doc.hist?.market?.early_price; const earlySeason = doc.hist?.cust?.early_season; - const bridgePremium = doc.pricing?.bridgePremium ?? 1.00000; + const earlyMarketSeason = doc.hist?.market?.early_season; const altHist = doc.hist?.cust?.ds; const iidx = doc.pricing?.iidx; const curr = doc.customer?.curr; + const chan = doc.customer?.chan; const fxrate = doc.customer?.fxrate ?? 1.0; const qty = doc.inputs?.qty; const pltq = doc.product?.pltq; - let anchorPrice = null; - let anchorSource = null; + const band = doc.pricing?.v1stdv ?? doc.pricing?.v0stdv ?? 0; let custPrice = null; let custSource = null; let guidance = {}; @@ -20,69 +41,106 @@ export function apply_guidance(doc: any) { let finalPriceUSD = null; let finalReason = ""; let finalPrice = null; - let ltp = qty < pltq ? 1.15 : null; + let ltp = qty < pltq ? .15 : 0; + let ltpf = qty < pltq ? true : false; let increase = null; - const inflation = Math.max(...Object.keys(iidx).map(Number)); - const inflationFactor = iidx[inflation] + 1; + let isWarehouse = chan[0] === "W" + const inflationidx = Math.max(...Object.keys(iidx).map(Number)); + const inflation = iidx[inflationidx]; const list = doc.pricing?.list && doc.product?.itemrel === "2" ? doc.pricing?.list : null; - // ------if there is not target price just exit--------------- - if (!targetPrice) { - anchorSource = "No target pricing setup"; - guidance.FinalReason = "No target pricing setup"; - } else { - // if there is no customer anchor price use target - if (earlyPrice) { - // translate alternate product history to current product quoted - custPrice = Number((earlyPrice * bridgePremium).toFixed(5)); - anchorPrice = custPrice; - // --------if the price needs bridged, add the details to the description-------- - if (bridgePremium === 1) { - anchorSource = earlySeason + ' Customer Price ' + earlyPrice; - custSource = anchorSource; - } else { - anchorSource = earlySeason + ' Similar (' + altHist + ') Customer Price ' + earlyPrice + ' x ' + bridgePremium + ' = ' + anchorPrice; - custSource = anchorSource; - } - // --------after the early price is translated see if target is still less------- - if (targetPrice < anchorPrice) { - anchorSource = `Target Price ${targetPrice}`; - anchorPrice = targetPrice; - } - } else { - anchorPrice = targetPrice; - anchorSource = `Target Price ${targetPrice}`; - } - //------get the most relevant inflation factor number--------------------------------- - //------anchor x inflation / fxrate--------------------------------------------------- - let calcPriceUSD = parseFloat((anchorPrice * inflationFactor).toFixed(5)); - let calcPrice = parseFloat((calcPriceUSD / fxrate).toFixed(5)); - if (calcPrice >= list && list) { - calcCeiling = "Cap At List"; - //multiply list by FX to get to USD if in CAD - finalPrice = list; - if (curr === "CA") { - finalReason = `${anchorSource} x ${inflationFactor} / ${fxrate} FX = ${calcPrice} CAD, cap at list ${list} CAD`; - } else { - finalReason = `${anchorSource} x ${inflationFactor} = ${calcPrice}, cap at list ${list}`; - } - } else { - finalPrice = calcPrice; - finalPriceUSD = calcPriceUSD; - if (curr === "CA") { - finalReason = `${anchorSource} x ${inflationFactor} / ${fxrate} FX = ${calcPrice} CAD`; - } else { - finalReason = `${anchorSource} x ${inflationFactor} = ${calcPrice}`; - } + const listUSD = (list && fxrate) ? list / fxrate : null; + +/*----------------------------------------------------------------------------------------------------------------------------------------------------- + determine anchor price +-----------------------------------------------------------------------------------------------------------------------------------------------------*/ + + let anchorPrice = + earlyPrice ? earlyPrice : + targetPrice ? targetPrice : + earlyMarketPrice ? earlyMarketPrice : + null; + + let anchorSource = + earlyPrice + ? bridgePremium + ? `${earlySeason} ${altHist} price ${earlyPriceOrig} x ${bridgePremium} = ${earlyPrice}` + : `${earlySeason} price ${(earlyPrice * 1000).toFixed(2)}` : + earlyPrice ? earlyReason : + targetPrice ? `Target price ${(targetPrice * 1000).toFixed(2)}` : + earlyMarketPrice ? `${earlyMarketSeason} price ${earlyMarketPrice}` : + null; + +/*----------------------------------------------------------------------------------------------------------------------------------------------------- + calculated increase percentages +-----------------------------------------------------------------------------------------------------------------------------------------------------*/ + + let anchorSD = (band && targetPrice) ? ((anchorPrice - targetPrice) / band).toFixed(2) : 0 + let optFactor = getAdjValue(anchorSD) ; + let increaseAnch = 1 + optFactor + ltp + inflation; + let increaseTarg = 1 + ltp + inflation; + +/*----------------------------------------------------------------------------------------------------------------------------------------------------- + apply increases +-----------------------------------------------------------------------------------------------------------------------------------------------------*/ + + let anchorGoal = anchorPrice * increaseAnch; + let capTarget = targetPrice * increaseTarg; + let capMarket = earlyMarketPrice * increaseTarg; + +/*----------------------------------------------------------------------------------------------------------------------------------------------------- + calculate price caps +-----------------------------------------------------------------------------------------------------------------------------------------------------*/ + + /* there are 3 price points + * anchor + increase + * target + increase + * list + goal is to demonstrate calculation of anchor + increase then give then cap if applicable + */ + + //default to anchor goal + finalPriceUSD = anchorGoal; + finalReason = ""; + let increaseReason = ""; + let cap = ""; + + //if the target is less than the anchor goal, cap at target + if ((capTarget ?? anchorGoal ) < anchorGoal) { + finalPriceUSD = capTarget; + cap = ` cap at target ${(targetPrice * 1000).toFixed(2)} + ${((increaseTarg - 1) * 100).toFixed(1)}%` + } + //if list price is even less than the capped price, then cap at list + if ((listUSD ?? anchorGoal) < finalPriceUSD ) { + finalPriceUSD = listUSD; + cap = ` cap at list ${listUSD}` + } + /*-----use _p.list if available for warehouse-----------*/ + if (isWarehouse) { + if (listUSD) { + finalPriceUSD = listUSD; + cap_curr = ` snap to list ${listUSD}`; } } + finalPrice = finalPriceUSD / fxrate; + +/*----------------------------------------------------------------------------------------------------------------------------------------------------- + build the logic text +-----------------------------------------------------------------------------------------------------------------------------------------------------*/ + + cap = cap ? ";" + cap : ""; + let fltp = ltpf ? ` + ${(ltp * 100).toFixed(1) + '%'} LTP` : ""; + let fopt = optFactor ? ` + ${(optFactor * 100).toFixed(1) + '%'} opt` : ""; + let fguidance = inflation ? ` + ${(inflation * 100).toFixed(1) + '%'} guidance` : ""; + finalReason = `${(finalPrice*1000).toFixed(2)} (${anchorSource}${fguidance}${fltp}${fopt}${cap}) `; + guidance.AnchorPrice = anchorPrice; guidance.AnchorSource = anchorSource; - guidance.CustAnchorPrice = custPrice; - guidance.CustAnchorSource = custSource; - guidance.InflationFactor = inflationFactor; - guidance.Ceiling = calcCeiling; + //guidance.CustAnchorPrice = custPrice; + //guidance.CustAnchorSource = custSource; + guidance.InflationFactor = inflation; + //guidance.Ceiling = calcCeiling; guidance.FinalPriceUSD = finalPriceUSD; - guidance.FinalReasonUSD = finalReasonUSD; + guidance.FinalReason = finalReason; guidance.FinalPrice = finalPrice; guidance.FinalReason = finalReason; guidance.BridgePremium = bridgePremium;