price_api/apply_guidance.ts

152 lines
7.2 KiB
TypeScript

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 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 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;
const band = doc.pricing?.v1stdv ?? doc.pricing?.v0stdv ?? 0;
let custPrice = null;
let custSource = null;
let guidance = {};
let calcCeiling = null;
let finalReasonUSD = "";
let finalPriceUSD = null;
let finalReason = "";
let finalPrice = null;
let ltp = qty < pltq ? .15 : 0;
let ltpf = qty < pltq ? true : false;
let increase = null;
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;
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 = inflation;
//guidance.Ceiling = calcCeiling;
guidance.FinalPriceUSD = finalPriceUSD;
guidance.FinalReason = finalReason;
guidance.FinalPrice = finalPrice;
guidance.FinalReason = finalReason;
guidance.BridgePremium = bridgePremium;
guidance.TargetPrice = targetPrice;
guidance.ListPrice = list;
doc.guidance = guidance;
return doc;
}