Compare commits
No commits in common. "master" and "javascript_relevance_logic" have entirely different histories.
master
...
javascript
21
api.ts
21
api.ts
@ -34,35 +34,18 @@ const query = await Deno.readTextFile("sql/get.pg.sql");
|
|||||||
const query_dseg = await Deno.readTextFile("sql/get_dseg.pg.sql");
|
const query_dseg = await Deno.readTextFile("sql/get_dseg.pg.sql");
|
||||||
|
|
||||||
// exact scenario for existing codes
|
// exact scenario for existing codes
|
||||||
router.get('/code/:billcode/:shipcode/:partcode/:qty', async (ctx) => {
|
router.get('/code_price/:billcode/:shipcode/:partcode/:qty', async (ctx) => {
|
||||||
const { billcode, shipcode, partcode, qty } = ctx.params;
|
const { billcode, shipcode, partcode, qty } = ctx.params;
|
||||||
const result = await client.queryObject({args: [billcode, shipcode, partcode, qty], text: query} );
|
const result = await client.queryObject({args: [billcode, shipcode, partcode, qty], text: query} );
|
||||||
ctx.response.body = apply_guidance(result.rows[0]["doc"]);
|
ctx.response.body = apply_guidance(result.rows[0]["doc"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
// specific customres codes but generic style code and data segment to accomodate custom colors and branding
|
|
||||||
router.get('/dseg/: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} );
|
|
||||||
ctx.response.body = apply_guidance(result.rows[0]["doc"]);
|
|
||||||
});
|
|
||||||
|
|
||||||
// specific customres codes but generic style code and data segment to accomodate custom colors and branding
|
// specific customres codes but generic style code and data segment to accomodate custom colors and branding
|
||||||
router.get('/dseg_price/:billcode/:shipcode/:stlc/:dseg/:qty', async (ctx) => {
|
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"]);
|
ctx.response.body = apply_guidance(result.rows[0]["doc"]);
|
||||||
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());
|
app.use(router.routes());
|
||||||
app.use(router.allowedMethods());
|
app.use(router.allowedMethods());
|
||||||
|
|
||||||
|
@ -1,165 +1,167 @@
|
|||||||
export function apply_guidance(doc: any) {
|
export function apply_guidance(doc: any) {
|
||||||
|
let mostRelevantMarketPrice = null;
|
||||||
|
let mostRelevantMarketPriceEarly = null;
|
||||||
|
let mostRelevantMarketKey = null;
|
||||||
|
let mostRelevantMarketSeason = null;
|
||||||
|
let mostRelevantMarketSeasonEarly = null;
|
||||||
|
let highestMarketRelevanceLevel = 0;
|
||||||
|
let mostRelevantMarketSource = null;
|
||||||
|
|
||||||
function sortObjectKeys(obj) {
|
let mostRelevantCustomerPriceEarly = null;
|
||||||
// If the object is not an actual object or is an array, return it as is
|
let mostRelevantCustomerPriceRecent = null;
|
||||||
if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
|
let mostRelevantCustomerKey = null;
|
||||||
return obj;
|
let mostRelevantCustomerSeasonEarly = null;
|
||||||
}
|
let mostRelevantCustomerSeasonRecent = null;
|
||||||
|
let highestCustomerRelevanceLevel = 0;
|
||||||
|
let mostRelevantCustomerSource = null;
|
||||||
|
|
||||||
// Create a new object and sort the keys
|
// Function to update price and assign relevance indicator
|
||||||
const sortedObj = {};
|
function setAnchors(items, channelFirstChar, v1ds, v0ds, histKey) {
|
||||||
Object.keys(obj).sort().forEach(key => {
|
for (let item of items) {
|
||||||
// Recursively apply the function for nested objects
|
// Update the last_price with the most recent price
|
||||||
sortedObj[key] = sortObjectKeys(obj[key]);
|
const years = Object.keys(item.season).map(Number).filter(year => year >= 2020);
|
||||||
});
|
if (years.length > 0) {
|
||||||
|
const recentYear = Math.max(...years.map(Number));
|
||||||
return sortedObj;
|
const earlyYear = Math.min(...years.map(Number));
|
||||||
}
|
const lastPrice = item.season[recentYear].price_usd;
|
||||||
|
const earlyPrice = item.season[earlyYear].price_usd;
|
||||||
function getAdjValue(number) {
|
item.last_price = lastPrice;
|
||||||
const data = [
|
item.early_price = earlyPrice;
|
||||||
{f: 2.001, t: 1000, snap: 3, adj: 0 },
|
item.last_season = recentYear;
|
||||||
{f: 1.001, t: 2, snap: 2, adj: 0 },
|
item.early_season = earlyYear;
|
||||||
{f: 0.1, t: 1, snap: 1, adj: 0 },
|
} else {
|
||||||
{f: 0, t: 0.1, snap: 0, adj: 0 },
|
item.last_price = null; // or some default value as appropriate
|
||||||
{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];
|
// Initialize relevance as numeric value
|
||||||
// Check if the current price is lower than the found so far
|
let marketRelevance = 0; // Assume 0 is 'not relevant'
|
||||||
if (cprice && cprice < Price) {
|
let customerRelevance = 0; // Assume 0 is 'not relevant'
|
||||||
Price = cprice;
|
|
||||||
Reason = creason;
|
|
||||||
Source = csource;
|
// Check if the first character of the item's channel matches the first character of the document's channel
|
||||||
Snapped = csnap;
|
if (item.chan.charAt(0) === channelFirstChar) {
|
||||||
|
marketRelevance = 1; // 'relevant'
|
||||||
|
|
||||||
|
|
||||||
|
// Further refine relevance based on v1ds and v0ds
|
||||||
|
if (item.v1ds === v1ds) {
|
||||||
|
marketRelevance = 2; // 'most relevant' because v1ds matches
|
||||||
|
|
||||||
|
// Check for customer relevance if 'cust' key exists
|
||||||
|
customerRelevance = item.cust ? 3 : 0;
|
||||||
|
} else if (item.v0ds === v0ds) {
|
||||||
|
marketRelevance = marketRelevance === 2 ? 2 : 1; // Keep relevance as is if v1ds was matched, otherwise it's just 'relevant'
|
||||||
|
customerRelevance = item.cust ? 2 : 0;
|
||||||
|
} else if (item.cust) {
|
||||||
|
customerRelevance = item.v1ds ? 2 : item.v0ds ? 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assign the calculated relevance to the item
|
||||||
|
item.marketRelevance = marketRelevance;
|
||||||
|
item.customerRelevance = customerRelevance;
|
||||||
|
|
||||||
|
// Update the most relevant market price if this item's relevance is higher and it doesn't have a 'cust' key
|
||||||
|
if (marketRelevance > highestMarketRelevanceLevel) {
|
||||||
|
highestMarketRelevanceLevel = marketRelevance;
|
||||||
|
mostRelevantMarketPrice = item.last_price;
|
||||||
|
mostRelevantMarketPriceEarly = item.early_price;
|
||||||
|
mostRelevantMarketKey = histKey;
|
||||||
|
mostRelevantMarketSource = item;
|
||||||
|
delete mostRelevantMarketSource.season;
|
||||||
|
mostRelevantMarketSeason = item.last_season; // Assuming 'season' is the key where the season info is stored
|
||||||
|
mostRelevantMarketSeasonEarly = item.early_season;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the most relevant customer price if this item's relevance is higher and it has a 'cust' key
|
||||||
|
if (customerRelevance > highestCustomerRelevanceLevel) {
|
||||||
|
highestCustomerRelevanceLevel = customerRelevance;
|
||||||
|
mostRelevantCustomerPriceRecent = item.last_price;
|
||||||
|
mostRelevantCustomerPriceEarly = item.early_price;
|
||||||
|
mostRelevantCustomerKey = histKey;
|
||||||
|
mostRelevantCustomerSource = item;
|
||||||
|
delete mostRelevantCustomerSource.season;
|
||||||
|
mostRelevantCustomerSeasonRecent = item.last_season; // Assuming 'season' is the key where the season info is stored
|
||||||
|
mostRelevantCustomerSeasonEarly = item.early_season; // Assuming 'season' is the key where the season info is stored
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return {Reason, Price, Source, Snapped};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function ceiling(value, significance) {
|
//// Iterate over each key in the "hist" object
|
||||||
return Math.ceil(value / significance) * significance;
|
//for (let key of Object.keys(doc.hist)) {
|
||||||
}
|
// // Update price and relevance for each item in the current key
|
||||||
|
// setAnchors(doc.hist[key], doc.chan[0], doc.v1ds, doc.v0ds, key);
|
||||||
|
//}
|
||||||
|
|
||||||
function r5(value) {
|
//// Assign the most relevant market price and key to the top level of the document
|
||||||
return Number(value.toFixed(5));
|
//if (mostRelevantMarketPrice !== null) {
|
||||||
}
|
// doc.mostRelevantMarketPriceInfo = {
|
||||||
|
// price: mostRelevantMarketPrice,
|
||||||
|
// price_early: mostRelevantMarketPriceEarly,
|
||||||
|
// source: mostRelevantMarketSource,
|
||||||
|
// season: mostRelevantMarketSeason,
|
||||||
|
// season_early: mostRelevantMarketSeasonEarly,
|
||||||
|
// relevance: highestMarketRelevanceLevel
|
||||||
|
// };
|
||||||
|
//}
|
||||||
|
|
||||||
function pp(value) {
|
//// Assign the most relevant customer price and key to the top level of the document
|
||||||
// Multiplies by 1000 and rounds to the nearest 2 decimals
|
//if (mostRelevantCustomerPriceRecent !== null) {
|
||||||
var result = Math.round(value * 1000 * 100) / 100;
|
// doc.mostRelevantCustomerPriceInfo = {
|
||||||
|
// price: mostRelevantCustomerPriceRecent,
|
||||||
|
// price_early: mostRelevantCustomerPriceEarly,
|
||||||
|
// source: mostRelevantCustomerSource,
|
||||||
|
// season: mostRelevantCustomerSeasonRecent,
|
||||||
|
// season_early: mostRelevantCustomerSeasonEarly,
|
||||||
|
// relevance: highestCustomerRelevanceLevel
|
||||||
|
// };
|
||||||
|
//}
|
||||||
|
|
||||||
// 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;
|
const targetPrice = doc.v1tp ?? doc.v0tp;
|
||||||
|
const earlyPrice = doc.hist?.cust?.early_price;
|
||||||
let custPrice = r5(bridgedPrice * (1 + custAdder));
|
let anchorPrice = null;
|
||||||
let custSeason = earlyCustSeason;
|
let anchorSource = null;
|
||||||
let custReason = bridgePremium
|
let bridgePremium = doc.bridgePremium ?? 1.00000;
|
||||||
? `${custSeason} (similar ${altHist} price ${pp(earlyCustPrice)} x ${bridgePremium} = ${pp(bridgedPrice)})${custAddReason}`
|
if (!targetPrice) {
|
||||||
: `${custSeason} price ${pp(bridgedPrice)}${custAddReason}`;
|
anchorSource = "No target pricing setup";
|
||||||
let markPrice = r5(earlyMarkPrice * (1 + markAdder));
|
doc.finalReason = "No target pricing setup";
|
||||||
let markReason = `${earlyMarkSeason} ASP ${pp(earlyMarkPrice)}${markAddReason}`;
|
} else {
|
||||||
let targPrice = targetPrice ? r5(targetPrice * (1 + markAdder)) : null;
|
// Determine the anchor price and source
|
||||||
let targReason = `Target price ${pp(targetPrice)}${markAddReason}`;
|
if (earlyPrice) {
|
||||||
let listPrice = listUSD;
|
// translate alternate product history to current product quoted
|
||||||
let listReason = fxrate === 1 ? `list ${pp(list)}` : `list ${pp(list)} CAD ${pp(listUSD)} USD`;
|
anchorPrice = Number((earlyPrice * bridgePremium).toFixed(5));
|
||||||
|
// after the early price is translated see if target is still less
|
||||||
|
if (targetPrice < anchorPrice) {
|
||||||
|
anchorSource = `Target Price ${targetPrice}`;
|
||||||
|
anchorPrice = targetPrice;
|
||||||
|
} else {
|
||||||
|
anchorSource = doc.hist.cust.early_season + ' Similar (' + doc.hist.cust.ds + ') Customer Price ' + earlyPrice + ' x ' + doc.bridgePremium + ' = ' + anchorPrice;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
anchorPrice = targetPrice;
|
||||||
|
anchorSource = `Target Price ${targetPrice}`;
|
||||||
|
}
|
||||||
|
|
||||||
let prices = {
|
const inflation = Math.max(...Object.keys(doc.iidx).map(Number));
|
||||||
cust: [custPrice, custReason, "cust", r5(ceiling(custPrice,snap))],
|
const inflationFactor = doc.iidx[inflation] + 1;
|
||||||
mark: [markPrice, markReason, "mark", r5(ceiling(markPrice,snap))],
|
var calcPrice = parseFloat((anchorPrice * inflationFactor).toFixed(5));
|
||||||
targ: [targPrice, targReason, "targ", r5(ceiling(targPrice,snap))],
|
let finalReason = "";
|
||||||
list: [listPrice, listReason, "list", r5(ceiling(listPrice,snap))]
|
if (calcPrice >= doc.list && doc.list) {
|
||||||
|
doc.calcCeiling = "Cap At List";
|
||||||
|
doc.finalPrice = doc.list;
|
||||||
|
finalReason = `${anchorSource} x ${inflationFactor} = ${calcPrice} but cap at list ${doc.list}`;
|
||||||
|
} else {
|
||||||
|
doc.finalPrice = calcPrice;
|
||||||
|
finalReason = `${anchorSource} x ${inflationFactor} = ${calcPrice}`;
|
||||||
|
}
|
||||||
|
doc.anchorPrice = anchorPrice;
|
||||||
|
doc.anchorSource = anchorSource;
|
||||||
|
doc.inflationFactor = inflationFactor;
|
||||||
|
doc.finalReason = finalReason;
|
||||||
|
doc.bridgePremium = bridgePremium;
|
||||||
|
doc.targetPrice = targetPrice;
|
||||||
}
|
}
|
||||||
|
|
||||||
let finalPrice = lowestPrice(prices);
|
return doc;
|
||||||
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;
|
|
||||||
return sortObjectKeys(doc);
|
|
||||||
}
|
}
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
|
|
||||||
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;
|
|
118
set_anchors.ts
118
set_anchors.ts
@ -1,118 +0,0 @@
|
|||||||
|
|
||||||
let mostRelevantMarketPrice = null;
|
|
||||||
let mostRelevantMarketPriceEarly = null;
|
|
||||||
let mostRelevantMarketKey = null;
|
|
||||||
let mostRelevantMarketSeason = null;
|
|
||||||
let mostRelevantMarketSeasonEarly = null;
|
|
||||||
let highestMarketRelevanceLevel = 0;
|
|
||||||
let mostRelevantMarketSource = null;
|
|
||||||
|
|
||||||
let mostRelevantCustomerPriceEarly = null;
|
|
||||||
let mostRelevantCustomerPriceRecent = null;
|
|
||||||
let mostRelevantCustomerKey = null;
|
|
||||||
let mostRelevantCustomerSeasonEarly = null;
|
|
||||||
let mostRelevantCustomerSeasonRecent = null;
|
|
||||||
let highestCustomerRelevanceLevel = 0;
|
|
||||||
let mostRelevantCustomerSource = null;
|
|
||||||
|
|
||||||
// Function to update price and assign relevance indicator
|
|
||||||
function setAnchors(items, channelFirstChar, v1ds, v0ds, histKey) {
|
|
||||||
for (let item of items) {
|
|
||||||
// Update the last_price with the most recent price
|
|
||||||
const years = Object.keys(item.season).map(Number).filter(year => year >= 2020);
|
|
||||||
if (years.length > 0) {
|
|
||||||
const recentYear = Math.max(...years.map(Number));
|
|
||||||
const earlyYear = Math.min(...years.map(Number));
|
|
||||||
const lastPrice = item.season[recentYear].price_usd;
|
|
||||||
const earlyPrice = item.season[earlyYear].price_usd;
|
|
||||||
item.last_price = lastPrice;
|
|
||||||
item.early_price = earlyPrice;
|
|
||||||
item.last_season = recentYear;
|
|
||||||
item.early_season = earlyYear;
|
|
||||||
} else {
|
|
||||||
item.last_price = null; // or some default value as appropriate
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize relevance as numeric value
|
|
||||||
let marketRelevance = 0; // Assume 0 is 'not relevant'
|
|
||||||
let customerRelevance = 0; // Assume 0 is 'not relevant'
|
|
||||||
|
|
||||||
|
|
||||||
// Check if the first character of the item's channel matches the first character of the document's channel
|
|
||||||
if (item.chan.charAt(0) === channelFirstChar) {
|
|
||||||
marketRelevance = 1; // 'relevant'
|
|
||||||
|
|
||||||
|
|
||||||
// Further refine relevance based on v1ds and v0ds
|
|
||||||
if (item.v1ds === v1ds) {
|
|
||||||
marketRelevance = 2; // 'most relevant' because v1ds matches
|
|
||||||
|
|
||||||
// Check for customer relevance if 'cust' key exists
|
|
||||||
customerRelevance = item.cust ? 3 : 0;
|
|
||||||
} else if (item.v0ds === v0ds) {
|
|
||||||
marketRelevance = marketRelevance === 2 ? 2 : 1; // Keep relevance as is if v1ds was matched, otherwise it's just 'relevant'
|
|
||||||
customerRelevance = item.cust ? 2 : 0;
|
|
||||||
} else if (item.cust) {
|
|
||||||
customerRelevance = item.v1ds ? 2 : item.v0ds ? 1 : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assign the calculated relevance to the item
|
|
||||||
item.marketRelevance = marketRelevance;
|
|
||||||
item.customerRelevance = customerRelevance;
|
|
||||||
|
|
||||||
// Update the most relevant market price if this item's relevance is higher and it doesn't have a 'cust' key
|
|
||||||
if (marketRelevance > highestMarketRelevanceLevel) {
|
|
||||||
highestMarketRelevanceLevel = marketRelevance;
|
|
||||||
mostRelevantMarketPrice = item.last_price;
|
|
||||||
mostRelevantMarketPriceEarly = item.early_price;
|
|
||||||
mostRelevantMarketKey = histKey;
|
|
||||||
mostRelevantMarketSource = item;
|
|
||||||
delete mostRelevantMarketSource.season;
|
|
||||||
mostRelevantMarketSeason = item.last_season; // Assuming 'season' is the key where the season info is stored
|
|
||||||
mostRelevantMarketSeasonEarly = item.early_season;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the most relevant customer price if this item's relevance is higher and it has a 'cust' key
|
|
||||||
if (customerRelevance > highestCustomerRelevanceLevel) {
|
|
||||||
highestCustomerRelevanceLevel = customerRelevance;
|
|
||||||
mostRelevantCustomerPriceRecent = item.last_price;
|
|
||||||
mostRelevantCustomerPriceEarly = item.early_price;
|
|
||||||
mostRelevantCustomerKey = histKey;
|
|
||||||
mostRelevantCustomerSource = item;
|
|
||||||
delete mostRelevantCustomerSource.season;
|
|
||||||
mostRelevantCustomerSeasonRecent = item.last_season; // Assuming 'season' is the key where the season info is stored
|
|
||||||
mostRelevantCustomerSeasonEarly = item.early_season; // Assuming 'season' is the key where the season info is stored
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//// Iterate over each key in the "hist" object
|
|
||||||
//for (let key of Object.keys(doc.hist)) {
|
|
||||||
// // Update price and relevance for each item in the current key
|
|
||||||
// setAnchors(doc.hist[key], doc.chan[0], doc.v1ds, doc.v0ds, key);
|
|
||||||
//}
|
|
||||||
|
|
||||||
//// Assign the most relevant market price and key to the top level of the document
|
|
||||||
//if (mostRelevantMarketPrice !== null) {
|
|
||||||
// doc.mostRelevantMarketPriceInfo = {
|
|
||||||
// price: mostRelevantMarketPrice,
|
|
||||||
// price_early: mostRelevantMarketPriceEarly,
|
|
||||||
// source: mostRelevantMarketSource,
|
|
||||||
// season: mostRelevantMarketSeason,
|
|
||||||
// season_early: mostRelevantMarketSeasonEarly,
|
|
||||||
// relevance: highestMarketRelevanceLevel
|
|
||||||
// };
|
|
||||||
//}
|
|
||||||
|
|
||||||
//// Assign the most relevant customer price and key to the top level of the document
|
|
||||||
//if (mostRelevantCustomerPriceRecent !== null) {
|
|
||||||
// doc.mostRelevantCustomerPriceInfo = {
|
|
||||||
// price: mostRelevantCustomerPriceRecent,
|
|
||||||
// price_early: mostRelevantCustomerPriceEarly,
|
|
||||||
// source: mostRelevantCustomerSource,
|
|
||||||
// season: mostRelevantCustomerSeasonRecent,
|
|
||||||
// season_early: mostRelevantCustomerSeasonEarly,
|
|
||||||
// relevance: highestCustomerRelevanceLevel
|
|
||||||
// };
|
|
||||||
//}
|
|
@ -1,152 +0,0 @@
|
|||||||
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$;
|
|
@ -1,33 +0,0 @@
|
|||||||
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'];
|
|
@ -1,79 +0,0 @@
|
|||||||
----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
|
INTO
|
||||||
_mold,_stlc,_v1ds , _v0ds, _iidx
|
_mold,_stlc,_v1ds , _v0ds, _iidx
|
||||||
FROM
|
FROM
|
||||||
"CMS.CUSLG".itemm i
|
"CMS.CUSLG".itemmv i
|
||||||
INNER JOIN rlarp.molds m ON
|
INNER JOIN rlarp.molds m ON
|
||||||
m.stlc = i.stlc
|
m.stlc = i.stlc
|
||||||
WHERE
|
WHERE
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
DROP FUNCTION rlarp.get_guidance_dseg CASCADE;
|
DROP FUNCTION rlarp.get_guidance_dseg;
|
||||||
CREATE OR REPLACE FUNCTION rlarp.get_guidance_dseg(_bill text, _ship text, _stlc text, _dseg text, _qty numeric, _seas int)
|
CREATE OR REPLACE FUNCTION rlarp.get_guidance_dseg(_bill text, _ship text, _stlc text, _dseg text, _qty numeric, _seas int)
|
||||||
RETURNS jsonb
|
RETURNS jsonb
|
||||||
LANGUAGE plpgsql AS
|
LANGUAGE plpgsql AS
|
||||||
@ -10,34 +10,23 @@ DECLARE
|
|||||||
--_ship text;
|
--_ship text;
|
||||||
--_qty numeric;
|
--_qty numeric;
|
||||||
--_seas int;
|
--_seas int;
|
||||||
_prem jsonb;
|
_prem jsonb;
|
||||||
_mold text;
|
_mold text;
|
||||||
_item text;
|
_item text;
|
||||||
_unti text;
|
_cust text;
|
||||||
_pltq numeric;
|
_curr text;
|
||||||
_cstd numeric;
|
_rate numeric;
|
||||||
_cstdina numeric;
|
_v1ds text;
|
||||||
_fstd numeric;
|
_v0ds text;
|
||||||
_fstdina numeric;
|
_v1tp jsonb;
|
||||||
_cust text;
|
_v0tp jsonb;
|
||||||
_curr text;
|
_chan text;
|
||||||
_rate numeric;
|
_regn text;
|
||||||
_v1ds text;
|
_rslt jsonb;
|
||||||
_v0ds text;
|
_targ jsonb;
|
||||||
_v1tp jsonb;
|
_list jsonb;
|
||||||
_v0tp jsonb;
|
_iidx jsonb;
|
||||||
_chan text;
|
_itemr text;
|
||||||
_regn text;
|
|
||||||
_rslt jsonb;
|
|
||||||
_targ jsonb;
|
|
||||||
_list jsonb;
|
|
||||||
_iidx jsonb;
|
|
||||||
_itemr text;
|
|
||||||
_input jsonb;
|
|
||||||
_product jsonb;
|
|
||||||
_customer jsonb;
|
|
||||||
_hist jsonb;
|
|
||||||
_pricing jsonb;
|
|
||||||
|
|
||||||
BEGIN
|
BEGIN
|
||||||
--_item := 'AMK06000G18B054';
|
--_item := 'AMK06000G18B054';
|
||||||
@ -49,141 +38,90 @@ BEGIN
|
|||||||
_v0ds := CASE split_part(substring(_dseg,4,100), '.',1) WHEN 'B' THEN 'BASE' ELSE 'COLOR' END || CASE split_part(substring(_dseg,4,100), '.',2) WHEN 'L' THEN ' LABELED' WHEN 'P' THEN ' PRINTED' ELSE '' END;
|
_v0ds := CASE split_part(substring(_dseg,4,100), '.',1) WHEN 'B' THEN 'BASE' ELSE 'COLOR' END || CASE split_part(substring(_dseg,4,100), '.',2) WHEN 'L' THEN ' LABELED' WHEN 'P' THEN ' PRINTED' ELSE '' END;
|
||||||
_v1ds := _dseg;
|
_v1ds := _dseg;
|
||||||
|
|
||||||
_input := jsonb_build_object(
|
|
||||||
'inputs'
|
|
||||||
,jsonb_build_object(
|
|
||||||
'dseg',_dseg,
|
|
||||||
'v0ds',_v0ds,
|
|
||||||
'v1ds',_v1ds,
|
|
||||||
'bill',_bill,
|
|
||||||
'ship',_ship,
|
|
||||||
'stlc',_stlc,
|
|
||||||
'qty',_qty,
|
|
||||||
'season',_seas
|
|
||||||
));
|
|
||||||
|
|
||||||
----------------base product--------------------------------
|
----------------base product--------------------------------
|
||||||
SELECT
|
SELECT
|
||||||
part_group
|
part_group
|
||||||
,item
|
,item
|
||||||
|
,stlc
|
||||||
,idxk
|
,idxk
|
||||||
,prefer
|
,prefer
|
||||||
,pltq
|
|
||||||
,curstdus
|
|
||||||
,curstdus_ina
|
|
||||||
,futstdus
|
|
||||||
,futstdus_ina
|
|
||||||
INTO
|
INTO
|
||||||
_mold
|
_mold
|
||||||
,_item
|
,_item
|
||||||
|
,_stlc
|
||||||
,_iidx
|
,_iidx
|
||||||
,_itemr
|
,_itemr
|
||||||
,_pltq
|
|
||||||
,_cstd
|
|
||||||
,_cstdina
|
|
||||||
,_fstd
|
|
||||||
,_fstdina
|
|
||||||
FROM
|
FROM
|
||||||
(
|
(
|
||||||
SELECT
|
SELECT
|
||||||
i.partgroup part_group
|
m.part_group
|
||||||
,min(i.item) item
|
,min(i.item) item
|
||||||
,i.stlc
|
,i.stlc
|
||||||
,i.v1ds
|
,i.v1ds
|
||||||
,_ds.dataseg v0ds
|
,i.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
|
,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 _ds.dataseg = _v0ds THEN 1 ELSE 0 END END prefer
|
,CASE WHEN i.v1ds = _v1ds THEN 2 ELSE CASE WHEN i.v0ds = _v0ds THEN 1 ELSE 0 END END prefer
|
||||||
FROM
|
FROM
|
||||||
"CMS.CUSLG".itemm i
|
"CMS.CUSLG".itemmv i
|
||||||
LEFT OUTER JOIN _ds ON
|
INNER JOIN rlarp.molds m ON
|
||||||
_ds.colgrp = i.colgrp
|
m.stlc = i.stlc
|
||||||
AND _ds.brand = SUBSTRING(i.branding,1,1)
|
|
||||||
--INNER JOIN rlarp.molds m ON
|
|
||||||
-- m.stlc = i.stlc
|
|
||||||
WHERE
|
WHERE
|
||||||
i.stlc = _stlc
|
i.stlc = _stlc
|
||||||
GROUP BY
|
GROUP BY
|
||||||
i.partgroup
|
m.part_group
|
||||||
,i.stlc
|
,i.stlc
|
||||||
,i.v1ds
|
,i.v1ds
|
||||||
,_ds.dataseg
|
,i.v0ds
|
||||||
,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))
|
,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 _ds.dataseg = _v0ds THEN 1 ELSE 0 END END
|
,CASE WHEN i.v1ds = _v1ds THEN 2 ELSE CASE WHEN i.v0ds = _v0ds THEN 1 ELSE 0 END END
|
||||||
) best
|
) best
|
||||||
ORDER BY
|
ORDER BY
|
||||||
prefer DESC
|
prefer DESC
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
_product :=
|
_rslt := jsonb_build_object('mold',_mold,'v1ds',_v1ds,'v0ds',_v0ds,'stlc',_stlc,'item',_item,'item rel',_itemr,'desg',_dseg)||_iidx;
|
||||||
jsonb_build_object(
|
RAISE NOTICE 'item data %', _iidx;
|
||||||
'product'
|
|
||||||
,jsonb_build_object(
|
|
||||||
'mold',_mold
|
|
||||||
,'item',_item
|
|
||||||
,'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-------------------------------------
|
----------------channel-------------------------------------
|
||||||
|
|
||||||
SELECT rlarp.get_cust(_bill, _ship) INTO _customer;
|
SELECT rlarp.channel_code(_bill, _ship) INTO _chan;
|
||||||
--_customer := jsonb_build_object('chan',_chan);
|
_rslt := _rslt||jsonb_build_object('chan',_chan);
|
||||||
|
RAISE NOTICE 'chan %', _chan;
|
||||||
|
|
||||||
----------------customer------------------------------------
|
----------------customer------------------------------------
|
||||||
--SELECT dba INTO _cust FROM rlarp.cust WHERE code = CASE WHEN _chan = 'DRP' THEN _ship ELSE _bill END ;
|
SELECT dba INTO _cust FROM rlarp.cust WHERE code = CASE WHEN _chan = 'DRP' THEN _ship ELSE _bill END ;
|
||||||
--SELECT
|
SELECT
|
||||||
-- currency,
|
currency,
|
||||||
-- (SELECT
|
(SELECT
|
||||||
-- x.rate
|
x.rate
|
||||||
-- FROM
|
FROM
|
||||||
-- rlarp.ffcret x
|
rlarp.ffcret x
|
||||||
-- WHERE
|
WHERE
|
||||||
-- x.perd = (select fspr from rlarp.gld where drange @> current_date)
|
x.perd = (select fspr from rlarp.gld where drange @> current_date)
|
||||||
-- AND x.rtyp = 'MA'
|
AND x.rtyp = 'MA'
|
||||||
-- and x.fcur = currency
|
and x.fcur = currency
|
||||||
-- AND x.tcur = 'US'
|
AND x.tcur = 'US'
|
||||||
-- )
|
)
|
||||||
--INTO
|
INTO
|
||||||
-- _curr
|
_curr
|
||||||
-- ,_rate
|
,_rate
|
||||||
--FROM
|
FROM
|
||||||
-- rlarp.cust
|
rlarp.cust
|
||||||
--WHERE
|
WHERE
|
||||||
-- code = _bill;
|
code = _bill;
|
||||||
|
|
||||||
--_customer := jsonb_build_object(
|
_rslt = _rslt||jsonb_build_object('cust',_cust,'curr',_curr,'fxrate',_rate);
|
||||||
-- 'customer',
|
RAISE NOTICE 'cust %', _cust;
|
||||||
-- _customer||jsonb_build_object(
|
|
||||||
-- 'cust',_cust
|
|
||||||
-- ,'curr',_curr
|
|
||||||
-- ,'fxrate',_rate
|
|
||||||
-- )
|
|
||||||
--);
|
|
||||||
--RAISE NOTICE 'cust %', jsonb_pretty(_customer);
|
|
||||||
|
|
||||||
----------------price history-------------------------------
|
----------------price history-------------------------------
|
||||||
--RAISE NOTICE 'varb %', _customer;
|
SELECT _rslt||jsonb_build_object('hist',rlarp.get_hist(_mold, _v1ds, _cust, substring(_chan,1,1))) INTO _rslt ;
|
||||||
SELECT jsonb_build_object('hist',rlarp.get_hist(_mold, _v1ds, _customer->'customer'->>'cust', substring(_customer->'customer'->>'chan',1,1))) INTO _hist;
|
RAISE NOTICE 'result %', _rslt;
|
||||||
--RAISE NOTICE 'history %', jsonb_pretty(_hist);
|
|
||||||
|
|
||||||
----------------target pricing------------------------------
|
----------------target pricing------------------------------
|
||||||
SELECT
|
SELECT
|
||||||
jsonb_build_object(
|
jsonb_build_object(
|
||||||
'v0tp',
|
'v0tp',
|
||||||
target_price,
|
target_price,
|
||||||
'v0stdv',
|
'stdv',
|
||||||
stdev_price
|
stdev_price
|
||||||
)
|
)
|
||||||
INTO
|
INTO
|
||||||
@ -194,14 +132,14 @@ BEGIN
|
|||||||
mold = _stlc
|
mold = _stlc
|
||||||
AND season = _seas
|
AND season = _seas
|
||||||
AND data_segment = _v0ds
|
AND data_segment = _v0ds
|
||||||
AND region = 'ALL'
|
AND region = 'ALL';
|
||||||
AND chan = _customer->'customer'->>'chantp';
|
_rslt := _rslt||COALESCE(_v0tp,'{}'::jsonb);
|
||||||
----------------target pricing------------------------------
|
----------------target pricing------------------------------
|
||||||
SELECT
|
SELECT
|
||||||
jsonb_build_object(
|
jsonb_build_object(
|
||||||
'v1tp',
|
'v1tp',
|
||||||
target_price,
|
target_price,
|
||||||
'v1stdv',
|
'stdv',
|
||||||
stdev_price
|
stdev_price
|
||||||
)
|
)
|
||||||
INTO
|
INTO
|
||||||
@ -212,12 +150,12 @@ BEGIN
|
|||||||
mold = _stlc
|
mold = _stlc
|
||||||
AND season = _seas
|
AND season = _seas
|
||||||
AND data_segment = _dseg
|
AND data_segment = _dseg
|
||||||
AND region = 'ALL'
|
AND region = 'ALL';
|
||||||
AND chan = _customer->'customer'->>'chantp';
|
|
||||||
--RAISE NOTICE 'target: %', jsonb_pretty(_targ);
|
--RAISE NOTICE 'target: %', jsonb_pretty(_targ);
|
||||||
_pricing := (COALESCE(_v0tp,'{}'::jsonb)||COALESCE(_v1tp,'{}'::jsonb));
|
_rslt := _rslt||COALESCE(_v1tp,'{}'::jsonb);
|
||||||
|
|
||||||
----------------inflation index-----------------------------
|
----------------inflation index-----------------------------
|
||||||
|
RAISE NOTICE 'infaltion : %', jsonb_pretty(_iidx);
|
||||||
SELECT
|
SELECT
|
||||||
jsonb_build_object(
|
jsonb_build_object(
|
||||||
'iidx'
|
'iidx'
|
||||||
@ -238,21 +176,17 @@ BEGIN
|
|||||||
)
|
)
|
||||||
GROUP BY
|
GROUP BY
|
||||||
priority;
|
priority;
|
||||||
_pricing := _pricing||COALESCE(_iidx,'{}'::jsonb);
|
_rslt := _rslt||COALESCE(_iidx,'{}'::jsonb);
|
||||||
--RAISE NOTICE 'add targets: %', jsonb_pretty(_pricing);
|
|
||||||
|
|
||||||
----------------list pricing---------------------------------
|
----------------list pricing---------------------------------
|
||||||
SELECT coalesce(rlarp.get_list(_bill, _ship, _item, _qty),'{}'::jsonb) INTO _list;
|
SELECT coalesce(rlarp.get_list(_bill, _ship, _item, _qty),'{}'::jsonb) INTO _list;
|
||||||
_pricing := _pricing||_list;
|
_rslt := _rslt||_list;
|
||||||
--RAISE NOTICE 'add list: %', jsonb_pretty(_pricing);
|
--RAISE NOTICE 'list: %', jsonb_pretty(_list);
|
||||||
|
|
||||||
----------------get premium for quote hist gap--------------
|
----------------get premium for quote hist gap--------------
|
||||||
SELECT coalesce(rlarp.get_premium(_stlc, _seas, _customer->'customer'->>'chantp',_hist->'hist'->'cust'->>'ds', _v1ds),'{}'::jsonb) INTO _prem;
|
SELECT coalesce(rlarp.get_premium(_stlc, _seas, (SELECT xchan FROM _chx WHERE chan = _chan),_rslt->'hist'->'cust'->>'ds', _v1ds),'{}'::jsonb) INTO _prem;
|
||||||
_pricing := jsonb_build_object('pricing',_pricing||_prem);
|
_rslt := _rslt||_prem;
|
||||||
--RAISE NOTICE 'add bridge: %', jsonb_pretty(_pricing);
|
--RAISE NOTICE 'list: %', jsonb_pretty(_list);
|
||||||
|
|
||||||
_rslt := _input||_product||_customer||_pricing||_hist;
|
|
||||||
|
|
||||||
|
|
||||||
RETURN _rslt;
|
RETURN _rslt;
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@ sort AS (
|
|||||||
,gset.*
|
,gset.*
|
||||||
,row_number() OVER (PARTITION BY p.agglevel ORDER BY avgunits DESC) rn
|
,row_number() OVER (PARTITION BY p.agglevel ORDER BY avgunits DESC) rn
|
||||||
,stats.*
|
,stats.*
|
||||||
,season
|
|
||||||
FROM
|
FROM
|
||||||
rlarp.price_pool_dev p
|
rlarp.price_pool_dev p
|
||||||
JOIN LATERAL jsonb_to_record(gset) AS gset(
|
JOIN LATERAL jsonb_to_record(gset) AS gset(
|
||||||
@ -38,8 +37,6 @@ sort AS (
|
|||||||
,early_price numeric
|
,early_price numeric
|
||||||
,recent_season int
|
,recent_season int
|
||||||
,recent_price numeric
|
,recent_price numeric
|
||||||
,last_season int
|
|
||||||
,last_price numeric
|
|
||||||
) ON TRUE
|
) ON TRUE
|
||||||
WHERE
|
WHERE
|
||||||
gset @> jsonb_build_object(
|
gset @> jsonb_build_object(
|
||||||
@ -98,9 +95,6 @@ SELECT
|
|||||||
,early_price
|
,early_price
|
||||||
,recent_season
|
,recent_season
|
||||||
,recent_price
|
,recent_price
|
||||||
,last_season
|
|
||||||
,last_price
|
|
||||||
,season
|
|
||||||
FROM
|
FROM
|
||||||
sort
|
sort
|
||||||
)
|
)
|
||||||
@ -110,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)
|
||||||
@ -136,16 +130,13 @@ FROM
|
|||||||
,'early_price' ,early_price
|
,'early_price' ,early_price
|
||||||
,'recent_season' ,recent_season
|
,'recent_season' ,recent_season
|
||||||
,'recent_price' ,recent_price
|
,'recent_price' ,recent_price
|
||||||
,'last_season' ,last_season
|
|
||||||
,'last_price' ,last_price
|
|
||||||
,'ds' ,COALESCE(v1ds,v0ds)
|
,'ds' ,COALESCE(v1ds,v0ds)
|
||||||
,'rank' ,row_number() OVER (PARTITION BY flag.source ORDER BY rel.prefer ASC)
|
,'rank'
|
||||||
,'pricinghistory' ,season
|
,row_number() OVER (PARTITION BY flag.source ORDER BY rel.prefer ASC)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
) doc
|
) doc
|
||||||
,row_number() OVER (PARTITION BY flag.source ORDER BY rel.prefer ASC) rnk
|
,row_number() OVER (PARTITION BY flag.source ORDER BY rel.prefer ASC) rnk
|
||||||
,season
|
|
||||||
FROM
|
FROM
|
||||||
flag
|
flag
|
||||||
LEFT OUTER JOIN rel ON
|
LEFT OUTER JOIN rel ON
|
||||||
|
@ -1,173 +0,0 @@
|
|||||||
WITH
|
|
||||||
sel AS (select 'v1:T..PLT..' _v1ds, 'KAWAHARA NURSERY' _cust, 'AZE10001' _mold, 'D' _chan)
|
|
||||||
,sort AS (
|
|
||||||
SELECT
|
|
||||||
p.agglevel
|
|
||||||
,CASE WHEN p.agglevel ? 'cust' THEN 'cust' ELSE 'market' END source
|
|
||||||
,COALESCE(gset.v1ds = _v1ds,false) v1ds_match
|
|
||||||
,gset.chan = _chan chan_match
|
|
||||||
,gset.*
|
|
||||||
,row_number() OVER (PARTITION BY p.agglevel ORDER BY avgunits DESC) rn
|
|
||||||
,stats.*
|
|
||||||
,season
|
|
||||||
FROM
|
|
||||||
rlarp.price_pool_dev p
|
|
||||||
CROSS JOIN sel
|
|
||||||
JOIN LATERAL jsonb_to_record(gset) AS gset(
|
|
||||||
chan text
|
|
||||||
,mold text
|
|
||||||
,v1ds text
|
|
||||||
,v0ds text
|
|
||||||
,cust text
|
|
||||||
,vers text
|
|
||||||
--,nurs text
|
|
||||||
--,ghse text
|
|
||||||
) ON TRUE
|
|
||||||
JOIN LATERAL jsonb_to_record(stats) AS stats(
|
|
||||||
avgunits numeric
|
|
||||||
,avgtargetprice numeric
|
|
||||||
,avgordcount numeric
|
|
||||||
,avgcustcount numeric
|
|
||||||
,early_season int
|
|
||||||
,early_price numeric
|
|
||||||
,recent_season int
|
|
||||||
,recent_price numeric
|
|
||||||
,last_season int
|
|
||||||
,last_price numeric
|
|
||||||
) ON TRUE
|
|
||||||
WHERE
|
|
||||||
gset @> jsonb_build_object(
|
|
||||||
'mold', _mold
|
|
||||||
,'vers', 'A'
|
|
||||||
)
|
|
||||||
AND (
|
|
||||||
gset @> jsonb_build_object(
|
|
||||||
'cust', _cust
|
|
||||||
)
|
|
||||||
OR NOT gset ? 'cust'
|
|
||||||
)
|
|
||||||
AND COALESCE(stats.early_season,stats.recent_season) IS NOT NULL
|
|
||||||
AND NOT p.agglevel ? 'nurs'
|
|
||||||
AND NOT p.agglevel ? 'ghse'
|
|
||||||
ORDER BY
|
|
||||||
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
|
|
||||||
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 relevance
|
|
||||||
,source
|
|
||||||
,v1ds_match
|
|
||||||
,chan_match
|
|
||||||
,chan
|
|
||||||
,mold
|
|
||||||
,v1ds
|
|
||||||
,v0ds
|
|
||||||
,cust
|
|
||||||
,vers
|
|
||||||
,rn
|
|
||||||
,row_number() OVER (PARTITION BY source ORDER BY rel.prefer ASC) rnk
|
|
||||||
,avgunits
|
|
||||||
,avgordcount
|
|
||||||
,avgcustcount
|
|
||||||
,avgtargetprice
|
|
||||||
,early_season
|
|
||||||
,early_price
|
|
||||||
,recent_season
|
|
||||||
,recent_price
|
|
||||||
,last_season
|
|
||||||
,last_price
|
|
||||||
,season
|
|
||||||
FROM
|
|
||||||
sort
|
|
||||||
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
|
|
||||||
-- flag.relevance
|
|
||||||
--,flag.source
|
|
||||||
--,rel.prefer
|
|
||||||
--,row_number() OVER (PARTITION BY flag.source ORDER BY rel.prefer ASC) best
|
|
||||||
jsonb_strip_nulls(
|
|
||||||
jsonb_build_object(
|
|
||||||
flag.source
|
|
||||||
,jsonb_build_object(
|
|
||||||
'relevance' ,relevance
|
|
||||||
,'avgunits' ,avgunits
|
|
||||||
,'avgordcount' ,avgordcount
|
|
||||||
,'avgcustcount' ,avgcustcount
|
|
||||||
,'avgtargetprice' ,avgtargetprice
|
|
||||||
,'early_season' ,early_season
|
|
||||||
,'early_price' ,early_price
|
|
||||||
,'recent_season' ,recent_season
|
|
||||||
,'recent_price' ,recent_price
|
|
||||||
,'last_season' ,last_season
|
|
||||||
,'last_price' ,last_price
|
|
||||||
,'ds' ,COALESCE(v1ds,v0ds)
|
|
||||||
,'rank' ,rnk
|
|
||||||
,'pricinghistory' ,season
|
|
||||||
)
|
|
||||||
)
|
|
||||||
) doc
|
|
||||||
,rnk
|
|
||||||
,season
|
|
||||||
FROM
|
|
||||||
flag
|
|
||||||
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 flag
|
|
||||||
--SELECT jsonb_obj_aggc(doc) FROM rel_sort WHERE rnk = 1;
|
|
@ -1,233 +0,0 @@
|
|||||||
CREATE OR REPLACE FUNCTION rlarp.get_list(_billto text, _shipto text, _item text, _qty numeric)
|
|
||||||
RETURNS jsonb
|
|
||||||
LANGUAGE plpgsql AS
|
|
||||||
--DO
|
|
||||||
$func$
|
|
||||||
DECLARE
|
|
||||||
-- _billto text;
|
|
||||||
-- _shipto text;
|
|
||||||
-- _item text;
|
|
||||||
-- _qty numeric;
|
|
||||||
_rslt jsonb;
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
--_billto := 'DIAM0004';
|
|
||||||
--_shipto := 'DIAM0004';
|
|
||||||
--_item := 'AMK06000G18B054';
|
|
||||||
--_qty := 5400;
|
|
||||||
|
|
||||||
CREATE TEMP TABLE IF NOT EXISTS cp AS (
|
|
||||||
--every unqiue price list scenario
|
|
||||||
SELECT
|
|
||||||
s.bill_cust
|
|
||||||
,s.ship_cust
|
|
||||||
,s.part
|
|
||||||
,i.unti unit
|
|
||||||
,s.qtyord
|
|
||||||
,i.uomp
|
|
||||||
,CASE WHEN COALESCE(sc.plevel,'') = '' THEN bc.plevel ELSE sc.plevel END plvl
|
|
||||||
FROM
|
|
||||||
(SELECT _billto bill_cust, _shipto ship_cust, _item part, _qty qtyord) s
|
|
||||||
LEFT OUTER JOIN "CMS.CUSLG".itemm i ON
|
|
||||||
i.item = s.part
|
|
||||||
LEFT OUTER JOIN rlarp.cust sc ON
|
|
||||||
sc.code = s.ship_cust
|
|
||||||
LEFT OUTER JOIN rlarp.cust bc ON
|
|
||||||
bc.code = s.bill_cust
|
|
||||||
WHERE
|
|
||||||
CASE WHEN COALESCE(sc.plevel,'') = '' THEN bc.plevel ELSE sc.plevel END <> ''
|
|
||||||
GROUP BY
|
|
||||||
s.bill_cust
|
|
||||||
,s.ship_cust
|
|
||||||
,s.part
|
|
||||||
,i.unti
|
|
||||||
,s.qtyord
|
|
||||||
,i.uomp
|
|
||||||
,CASE WHEN COALESCE(sc.plevel,'') = '' THEN bc.plevel ELSE sc.plevel END
|
|
||||||
) WITH DATA;
|
|
||||||
|
|
||||||
--drop table cp
|
|
||||||
--SELECT * FROM cp WHERE bill_cust = 'DIST0008' and part = 'TCF06SG0G18C050' and ship_cust = 'DIST0007'
|
|
||||||
|
|
||||||
CREATE TEMP TABLE IF NOT EXISTS plfull AS (
|
|
||||||
--all all rows for relevant part/price levels
|
|
||||||
WITH
|
|
||||||
----------unique price points-----------------------
|
|
||||||
lvl AS (
|
|
||||||
SELECT DISTINCT
|
|
||||||
plvl
|
|
||||||
,part
|
|
||||||
,unit
|
|
||||||
FROM
|
|
||||||
cp
|
|
||||||
)
|
|
||||||
------------join prices for price level------------
|
|
||||||
,plj AS (
|
|
||||||
SELECT
|
|
||||||
lvl.plvl
|
|
||||||
,lvl.part
|
|
||||||
,lvl.unit
|
|
||||||
,i.jcplcd
|
|
||||||
,i.jcunit
|
|
||||||
,i.jcvoll
|
|
||||||
,i.jcpric
|
|
||||||
FROM
|
|
||||||
lvl
|
|
||||||
INNER JOIN "CMS.CUSLG".iprcbhc hc ON
|
|
||||||
hc.jbplvl = lvl.plvl
|
|
||||||
AND current_date BETWEEN hc.jbfdat AND hc.jbtdat
|
|
||||||
INNER JOIN lgdat.iprcc i ON
|
|
||||||
i.jcplcd = hc.jbplcd
|
|
||||||
AND i.jcpart = lvl.part
|
|
||||||
)
|
|
||||||
-----------uom conversions-------------------
|
|
||||||
,uom AS (
|
|
||||||
SELECT
|
|
||||||
uom.p part
|
|
||||||
,uom.f
|
|
||||||
,uom.t
|
|
||||||
,uom.nm/uom.dm rate
|
|
||||||
FROM
|
|
||||||
(
|
|
||||||
SELECT
|
|
||||||
jsonb_agg(row_to_json(d)::jsonb) jdoc
|
|
||||||
FROM
|
|
||||||
(
|
|
||||||
SELECT DISTINCT
|
|
||||||
part partn
|
|
||||||
,jcunit fu
|
|
||||||
,unit tu
|
|
||||||
FROM
|
|
||||||
plj
|
|
||||||
WHERE
|
|
||||||
part <> ''
|
|
||||||
) d
|
|
||||||
) c
|
|
||||||
JOIN LATERAL rlarp.uom_array(c.jdoc) uom ON TRUE
|
|
||||||
)
|
|
||||||
------price list sorted---------------------
|
|
||||||
SELECT
|
|
||||||
plj.plvl
|
|
||||||
,plj.part
|
|
||||||
,plj.unit
|
|
||||||
,plj.jcplcd
|
|
||||||
--,plj.jcunit
|
|
||||||
,round(plj.jcvoll * uom.rate,5) vol
|
|
||||||
,round(plj.jcpric / uom.rate,5) price
|
|
||||||
--,uom.rate
|
|
||||||
--dont partition by list code becuase there could be duplicate assignments
|
|
||||||
,row_number() OVER (PARTITION BY plj.plvl, plj.part, plj.unit ORDER BY round(plj.jcvoll * uom.rate,5) ASC) rn
|
|
||||||
FROM
|
|
||||||
plj
|
|
||||||
INNER JOIN uom ON
|
|
||||||
uom.part = plj.part
|
|
||||||
AND uom.f = plj.jcunit
|
|
||||||
AND uom.t = plj.unit
|
|
||||||
) WITH DATA;
|
|
||||||
|
|
||||||
--select * from plfull
|
|
||||||
|
|
||||||
CREATE TEMP TABLE IF NOT EXISTS pl AS (
|
|
||||||
--create from-to volume range for price list
|
|
||||||
WITH RECURSIVE
|
|
||||||
pl(plvl, listcode, part, unit, volf, volt, price1, price2, rn, lvl) AS (
|
|
||||||
SELECT
|
|
||||||
p1.plvl
|
|
||||||
,p1.jcplcd as listcode
|
|
||||||
,p1.part
|
|
||||||
,p1.unit
|
|
||||||
,0::numeric volf
|
|
||||||
,p1.vol volt
|
|
||||||
,null::numeric price1
|
|
||||||
,p1.price price2
|
|
||||||
,p1.rn
|
|
||||||
,0 lvl
|
|
||||||
FROM
|
|
||||||
plfull p1
|
|
||||||
WHERE
|
|
||||||
p1.rn = 1
|
|
||||||
UNION ALL
|
|
||||||
SELECT
|
|
||||||
pl.plvl
|
|
||||||
,COALESCE(f.jcplcd,pl.listcode) listcode
|
|
||||||
,pl.part
|
|
||||||
,pl.unit
|
|
||||||
,pl.volt volf
|
|
||||||
,COALESCE(f.vol,999999999) volt
|
|
||||||
,pl.price2 price1
|
|
||||||
,f.price price2
|
|
||||||
,f.rn
|
|
||||||
,pl.lvl + 1
|
|
||||||
FROM
|
|
||||||
pl
|
|
||||||
LEFT OUTER JOIN plfull f ON
|
|
||||||
f.plvl = pl.plvl
|
|
||||||
AND f.part = pl.part
|
|
||||||
AND f.unit = pl.unit
|
|
||||||
AND f.rn = pl.rn + 1
|
|
||||||
WHERE
|
|
||||||
pl.price2 IS NOT NULL
|
|
||||||
) SEARCH DEPTH FIRST BY part, plvl, unit SET ordercol
|
|
||||||
SELECT
|
|
||||||
plvl
|
|
||||||
,listcode
|
|
||||||
,part
|
|
||||||
,unit
|
|
||||||
,volf
|
|
||||||
,volt
|
|
||||||
,numrange(volf, volt) vrange
|
|
||||||
,price1 price
|
|
||||||
--,price2
|
|
||||||
--,rn
|
|
||||||
--,lvl
|
|
||||||
--,ordercol
|
|
||||||
FROM
|
|
||||||
pl
|
|
||||||
ORDER BY
|
|
||||||
ordercol
|
|
||||||
) WITH DATA;
|
|
||||||
|
|
||||||
--select * from pl
|
|
||||||
--add primary key to test if there are any price level that overlap the same part number
|
|
||||||
--alter table pl add primary key (plvl, part, unit, vrange);
|
|
||||||
|
|
||||||
CREATE TEMP TABLE IF NOT EXISTS cpj AS (
|
|
||||||
--go back to every unique scenario and join to modified list with volum range
|
|
||||||
SELECT
|
|
||||||
cp.*
|
|
||||||
,pl.price
|
|
||||||
,pl.listcode
|
|
||||||
FROM
|
|
||||||
cp
|
|
||||||
INNER JOIN pl ON
|
|
||||||
pl.part = cp.part
|
|
||||||
AND pl.plvl = cp.plvl
|
|
||||||
AND pl.unit = cp.unit
|
|
||||||
WHERE
|
|
||||||
pl.vrange @> cp.qtyord
|
|
||||||
) WITH DATA;
|
|
||||||
|
|
||||||
--select * from cpj where part = 'TCF06SG0G18C050'
|
|
||||||
|
|
||||||
SELECT
|
|
||||||
jsonb_build_object('list',cpj.price)
|
|
||||||
||jsonb_build_object('listcode',cpj.listcode)
|
|
||||||
||jsonb_build_object('plvl',cpj.plvl)
|
|
||||||
INTO
|
|
||||||
_rslt
|
|
||||||
FROM
|
|
||||||
cpj;
|
|
||||||
|
|
||||||
--RAISE NOTICE 'list: %' ,_rslt;
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS cp;
|
|
||||||
DROP TABLE IF EXISTS plfull;
|
|
||||||
DROP TABLE IF EXISTS pl;
|
|
||||||
DROP TABLE IF EXISTS cpj;
|
|
||||||
|
|
||||||
RETURN _rslt;
|
|
||||||
|
|
||||||
|
|
||||||
END;
|
|
||||||
$func$;
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
|||||||
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;
|
|
@ -1,70 +0,0 @@
|
|||||||
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,2025)
|
|
||||||
) 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
|
|
@ -1,59 +0,0 @@
|
|||||||
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,10 +1,9 @@
|
|||||||
--CREATE OR REPLACE PROCEDURE rlarp.price_pool()
|
--CREATE OR REPLACE PROCEDURE rlarp.price_pool()
|
||||||
--LANGUAGE plpgsql AS
|
--LANGUAGE plpgsql AS
|
||||||
--$func$
|
--$func$
|
||||||
--BEGIN;
|
--BEGIN
|
||||||
DROP MATERIALIZED VIEW IF EXISTS rlarp.price_pool CASCADE;
|
DROP TABLE IF EXISTS rlarp.price_pool_dev;
|
||||||
--CREATE TABLE IF NOT EXISTS rlarp.price_pool_dev AS (
|
CREATE TABLE IF NOT EXISTS rlarp.price_pool_dev AS (
|
||||||
CREATE MATERIALIZED VIEW rlarp.price_pool AS (
|
|
||||||
WITH
|
WITH
|
||||||
agg AS (
|
agg AS (
|
||||||
SELECT
|
SELECT
|
||||||
@ -76,76 +75,6 @@ CREATE MATERIALIZED VIEW rlarp.price_pool AS (
|
|||||||
HAVING
|
HAVING
|
||||||
round(sum(o.qty),0) > 0
|
round(sum(o.qty),0) > 0
|
||||||
AND round(sum(o.sales_usd)/sum(o.qty),5) > 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 (
|
,gsets AS (
|
||||||
SELECT
|
SELECT
|
||||||
@ -195,9 +124,8 @@ CREATE MATERIALIZED VIEW rlarp.price_pool AS (
|
|||||||
,round(avg(ordcount) ,1) avgordcount
|
,round(avg(ordcount) ,1) avgordcount
|
||||||
,round(avg(units) ,0) avgunits
|
,round(avg(units) ,0) avgunits
|
||||||
,round(avg(target_price),5) avgtargetprice
|
,round(avg(target_price),5) avgtargetprice
|
||||||
,min(oseas) FILTER (WHERE oseas BETWEEN 2020 AND 2023)::text early_season
|
,min(oseas) FILTER (WHERE oseas BETWEEN 2020 AND 2022)::text early_season
|
||||||
,min(oseas) FILTER (WHERE oseas >= 2024)::text recent_season
|
,min(oseas) FILTER (WHERE oseas >= 2024)::text recent_season
|
||||||
,max(oseas) FILTER (WHERE oseas >= 2020)::text last_season
|
|
||||||
--,oseas
|
--,oseas
|
||||||
--,units
|
--,units
|
||||||
--,sales_usd
|
--,sales_usd
|
||||||
@ -231,15 +159,10 @@ CREATE MATERIALIZED VIEW rlarp.price_pool AS (
|
|||||||
,recent_season::int
|
,recent_season::int
|
||||||
,'recent_price'
|
,'recent_price'
|
||||||
,(season->recent_season->>'price_usd')::numeric
|
,(season->recent_season->>'price_usd')::numeric
|
||||||
,'last_season'
|
|
||||||
,last_season::int
|
|
||||||
,'last_price'
|
|
||||||
,(season->last_season->>'price_usd')::numeric
|
|
||||||
) stats
|
) stats
|
||||||
FROM
|
FROM
|
||||||
find_stats
|
find_stats
|
||||||
--LIMIT 1000
|
--LIMIT 1000
|
||||||
) WITH DATA;
|
) WITH DATA;
|
||||||
|
|
||||||
create index ppd_gset on rlarp.price_pool using gin (gset);
|
create index ppd_gset on rlarp.price_pool_dev using gin (gset);
|
||||||
--END;
|
|
||||||
|
@ -1,139 +0,0 @@
|
|||||||
-- set work_mem TO '4GB';
|
|
||||||
--
|
|
||||||
DROP VIEW IF EXISTS rlarp.quote_review;
|
|
||||||
CREATE VIEW rlarp.quote_review AS
|
|
||||||
WITH
|
|
||||||
lq AS MATERIALIZED (
|
|
||||||
SELECT
|
|
||||||
lq.*
|
|
||||||
,substring(lq.part,1,8) mold
|
|
||||||
FROM
|
|
||||||
pricequote.live_quotes lq
|
|
||||||
WHERE
|
|
||||||
qstat LIKE 'Submitted%'
|
|
||||||
)
|
|
||||||
,lqg AS (
|
|
||||||
SELECT
|
|
||||||
lq.qid
|
|
||||||
,lq.qline
|
|
||||||
,lq.rep
|
|
||||||
,lq.touched
|
|
||||||
,lq.expires
|
|
||||||
,lq.request
|
|
||||||
,lq.qtitle
|
|
||||||
,lq.qstatid
|
|
||||||
,lq.qstat
|
|
||||||
,lq.quotenumber
|
|
||||||
,lq.billto
|
|
||||||
,lq.shipto
|
|
||||||
,lq.qchan
|
|
||||||
,lq.qcustomer
|
|
||||||
,lq.part
|
|
||||||
,lq.qoptions
|
|
||||||
,lq.partbuilt
|
|
||||||
,lq.colgrp
|
|
||||||
,lq.colc
|
|
||||||
,lq.coltier
|
|
||||||
,lq.brand
|
|
||||||
,lq.dataseg
|
|
||||||
,lq.v1ds
|
|
||||||
,lq.comment
|
|
||||||
,lq.units_each
|
|
||||||
,lq.price
|
|
||||||
,lq.sales
|
|
||||||
,lq.histprice
|
|
||||||
,lq.targetp
|
|
||||||
,lq.lastsalesprice
|
|
||||||
,lq.r_curr
|
|
||||||
,lq.qt_rate
|
|
||||||
,lq.qrn
|
|
||||||
,lq.url
|
|
||||||
,lq.tacticalmodifier
|
|
||||||
,lq.finalrecommendedprice
|
|
||||||
,lq.lowerpricelimit
|
|
||||||
,lq.upperpricelimit
|
|
||||||
,(lq.upperpricelimit + lq.lowerpricelimit) / 2 midrange
|
|
||||||
,i.partgroup part_group
|
|
||||||
-- ,pricing->'product'->>'itemrel' item_fit
|
|
||||||
,i.mpck pltq
|
|
||||||
-- ,(pricing->'guidance'->'finalPrice'->>'Price')::numeric guidance
|
|
||||||
-- ,pricing->'guidance'->'finalPrice'->>'Reason' reason
|
|
||||||
,lq.curstdus cstd_usd
|
|
||||||
,lq.futstdus fstd_usd
|
|
||||||
,CASE
|
|
||||||
WHEN i.glec = '1NU' THEN
|
|
||||||
--if more than 8/24 pallets, use floor
|
|
||||||
CASE WHEN units_each >= 24*mpck THEN lq.lowerpricelimit
|
|
||||||
-- if more than a pallet use the target price
|
|
||||||
ELSE CASE WHEN units_each >= 8*mpck THEN (lq.upperpricelimit + lq.lowerpricelimit) / 2
|
|
||||||
-- if more than a pallet use the target price
|
|
||||||
ELSE CASE WHEN units_each >= 4*mpck THEN lq.upperpricelimit
|
|
||||||
-- if more than a pallet use the target price
|
|
||||||
ELSE lq.upperpricelimit * 1.15
|
|
||||||
END END END
|
|
||||||
ELSE
|
|
||||||
CASE WHEN i.pricegroup ~ '(Hanger|Dish)' THEN
|
|
||||||
--at least 1 pallets is lower limit
|
|
||||||
CASE WHEN units_each >= 01*mpck THEN lq.lowerpricelimit
|
|
||||||
--at least 2 pallets is mid range
|
|
||||||
ELSE CASE WHEN units_each >= 0.5*mpck THEN (lq.upperpricelimit + lq.lowerpricelimit) / 2
|
|
||||||
--less than a pallet is upper + 15%
|
|
||||||
ELSE lq.upperpricelimit
|
|
||||||
END END
|
|
||||||
ELSE
|
|
||||||
--at least 8 pallets is lower limit
|
|
||||||
CASE WHEN units_each >= 08*mpck THEN lq.lowerpricelimit
|
|
||||||
--at least 2 pallets is mid range
|
|
||||||
ELSE CASE WHEN units_each >= 2*mpck THEN (lq.upperpricelimit + lq.lowerpricelimit) / 2
|
|
||||||
--at least 1 pallet is upper range
|
|
||||||
ELSE CASE WHEN units_each >= 1*mpck THEN lq.upperpricelimit
|
|
||||||
--less than a pallet is upper + 15%
|
|
||||||
ELSE lq.upperpricelimit * 1.15
|
|
||||||
END END END
|
|
||||||
END
|
|
||||||
END guidance
|
|
||||||
-- ,(pricing->'guidance'->>'ltp')::numeric ltp
|
|
||||||
-- ,(pricing->'guidance'->>'optimization')::numeric optimization
|
|
||||||
-- ,(pricing->'guidance'->>'inflationFactor')::numeric inflation
|
|
||||||
-- ,jsonb_pretty(pricing) pricing
|
|
||||||
FROM
|
|
||||||
lq
|
|
||||||
LEFT OUTER JOIN "CMS.CUSLG".itemm i ON
|
|
||||||
i.item = lq.part
|
|
||||||
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 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 = 108655
|
|
Loading…
Reference in New Issue
Block a user