Compare commits

..

No commits in common. "43e64a1533a1f6aaa76455fc8115353cf1e6ed04" and "32217d52c4a7e4e5353989ebb20b79afd5afc767" have entirely different histories.

4 changed files with 102 additions and 101 deletions

2
api.ts
View File

@ -52,7 +52,7 @@ router.get('/dseg_price/:billcode/:shipcode/:stlc/:dseg/:qty', async (ctx) => {
const { billcode, shipcode, stlc, dseg, qty } = ctx.params; const { billcode, shipcode, stlc, dseg, qty } = ctx.params;
const result = await client.queryObject({args: [billcode, shipcode, stlc, dseg, qty], text: query_dseg} ); const result = await client.queryObject({args: [billcode, shipcode, stlc, dseg, qty], text: query_dseg} );
const ag = apply_guidance(result.rows[0]["doc"]); const ag = apply_guidance(result.rows[0]["doc"]);
ctx.response.body = ag.guidance.finalPrice.Snapped; ctx.response.body = ag.guidance.FinalReason;
}); });
app.use(router.routes()); app.use(router.routes());

View File

@ -14,109 +14,110 @@ export function apply_guidance(doc: any) {
return match ? match.adj : null; return match ? match.adj : null;
} }
function lowestPrice(priceObject) { //let custPrice null;
let Price = Infinity; //let custReason null;
let Reason = ''; //let cvolPrice null;
let Source = ''; //let cvolReason null;
let Snapped = Infinity; //let markPrice null;
//let markReason null;
//let targPrice null;
//let targReason null;
//console.log(priceObject["targ"][0]);
// Iterate over each property in the object
for (let key in priceObject) {
// Ignore markPrice unless targPrice is null
if (key === "mark" && priceObject["targ"][0] !== null) {
continue;
}
if (priceObject.hasOwnProperty(key)) {
let [cprice, creason, csource, csnap] = priceObject[key];
// Check if the current price is lower than the found so far
if (cprice && cprice < Price) {
Price = cprice;
Reason = creason;
Source = csource;
Snapped = csnap;
}
}
}
return {Reason, Price, Source, Snapped};
}
function ceiling(value, significance) {
return Math.ceil(value / significance) * significance;
}
function r5(value) {
return Number(value.toFixed(5));
}
function pp(value) {
// Multiplies by 1000 and rounds to the nearest 2 decimals
var result = Math.round(value * 1000 * 100) / 100;
// Converts the number to a string with commas for thousand separators
return result.toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2});
}
// --------------------extract incoming data------------------------------------------------------
const targetPrice = doc.pricing?.v1tp ?? doc.pricing?.v0tp; const targetPrice = doc.pricing?.v1tp ?? doc.pricing?.v0tp;
const priceBand = doc.pricing?.v1stdv ?? doc.pricing?.v0stdv; const priceBand = doc.pricing?.v1stdv ?? doc.pricing?.v0stdv;
const earlyCustPrice = doc.hist?.cust?.early_price; const earlyPrice = doc.hist?.cust?.early_price;
const earlyCustSeason = doc.hist?.cust?.early_season; const earlySeason = doc.hist?.cust?.early_season;
const earlyMarkPrice = doc.hist?.market?.early_price; const bridgePremium = doc.pricing?.bridgePremium ?? 1.00000;
const earlyMarkSeason = doc.hist?.market?.early_season;
const bridgePremium = doc.pricing?.bridgePremium;
const bridgedPrice = Number((earlyCustPrice * (bridgePremium ?? 1.00)).toFixed(5));
const altHist = doc.hist?.cust?.ds; const altHist = doc.hist?.cust?.ds;
const iidx = doc.pricing?.iidx; const iidx = doc.pricing?.iidx;
const curr = doc.customer?.curr; const curr = doc.customer?.curr;
const fxrate = doc.customer?.fxrate ?? 1.0; const fxrate = doc.customer?.fxrate ?? 1.0;
const qty = doc.inputs?.qty; const qty = doc.inputs?.qty;
const pltq = doc.product?.pltq; const pltq = doc.product?.pltq;
let anchorPrice = null;
let anchorSource = null;
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 ? 1.15 : null;
let increase = null;
const inflation = Math.max(...Object.keys(iidx).map(Number)); const inflation = Math.max(...Object.keys(iidx).map(Number));
const inflationFactor = iidx[inflation]; const inflationFactor = iidx[inflation] + 1;
const list = doc.pricing?.list && doc.product?.itemrel === "2" ? doc.pricing?.list : null; const list = doc.pricing?.list && doc.product?.itemrel === "2" ? doc.pricing?.list : null;
const listUSD = list ? list * fxrate :null;
// ------------------calculate price adders------------------------------------------------------ //-------set basic customer pricing--------------
let ltp = qty < pltq ? 0.15 : null; custPrice = Number((earlyPrice * bridgePremium).toFixed(5));
let anchor_sd = priceBand ? ((bridgedPrice - targetPrice) / priceBand).toFixed(2) : 0 anchorPrice = custPrice;
let anchor_sd = priceBand ? ((anchorPrice - targetPrice) / priceBand).toFixed(2) : 0
let optimization = getAdjValue(anchor_sd); let optimization = getAdjValue(anchor_sd);
let custAdder = (ltp ?? 0) + optimization + inflationFactor;
let markAdder = (ltp ?? 0) + inflationFactor;
let inflReason = (inflationFactor ?? 0) !== 0 ? ` + ${(inflationFactor * 100).toFixed(1)}% infl`: "";
let ltpReason = ltp ? ` + ${(ltp * 100).toFixed(1)}% ltp` : "";
let optReason = (optimization ?? 0) !== 0 ? ` + ${(optimization * 100).toFixed(1)}% opt`: "";
let custAddReason = `${inflReason}${ltpReason}${optReason}`;
let markAddReason = `${inflReason}${ltpReason}`;
// ------------------start building price options------------------------------------------------
let snap = .0005; // ------if there is not target price just exit---------------
if (!targetPrice) {
let custPrice = r5(bridgedPrice * (1 + custAdder)); anchorSource = "No target pricing setup";
let custSeason = earlyCustSeason; guidance.FinalReason = "No target pricing setup";
let custReason = bridgePremium } else {
? `${custSeason} (similar ${altHist} price ${pp(earlyCustPrice)} x ${bridgePremium} = ${pp(bridgedPrice)})${custAddReason}` // if there is no customer anchor price use target
: `${custSeason} price ${pp(bridgedPrice)}${custAddReason}`; if (earlyPrice) {
let markPrice = r5(earlyMarkPrice * (1 + markAdder)); // translate alternate product history to current product quoted
let markReason = `${earlyMarkSeason} ASP ${pp(earlyMarkPrice)}${markAddReason}`; // --------if the price needs bridged, add the details to the description--------
let targPrice = targetPrice ? r5(targetPrice * (1 + markAdder)) : null; if (bridgePremium === 1) {
let targReason = `Target price ${pp(targetPrice)}${markAddReason}`; anchorSource = earlySeason + ' Price ' + earlyPrice;
let listPrice = listUSD; custSource = anchorSource;
let listReason = fxrate === 1 ? "" : `list ${pp(list)} CAD ${pp(listUSD)} USD` } else {
anchorSource = earlySeason + ' Similar (' + altHist + ') Price ' + earlyPrice + ' x ' + bridgePremium + ' = ' + anchorPrice;
let prices = { custSource = anchorSource;
cust: [custPrice, custReason, "cust", ceiling(custPrice,snap)],
mark: [markPrice, markReason, "mark", ceiling(markPrice,snap)],
targ: [targPrice, targReason, "targ", ceiling(targPrice,snap)],
list: [listPrice, listReason, "list", ceiling(listPrice,snap)]
} }
// --------after the early price is translated see if target is still less-------
let finalPrice = lowestPrice(prices); if (targetPrice < anchorPrice) {
let guidance = { anchorSource = `Target Price ${targetPrice}`;
prices anchorPrice = targetPrice;
,finalPrice
} }
} 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}`;
}
}
}
guidance.AnchorPrice = anchorPrice;
guidance.AnchorSource = anchorSource;
guidance.CustAnchorPrice = custPrice;
guidance.CustAnchorSource = custSource;
guidance.InflationFactor = inflationFactor;
guidance.Ceiling = calcCeiling;
guidance.FinalPriceUSD = finalPriceUSD;
guidance.FinalReasonUSD = finalReasonUSD;
guidance.FinalPrice = finalPrice;
guidance.FinalReason = finalReason;
guidance.BridgePremium = bridgePremium;
guidance.TargetPrice = targetPrice;
guidance.ListPrice = list;
doc.guidance = guidance; doc.guidance = guidance;
return doc; return doc;
} }

View File

@ -110,7 +110,7 @@ FROM
,('customer v0ds other',7) ,('customer v0ds other',7)
,('customer v0ds vol' ,3) ,('customer v0ds vol' ,3)
,('customer v1ds other',6) ,('customer v1ds other',6)
,('customer v1ds vol' ,2) --this will always sort to the top, v0ds will never sort to the top. you will always be getting the highest volume base price ,('customer v1ds vol' ,2)
,('market exact' ,4) ,('market exact' ,4)
,('market v0ds other' ,9) ,('market v0ds other' ,9)
,('market v0ds vol' ,5) ,('market v0ds vol' ,5)

View File

@ -104,7 +104,7 @@ FROM
,('customer v0ds other',7) ,('customer v0ds other',7)
,('customer v0ds vol' ,3) ,('customer v0ds vol' ,3)
,('customer v1ds other',6) ,('customer v1ds other',6)
,('customer v1ds vol' ,2) --this will always sort to the top, v0ds will never sort to the top. you will always be getting the highest volume base price ,('customer v1ds vol' ,2)
,('market exact' ,4) ,('market exact' ,4)
,('market v0ds other' ,9) ,('market v0ds other' ,9)
,('market v0ds vol' ,5) ,('market v0ds vol' ,5)