Compare commits
31 Commits
Author | SHA1 | Date | |
---|---|---|---|
86656f6952 | |||
fb5968343a | |||
51ba3fe3ca | |||
6d987ee0aa | |||
618a744e05 | |||
de9ecd5033 | |||
5234516dee | |||
970968f980 | |||
3050bbfe7a | |||
50781c6b2f | |||
229291f9bc | |||
e1406f70ab | |||
885a2982ee | |||
eb0c969ec7 | |||
a2322876e1 | |||
eca0da084e | |||
a63f176293 | |||
b04f67d9f0 | |||
d6c4d71851 | |||
764a6f8ebe | |||
062cea58a6 | |||
14ee797b91 | |||
aaa62afb5d | |||
453ec561ee | |||
baeeaccf53 | |||
43e64a1533 | |||
0219b2d5ce | |||
8a9102dbca | |||
56d139c22d | |||
52e802b389 | |||
dc1f493700 |
10
api.ts
10
api.ts
@ -52,7 +52,15 @@ router.get('/dseg_price/:billcode/:shipcode/:stlc/:dseg/:qty', async (ctx) => {
|
||||
const { billcode, shipcode, stlc, dseg, qty } = ctx.params;
|
||||
const result = await client.queryObject({args: [billcode, shipcode, stlc, dseg, qty], text: query_dseg} );
|
||||
const ag = apply_guidance(result.rows[0]["doc"]);
|
||||
ctx.response.body = ag.guidance.FinalReason;
|
||||
ctx.response.body = ag.guidance.finalPrice.Snapped;
|
||||
});
|
||||
|
||||
// specific customres codes but generic style code and data segment to accomodate custom colors and branding
|
||||
router.get('/dseg_reason/:billcode/:shipcode/:stlc/:dseg/:qty', async (ctx) => {
|
||||
const { billcode, shipcode, stlc, dseg, qty } = ctx.params;
|
||||
const result = await client.queryObject({args: [billcode, shipcode, stlc, dseg, qty], text: query_dseg} );
|
||||
const ag = apply_guidance(result.rows[0]["doc"]);
|
||||
ctx.response.body = ag.guidance.finalPrice.Snapped + ' (' + ag.guidance.finalPrice.Reason + ')';
|
||||
});
|
||||
|
||||
app.use(router.routes());
|
||||
|
@ -1,5 +1,21 @@
|
||||
export function apply_guidance(doc: any) {
|
||||
|
||||
function sortObjectKeys(obj) {
|
||||
// If the object is not an actual object or is an array, return it as is
|
||||
if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Create a new object and sort the keys
|
||||
const sortedObj = {};
|
||||
Object.keys(obj).sort().forEach(key => {
|
||||
// Recursively apply the function for nested objects
|
||||
sortedObj[key] = sortObjectKeys(obj[key]);
|
||||
});
|
||||
|
||||
return sortedObj;
|
||||
}
|
||||
|
||||
function getAdjValue(number) {
|
||||
const data = [
|
||||
{f: 2.001, t: 1000, snap: 3, adj: 0 },
|
||||
@ -14,110 +30,136 @@ export function apply_guidance(doc: any) {
|
||||
return match ? match.adj : null;
|
||||
}
|
||||
|
||||
//let custPrice null;
|
||||
//let custReason null;
|
||||
//let cvolPrice null;
|
||||
//let cvolReason null;
|
||||
//let markPrice null;
|
||||
//let markReason null;
|
||||
//let targPrice null;
|
||||
//let targReason null;
|
||||
|
||||
const targetPrice = doc.pricing?.v1tp ?? doc.pricing?.v0tp;
|
||||
const priceBand = doc.pricing?.v1stdv ?? doc.pricing?.v0stdv;
|
||||
const earlyPrice = doc.hist?.cust?.early_price;
|
||||
const earlySeason = doc.hist?.cust?.early_season;
|
||||
const bridgePremium = doc.pricing?.bridgePremium ?? 1.00000;
|
||||
const altHist = doc.hist?.cust?.ds;
|
||||
const iidx = doc.pricing?.iidx;
|
||||
const curr = doc.customer?.curr;
|
||||
const fxrate = doc.customer?.fxrate ?? 1.0;
|
||||
const qty = doc.inputs?.qty;
|
||||
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 inflationFactor = iidx[inflation] + 1;
|
||||
const list = doc.pricing?.list && doc.product?.itemrel === "2" ? doc.pricing?.list : null;
|
||||
|
||||
//-------set basic customer pricing--------------
|
||||
custPrice = Number((earlyPrice * bridgePremium).toFixed(5));
|
||||
anchorPrice = custPrice;
|
||||
let anchor_sd = priceBand ? ((anchorPrice - targetPrice) / priceBand).toFixed(2) : 0
|
||||
let optimization = getAdjValue(anchor_sd);
|
||||
|
||||
|
||||
// ------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
|
||||
// --------if the price needs bridged, add the details to the description--------
|
||||
if (bridgePremium === 1) {
|
||||
anchorSource = earlySeason + ' Price ' + earlyPrice;
|
||||
custSource = anchorSource;
|
||||
} else {
|
||||
anchorSource = earlySeason + ' Similar (' + altHist + ') 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}`;
|
||||
}
|
||||
}
|
||||
//-------------------------------set flor prices-------------------------------
|
||||
function getFloor(stlc) {
|
||||
switch (stlc) {
|
||||
case "SDD10000":
|
||||
return 0.045;
|
||||
case "SDD10001":
|
||||
return 0.045;
|
||||
case "SDD12000":
|
||||
return 0.065;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function lowestPrice(priceObject) {
|
||||
let Price = Infinity;
|
||||
let Reason = '';
|
||||
let Source = '';
|
||||
let Snapped = Infinity;
|
||||
|
||||
//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 priceBand = doc.pricing?.v1stdv ?? doc.pricing?.v0stdv;
|
||||
const earlyCustPrice = doc.hist?.cust?.early_price;
|
||||
const earlyCustSeason = doc.hist?.cust?.early_season;
|
||||
const earlyMarkPrice = doc.hist?.market?.early_price;
|
||||
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 iidx = doc.pricing?.iidx;
|
||||
const curr = doc.customer?.curr;
|
||||
const fxrate = doc.customer?.fxrate ?? 1.0;
|
||||
const qty = doc.inputs?.qty;
|
||||
const pltq = doc.product?.pltq;
|
||||
const inflation = Math.max(...Object.keys(iidx).map(Number));
|
||||
const inflationFactor = iidx[inflation];
|
||||
const list = doc.pricing?.list && doc.product?.itemrel === "2" ? doc.pricing?.list : null;
|
||||
const listUSD = list ? list * fxrate :null;
|
||||
const stlc = doc.inputs.stlc;
|
||||
|
||||
// ------------------calculate price adders------------------------------------------------------
|
||||
let ltp = stlc.includes("SDD") || stlc.includes("HZP") ? 0 : (qty < pltq ? 0.15 : null);
|
||||
let anchor_sd = priceBand ? ((bridgedPrice - targetPrice) / priceBand).toFixed(2) : 0
|
||||
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}`;
|
||||
let floor = getFloor(stlc);
|
||||
|
||||
// ------------------start building price options------------------------------------------------
|
||||
|
||||
let snap = .0005;
|
||||
|
||||
let custPrice = r5(bridgedPrice * (1 + custAdder));
|
||||
let custSeason = earlyCustSeason;
|
||||
let custReason = bridgePremium
|
||||
? `${custSeason} (similar ${altHist} price ${pp(earlyCustPrice)} x ${bridgePremium} = ${pp(bridgedPrice)})${custAddReason}`
|
||||
: `${custSeason} price ${pp(bridgedPrice)}${custAddReason}`;
|
||||
let markPrice = r5(earlyMarkPrice * (1 + markAdder));
|
||||
let markReason = `${earlyMarkSeason} ASP ${pp(earlyMarkPrice)}${markAddReason}`;
|
||||
let targPrice = targetPrice ? r5(targetPrice * (1 + markAdder)) : null;
|
||||
let targReason = `Target price ${pp(targetPrice)}${markAddReason}`;
|
||||
let listPrice = listUSD;
|
||||
let listReason = fxrate === 1 ? `list ${pp(list)}` : `list ${pp(list)} CAD ${pp(listUSD)} USD`;
|
||||
|
||||
let prices = {
|
||||
cust: [custPrice, custReason, "cust", r5(ceiling(custPrice,snap))],
|
||||
mark: [markPrice, markReason, "mark", r5(ceiling(markPrice,snap))],
|
||||
targ: [targPrice, targReason, "targ", r5(ceiling(targPrice,snap))],
|
||||
list: [listPrice, listReason, "list", r5(ceiling(listPrice,snap))]
|
||||
}
|
||||
|
||||
let finalPrice = lowestPrice(prices);
|
||||
if (floor && floor > finalPrice.Price) {
|
||||
finalPrice.Price = floor;
|
||||
finalPrice.Snapped = floor;
|
||||
finalPrice.Reason = `${finalPrice.Reason} floor at ${floor}`;
|
||||
}
|
||||
let guidance = {
|
||||
prices
|
||||
,finalPrice
|
||||
,targetPrice
|
||||
,listUSD
|
||||
,ltp
|
||||
,inflationFactor
|
||||
,optimization
|
||||
}
|
||||
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;
|
||||
return doc;
|
||||
//return doc;
|
||||
return sortObjectKeys(doc);
|
||||
}
|
||||
|
70
live_quote_mv.pg.sql
Normal file
70
live_quote_mv.pg.sql
Normal file
@ -0,0 +1,70 @@
|
||||
|
||||
set work_mem TO '4GB';
|
||||
|
||||
DROP TABLE IF EXISTS rlarp.live_quotes_review_mv;
|
||||
CREATE TABLE rlarp.live_quotes_review_mv AS
|
||||
WITH
|
||||
lq AS MATERIALIZED (
|
||||
SELECT
|
||||
lq.*
|
||||
,substring(lq.part,1,8) mold
|
||||
FROM
|
||||
pricequote.live_quotes lq
|
||||
)
|
||||
,lqg AS (
|
||||
SELECT
|
||||
lq.*
|
||||
,pricing->'product'->>'mold' part_group
|
||||
,substring(pricing->'customer'->>'chan',1,1) qchan
|
||||
,pricing->'customer'->>'cust' qcust
|
||||
,pricing->'product'->>'itemrel' item_fit
|
||||
,(pricing->'product'->>'pltq')::numeric pltq
|
||||
,(pricing->'guidance'->'finalPrice'->>'Price')::numeric guidance
|
||||
,pricing->'guidance'->'finalPrice'->>'Reason' reason
|
||||
,(pricing->'product'->>'cstd_usd_ina')::numeric fstd_usd
|
||||
,(pricing->'guidance'->>'ltp')::numeric ltp
|
||||
,(pricing->'guidance'->>'optimization')::numeric optimization
|
||||
,(pricing->'guidance'->>'inflationFactor')::numeric inflation
|
||||
,jsonb_pretty(pricing) pricing
|
||||
FROM
|
||||
lq
|
||||
LEFT JOIN LATERAL rlarp.guidance_r1(
|
||||
rlarp.get_guidance_dseg(lq.billto,lq.shipto,substring(lq.part,1,8),lq.v1ds,lq.units_each,2024)
|
||||
) pricing ON TRUE
|
||||
WHERE
|
||||
lq.qstat ~ 'Submitted'
|
||||
)
|
||||
,hist AS (
|
||||
SELECT
|
||||
g.*
|
||||
,gset.chan
|
||||
--,gset.mold moldh
|
||||
,gset.v1ds v1dsh
|
||||
,gset.cust
|
||||
,gset.vers
|
||||
,je.k
|
||||
,seas.*
|
||||
FROM
|
||||
lqg g
|
||||
LEFT OUTER JOIN rlarp.price_pool_dev p ON
|
||||
p.gset @> jsonb_build_object('mold',g.part_group)
|
||||
AND p.gset ? 'cust'
|
||||
AND p.gset ? 'v1ds'
|
||||
LEFT JOIN LATERAL jsonb_to_record(p.gset) AS gset(
|
||||
chan text
|
||||
,mold text
|
||||
,v1ds text
|
||||
,v0ds text
|
||||
,cust text
|
||||
,vers text
|
||||
--,nurs text
|
||||
--,ghse text
|
||||
) ON TRUE
|
||||
LEFT JOIN LATERAL jsonb_each(p.season) je(k,v) on true
|
||||
LEFT JOIN Lateral jsonb_to_record(je.v) as seas(
|
||||
units numeric
|
||||
,sales_usd numeric
|
||||
,price_usd numeric
|
||||
) ON TRUE
|
||||
)
|
||||
SELECT * FROM hist;
|
152
sql/apply_guidance.pg.sql
Normal file
152
sql/apply_guidance.pg.sql
Normal file
@ -0,0 +1,152 @@
|
||||
CREATE OR REPLACE FUNCTION rlarp.guidance_r1(doc jsonb)
|
||||
RETURNS jsonb
|
||||
LANGUAGE plv8
|
||||
AS $function$
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//-------------------------------set flor prices-------------------------------
|
||||
function getFloor(stlc) {
|
||||
switch (stlc) {
|
||||
case "SDD10000":
|
||||
return 0.045;
|
||||
case "SDD10001":
|
||||
return 0.045;
|
||||
case "SDD12000":
|
||||
return 0.065;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function lowestPrice(priceObject) {
|
||||
let Price = Infinity;
|
||||
let Reason = '';
|
||||
let Source = '';
|
||||
let Snapped = Infinity;
|
||||
|
||||
//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 priceBand = doc.pricing?.v1stdv ?? doc.pricing?.v0stdv;
|
||||
const earlyCustPrice = doc.hist?.cust?.early_price;
|
||||
const earlyCustSeason = doc.hist?.cust?.early_season;
|
||||
const earlyMarkPrice = doc.hist?.market?.early_price;
|
||||
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 iidx = doc.pricing?.iidx;
|
||||
const curr = doc.customer?.curr;
|
||||
const fxrate = doc.customer?.fxrate ?? 1.0;
|
||||
const qty = doc.inputs?.qty;
|
||||
const pltq = doc.product?.pltq;
|
||||
const inflation = iidx ? Math.max(...Object.keys(iidx).map(Number)) : null;
|
||||
const inflationFactor = iidx ? iidx[inflation] : 0;
|
||||
const list = doc.pricing?.list && doc.product?.itemrel === "2" ? doc.pricing?.list : null;
|
||||
const listUSD = list ? list * fxrate :null;
|
||||
const stlc = doc.inputs.stlc;
|
||||
|
||||
// ------------------calculate price adders------------------------------------------------------
|
||||
let ltp = stlc.includes("SDD") || stlc.includes("HZP") ? 0 : (qty < pltq ? 0.15 : null);
|
||||
let anchor_sd = priceBand ? ((bridgedPrice - targetPrice) / priceBand).toFixed(2) : 0
|
||||
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}`;
|
||||
let floor = getFloor(stlc);
|
||||
|
||||
// ------------------start building price options------------------------------------------------
|
||||
|
||||
let snap = .0005;
|
||||
|
||||
let custPrice = r5(bridgedPrice * (1 + custAdder));
|
||||
let custSeason = earlyCustSeason;
|
||||
let custReason = bridgePremium
|
||||
? `${custSeason} (similar ${altHist} price ${pp(earlyCustPrice)} x ${bridgePremium} = ${pp(bridgedPrice)})${custAddReason}`
|
||||
: `${custSeason} price ${pp(bridgedPrice)}${custAddReason}`;
|
||||
let markPrice = r5(earlyMarkPrice * (1 + markAdder));
|
||||
let markReason = `${earlyMarkSeason} ASP ${pp(earlyMarkPrice)}${markAddReason}`;
|
||||
let targPrice = targetPrice ? r5(targetPrice * (1 + markAdder)) : null;
|
||||
let targReason = `Target price ${pp(targetPrice)}${markAddReason}`;
|
||||
let listPrice = listUSD;
|
||||
let listReason = fxrate === 1 ? `list ${pp(list)}` : `list ${pp(list)} CAD ${pp(listUSD)} USD`;
|
||||
|
||||
let prices = {
|
||||
cust: [custPrice, custReason, "cust", r5(ceiling(custPrice,snap))],
|
||||
mark: [markPrice, markReason, "mark", r5(ceiling(markPrice,snap))],
|
||||
targ: [targPrice, targReason, "targ", r5(ceiling(targPrice,snap))],
|
||||
list: [listPrice, listReason, "list", r5(ceiling(listPrice,snap))]
|
||||
}
|
||||
|
||||
let finalPrice = lowestPrice(prices);
|
||||
if (floor && floor > finalPrice.Price) {
|
||||
finalPrice.Price = floor;
|
||||
finalPrice.Snapped = floor;
|
||||
finalPrice.Reason = `${finalPrice.Reason} floor at ${floor}`;
|
||||
}
|
||||
let guidance = {
|
||||
prices
|
||||
,finalPrice
|
||||
,targetPrice
|
||||
,listUSD
|
||||
,ltp
|
||||
,inflationFactor
|
||||
,optimization
|
||||
}
|
||||
doc.guidance = guidance;
|
||||
return doc;
|
||||
|
||||
$function$;
|
33
sql/consume_pricepool.pg.sql
Normal file
33
sql/consume_pricepool.pg.sql
Normal file
@ -0,0 +1,33 @@
|
||||
SELECT
|
||||
gset.cust
|
||||
,gset.vers
|
||||
,gset.chan
|
||||
,gset.nurs
|
||||
,gset.ghse
|
||||
,gset.mold
|
||||
,gset.v1ds
|
||||
,gset.v0ds
|
||||
,je.k
|
||||
,seas.*
|
||||
FROM
|
||||
rlarp.price_pool_dev p
|
||||
LEFT JOIN LATERAL jsonb_to_record(p.gset) AS gset(
|
||||
chan text
|
||||
,mold text
|
||||
,v1ds text
|
||||
,v0ds text
|
||||
,cust text
|
||||
,vers text
|
||||
,nurs text
|
||||
,ghse text
|
||||
) ON TRUE
|
||||
LEFT JOIN LATERAL jsonb_each(p.season) je(k,v) on true
|
||||
LEFT JOIN Lateral jsonb_to_record(je.v) as seas(
|
||||
units numeric
|
||||
,sales_usd numeric
|
||||
,price_usd numeric
|
||||
) ON TRUE
|
||||
WHERE
|
||||
gset @> '{"mold":"TFR001G0","v0ds":"BASE"}'
|
||||
AND agglevel ?| array['chan', 'mold', 'v0ds']
|
||||
AND NOT agglevel ?| array['cust','ghse'];
|
79
sql/get_cust.pg.sql
Normal file
79
sql/get_cust.pg.sql
Normal file
@ -0,0 +1,79 @@
|
||||
----takes 2 DBA's and returns the channel----------
|
||||
CREATE OR REPLACE FUNCTION rlarp.get_cust(billcode text, shipcode text)
|
||||
RETURNS jsonb
|
||||
LANGUAGE plpgsql AS
|
||||
$func$
|
||||
DECLARE
|
||||
_chan text;
|
||||
_chantp text;
|
||||
_bill_class text;
|
||||
_ship_class text;
|
||||
_bill_dba text;
|
||||
_ship_dba text;
|
||||
_cust text;
|
||||
_bill_curr text;
|
||||
_bill_rate numeric;
|
||||
_crec jsonb;
|
||||
_ret jsonb;
|
||||
_record jsonb;
|
||||
|
||||
BEGIN
|
||||
SELECT jsonb_agg(row_to_json(c)::jsonb) INTO _crec FROM rlarp.cust c WHERE code IN (billcode, shipcode);
|
||||
|
||||
--RAISE NOTICE '%', jsonb_pretty(_crec);
|
||||
|
||||
FOR _record IN SELECT * FROM jsonb_array_elements(_crec)
|
||||
LOOP
|
||||
-- Check if the record is for billcode or shipcode and assign values accordingly
|
||||
IF (_record->>'code')::text = billcode THEN
|
||||
_bill_dba := (_record->>'dba')::text;
|
||||
_bill_class := (_record->>'cclass')::text;
|
||||
_bill_curr := (_record->>'currency')::text;
|
||||
_bill_rate := (_record->>'fxcurr')::text;
|
||||
-- Add other billcode related assignments here
|
||||
END IF;
|
||||
|
||||
IF (_record->>'code')::text = shipcode THEN
|
||||
_ship_dba := (_record->>'dba')::text;
|
||||
_ship_class := (_record->>'cclass')::text;
|
||||
-- Add other shipcode related assignments here
|
||||
END IF;
|
||||
END LOOP;
|
||||
|
||||
SELECT
|
||||
CASE WHEN SUBSTRING(_bill_class,2,3) = 'DIS'
|
||||
THEN CASE WHEN SUBSTRING(_ship_class,2,3) = 'DIS' THEN 'WHS' ELSE 'DRP' END
|
||||
ELSE 'DIR'
|
||||
END
|
||||
INTO
|
||||
_chan;
|
||||
|
||||
SELECT
|
||||
CASE WHEN SUBSTRING(_bill_class,2,3) = 'DIS'
|
||||
THEN CASE WHEN SUBSTRING(_ship_class,2,3) = 'DIS' THEN 'DISTRIBUTOR' ELSE 'DISTRIB DROP SHIP' END
|
||||
ELSE 'DIRECT'
|
||||
END
|
||||
INTO
|
||||
_chantp;
|
||||
|
||||
SELECT
|
||||
CASE WHEN _chan = 'DRP' THEN _ship_dba ELSE _bill_dba END
|
||||
INTO
|
||||
_cust;
|
||||
|
||||
_ret := jsonb_build_object('customer',
|
||||
jsonb_build_object(
|
||||
'cust',_cust,
|
||||
'chan',_chan,
|
||||
'chantp',_chantp,
|
||||
'curr',_bill_curr,
|
||||
'fxrate',_bill_rate,
|
||||
'bill_dba',_bill_dba,
|
||||
'ship_dba',_ship_dba
|
||||
)
|
||||
);
|
||||
|
||||
RETURN _ret;
|
||||
|
||||
END
|
||||
$func$;
|
@ -42,7 +42,7 @@ BEGIN
|
||||
INTO
|
||||
_mold,_stlc,_v1ds , _v0ds, _iidx
|
||||
FROM
|
||||
"CMS.CUSLG".itemmv i
|
||||
"CMS.CUSLG".itemm i
|
||||
INNER JOIN rlarp.molds m ON
|
||||
m.stlc = i.stlc
|
||||
WHERE
|
||||
|
@ -1,4 +1,4 @@
|
||||
DROP FUNCTION rlarp.get_guidance_dseg;
|
||||
DROP FUNCTION rlarp.get_guidance_dseg CASCADE;
|
||||
CREATE OR REPLACE FUNCTION rlarp.get_guidance_dseg(_bill text, _ship text, _stlc text, _dseg text, _qty numeric, _seas int)
|
||||
RETURNS jsonb
|
||||
LANGUAGE plpgsql AS
|
||||
@ -15,6 +15,10 @@ DECLARE
|
||||
_item text;
|
||||
_unti text;
|
||||
_pltq numeric;
|
||||
_cstd numeric;
|
||||
_cstdina numeric;
|
||||
_fstd numeric;
|
||||
_fstdina numeric;
|
||||
_cust text;
|
||||
_curr text;
|
||||
_rate numeric;
|
||||
@ -65,37 +69,52 @@ BEGIN
|
||||
,idxk
|
||||
,prefer
|
||||
,pltq
|
||||
,curstdus
|
||||
,curstdus_ina
|
||||
,futstdus
|
||||
,futstdus_ina
|
||||
INTO
|
||||
_mold
|
||||
,_item
|
||||
,_iidx
|
||||
,_itemr
|
||||
,_pltq
|
||||
,_cstd
|
||||
,_cstdina
|
||||
,_fstd
|
||||
,_fstdina
|
||||
FROM
|
||||
(
|
||||
SELECT
|
||||
m.part_group
|
||||
i.partgroup part_group
|
||||
,min(i.item) item
|
||||
,i.stlc
|
||||
,i.v1ds
|
||||
,i.v0ds
|
||||
,i.pltq
|
||||
,_ds.dataseg v0ds
|
||||
,i.mpck pltq
|
||||
,avg(i.curstdus) FILTER (WHERE aplnt <> 'I') curstdus
|
||||
,avg(i.curstdus) curstdus_ina
|
||||
,avg(i.futstdus) FILTER (WHERE aplnt <> 'I') futstdus
|
||||
,avg(i.futstdus) futstdus_ina
|
||||
,jsonb_strip_nulls(jsonb_build_object('assc',CASE WHEN i.assc <> '' THEN i.assc ELSE null::text END,'majg',i.majg::int,'coltier',i.coltier)) idxk
|
||||
,CASE WHEN i.v1ds = _v1ds THEN 2 ELSE CASE WHEN i.v0ds = _v0ds THEN 1 ELSE 0 END END prefer
|
||||
,CASE WHEN i.v1ds = _v1ds THEN 2 ELSE CASE WHEN _ds.dataseg = _v0ds THEN 1 ELSE 0 END END prefer
|
||||
FROM
|
||||
"CMS.CUSLG".itemmv i
|
||||
INNER JOIN rlarp.molds m ON
|
||||
m.stlc = i.stlc
|
||||
"CMS.CUSLG".itemm i
|
||||
LEFT OUTER JOIN _ds ON
|
||||
_ds.colgrp = i.colgrp
|
||||
AND _ds.brand = SUBSTRING(i.branding,1,1)
|
||||
--INNER JOIN rlarp.molds m ON
|
||||
-- m.stlc = i.stlc
|
||||
WHERE
|
||||
i.stlc = _stlc
|
||||
GROUP BY
|
||||
m.part_group
|
||||
i.partgroup
|
||||
,i.stlc
|
||||
,i.v1ds
|
||||
,i.v0ds
|
||||
,i.pltq
|
||||
,_ds.dataseg
|
||||
,i.mpck
|
||||
,jsonb_strip_nulls(jsonb_build_object('assc',CASE WHEN i.assc <> '' THEN i.assc ELSE null::text END,'majg',i.majg::int,'coltier',i.coltier))
|
||||
,CASE WHEN i.v1ds = _v1ds THEN 2 ELSE CASE WHEN i.v0ds = _v0ds THEN 1 ELSE 0 END END
|
||||
,CASE WHEN i.v1ds = _v1ds THEN 2 ELSE CASE WHEN _ds.dataseg = _v0ds THEN 1 ELSE 0 END END
|
||||
) best
|
||||
ORDER BY
|
||||
prefer DESC
|
||||
@ -109,49 +128,54 @@ BEGIN
|
||||
,'itemrel',_itemr
|
||||
,'iidx',_iidx
|
||||
,'pltq',_pltq
|
||||
,'cstd_usd',_cstd
|
||||
,'cstd_usd_ina',_cstdina
|
||||
,'fstd_usd',_fstd
|
||||
,'fstd_usd_ina',_fstdina
|
||||
)
|
||||
);
|
||||
--RAISE NOTICE 'item data %', jsonb_pretty(_product||_input);
|
||||
|
||||
----------------channel-------------------------------------
|
||||
|
||||
SELECT rlarp.channel_code(_bill, _ship) INTO _chan;
|
||||
_customer := jsonb_build_object('chan',_chan);
|
||||
SELECT rlarp.get_cust(_bill, _ship) INTO _customer;
|
||||
--_customer := jsonb_build_object('chan',_chan);
|
||||
|
||||
----------------customer------------------------------------
|
||||
SELECT dba INTO _cust FROM rlarp.cust WHERE code = CASE WHEN _chan = 'DRP' THEN _ship ELSE _bill END ;
|
||||
SELECT
|
||||
currency,
|
||||
(SELECT
|
||||
x.rate
|
||||
FROM
|
||||
rlarp.ffcret x
|
||||
WHERE
|
||||
x.perd = (select fspr from rlarp.gld where drange @> current_date)
|
||||
AND x.rtyp = 'MA'
|
||||
and x.fcur = currency
|
||||
AND x.tcur = 'US'
|
||||
)
|
||||
INTO
|
||||
_curr
|
||||
,_rate
|
||||
FROM
|
||||
rlarp.cust
|
||||
WHERE
|
||||
code = _bill;
|
||||
--SELECT dba INTO _cust FROM rlarp.cust WHERE code = CASE WHEN _chan = 'DRP' THEN _ship ELSE _bill END ;
|
||||
--SELECT
|
||||
-- currency,
|
||||
-- (SELECT
|
||||
-- x.rate
|
||||
-- FROM
|
||||
-- rlarp.ffcret x
|
||||
-- WHERE
|
||||
-- x.perd = (select fspr from rlarp.gld where drange @> current_date)
|
||||
-- AND x.rtyp = 'MA'
|
||||
-- and x.fcur = currency
|
||||
-- AND x.tcur = 'US'
|
||||
-- )
|
||||
--INTO
|
||||
-- _curr
|
||||
-- ,_rate
|
||||
--FROM
|
||||
-- rlarp.cust
|
||||
--WHERE
|
||||
-- code = _bill;
|
||||
|
||||
_customer := jsonb_build_object(
|
||||
'customer',
|
||||
_customer||jsonb_build_object(
|
||||
'cust',_cust
|
||||
,'curr',_curr
|
||||
,'fxrate',_rate
|
||||
)
|
||||
);
|
||||
--_customer := jsonb_build_object(
|
||||
-- 'customer',
|
||||
-- _customer||jsonb_build_object(
|
||||
-- 'cust',_cust
|
||||
-- ,'curr',_curr
|
||||
-- ,'fxrate',_rate
|
||||
-- )
|
||||
--);
|
||||
--RAISE NOTICE 'cust %', jsonb_pretty(_customer);
|
||||
|
||||
----------------price history-------------------------------
|
||||
SELECT jsonb_build_object('hist',rlarp.get_hist(_mold, _v1ds, _cust, substring(_chan,1,1))) INTO _hist;
|
||||
--RAISE NOTICE 'varb %', _customer;
|
||||
SELECT jsonb_build_object('hist',rlarp.get_hist(_mold, _v1ds, _customer->'customer'->>'cust', substring(_customer->'customer'->>'chan',1,1))) INTO _hist;
|
||||
--RAISE NOTICE 'history %', jsonb_pretty(_hist);
|
||||
|
||||
----------------target pricing------------------------------
|
||||
@ -170,7 +194,8 @@ BEGIN
|
||||
mold = _stlc
|
||||
AND season = _seas
|
||||
AND data_segment = _v0ds
|
||||
AND region = 'ALL';
|
||||
AND region = 'ALL'
|
||||
AND chan = _customer->'customer'->>'chantp';
|
||||
----------------target pricing------------------------------
|
||||
SELECT
|
||||
jsonb_build_object(
|
||||
@ -187,7 +212,8 @@ BEGIN
|
||||
mold = _stlc
|
||||
AND season = _seas
|
||||
AND data_segment = _dseg
|
||||
AND region = 'ALL';
|
||||
AND region = 'ALL'
|
||||
AND chan = _customer->'customer'->>'chantp';
|
||||
--RAISE NOTICE 'target: %', jsonb_pretty(_targ);
|
||||
_pricing := (COALESCE(_v0tp,'{}'::jsonb)||COALESCE(_v1tp,'{}'::jsonb));
|
||||
|
||||
@ -221,7 +247,7 @@ BEGIN
|
||||
--RAISE NOTICE 'add list: %', jsonb_pretty(_pricing);
|
||||
|
||||
----------------get premium for quote hist gap--------------
|
||||
SELECT coalesce(rlarp.get_premium(_stlc, _seas, (SELECT xchan FROM _chx WHERE chan = _chan),_hist->'hist'->'cust'->>'ds', _v1ds),'{}'::jsonb) INTO _prem;
|
||||
SELECT coalesce(rlarp.get_premium(_stlc, _seas, _customer->'customer'->>'chantp',_hist->'hist'->'cust'->>'ds', _v1ds),'{}'::jsonb) INTO _prem;
|
||||
_pricing := jsonb_build_object('pricing',_pricing||_prem);
|
||||
--RAISE NOTICE 'add bridge: %', jsonb_pretty(_pricing);
|
||||
|
||||
|
@ -110,7 +110,7 @@ FROM
|
||||
,('customer v0ds other',7)
|
||||
,('customer v0ds vol' ,3)
|
||||
,('customer v1ds other',6)
|
||||
,('customer v1ds vol' ,2)
|
||||
,('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
|
||||
,('market exact' ,4)
|
||||
,('market v0ds other' ,9)
|
||||
,('market v0ds vol' ,5)
|
||||
|
@ -1,5 +1,5 @@
|
||||
WITH
|
||||
sel AS (select 'v1:P.P.PLT..' _v1ds, 'ALTMAN PLANTS' _cust, 'XNS0T1G3' _mold, 'D' _chan)
|
||||
sel AS (select 'v1:T..PLT..' _v1ds, 'KAWAHARA NURSERY' _cust, 'AZE10001' _mold, 'D' _chan)
|
||||
,sort AS (
|
||||
SELECT
|
||||
p.agglevel
|
||||
@ -53,6 +53,19 @@ sel AS (select 'v1:P.P.PLT..' _v1ds, 'ALTMAN PLANTS' _cust, 'XNS0T1G3' _mold, 'D
|
||||
source ASC
|
||||
,rn ASC
|
||||
)
|
||||
,rel AS (
|
||||
SELECT * FROM (values
|
||||
('customer exact' ,1)
|
||||
,('customer v0ds other',7)
|
||||
,('customer v0ds vol' ,3)
|
||||
,('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
|
||||
,('market exact' ,4)
|
||||
,('market v0ds other' ,9)
|
||||
,('market v0ds vol' ,5)
|
||||
,('market v1ds other' ,8)
|
||||
) x (flag,prefer)
|
||||
)
|
||||
,flag AS (
|
||||
SELECT
|
||||
--agglevel
|
||||
@ -84,6 +97,7 @@ SELECT
|
||||
,cust
|
||||
,vers
|
||||
,rn
|
||||
,row_number() OVER (PARTITION BY source ORDER BY rel.prefer ASC) rnk
|
||||
,avgunits
|
||||
,avgordcount
|
||||
,avgcustcount
|
||||
@ -97,19 +111,25 @@ SELECT
|
||||
,season
|
||||
FROM
|
||||
sort
|
||||
)
|
||||
,rel AS (
|
||||
SELECT * FROM (values
|
||||
('customer exact' ,1)
|
||||
,('customer v0ds other',7)
|
||||
,('customer v0ds vol' ,3)
|
||||
,('customer v1ds other',6)
|
||||
,('customer v1ds vol' ,2)
|
||||
,('market exact' ,4)
|
||||
,('market v0ds other' ,9)
|
||||
,('market v0ds vol' ,5)
|
||||
,('market v1ds other' ,8)
|
||||
) x (flag,prefer)
|
||||
LEFT OUTER JOIN rel ON
|
||||
rel.flag = CASE source
|
||||
WHEN 'cust' THEN
|
||||
CASE WHEN v1ds IS NOT NULL THEN
|
||||
CASE WHEN v1ds_match THEN 'customer exact' ELSE
|
||||
CASE WHEN rn = 1 THEN 'customer v1ds vol' ELSE 'customer v1ds other' END
|
||||
END
|
||||
ELSE
|
||||
CASE WHEN rn = 1 THEN 'customer v0ds vol' ELSE 'customer v0ds other' END
|
||||
END
|
||||
ELSE
|
||||
CASE WHEN v1ds IS NOT NULL THEN
|
||||
CASE WHEN v1ds_match THEN 'market exact' ELSE
|
||||
CASE WHEN rn = 1 THEN 'market v1ds vol' ELSE 'market v1ds other' END
|
||||
END
|
||||
ELSE
|
||||
CASE WHEN rn = 1 THEN 'market v0ds vol' ELSE 'market v0ds other' END
|
||||
END
|
||||
END
|
||||
)
|
||||
,rel_sort AS (
|
||||
SELECT
|
||||
@ -133,21 +153,21 @@ FROM
|
||||
,'last_season' ,last_season
|
||||
,'last_price' ,last_price
|
||||
,'ds' ,COALESCE(v1ds,v0ds)
|
||||
,'rank' ,row_number() OVER (PARTITION BY flag.source ORDER BY rel.prefer ASC)
|
||||
,'rank' ,rnk
|
||||
,'pricinghistory' ,season
|
||||
)
|
||||
)
|
||||
) doc
|
||||
,row_number() OVER (PARTITION BY flag.source ORDER BY rel.prefer ASC) rnk
|
||||
,rnk
|
||||
,season
|
||||
FROM
|
||||
flag
|
||||
LEFT OUTER JOIN rel ON
|
||||
rel.flag = flag.relevance
|
||||
WHERE
|
||||
relevance ~ 'vol|exact'
|
||||
)
|
||||
--SELECT rnk, jsonb_pretty(doc) doc, jsonb_pretty(season) season FROM rel_sort
|
||||
--SELECT jsonb_pretty(jsonb_agg(doc)) FROM rel_sort
|
||||
--SELECT jsonb_pretty(jsonb_obj_aggc(doc)) FROM rel_sort--INTO _result FROM rel_sort WHERE rnk = 1;
|
||||
SELECT * FROM rel_sort;
|
||||
--SELECT * FROM rel_sort;
|
||||
SELECT * FROM flag
|
||||
--SELECT jsonb_obj_aggc(doc) FROM rel_sort WHERE rnk = 1;
|
||||
|
69
sql/live_quote_nohist.pg.sql
Normal file
69
sql/live_quote_nohist.pg.sql
Normal file
@ -0,0 +1,69 @@
|
||||
DROP TABLE IF EXISTS rlarp.live_quotes_nohist;
|
||||
|
||||
CREATE TABLE rlarp.live_quotes_nohist AS
|
||||
WITH
|
||||
lq AS MATERIALIZED (
|
||||
SELECT
|
||||
lq.*
|
||||
,substring(lq.part,1,8) mold
|
||||
FROM
|
||||
pricequote.live_quotes lq
|
||||
)
|
||||
,lqg AS (
|
||||
SELECT
|
||||
lq.*
|
||||
,pricing->'product'->>'mold' part_group
|
||||
,substring(pricing->'customer'->>'chan',1,1) qchan
|
||||
,pricing->'customer'->>'cust' qcust
|
||||
,pricing->'product'->>'itemrel' item_fit
|
||||
,(pricing->'product'->>'pltq')::numeric pltq
|
||||
,(pricing->'guidance'->'finalPrice'->>'Price')::numeric guidance
|
||||
,pricing->'guidance'->'finalPrice'->>'Reason' reason
|
||||
,(pricing->'product'->>'cstd_usd_ina')::numeric fstd_usd
|
||||
,(pricing->'guidance'->>'ltp')::numeric ltp
|
||||
,(pricing->'guidance'->>'optimization')::numeric optimization
|
||||
,(pricing->'guidance'->>'inflationFactor')::numeric inflation
|
||||
,jsonb_pretty(pricing) pricing
|
||||
FROM
|
||||
lq
|
||||
LEFT JOIN LATERAL rlarp.guidance_r1(
|
||||
rlarp.get_guidance_dseg(lq.billto,lq.shipto,substring(lq.part,1,8),lq.v1ds,lq.units_each,2024)
|
||||
) pricing ON TRUE
|
||||
WHERE
|
||||
TRUE
|
||||
--lq.qstat ~ 'Submitted'
|
||||
)
|
||||
--,hist AS (
|
||||
-- SELECT
|
||||
-- g.*
|
||||
-- ,gset.chan
|
||||
-- --,gset.mold moldh
|
||||
-- ,gset.v1ds v1dsh
|
||||
-- ,gset.cust
|
||||
-- ,gset.vers
|
||||
-- ,je.k
|
||||
-- ,seas.*
|
||||
-- FROM
|
||||
-- lqg g
|
||||
-- LEFT OUTER JOIN rlarp.price_pool_dev p ON
|
||||
-- p.gset @> jsonb_build_object('mold',g.part_group)
|
||||
-- AND p.gset ? 'cust'
|
||||
-- AND p.gset ? 'v1ds'
|
||||
-- LEFT JOIN LATERAL jsonb_to_record(p.gset) AS gset(
|
||||
-- chan text
|
||||
-- ,mold text
|
||||
-- ,v1ds text
|
||||
-- ,v0ds text
|
||||
-- ,cust text
|
||||
-- ,vers text
|
||||
-- --,nurs text
|
||||
-- --,ghse text
|
||||
-- ) ON TRUE
|
||||
-- LEFT JOIN LATERAL jsonb_each(p.season) je(k,v) on true
|
||||
-- LEFT JOIN Lateral jsonb_to_record(je.v) as seas(
|
||||
-- units numeric
|
||||
-- ,sales_usd numeric
|
||||
-- ,price_usd numeric
|
||||
-- ) ON TRUE
|
||||
--)
|
||||
SELECT * FROM lqg;
|
70
sql/livequotes.pg.sql
Normal file
70
sql/livequotes.pg.sql
Normal file
@ -0,0 +1,70 @@
|
||||
set work_mem TO '4GB';
|
||||
|
||||
DROP VIEW IF EXISTS rlarp.live_quotes_review;
|
||||
CREATE VIEW rlarp.live_quotes_review AS
|
||||
WITH
|
||||
lq AS MATERIALIZED (
|
||||
SELECT
|
||||
lq.*
|
||||
,substring(lq.part,1,8) mold
|
||||
FROM
|
||||
pricequote.live_quotes lq
|
||||
)
|
||||
,lqg AS (
|
||||
SELECT
|
||||
lq.*
|
||||
,pricing->'product'->>'mold' part_group
|
||||
,substring(pricing->'customer'->>'chan',1,1) qchan
|
||||
,pricing->'customer'->>'cust' qcust
|
||||
,pricing->'product'->>'itemrel' item_fit
|
||||
,(pricing->'product'->>'pltq')::numeric pltq
|
||||
,(pricing->'guidance'->'finalPrice'->>'Price')::numeric guidance
|
||||
,pricing->'guidance'->'finalPrice'->>'Reason' reason
|
||||
,(pricing->'product'->>'cstd_usd_ina')::numeric cstd_usd
|
||||
,(pricing->'product'->>'fstd_usd_ina')::numeric fstd_usd
|
||||
,(pricing->'guidance'->>'ltp')::numeric ltp
|
||||
,(pricing->'guidance'->>'optimization')::numeric optimization
|
||||
,(pricing->'guidance'->>'inflationFactor')::numeric inflation
|
||||
,jsonb_pretty(pricing) pricing
|
||||
FROM
|
||||
lq
|
||||
LEFT JOIN LATERAL rlarp.guidance_r1(
|
||||
rlarp.get_guidance_dseg(lq.billto,lq.shipto,substring(lq.part,1,8),lq.v1ds,lq.units_each,2024)
|
||||
) pricing ON TRUE
|
||||
WHERE
|
||||
lq.qstat ~ 'Submitted'
|
||||
)
|
||||
,hist AS (
|
||||
SELECT
|
||||
g.*
|
||||
,gset.chan
|
||||
--,gset.mold moldh
|
||||
,gset.v1ds v1dsh
|
||||
,gset.cust
|
||||
,gset.vers
|
||||
,je.k
|
||||
,seas.*
|
||||
FROM
|
||||
lqg g
|
||||
LEFT OUTER JOIN rlarp.price_pool_dev p ON
|
||||
p.gset @> jsonb_build_object('mold',g.part_group)
|
||||
AND p.gset ? 'cust'
|
||||
AND p.gset ? 'v1ds'
|
||||
LEFT JOIN LATERAL jsonb_to_record(p.gset) AS gset(
|
||||
chan text
|
||||
,mold text
|
||||
,v1ds text
|
||||
,v0ds text
|
||||
,cust text
|
||||
,vers text
|
||||
--,nurs text
|
||||
--,ghse text
|
||||
) ON TRUE
|
||||
LEFT JOIN LATERAL jsonb_each(p.season) je(k,v) on true
|
||||
LEFT JOIN Lateral jsonb_to_record(je.v) as seas(
|
||||
units numeric
|
||||
,sales_usd numeric
|
||||
,price_usd numeric
|
||||
) ON TRUE
|
||||
)
|
||||
SELECT * FROM hist
|
59
sql/livequotes_dev.pg.sql
Normal file
59
sql/livequotes_dev.pg.sql
Normal file
@ -0,0 +1,59 @@
|
||||
WITH
|
||||
lq AS MATERIALIZED (
|
||||
SELECT
|
||||
lq.*
|
||||
,substring(lq.part,1,8) mold
|
||||
FROM
|
||||
pricequote.live_quotes lq
|
||||
)
|
||||
,lqg AS (
|
||||
SELECT
|
||||
lq.*
|
||||
,m.part_group
|
||||
,(pricing->'guidance'->'finalPrice'->>'Price')::numeric guidance
|
||||
,pricing->'guidance'->'finalPrice'->>'Reason' reason
|
||||
,jsonb_pretty(pricing) pricing
|
||||
FROM
|
||||
lq
|
||||
JOIN LATERAL rlarp.guidance_r1(
|
||||
rlarp.get_guidance_dseg(lq.billto,lq.shipto,substring(lq.part,1,8),lq.v1ds,lq.units_each,2024)
|
||||
) pricing ON TRUE
|
||||
LEFT OUTER JOIN rlarp.molds m ON
|
||||
m.stlc = lq.mold
|
||||
WHERE
|
||||
lq.qstat ~ 'Submitted'
|
||||
)
|
||||
,hist AS (
|
||||
SELECT
|
||||
g.*
|
||||
,gset.chan
|
||||
--,gset.mold moldh
|
||||
,gset.v1ds v1dsh
|
||||
,gset.cust
|
||||
,gset.vers
|
||||
,je.k
|
||||
,seas.*
|
||||
FROM
|
||||
lqg g
|
||||
LEFT OUTER JOIN rlarp.price_pool_dev p ON
|
||||
p.gset @> jsonb_build_object('mold',g.part_group)
|
||||
AND p.gset ? 'cust'
|
||||
AND p.gset ? 'v1ds'
|
||||
LEFT JOIN LATERAL jsonb_to_record(p.gset) AS gset(
|
||||
chan text
|
||||
,mold text
|
||||
,v1ds text
|
||||
,v0ds text
|
||||
,cust text
|
||||
,vers text
|
||||
--,nurs text
|
||||
--,ghse text
|
||||
) ON TRUE
|
||||
LEFT JOIN LATERAL jsonb_each(p.season) je(k,v) on true
|
||||
LEFT JOIN Lateral jsonb_to_record(je.v) as seas(
|
||||
units numeric
|
||||
,sales_usd numeric
|
||||
,price_usd numeric
|
||||
) ON TRUE
|
||||
)
|
||||
SELECT * FROM hist WHERE qid = 73059
|
@ -1,9 +1,10 @@
|
||||
--CREATE OR REPLACE PROCEDURE rlarp.price_pool()
|
||||
--LANGUAGE plpgsql AS
|
||||
--$func$
|
||||
BEGIN;
|
||||
DROP TABLE IF EXISTS rlarp.price_pool_dev;
|
||||
CREATE TABLE IF NOT EXISTS rlarp.price_pool_dev AS (
|
||||
--BEGIN;
|
||||
DROP MATERIALIZED VIEW IF EXISTS rlarp.price_pool_dev CASCADE;
|
||||
--CREATE TABLE IF NOT EXISTS rlarp.price_pool_dev AS (
|
||||
CREATE MATERIALIZED VIEW rlarp.price_pool_dev AS (
|
||||
WITH
|
||||
agg AS (
|
||||
SELECT
|
||||
@ -75,6 +76,76 @@ CREATE TABLE IF NOT EXISTS rlarp.price_pool_dev AS (
|
||||
HAVING
|
||||
round(sum(o.qty),0) > 0
|
||||
AND round(sum(o.sales_usd)/sum(o.qty),5) > 0
|
||||
UNION ALL
|
||||
SELECT
|
||||
o.customer
|
||||
,substring(o.version,1,1) version
|
||||
,o.chanwide
|
||||
,o.nursery_region
|
||||
,c.greenhouse_region
|
||||
,m.part_group baseitem
|
||||
,m.majg
|
||||
,m.assc
|
||||
,i.coltier
|
||||
,'v1:' || rtrim(COALESCE(i.coltier, ''))|| '.' || rtrim(substring(COALESCE(i.branding, ''), 1, 1))|| '.' || rtrim(COALESCE(i.uomp, ''))|| '.' || rtrim(COALESCE(i.suffix, ''))|| '.' || rtrim(COALESCE(i.accs_ps, '')) v1dataseg
|
||||
,_ds.dataseg v0dataseg
|
||||
,0 oseas
|
||||
,round(sum(o.qty),0) units
|
||||
,round(sum(o.sales_usd),0) sales_usd
|
||||
,round(sum(COALESCE(tp.target_price,tq.target_price) * o.qty),2) target_price
|
||||
,count(DISTINCT o.ordnum) ordcount
|
||||
FROM
|
||||
rlarp.osm_stack o
|
||||
INNER JOIN "CMS.CUSLG".itemm i ON
|
||||
i.item = o.part
|
||||
LEFT OUTER JOIN rlarp.molds m ON
|
||||
m.stlc = i.stlc
|
||||
LEFT OUTER JOIN _ds ON
|
||||
_ds.colgrp = o.colgrp
|
||||
AND _ds.brand = substring(i.branding,1,1)
|
||||
LEFT OUTER JOIN pricequote.market_setavgprice tp ON
|
||||
tp.season = (SELECT ssyr FROM rlarp.gld where drange @> current_date)
|
||||
AND tp.country = 'ALL'
|
||||
AND tp.geo = 'ALL'
|
||||
AND tp.region = 'ALL'
|
||||
AND tp.mold = i.stlc
|
||||
AND tp.chan = 'DISTRIB DROP SHIP'
|
||||
AND tp.data_segment = 'v1:' || rtrim(COALESCE(i.coltier, ''))|| '.' || rtrim(substring(COALESCE(i.branding, ''), 1, 1))|| '.' || rtrim(COALESCE(i.uomp, ''))|| '.' || rtrim(COALESCE(i.suffix, ''))|| '.' || rtrim(COALESCE(i.accs_ps, ''))
|
||||
LEFT OUTER JOIN pricequote.market_setavgprice tq ON
|
||||
tq.season = (SELECT ssyr FROM rlarp.gld where drange @> current_date)
|
||||
AND tq.country = 'ALL'
|
||||
AND tq.geo = 'ALL'
|
||||
AND tq.region = 'ALL'
|
||||
AND tq.mold = i.stlc
|
||||
AND tq.chan = 'DISTRIB DROP SHIP'
|
||||
AND tq.data_segment = _ds.dataseg
|
||||
LEFT OUTER JOIN rlarp.cust c ON
|
||||
c.code = CASE o.chan WHEN 'DIR' THEN o.bill_cust ELSE o.ship_cust END
|
||||
WHERE
|
||||
o.version IN ('Actual','Quotes')
|
||||
AND o.odate >= current_date - '4 months'::interval
|
||||
AND o.dsm <> 'PW'
|
||||
--AND o.part like 'SQL035%'
|
||||
--AND o.calc_status <> 'CANCELED'
|
||||
--AND o.fs_line = '41010'
|
||||
--AND o.dsm <> 'PW'
|
||||
--AND i.coltier <> 'C'
|
||||
GROUP BY
|
||||
o.customer
|
||||
,substring(o.version,1,1)
|
||||
,o.chanwide
|
||||
,o.nursery_region
|
||||
,c.greenhouse_region
|
||||
,m.part_group
|
||||
,m.majg
|
||||
,m.assc
|
||||
,i.coltier
|
||||
,'v1:' || rtrim(COALESCE(i.coltier, ''))|| '.' || rtrim(substring(COALESCE(i.branding, ''), 1, 1))|| '.' || rtrim(COALESCE(i.uomp, ''))|| '.' || rtrim(COALESCE(i.suffix, ''))|| '.' || rtrim(COALESCE(i.accs_ps, ''))
|
||||
,_ds.dataseg
|
||||
,o.oseas
|
||||
HAVING
|
||||
round(sum(o.qty),0) > 0
|
||||
AND round(sum(o.sales_usd)/sum(o.qty),5) > 0
|
||||
)
|
||||
,gsets AS (
|
||||
SELECT
|
||||
@ -171,4 +242,4 @@ CREATE TABLE IF NOT EXISTS rlarp.price_pool_dev AS (
|
||||
) WITH DATA;
|
||||
|
||||
create index ppd_gset on rlarp.price_pool_dev using gin (gset);
|
||||
END;
|
||||
--END;
|
||||
|
Loading…
Reference in New Issue
Block a user