Compare commits

..

No commits in common. "master" and "javascript_relevance_logic" have entirely different histories.

57 changed files with 270 additions and 4528 deletions

17
.gitignore vendored
View File

@ -1,17 +1,2 @@
.env
.vscode/
.idea/hc_ubm.iml
.idea/modules.xml
.idea/workspace.xml
.project
.dbeaver-data-sources.xml
Diagrams/
.vs/
*.swp
*.swo
.settings/org.eclipse.core.resources.prefs
.vscode/*
.dbeaver/
.env
.obsidian/
.vscode/

21
api.ts
View File

@ -34,35 +34,18 @@ const query = await Deno.readTextFile("sql/get.pg.sql");
const query_dseg = await Deno.readTextFile("sql/get_dseg.pg.sql");
// 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 result = await client.queryObject({args: [billcode, shipcode, partcode, qty], text: query} );
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
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.finalPrice.Snapped;
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_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.allowedMethods());

View File

@ -1,165 +1,167 @@
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) {
// 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;
}
let mostRelevantCustomerPriceEarly = null;
let mostRelevantCustomerPriceRecent = null;
let mostRelevantCustomerKey = null;
let mostRelevantCustomerSeasonEarly = null;
let mostRelevantCustomerSeasonRecent = null;
let highestCustomerRelevanceLevel = 0;
let mostRelevantCustomerSource = null;
// 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 },
{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;
// 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
}
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;
// 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
}
}
return {Reason, Price, Source, Snapped};
}
function ceiling(value, significance) {
return Math.ceil(value / significance) * significance;
}
//// 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);
//}
function r5(value) {
return Number(value.toFixed(5));
}
//// 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
// };
//}
function pp(value) {
// Multiplies by 1000 and rounds to the nearest 2 decimals
var result = Math.round(value * 1000 * 100) / 100;
//// 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
// };
//}
// 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`;
const targetPrice = doc.v1tp ?? doc.v0tp;
const earlyPrice = doc.hist?.cust?.early_price;
let anchorPrice = null;
let anchorSource = null;
let bridgePremium = doc.bridgePremium ?? 1.00000;
if (!targetPrice) {
anchorSource = "No target pricing setup";
doc.finalReason = "No target pricing setup";
} else {
// Determine the anchor price and source
if (earlyPrice) {
// translate alternate product history to current product quoted
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 = {
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))]
const inflation = Math.max(...Object.keys(doc.iidx).map(Number));
const inflationFactor = doc.iidx[inflation] + 1;
var calcPrice = parseFloat((anchorPrice * inflationFactor).toFixed(5));
let finalReason = "";
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);
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);
return doc;
}

View File

@ -1,13 +0,0 @@
-- FAnalysis.PRICING.lastprice definition
-- Drop table
-- DROP TABLE FAnalysis.PRICING.lastprice;
CREATE TABLE pricing.lastprice (
customer varchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
mold varchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
part_stats nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
);
CREATE UNIQUE NONCLUSTERED INDEX lastprice_cust_mold ON FAnalysis.PRICING.lastprice (customer ASC, mold ASC) ;

View File

@ -1,59 +0,0 @@
--------------------------------------------------------------------------------
-- Step 1: Rebuild last price history at sales matrix refresh time
--------------------------------------------------------------------------------
DELETE FROM pricing.lastprice;
WITH srt AS (
SELECT
customer,
mold,
part,
version,
qty,
ROUND(sales_usd / qty, 5) AS price,
odate,
oseas,
ordnum,
quoten,
ROW_NUMBER() OVER (
PARTITION BY customer, mold, part, version
ORDER BY odate DESC
) AS rn
FROM rlarp.osm_stack
WHERE
--quotes can't be integrated until we have datasegment or correct part code
version IN ('Actual'/*,'Quotes'*/) AND
customer IS NOT NULL AND
fs_line = '41010' AND
calc_status <> 'CANCELLED' AND
qty <> 0 AND
mold <> ''
),
json_rows AS (
SELECT
customer,
mold,
part,
version,
CONCAT(
'"', part, '":',
(
SELECT version, qty, price, odate, ordnum, quoten
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
)
) AS part_json
FROM srt
WHERE rn = 1
)
,onerow AS (
SELECT
customer,
mold,
CONCAT('{', STRING_AGG(part_json, ','), '}') AS part_stats
FROM json_rows
GROUP BY customer, mold
)
INSERT INTO pricing.lastprice SELECT * FROM onerow;
--CREATE UNIQUE INDEX lastprice_cust_mold ON pricing.lastprice(customer, mold);

View File

@ -1,26 +0,0 @@
minimal setup to run a single pricing call:
```sql
EXEC pricing.single_price_call
@bill = 'GRIF0001',
@ship = 'GRIF0001',
@part = 'XNS0T1G3G18B096',
@stlc = 'XNS0T1G3',
@v1ds = 'v1:T..PLT..',
@vol = 9600;
```
make sure pricing schema is setup
Target Prices
----------------------
1. create target table: `target_prices.ms.sql`
2. populate targets: `target_prices_copy.ms.sql`
Price History
----------------------
1. create history table: `lastprice.ms.sql`
2. populate history: `make_hist.ms.sql`
Proc Definitions
----------------------
1. create proc: `single_price_call.ms.sql`

View File

@ -1,162 +0,0 @@
CREATE OR ALTER PROCEDURE pricing.single_price_call
@bill VARCHAR(100),
@ship VARCHAR(100),
@part VARCHAR(100),
@stlc VARCHAR(100),
@v1ds VARCHAR(100),
@vol NUMERIC(18,6)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @phist NVARCHAR(MAX);
-- Declare table variable for the input row
DECLARE @queue TABLE (
bill VARCHAR(100),
ship VARCHAR(100),
part VARCHAR(100),
stlc VARCHAR(100),
v1ds VARCHAR(100),
vol NUMERIC(18,6),
chan VARCHAR(50),
cust VARCHAR(100),
tier VARCHAR(50),
pltq NUMERIC(18,6),
price NUMERIC(18,6),
expl NVARCHAR(MAX),
hist NVARCHAR(MAX),
LAST nvarchar(max)
);
--------------------------------------------------------------------------------
-- Step 1: Insert input row into queue
--------------------------------------------------------------------------------
INSERT INTO @queue (bill, ship, part, stlc, v1ds, vol)
VALUES (@bill, @ship, @part, @stlc, @v1ds, @vol);
--------------------------------------------------------------------------------
-- Step 2: Enrich the row with chan, tier, cust, pltq
--------------------------------------------------------------------------------
UPDATE q
SET
chan =
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN
CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN 'WHS'
ELSE 'DRP'
END
ELSE 'DIR'
END,
tier =
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIR' THEN bc.tier
ELSE ISNULL(sc.tier, bc.tier)
END,
cust =
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN
CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN bc.dba
ELSE sc.dba
END
ELSE q.bill
END,
pltq = i.mpck
FROM @queue q
LEFT JOIN rlarp.cust bc ON bc.code = q.bill
LEFT JOIN rlarp.cust sc ON sc.code = q.ship
LEFT JOIN CMSInterfaceIn.[CMS.CUSLG].itemm i ON i.item = q.part;
--------------------------------------------------------------------------------
-- Step 3: Get last price info directly into @queue columns
--------------------------------------------------------------------------------
UPDATE q
SET
q.hist = (
SELECT TOP 1
j.qty,
j.price,
j.odate,
j.ordnum,
j.quoten
FROM pricing.lastprice lp
OUTER APPLY OPENJSON(lp.part_stats) AS p
OUTER APPLY OPENJSON(p.value)
WITH (
qty NUMERIC(20,5),
price NUMERIC(20,5),
odate DATE,
ordnum INT,
quoten INT
) AS j
WHERE
lp.customer = q.cust
AND lp.mold = SUBSTRING(q.part,1,8)
AND p.[key] COLLATE SQL_Latin1_General_CP1_CI_AS = q.part
ORDER BY j.odate DESC
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
),
q.last = (
SELECT TOP 1
CAST(ROUND(j.price, 5) AS NVARCHAR(50)) -- must be string to store in NVARCHAR column
FROM pricing.lastprice lp
OUTER APPLY OPENJSON(lp.part_stats) AS p
OUTER APPLY OPENJSON(p.value)
WITH (
qty NUMERIC(20,5),
price NUMERIC(20,5),
odate DATE,
ordnum INT,
quoten INT
) AS j
WHERE
lp.customer = q.cust
AND lp.mold = SUBSTRING(q.part,1,8)
AND p.[key] COLLATE SQL_Latin1_General_CP1_CI_AS = q.part
ORDER BY j.odate DESC
)
FROM @queue q;
--------------------------------------------------------------------------------
-- Step 4: Apply pricing and embed price history + last price from queue columns
--------------------------------------------------------------------------------
UPDATE q
SET
price = tp.price,
expl = (
SELECT
'target price' AS [source],
tp.price AS [target_price],
CAST(q.last AS NUMERIC(20,5)) AS [last_price],
FLOOR(q.vol / NULLIF(q.pltq, 0)) AS [calculated_pallets],
ROUND(q.vol / NULLIF(q.pltq, 0), 5) AS [exact_pallets],
CONCAT(tp.lower_bound, '-', ISNULL(CAST(tp.upper_bound AS VARCHAR), '')) AS [volume range],
q.cust AS [customer],
q.chan AS [channel],
q.tier AS [tier],
JSON_QUERY(tp.math) AS [target math],
JSON_QUERY(q.hist) AS [price history]
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
)
FROM @queue q
INNER JOIN pricing.target_prices tp ON
q.stlc = tp.stlc
AND q.v1ds = tp.ds
AND q.chan = tp.chan
AND q.tier = tp.tier
AND FLOOR(q.vol / NULLIF(q.pltq, 0)) >= tp.lower_bound
AND (
tp.upper_bound IS NULL OR FLOOR(q.vol / NULLIF(q.pltq, 0)) < tp.upper_bound
);
--------------------------------------------------------------------------------
-- Step Last: Return just the enriched row
--------------------------------------------------------------------------------
SELECT price, expl FROM @queue;
END;

View File

@ -1,18 +0,0 @@
DROP TABLE pricing.target_prices;
CREATE TABLE pricing.target_prices (
stlc nvarchar(8) NOT NULL,
ds nvarchar(20) NOT NULL,
chan nvarchar(3) NOT NULL,
tier nvarchar(1) NOT NULL,
vol nvarchar(20) NOT NULL,
lower_bound int NOT NULL,
upper_bound int NULL,
price numeric(28,6) NOT NULL,
math nvarchar(MAX) NULL
);
ALTER TABLE pricing.target_prices
ADD CONSTRAINT uq_target_prices_unique_combo
UNIQUE (stlc, ds, chan, tier, vol, lower_bound);

View File

@ -1,23 +0,0 @@
DELETE FROM pricing.target_prices;
INSERT INTO
pricing.target_prices
SELECT
stlc,
ds,
chan,
tier,
vol,
-- Extract lower bound: text between '[' and ','
TRY_CAST(SUBSTRING(vol, 2, CHARINDEX(',', vol) - 2) AS INT) AS lower_bound,
-- Extract upper bound: text between ',' and ')'
CASE
WHEN RIGHT(vol, 2) = ',)' THEN NULL
ELSE TRY_CAST(SUBSTRING(vol, CHARINDEX(',', vol) + 1, LEN(vol) - CHARINDEX(',', vol) - 1) AS INT)
END AS upper_bound,
price,
math
FROM
usmidsap02.ubm.pricequote.target_prices_view;
--SELECT COUNT(*) FROM pricing.target_prices

View File

@ -1,17 +0,0 @@
DROP TABLE pricing.price_queue
CREATE TABLE pricing.price_queue (
id BIGINT IDENTITY(1,1) PRIMARY KEY,
bill VARCHAR(100),
ship VARCHAR(100),
part VARCHAR(100),
stlc VARCHAR(100),
v1ds VARCHAR(100),
vol NUMERIC(18,6),
chan VARCHAR(50),
cust VARCHAR(100),
tier VARCHAR(50),
pltq NUMERIC(18,6),
price NUMERIC(18,6),
expl NVARCHAR(MAX) -- if storing JSON-like data
);

View File

@ -1,19 +0,0 @@
DROP TABLE pricequote.price_queue CASCADE;
CREATE TABLE IF NOT EXISTS pricequote.price_queue (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY
,bill TEXT
,ship TEXT
,part TEXT
,stlc TEXT
,v1ds TEXT
,vol NUMERIC
,cust TEXT
,chan TEXT
,tier TEXT
,pltq NUMERIC
,price NUMERIC
,expl JSONB
);
GRANT SELECT, INSERT, UPDATE, DELETE ON pricequote.price_queue TO PUBLIC;

View File

@ -1,72 +0,0 @@
DELETE FROM pricing.price_queue;
INSERT INTO pricing.price_queue (bill, ship, part, stlc, v1ds, vol) SELECT 'GRIF0001','GRIF0001','XNS0T1G3G18B096','XNS0T1G3','v1:L..PLT..',9600;
SELECT * FROM pricing.price_queue
EXEC pricing.process_queue
EXEC pricing.single_price_call
@bill = 'GRIF0001',
@ship = 'JRSG0001',
@part = 'XNS0T1G3G18B096',
@stlc = 'XNS0T1G3',
@v1ds = 'v1:B..PLT..',
@vol = 9600;
SELECT
*
FROM pricing.single_price_call_fn(
'GRIF0001',
'GRIF0001',
'XNS0T1G3G18B096',
'XNS0T1G3',
'v1:B..PLT..',
9600
) f
SELECT * INTO #result FROM pricing.price_queue WHERE 0=1
INSERT INTO #result
EXEC pricing.single_price_call_nowrite
@bill = 'GRIF0001',
@ship = 'JRSG0001',
@part = 'XNS0T1G3G18B096',
@stlc = 'XNS0T1G3',
@v1ds = 'v1:T..PLT..',
@vol = 19200;
SELECT * FROM #RESULT
SELECT
q.qid,
q.qrn,
q.qcustomer,
q.part,
q.v1ds,
q.units_each,
q.price,
q.targetp,
q.lastsalesprice,
q.finalrecommendedprice,
q.lowerpricelimit,
q.upperpricelimit,
q.curstdus,
p.price guidance,
p.expl
FROM
rlarp.live_quotes q
OUTER APPLY pricing.single_price_call_fn(
q.billto
,q.shipto
,q.part
,substring(q.part,1,8)
,q.v1ds
,q.units_each
) p
WHERE
qstat LIKE 'Submitted%'

View File

@ -1,9 +0,0 @@
SELECT * FROM
pricequote.single_price_call(
'GRIF0001' ,
'GRIF0001' ,
'XNS0T1G3G18B096' ,
'XNS0T1G3',
'v1:B.L.PLT..',
9600
)

View File

@ -1,109 +0,0 @@
CREATE OR ALTER PROCEDURE pricing.process_queue
AS
BEGIN
SET NOCOUNT ON;
--------------------------------------------------------------------------------
-- Step 1: Insert input row into real queue table
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Step 2: Enrich the row with chan, tier, cust, pltq
--------------------------------------------------------------------------------
UPDATE q
SET
q.chan =
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN
CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN 'WHS'
ELSE 'DRP'
END
ELSE 'DIR'
END,
q.tier =
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIR' THEN bc.tier
ELSE ISNULL(sc.tier, bc.tier)
END,
q.cust =
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN
CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN q.ship
ELSE q.ship
END
ELSE q.bill
END,
q.pltq = i.mpck
FROM
pricing.price_queue q
LEFT JOIN rlarp.cust bc ON bc.code = q.bill
LEFT JOIN rlarp.cust sc ON sc.code = q.ship
LEFT JOIN CMSInterfaceIn.[CMS.CUSLG].itemm i ON i.item = q.part;
--------------------------------------------------------------------------------
-- Step 3: Apply pricing from target_prices
--------------------------------------------------------------------------------
DECLARE @updated TABLE (
id BIGINT,
bill VARCHAR(100),
ship VARCHAR(100),
part VARCHAR(100),
stlc VARCHAR(100),
v1ds VARCHAR(100),
vol NUMERIC(18,6),
chan VARCHAR(50),
cust VARCHAR(100),
tier VARCHAR(50),
pltq NUMERIC(18,6),
price NUMERIC(18,6),
expl NVARCHAR(MAX)
);
UPDATE q
SET
q.price = tp.price,
q.expl = (
SELECT
'target price' AS [source],
FLOOR(q.vol / NULLIF(q.pltq, 0)) AS [calculated_pallets],
ROUND(q.vol / NULLIF(q.pltq, 0), 5) AS [exact_pallets],
CONCAT(tp.lower_bound, '-', ISNULL(CAST(tp.upper_bound AS VARCHAR), '')) AS [volume range],
q.cust AS [customer],
q.chan AS [channel],
q.tier AS [tier],
JSON_QUERY(tp.math) AS [target math] -- important if math is JSON
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
)
OUTPUT
inserted.id,
inserted.bill,
inserted.ship,
inserted.part,
inserted.stlc,
inserted.v1ds,
inserted.vol,
inserted.chan,
inserted.cust,
inserted.tier,
inserted.pltq,
inserted.price,
inserted.expl
INTO @updated
FROM pricing.price_queue q
INNER JOIN pricing.target_prices tp ON
q.stlc = tp.stlc
AND q.v1ds = tp.ds
AND q.chan = tp.chan
AND q.tier = tp.tier
AND FLOOR(q.vol / NULLIF(q.pltq, 0)) >= tp.lower_bound
AND (
tp.upper_bound IS NULL OR FLOOR(q.vol / NULLIF(q.pltq, 0)) < tp.upper_bound
);
--------------------------------------------------------------------------------
-- Step 4: Return just the enriched row
--------------------------------------------------------------------------------
SELECT * FROM @updated;
END;

View File

@ -1,69 +0,0 @@
CREATE OR REPLACE FUNCTION pricequote.process_queue()
RETURNS SETOF pricequote.price_queue
LANGUAGE plpgsql
AS $$
BEGIN
--------------------------------------------------------------------------------
-- Step 1: Set channel, tier, and pallet quantity
--------------------------------------------------------------------------------
UPDATE pricequote.price_queue s
SET
chan = cr.chan,
tier = cr.tier,
pltq = cr.mpck
FROM (
SELECT
q.bill,
q.ship,
q.part,
i.mpck,
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN
CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN 'WHS'
ELSE 'DRP'
END
ELSE 'DIR'
END AS chan,
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIR' THEN bc.tier
ELSE COALESCE(sc.tier, bc.tier)
END AS tier
FROM pricequote.price_queue q
LEFT JOIN rlarp.cust bc ON bc.code = q.bill
LEFT JOIN rlarp.cust sc ON sc.code = q.ship
LEFT JOIN "CMS.CUSLG".itemm i ON i.item = q.part
) cr
WHERE
cr.bill = s.bill AND
COALESCE(cr.ship, '') = COALESCE(s.ship, '') AND
cr.part = s.part;
--------------------------------------------------------------------------------
-- Step 2: Set price and explanation from target_prices, return touched rows
--------------------------------------------------------------------------------
RETURN QUERY
WITH updated AS (
UPDATE pricequote.price_queue q
SET
price = tp.price,
expl = jsonb_build_object(
'source', 'target price',
'calculated_pallets', FLOOR(q.vol / NULLIF(q.pltq, 0))::INT,
'exact_pallets', ROUND(q.vol / NULLIF(q.pltq, 0), 5),
'volume range', tp.vol
)
FROM pricequote.target_prices tp
WHERE
q.stlc = tp.stlc
AND q.v1ds = tp.ds
AND q.chan = tp.chan
AND q.tier = tp.tier
AND tp.vol @> FLOOR(q.vol / NULLIF(q.pltq, 0))::INT
RETURNING q.*
)
SELECT * FROM updated;
END;
$$;

View File

@ -1,69 +0,0 @@
CREATE OR REPLACE PROCEDURE pricequote.process_queue_proc()
LANGUAGE plpgsql
AS $$
BEGIN
--------------------------------------------------------------------------------
-- Step 1: Set channel, tier, and pallet quantity
--------------------------------------------------------------------------------
UPDATE pricequote.price_queue s
SET
chan = cr.chan,
tier = cr.tier,
pltq = cr.mpck,
cust = cr.cust
FROM (
SELECT
q.bill,
q.ship,
q.part,
i.mpck,
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN
CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN 'WHS'
ELSE 'DRP'
END
ELSE 'DIR'
END AS chan,
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIR' THEN bc.tier
ELSE COALESCE(sc.tier, bc.tier)
END AS tier,
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIR' THEN bc.dba
ELSE COALESCE(sc.dba, bc.dba)
END AS cust
FROM pricequote.price_queue q
LEFT JOIN rlarp.cust bc ON bc.code = q.bill
LEFT JOIN rlarp.cust sc ON sc.code = q.ship
LEFT JOIN "CMS.CUSLG".itemm i ON i.item = q.part
) cr
WHERE
cr.bill = s.bill AND
COALESCE(cr.ship, '') = COALESCE(s.ship, '') AND
cr.part = s.part;
--------------------------------------------------------------------------------
-- Step 2: Set price and explanation from target_prices
--------------------------------------------------------------------------------
UPDATE pricequote.price_queue q
SET
price = tp.price,
expl = jsonb_build_object(
'source', 'target price',
'calculated_pallets', FLOOR(q.vol / NULLIF(q.pltq, 0))::INT,
'exact_pallets', ROUND(q.vol / NULLIF(q.pltq, 0), 5),
'volume range', tp.vol
)
FROM pricequote.target_prices tp
WHERE
q.stlc = tp.stlc
AND q.v1ds = tp.ds
AND q.chan = tp.chan
AND q.tier = tp.tier
AND tp.vol @> FLOOR(q.vol / NULLIF(q.pltq, 0))::INT;
END;
$$;

View File

@ -1,164 +0,0 @@
DROP FUNCTION pricequote.build_pricing_path;
CREATE OR REPLACE FUNCTION pricequote.build_pricing_path(
_json JSONB
)
RETURNS TABLE (
stlc TEXT
,seq BIGINT
,srtcode TEXT
,ds TEXT
,chan TEXT
,tier TEXT
,vol INT4RANGE
,func TEXT
,val NUMERIC
,price NUMERIC
,math TEXT[]
,lastflag BOOLEAN
)
LANGUAGE plpgsql AS
$$
BEGIN
RETURN QUERY
WITH RECURSIVE
-- 1⃣ Parse JSONB into rows of (entity, attr, val)
parsed AS (
SELECT
e.entity,
COALESCE(e.attr, '') AS attr,
e.val,
e.func
FROM jsonb_to_recordset(_json)
AS e(entity TEXT, attr TEXT, val NUMERIC, func TEXT)
),
-- 2⃣ Attach sequence & func from master option_sequence table
sequenced AS (
SELECT
p.entity,
p.attr,
p.val,
p.func,
s.DOMAIN,
DENSE_RANK() OVER (ORDER BY s.seq) AS seq,
ROW_NUMBER() OVER (PARTITION BY p.entity ORDER BY COALESCE(p.val,0) ASC) srt
FROM parsed p
JOIN pricequote.option_sequence s
ON p.entity = s.entity
)
--select * from sequenced ORDER BY seq, srt
-- 3⃣ Recursively accumulate pricing path
,combos AS (
-- 🚀 Base case: first in sequence
SELECT
s.entity,
s.attr,
s.seq,
to_char(s.srt,'FM000') srtcode,
'' ds,
'' chan,
'' tier,
null::TEXT vol,
s.func,
s.val,
s.val agg,
-- jsonb_build_array(jsonb_build_object('entity',s.entity,'attr',s.attr,'function',s.func, 'val',s.val,'seq',s.seq)) math
ARRAY[
CASE
WHEN s.func = 'Price' THEN
RPAD(s.entity || ':' || s.attr, 17, ' ') || ' + ' || LPAD(to_char(s.val, 'FM9999999990.00000'), 10, ' ')
WHEN s.func = 'Factor' THEN
RPAD(s.entity || ':' || s.attr, 17, ' ') || ' x ' || LPAD(to_char(s.val, 'FM9999999990.00000'), 10, ' ')
ELSE
RPAD(s.entity || ':' || s.attr, 17, ' ') || ' ' || LPAD(to_char(s.val, 'FM9999999990.00000'), 10, ' ')
END
] math
FROM
sequenced s
WHERE
s.seq = (SELECT MIN(x.seq) FROM sequenced x)
UNION ALL
-- 🔁 Recursive step: process next in sequence
SELECT
c.entity,
c.attr,
o.seq,
c.srtcode || '.' || to_char(o.srt,'FM000'),
c.ds || CASE WHEN o.DOMAIN = 'Product' THEN '.' || o.attr ELSE '' END ds,
CASE WHEN o.DOMAIN = 'Channel' THEN o.attr ELSE c.chan END chan,
CASE WHEN o.DOMAIN = 'Tier' THEN o.attr ELSE c.tier END tier,
CASE WHEN o.DOMAIN = 'Volume' THEN o.attr ELSE c.vol END vol,
o.func,
o.val,
CASE o.func WHEN 'Price' THEN c.agg + o.val WHEN 'Factor' THEN c.agg * o.val END agg,
-- c.math || jsonb_build_array(jsonb_build_object('entity',o.entity,'attr',o.attr,'function',o.func, 'val',o.val,'seq',o.seq)) math,
CASE WHEN (o.func = 'Price' AND o.val <> 0) OR (o.func = 'Factor' AND o.val <> 1) THEN
c.math ||
ARRAY[
CASE
WHEN o.func = 'Price' THEN
RPAD(o.entity || ':' || o.attr, 17, ' ') || ' + ' || LPAD(to_char(o.val, 'FM9999999990.00000'), 10, ' ')
WHEN o.func = 'Factor' THEN
RPAD(o.entity || ':' || o.attr, 17, ' ') || ' x ' || LPAD(to_char(o.val, 'FM9999999990.00000'), 10, ' ')
ELSE
RPAD(o.entity || ':' || o.attr, 17, ' ') || ' ' || LPAD(to_char(o.val, 'FM9999999990.00000'), 10, ' ')
END
]
ELSE
c.math
END math
FROM
combos c
JOIN sequenced o ON
o.seq = c.seq + 1
)
SELECT
-- c.entity
c.attr
,c.seq
,c.srtcode
,'v1:'||SUBSTRING(c.ds,2,100) ds
,c.chan
,c.tier
-- ,c.vol
,CASE
WHEN c.vol ~ '^[0-9]+-[0-9]+$' THEN
int4range(
split_part(c.vol, '-', 1)::int,
split_part(c.vol, '-', 2)::int,
'[)'
)
WHEN c.vol ~ '^[0-9]+$' THEN
int4range(
c.vol::int,
NULL,
'[)'
)
ELSE NULL
END AS vol
,c.func
,c.val
,c.agg
,c.math
,c.seq = (SELECT max(x.seq) FROM sequenced x) lastflag
FROM
combos c /*WHERE seq = (SELECT max(seq) FROM sequenced)*/
ORDER BY
c.srtcode ASC;
END;
$$;
/*
Anchor:EU170S50 + 0.08
Color Tier:P x 1.30
Branding: + 0.00
Packaging:SLV + 0.00
Suffix:PCR x 1.00
Accessories: + 0.00
Channel:WHS + 0.00
Volume:8 x 1.00
-----------------------
0.104
*/

View File

@ -1,104 +0,0 @@
DROP FUNCTION IF EXISTS rlarp.get_option_costs_priceg;
CREATE FUNCTION rlarp.get_option_costs_priceg(_priceg text, _majg text)
RETURNS TABLE (
stlc text
,coltier text
,branding text
,accs_ps text
,acc_list text
,suffix text
,uomp text
,avgsc numeric
,avgfc numeric
,weight numeric
,target numeric
,futmargin numeric
)
LANGUAGE plpgsql AS
$function$
BEGIN
RETURN QUERY
WITH
sel AS (
SELECT
i.stlc
,i.coltier
,i.branding
--,accs
,i.accs_ps
,i.acc_list
,i.suffix
--,COALESCE(accs_ps,accs) accs_c
--,jsonb_agg(DISTINCT r.aomult) cavitation
--,jsonb_agg(DISTINCT r.aoctme) cyclet
--,jsonb_arr_aggcd(mino) min_ord
,i.uomp
--,jsonb_agg(DISTINCT aplnt) aplnt
--,jsonb_agg(DISTINCT colc) colc
--,jsonb_agg(DISTINCT substring(item,12,case when branding = '' THEN 7 ELSE 4 end)) items
--,jsonb_agg(DISTINCT majg) majgs
--,jsonb_agg(DISTINCT assc) accs
,round(avg(curstdus),5) avgsc
,round(avg(futstdus),5) avgfc
,round(avg(nwht),5) avgwt
,i.v1ds
FROM
"CMS.CUSLG".itemm i
WHERE
true
--stlc ~ 'TWA10200'
--AND branding = ''
AND aplnt <> 'I'
AND COALESCE(i.uomp,'') <> ''
--AND branding = ''
GROUP BY
i.stlc
,i.coltier
,i.uomp
,i.branding
,i.acc_list
,i.accs_ps
,i.suffix
,i.v1ds
ORDER BY
i.stlc ASC
)
SELECT
sel.stlc
,sel.coltier
,sel.branding
,sel.accs_ps
,sel.acc_list
,sel.suffix
,sel.uomp
,sel.avgsc
,sel.avgfc
,sel.avgwt
,t.price
,round(CASE WHEN coalesce(t.price,0) <> 0 THEN (t.price-COALESCE(sel.avgfc,0))/t.price ELSE 0 END,3) futmarg
FROM
sel
LEFT OUTER JOIN pricequote.target_prices t ON
sel.stlc = t.stlc
AND sel.v1ds = t.ds
AND t.chan = 'DIR'
AND COALESCE(t.tier,'') IN ('1')
AND 24 <@ t.vol
-- LEFT OUTER JOIN pricequote.market_setavgprice t ON
-- t.mold = sel.stlc
-- AND t.data_segment = sel.v1ds
-- AND t.season = 2025
-- AND t.chan = 'DIRECT'
-- AND t.country = 'ALL'
-- AND t.geo = 'ALL'
-- AND t.region = 'ALL'
WHERE
sel.stlc IN (SELECT DISTINCT m.stlc FROM rlarp.molds m WHERE m.priceg ~ _priceg AND m.majg ~ _majg);
END
$function$

View File

@ -1,194 +0,0 @@
DROP FUNCTION rlarp.get_options_merged;
CREATE OR REPLACE FUNCTION rlarp.get_options_merged(
_priceg TEXT,
_majg TEXT,
existing_json JSONB
)
RETURNS TABLE (
entity TEXT,
attr TEXT,
val NUMERIC,
func TEXT
)
LANGUAGE plpgsql AS
$$
BEGIN
RETURN QUERY
WITH
-- 1⃣ Parse existing pricing from JSONB
existing AS (
SELECT
e.entity,
COALESCE(e.attr, '') AS attr,
e.val,
e.func
FROM jsonb_to_recordset(existing_json)
AS e(entity TEXT, attr TEXT, val NUMERIC, func TEXT)
)
,items AS (
SELECT
item
FROM
"CMS.CUSLG".itemm
WHERE
stlc IN (SELECT DISTINCT stlc FROM "CMS.CUSLG".itemm WHERE pricegroup ~ _priceg AND majg ~ _majg)
AND aplnt <> 'I'
)
-- 2⃣ Build raw stack without hard-coded func
,stack AS (
-- Anchor
SELECT 'Anchor' AS entity, stlc AS attr, 0::numeric AS val
FROM "CMS.CUSLG".itemm
WHERE item IN (
SELECT item
FROM "CMS.CUSLG".itemm
WHERE item IN (SELECT item FROM items)
)
GROUP BY stlc
UNION ALL
-- Color Tier
SELECT 'Color Tier' AS entity, coltier AS attr, 1 AS val
FROM "CMS.CUSLG".itemm
WHERE item IN (
SELECT item
FROM "CMS.CUSLG".itemm
WHERE item IN (SELECT item FROM items)
)
GROUP BY coltier
UNION ALL
-- Branding
SELECT 'Branding' AS entity, COALESCE(substring(branding,1,1), '') AS attr, 0 AS val
FROM "CMS.CUSLG".itemm
WHERE item IN (
SELECT item
FROM "CMS.CUSLG".itemm
WHERE item IN (SELECT item FROM items)
)
GROUP BY COALESCE(substring(branding,1,1), '')
UNION ALL
-- Packaging
SELECT 'Packaging' AS entity, COALESCE(uomp, '') AS attr, 0 AS val
FROM "CMS.CUSLG".itemm
WHERE item IN (
SELECT item
FROM "CMS.CUSLG".itemm
WHERE item IN (SELECT item FROM items)
)
GROUP BY COALESCE(uomp, '')
UNION ALL
-- Accessories
SELECT 'Accessories' AS entity, COALESCE(accs_ps, '') AS attr, 0 AS val
FROM "CMS.CUSLG".itemm
WHERE item IN (
SELECT item
FROM "CMS.CUSLG".itemm
WHERE item IN (SELECT item FROM items)
)
GROUP BY COALESCE(accs_ps, '')
UNION ALL
-- Suffix
SELECT 'Suffix' AS entity, COALESCE(suffix, '') AS attr, 1 AS val
FROM "CMS.CUSLG".itemm
WHERE item IN (
SELECT item
FROM "CMS.CUSLG".itemm
WHERE item IN (SELECT item FROM items)
)
GROUP BY COALESCE(suffix, '')
UNION ALL
-- Channel
SELECT 'Channel' AS entity, x.chan AS attr, 0 AS val
FROM (VALUES ('DIR'), ('DRP'), ('WHS')) AS x(chan)
UNION ALL
-- Customer Tier
SELECT 'Tier' AS entity, x.tier AS attr, 0 AS val
FROM (VALUES ('1'), ('2'), ('3')) AS x(tier)
UNION ALL
-- Volume
SELECT 'Volume' AS entity, x.chan AS attr, 0 AS val
FROM (VALUES ('0-1'),('1-8'),('8-24'),('24')) AS x(chan)
),
-- 3⃣ Attach pricing func and sequence from option_sequence
stack_with_meta AS (
SELECT
s.entity,
COALESCE(s.attr, '') AS attr,
s.val,
os.func,
os.seq
FROM stack s
LEFT JOIN pricequote.option_sequence os
ON s.entity = os.entity
),
-- 4⃣ Merge: master rows with overrides
overridden AS (
SELECT
s.entity,
s.attr,
COALESCE(e.val, s.val) AS val,
s.func,
s.seq
FROM stack_with_meta s
LEFT JOIN existing e
ON s.entity = e.entity
AND COALESCE(s.attr, '') = COALESCE(e.attr, '')
AND s.func = e.func
),
-- 5⃣ Extras in saved JSON but not in master
extras AS (
SELECT
e.entity,
COALESCE(e.attr, '') AS attr,
e.val,
e.func,
os.seq
FROM existing e
LEFT JOIN stack_with_meta s
ON e.entity = s.entity
AND COALESCE(e.attr, '') = COALESCE(s.attr, '')
AND e.func = s.func
LEFT JOIN pricequote.option_sequence os
ON e.entity = os.entity
WHERE s.entity IS NULL
),
-- 6⃣ Combine both sources
combined AS (
SELECT o.entity, o.attr, o.val, o.func, o.seq FROM overridden o
UNION ALL
SELECT e.entity, e.attr, e.val, e.func, e.seq FROM extras e
)
-- 7⃣ Return ordered by sequence
SELECT
combined.entity,
combined.attr,
combined.val,
combined.func
FROM combined
ORDER BY combined.seq NULLS LAST, combined.entity, combined.attr;
END;
$$;

View File

@ -1,27 +0,0 @@
CREATE OR ALTER FUNCTION dbo.LEAST_NUMERIC205(
@a NUMERIC(20,5),
@b NUMERIC(20,5)
)
RETURNS NUMERIC(20,5)
AS
BEGIN
RETURN CASE
WHEN @a IS NULL THEN @b
WHEN @b IS NULL THEN @a
WHEN @a < @b THEN @a ELSE @b
END
END
CREATE OR ALTER FUNCTION dbo.GREATEST_NUMERIC205(
@a NUMERIC(20,5),
@b NUMERIC(20,5)
)
RETURNS NUMERIC(20,5)
AS
BEGIN
RETURN CASE
WHEN @a IS NULL THEN @b
WHEN @b IS NULL THEN @a
WHEN @a > @b THEN @a ELSE @b
END
END

View File

@ -1,84 +0,0 @@
CREATE OR ALTER FUNCTION pricing.guidance_logic (
@target_price NUMERIC(20,5),
@last_price NUMERIC(20,5),
@list_price NUMERIC(20,5),
@last_date DATE
)
RETURNS @result TABLE (
guidance_price NUMERIC(20,5),
guidance_reason NVARCHAR(MAX)
)
AS
BEGIN
DECLARE @price NUMERIC(20,5);
DECLARE @reason NVARCHAR(MAX) = '';
DECLARE @floored NUMERIC(20,5);
DECLARE @capped NUMERIC(20,5);
DECLARE @use_last_price BIT = 0;
-- Determine if last price is recent (within last 2 years)
IF @last_price IS NOT NULL AND @last_date IS NOT NULL AND @last_date > DATEADD(YEAR, -2, CAST(GETDATE() AS DATE))
SET @use_last_price = 1;
IF @target_price IS NOT NULL AND @use_last_price = 1
BEGIN
SET @floored = dbo.GREATEST_NUMERIC205(@target_price, @last_price * 0.95);
SET @capped = dbo.LEAST_NUMERIC205(@floored, @last_price);
SET @price = dbo.LEAST_NUMERIC205(ISNULL(@list_price, 1e9), @capped);
IF @price = @last_price
BEGIN
SET @reason = 'Cap at last price';
END
ELSE
BEGIN
SET @reason = 'Using target price';
IF @target_price < @last_price * 0.95
SET @reason += ', floored to 5% below last price';
IF @target_price > @last_price
SET @reason += ', capped to not exceed last price';
IF @list_price IS NOT NULL AND @price = @list_price AND @target_price > @list_price
SET @reason += ', capped to not exceed list price';
END
END
ELSE IF @use_last_price = 1
BEGIN
SET @price = @last_price;
SET @reason = 'Last price - no target';
END
ELSE IF @target_price IS NOT NULL
BEGIN
SET @price = @target_price;
IF @last_price IS NOT NULL AND @last_date IS NOT NULL
BEGIN
SET @reason = CONCAT(
'Last price ignored (too old: ',
CONVERT(NVARCHAR(10), @last_date, 120),
'), using target price'
);
END
ELSE
BEGIN
SET @reason = 'Target price - no prior sale';
END
END
ELSE
BEGIN
SET @price = NULL;
IF @last_price IS NOT NULL AND @last_date IS NOT NULL
BEGIN
SET @reason = CONCAT(
'Last price ignored (too old: ',
CONVERT(NVARCHAR(10), @last_date, 120),
'), no pricing available'
);
END
ELSE
BEGIN
SET @reason = 'No pricing available';
END
END
INSERT INTO @result VALUES (@price, @reason);
RETURN;
END

View File

@ -1,74 +0,0 @@
CREATE OR REPLACE FUNCTION pricequote.guidance_logic(
_target_price NUMERIC(20,5),
_last_price NUMERIC(20,5),
_list_price NUMERIC(20,5),
_last_date DATE
)
RETURNS TABLE (
guidance_price NUMERIC(20,5),
guidance_reason TEXT
) AS $$
DECLARE
_price NUMERIC(20,5);
_reason TEXT := '';
_floored NUMERIC(20,5);
_capped NUMERIC(20,5);
_use_last_price BOOLEAN := FALSE;
BEGIN
-- Evaluate whether last price is recent enough
IF _last_price IS NOT NULL AND _last_date IS NOT NULL AND _last_date > CURRENT_DATE - INTERVAL '2 years' THEN
_use_last_price := TRUE;
END IF;
IF _target_price IS NOT NULL AND _use_last_price THEN
_floored := GREATEST(_target_price, _last_price * 0.95);
_capped := LEAST(_floored, _last_price);
_price := LEAST(COALESCE(_list_price, 1e9), _capped);
IF _price = _last_price THEN
_reason := 'Cap at last price';
ELSE
_reason := 'Using target price';
IF _target_price < _last_price * 0.95 THEN
_reason := _reason || ', floored to 5% below last price';
END IF;
IF _target_price > _last_price THEN
_reason := _reason || ', capped to not exceed last price';
END IF;
IF _list_price IS NOT NULL AND _price = _list_price AND _target_price > _list_price THEN
_reason := _reason || ', capped to not exceed list price';
END IF;
END IF;
ELSIF _use_last_price THEN
_price := _last_price;
_reason := 'Last price - no target';
ELSIF _target_price IS NOT NULL THEN
_price := _target_price;
IF _last_price IS NOT NULL AND _last_date IS NOT NULL THEN
_reason := format(
'Last price ignored (too old: %s), using target price',
to_char(_last_date, 'YYYY-MM-DD')
);
ELSE
_reason := 'Target price - no prior sale';
END IF;
ELSE
_price := NULL;
IF _last_price IS NOT NULL AND _last_date IS NOT NULL THEN
_reason := format(
'Last price ignored (too old: %s), no pricing available',
to_char(_last_date, 'YYYY-MM-DD')
);
ELSE
_reason := 'No pricing available';
END IF;
END IF;
RETURN QUERY SELECT _price, _reason;
END;
$$ LANGUAGE plpgsql;

View File

@ -1,42 +0,0 @@
CREATE OR REPLACE PROCEDURE pricequote.load_target_prices(input_json JSONB)
LANGUAGE plpgsql
AS $$
BEGIN
-- 1⃣ Materialize the function output once
CREATE TEMP TABLE temp_new_data ON COMMIT DROP AS
SELECT
stlc, ds, chan, tier, vol, price, math
FROM
pricequote.build_pricing_path(input_json)
WHERE
lastflag;
-- 2⃣ Delete matching old rows
DELETE FROM pricequote.target_prices t
USING (
SELECT DISTINCT stlc FROM temp_new_data
) to_delete
WHERE t.stlc = to_delete.stlc;
-- 3⃣ Insert new rows
INSERT INTO pricequote.target_prices (stlc, ds, chan, tier, vol, price, math)
SELECT stlc, ds, chan, tier, vol, price, math FROM temp_new_data;
END;
$$;
/*
SELECT
stlc,
ds,
chan,
tier,
vol,
price,
-- array_to_string(math, E'\n') AS math_text
jsonb_build_object('target math',to_jsonb(math)) AS math_text
FROM
pricequote.build_pricing_path('[{"entity":"Anchor","attr":"JNS0T1G3","val":"0.08","func":"Price"},{"entity":"Anchor","attr":"XNS0T1G3","val":"0.08","func":"Price"},{"entity":"Anchor","attr":"XRD16002","val":"0.085","func":"Price"},{"entity":"Anchor","attr":"EU170S50","val":"0.085","func":"Price"},{"entity":"Anchor","attr":"EU170T50","val":"0.095","func":"Price"},{"entity":"Anchor","attr":"AZN06501","val":"0.12","func":"Price"},{"entity":"Anchor","attr":"1CP07010","val":"0.125","func":"Price"},{"entity":"Anchor","attr":"1CP06060","val":"0.13","func":"Price"},{"entity":"Anchor","attr":"AZA06500","val":"0.15","func":"Price"},{"entity":"Color Tier","attr":"B","val":1,"func":"Factor"},{"entity":"Color Tier","attr":"T","val":1.1,"func":"Factor"},{"entity":"Color Tier","attr":"L","val":1.1,"func":"Factor"},{"entity":"Color Tier","attr":"M","val":1.2,"func":"Factor"},{"entity":"Color Tier","attr":"P","val":1.3,"func":"Factor"},{"entity":"Color Tier","attr":"C","val":1.35,"func":"Factor"},{"entity":"Branding","val":"0","func":"Price"},{"entity":"Branding","attr":"L","val":"0.03","func":"Price"},{"entity":"Branding","attr":"P","val":"0.08","func":"Price"},{"entity":"Packaging","attr":"BDL","val":"0.002","func":"Price"},{"entity":"Packaging","attr":"CSE","val":"0.005","func":"Price"},{"entity":"Packaging","attr":"PC","val":"0.005","func":"Price"},{"entity":"Packaging","attr":"PLT","val":"0","func":"Price"},{"entity":"Packaging","attr":"SLV","val":"0.002","func":"Price"},{"entity":"Suffix","val":1,"func":"Factor"},{"entity":"Accessories","val":"0","func":"Price"},{"entity":"Channel","attr":"DIR","val":1,"func":"Factor"},{"entity":"Channel","attr":"DRP","val":1,"func":"Factor"},{"entity":"Channel","attr":"WHS","val":1.2,"func":"Factor"},{"entity":"Volume","attr":24,"val":1,"func":"Factor"},{"entity":"Volume","attr":"8-24","val":1.05,"func":"Factor"},{"entity":"Volume","attr":"1-8","val":1.1,"func":"Factor"},{"entity":"Volume","attr":"0-1","val":1.2,"func":"Factor"},{"entity":"Tier","attr":1,"val":1,"func":"Factor"},{"entity":"Tier","attr":2,"val":1.05,"func":"Factor"},{"entity":"Tier","attr":3,"val":1.07,"func":"Factor"}]'::jsonb)
WHERE
lastflag
*/

View File

@ -1,270 +0,0 @@
CREATE OR ALTER PROCEDURE pricing.single_price_call
@bill VARCHAR(100),
@ship VARCHAR(100),
@part VARCHAR(100),
@v1ds VARCHAR(100),
@vol NUMERIC(18,6)
AS
BEGIN
SET NOCOUNT ON;
-- Working table for enriched pricing request
DECLARE @queue TABLE (
bill VARCHAR(100),
ship VARCHAR(100),
part VARCHAR(100),
stlc VARCHAR(100),
v1ds VARCHAR(100),
vol NUMERIC(18,6),
chan VARCHAR(50),
cust VARCHAR(100),
tier VARCHAR(50),
pltq NUMERIC(18,6),
volume_range TEXT,
plevel NVARCHAR(20),
listprice NUMERIC(20,5),
listcode VARCHAR(10),
hist NVARCHAR(MAX),
last_price NUMERIC(20,5),
last_date DATE,
last_order NVARCHAR(10),
last_quote NVARCHAR(10),
tprice NUMERIC(20,5),
guidance_price NUMERIC(20,5),
guidance_reason NVARCHAR(MAX),
expl NVARCHAR(MAX),
expl_pretty NVARCHAR(MAX)
);
--------------------------------------------------------------------------------
-- Step 1: Seed the queue with input row
--------------------------------------------------------------------------------
INSERT INTO @queue (bill, ship, part, v1ds, vol, expl)
VALUES (@bill, @ship, @part, @v1ds, @vol, '{}');
--------------------------------------------------------------------------------
-- Step 2: Enrich with channel, tier, customer, pack quantity, and price level
--------------------------------------------------------------------------------
UPDATE q
SET
chan =
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN
CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN 'WHS'
ELSE 'DRP'
END
ELSE 'DIR'
END,
tier =
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIR' THEN bc.tier
ELSE ISNULL(sc.tier, bc.tier)
END,
cust =
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN
CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN bc.dba
ELSE sc.dba
END
ELSE q.bill
END,
pltq = i.mpck,
plevel =
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN
CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN sc.plevel
ELSE bc.plevel
END
ELSE bc.plevel
END,
stlc = substring(q.part,1,8)
FROM @queue q
LEFT JOIN rlarp.cust bc ON bc.code = q.bill
LEFT JOIN rlarp.cust sc ON sc.code = q.ship
LEFT JOIN CMSInterfaceIn.[CMS.CUSLG].itemm i ON i.item = q.part;
--------------------------------------------------------------------------------
-- Step 3: Apply target price and embed metadata as JSON
--------------------------------------------------------------------------------
UPDATE q
SET
tprice = tp.price,
expl = (
SELECT
'target price' AS [source],
tp.price AS [target_price],
FLOOR(q.vol / NULLIF(q.pltq, 0)) AS [calculated_pallets],
CAST(ROUND(q.vol / NULLIF(q.pltq, 0), 5) AS NUMERIC(20,5)) AS [exact_pallets],
CONCAT(tp.lower_bound, '-', ISNULL(CAST(tp.upper_bound AS VARCHAR), '')) AS [volume_range],
q.cust AS [customer],
q.chan AS [channel],
TRIM(q.tier) AS [tier],
JSON_QUERY(tp.math) AS [target_math]
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
),
volume_range = CONCAT(tp.lower_bound, '-', ISNULL(CAST(tp.upper_bound AS VARCHAR), ''))
FROM @queue q
INNER JOIN pricing.target_prices tp ON
q.stlc = tp.stlc
AND q.v1ds = tp.ds
AND q.chan = tp.chan
AND q.tier = tp.tier
AND FLOOR(q.vol / NULLIF(q.pltq, 0)) >= tp.lower_bound
AND (
tp.upper_bound IS NULL OR FLOOR(q.vol / NULLIF(q.pltq, 0)) < tp.upper_bound
);
--------------------------------------------------------------------------------
-- Step 4: Pull last sale data and embed in columns and JSON
--------------------------------------------------------------------------------
UPDATE q
SET
hist = JSON_MODIFY('{}', '$.full_history', JSON_QUERY(lp.part_stats)),
last_price = j.price,
last_date = j.odate,
last_order = j.ordnum,
last_quote = j.quoten,
expl = JSON_MODIFY(
JSON_MODIFY(
JSON_MODIFY(
JSON_MODIFY(
ISNULL(q.expl, '{}'),
'$.last_price', j.price
),
'$.last_date', CONVERT(NVARCHAR(10), j.odate, 23)
),
'$.last_order', j.ordnum
),
'$.last_quote', j.quoten
)
FROM @queue q
JOIN pricing.lastprice lp
ON lp.customer = q.cust
AND lp.mold = SUBSTRING(q.part, 1, 8)
OUTER APPLY (
SELECT TOP 1 *
FROM OPENJSON(lp.part_stats) AS p
OUTER APPLY OPENJSON(p.value)
WITH (
qty NUMERIC(20,5),
price NUMERIC(20,5),
odate DATE,
ordnum INT,
quoten INT
) AS j
WHERE p.[key] COLLATE SQL_Latin1_General_CP1_CI_AS = q.part
ORDER BY j.odate DESC
) AS j;
--------------------------------------------------------------------------------
-- Step 5: Add list price info from external pricelist
--------------------------------------------------------------------------------
WITH ranked_prices AS (
SELECT
q.bill, q.ship, q.part, q.stlc, q.v1ds, q.vol,
CAST(p.price AS NUMERIC(20,5)) AS price,
p.jcplcd,
ROW_NUMBER() OVER (
PARTITION BY q.bill, q.ship, q.part, q.stlc, q.v1ds, q.vol
ORDER BY p.price ASC
) AS rn
FROM @queue q
INNER JOIN CMSInterfaceIn."CMS.CUSLG".IPRCBHC i
ON TRIM(i.jbplvl) = TRIM(q.plevel)
AND CAST(GETDATE() AS DATE) BETWEEN i.jbfdat AND i.jbtdat
INNER JOIN pricing.pricelist_ranged p
ON p.jcplcd = TRIM(i.jbplcd)
AND p.jcpart = q.part
AND q.vol >= p.vb_from
AND (p.vb_to IS NULL OR q.vol < p.vb_to)
)
UPDATE q
SET expl = JSON_MODIFY(
JSON_MODIFY(
ISNULL(q.expl, '{}'),
'$.list_price', rp.price
),
'$.list_code', rp.jcplcd
)
,listcode = rp.jcplcd
,listprice = rp.price
FROM @queue q
JOIN ranked_prices rp
ON q.bill = rp.bill
AND q.ship = rp.ship
AND q.part = rp.part
AND q.stlc = rp.stlc
AND q.v1ds = rp.v1ds
AND q.vol = rp.vol
AND rp.rn = 1;
--------------------------------------------------------------------------------
-- Step 6: Compute guidance price and logic, and embed in JSON
--------------------------------------------------------------------------------
UPDATE q
SET
guidance_price = g.guidance_price,
guidance_reason = g.guidance_reason,
expl = JSON_MODIFY(
JSON_MODIFY(
ISNULL(q.expl, '{}'),
'$.guidance_reason',
g.guidance_reason
),
'$.guidance_price',
g.guidance_price
)
FROM @queue q
CROSS APPLY pricing.guidance_logic(
CAST(JSON_VALUE(q.expl, '$.target_price') AS NUMERIC(20,5)),
CAST(JSON_VALUE(q.expl, '$.last_price') AS NUMERIC(20,5)),
CAST(JSON_VALUE(q.expl, '$.list_price') AS NUMERIC(20,5)),
CAST(JSON_VALUE(q.expl, '$.last_date') AS DATE)
) g;
--------------------------------------------------------------------------------
-- Step 7: Clean up for UI
--------------------------------------------------------------------------------
UPDATE q
SET expl_pretty =
(
SELECT
'Target Price' AS [target_price.label],
q.tprice AS [target_price.value],
'Volume Range' AS [volume_range.label],
q.volume_range AS [volume_range.value],
'Channel' AS [channel.label],
q.chan AS [channel.value],
'Tier' AS [tier.label],
q.tier AS [tier.value],
'Last Price' AS [last_price.label],
q.last_price AS [last_price.value],
'Last Date' AS [last_date.label],
q.last_date AS [last_date.value],
'Last Order' AS [last_order.label],
q.last_order AS [last_order.value],
'List Price' AS [list_price.label],
q.listprice AS [list_price.value],
'List Code' AS [list_code.label],
q.listcode AS [list_code.value],
'Guidance Reason' AS [guidance_reason.label],
q.guidance_reason AS [guidance_reason.value],
'Guidance Price' AS [guidance_price.label],
q.guidance_price AS [guidance_price.value]
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
)
FROM @queue q;
--------------------------------------------------------------------------------
-- Final: Return the enriched result row
--------------------------------------------------------------------------------
SELECT * FROM @queue;
END;

View File

@ -1,209 +0,0 @@
DROP FUNCTION IF EXISTS pricequote.single_price_call;
CREATE OR REPLACE FUNCTION pricequote.single_price_call(
_bill TEXT,
_ship TEXT,
_part TEXT,
_stlc TEXT,
_v1ds TEXT,
_vol NUMERIC
)
RETURNS TABLE (
bill TEXT,
ship TEXT,
part TEXT,
stlc TEXT,
v1ds TEXT,
vol NUMERIC,
chan TEXT,
cust TEXT,
tier TEXT,
pltq NUMERIC,
plevel TEXT,
-- hist JSONB,
last_price NUMERIC,
last_date DATE,
last_order TEXT,
last_quote TEXT,
tprice NUMERIC,
guidance_price NUMERIC,
guidance_reason TEXT,
expl JSONB
) AS $$
DECLARE
_pltq NUMERIC;
_chan TEXT;
_tier TEXT;
_cust TEXT;
_plevel TEXT;
_tprice NUMERIC;
_last_price NUMERIC;
_last_date DATE;
_last_order TEXT;
_last_quote TEXT;
_list_price NUMERIC;
_list_code TEXT;
_hist JSONB := '{}'::jsonb;
_expl JSONB := '{}'::jsonb;
_this JSONB := '{}'::jsonb;
_guidance_price NUMERIC;
_guidance_reason TEXT;
_partgroup TEXT;
BEGIN
------------------------------------------------------------------
-- Step 1: Resolve customer metadata
------------------------------------------------------------------
SELECT
i.mpck,
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN
CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN 'WHS'
ELSE 'DRP'
END
ELSE 'DIR'
END,
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIR' THEN bc.tier
ELSE COALESCE(sc.tier, bc.tier)
END,
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN
CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN bc.dba
ELSE sc.dba
END
ELSE bc.dba
END,
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN
CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN sc.plevel
ELSE bc.plevel
END
ELSE bc.plevel
END,
i.partgroup
INTO _pltq, _chan, _tier, _cust, _plevel, _partgroup
FROM rlarp.cust bc
LEFT JOIN rlarp.cust sc ON sc.code = _ship
LEFT JOIN "CMS.CUSLG".itemm i ON i.item = _part
WHERE bc.code = _bill;
-- RAISE NOTICE 'Step 1: %', _expl;
------------------------------------------------------------------
-- Step 2: Target price logic
------------------------------------------------------------------
SELECT tp.price,
jsonb_build_object(
'source', 'target price',
'target_price', tp.price,
'calculated_pallets', FLOOR(_vol / NULLIF(_pltq, 0)),
'exact_pallets', ROUND(_vol / NULLIF(_pltq, 0), 5),
'volume range', tp.vol::TEXT,
'customer', _cust,
'channel', _chan,
'tier', TRIM(_tier),
'target math', tp.math
)
INTO _tprice, _this
FROM pricequote.target_prices tp
WHERE tp.stlc = _stlc
AND tp.ds = _v1ds
AND tp.chan = _chan
AND tp.tier = _tier
AND FLOOR(_vol / NULLIF(_pltq, 0))::int <@ tp.vol;
IF _this IS NOT NULL THEN
_expl := _expl || _this;
END IF;
-- RAISE NOTICE 'Step 2: %', _expl;
------------------------------------------------------------------
-- Step 3: Last sale data
------------------------------------------------------------------
SELECT
(lp.dataseg_stats -> _v1ds) ->> 'price',
(lp.dataseg_stats -> _v1ds) ->> 'odate',
(lp.dataseg_stats -> _v1ds) ->> 'ordnum',
(lp.dataseg_stats -> _v1ds) ->> 'quoten',
lp.dataseg_stats
INTO
_last_price, _last_date, _last_order, _last_quote, _hist
FROM pricequote.lastprice lp
WHERE lp.customer = _cust
AND lp.partgroup = _partgroup;
_expl := _expl || jsonb_build_object(
'last_price', _last_price,
'last_date', _last_date,
'last_order', _last_order,
'last_quote', _last_quote
-- 'full_history_________', _hist
);
-- RAISE NOTICE 'Step 3: %', _expl;
------------------------------------------------------------------
-- Step 4: List price
------------------------------------------------------------------
SELECT
pr.price::numeric(20,5), pr.jcplcd
INTO
_list_price, _list_code
FROM
"CMS.CUSLG".IPRCBHC i
JOIN pricequote.pricelist_ranged pr
ON pr.jcplcd = TRIM(i.jbplcd)
AND pr.jcpart = _part
AND _vol >= pr.vb_from
AND _vol < pr.vb_to
WHERE TRIM(i.jbplvl) = TRIM(_plevel)
AND CURRENT_DATE BETWEEN i.jbfdat AND i.jbtdat
ORDER BY pr.price ASC
LIMIT 1;
_expl := _expl || jsonb_build_object(
'list_price', _list_price,
'list_code', _list_code
);
-- RAISE NOTICE 'Step 4: %', _expl;
------------------------------------------------------------------
-- Step 5: Compute guidance price and embed it
------------------------------------------------------------------
SELECT
gl.guidance_price, gl.guidance_reason
INTO
_guidance_price, _guidance_reason
FROM
pricequote.guidance_logic(_tprice, _last_price, _list_price, _last_date) gl;
_expl := _expl || jsonb_build_object(
'guidance_price', _guidance_price,
'guidance_reason', _guidance_reason
);
-- RAISE NOTICE 'Step 5: %', _expl;
------------------------------------------------------------------
-- Final: Return row
------------------------------------------------------------------
RETURN QUERY
SELECT
_bill, _ship, _part, _stlc, _v1ds, _vol,
_chan, _cust, _tier, _pltq, _plevel,
-- _hist,
_last_price, _last_date, _last_order, _last_quote,
_tprice,
_guidance_price,
_guidance_reason,
_expl;
END;
$$ LANGUAGE plpgsql;

View File

@ -1,164 +0,0 @@
CREATE OR ALTER FUNCTION pricing.single_price_call_fn (
@bill VARCHAR(100),
@ship VARCHAR(100),
@part VARCHAR(100),
@stlc VARCHAR(100),
@v1ds VARCHAR(100),
@vol NUMERIC(18, 6)
)
RETURNS TABLE
AS
RETURN (
WITH queue AS (
SELECT
@bill AS bill,
@ship AS ship,
@part AS part,
@stlc AS stlc,
@v1ds AS v1ds,
@vol AS vol
),
enriched AS (
SELECT
q.*,
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN
CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN 'WHS'
ELSE 'DRP'
END
ELSE 'DIR'
END AS chan,
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIR' THEN bc.tier
ELSE ISNULL(sc.tier, bc.tier)
END AS tier,
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN
CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN bc.dba
ELSE sc.dba
END
ELSE q.bill
END AS cust,
i.mpck AS pltq,
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN
CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN sc.plevel
ELSE bc.plevel
END
ELSE bc.plevel
END AS plevel
FROM
queue q
LEFT JOIN rlarp.cust bc ON bc.code = q.bill
LEFT JOIN rlarp.cust sc ON sc.code = q.ship
LEFT JOIN CMSInterfaceIn.[CMS.CUSLG].itemm i ON i.item = q.part
),
hist AS (
SELECT TOP 1
e.part,
j.qty,
j.price AS last_price,
j.odate AS last_date,
j.ordnum AS last_order,
j.quoten AS last_quote,
JSON_QUERY(lp.part_stats) AS full_history
FROM pricing.lastprice lp
OUTER APPLY OPENJSON(lp.part_stats) AS p
OUTER APPLY OPENJSON(p.value)
WITH (
qty NUMERIC(20, 5),
price NUMERIC(20, 5),
odate DATE,
ordnum INT,
quoten INT
) AS j
INNER JOIN enriched e ON
lp.customer = e.cust AND
lp.mold = SUBSTRING(e.part, 1, 8)
WHERE
p.[key] COLLATE SQL_Latin1_General_CP1_CI_AS = e.part
ORDER BY j.odate DESC
),
list_price_cte AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY e.part ORDER BY p.price ASC) AS rn
FROM enriched e
INNER JOIN CMSInterfaceIn."CMS.CUSLG".IPRCBHC i
ON TRIM(i.jbplvl) = TRIM(e.plevel)
AND CAST(GETDATE() AS DATE) BETWEEN i.jbfdat AND i.jbtdat
INNER JOIN pricing.pricelist_ranged p
ON p.jcplcd = TRIM(i.jbplcd)
AND p.jcpart = e.part
AND e.vol >= p.vb_from
AND (p.vb_to IS NULL OR e.vol < p.vb_to)
),
FINAL AS (
SELECT
e.part,
tp.price,
e.plevel,
h.full_history,
h.last_price,
h.last_date,
h.last_order,
h.last_quote,
lp.price AS list_price,
lp.jcplcd AS list_code,
g.guidance_price,
g.guidance_reason,
(
SELECT
'target price' AS source,
tp.price AS target_price,
h.last_price,
FORMAT(h.last_date, 'yyyy-MM-dd') AS last_date,
h.last_order,
h.last_quote,
lp.price AS list_price,
lp.jcplcd AS list_code,
FLOOR(e.vol / NULLIF(e.pltq, 0)) AS calculated_pallets,
CAST(e.vol / NULLIF(e.pltq, 0) AS NUMERIC(20,5)) AS exact_pallets,
CONCAT(tp.lower_bound, '-', ISNULL(CAST(tp.upper_bound AS VARCHAR), '')) AS [volume range],
e.cust AS customer,
e.chan AS channel,
RTRIM(e.tier) AS tier,
JSON_QUERY(tp.math) AS [target math],
-- JSON_QUERY(h.full_history) AS [price history],
g.guidance_price,
g.guidance_reason
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
) AS expl
FROM enriched e
INNER JOIN pricing.target_prices tp ON
e.stlc = tp.stlc AND
e.v1ds = tp.ds AND
e.chan = tp.chan AND
RTRIM(e.tier) = RTRIM(tp.tier) AND
FLOOR(e.vol / NULLIF(e.pltq, 0)) >= tp.lower_bound AND
(tp.upper_bound IS NULL OR FLOOR(e.vol / NULLIF(e.pltq, 0)) < tp.upper_bound)
LEFT JOIN hist h ON h.part = e.part
LEFT JOIN list_price_cte lp ON lp.part = e.part AND lp.rn = 1
CROSS APPLY pricing.guidance_logic(
tp.price,
h.last_price,
lp.price
) g
)
SELECT
part,
price AS target_price,
plevel,
last_price,
last_date,
last_order,
last_quote,
list_price,
list_code,
guidance_price,
guidance_reason,
expl
FROM FINAL
);

View File

@ -1,15 +0,0 @@
SELECT
lq.*
,t.*
FROM
rlarp.live_quotes lq
OUTER APPLY pricing.fn_single_price_call(
lq.billto,
lq.shipto,
lq.part,
substring(lq.part,1,8),
lq.v1ds,
lq.units_each
) t
--WHERE
-- qid = 112794

View File

@ -1,59 +0,0 @@
--------------------------------------------------------------------------------
-- Step 1: Rebuild last price history at sales matrix refresh time
--------------------------------------------------------------------------------
DELETE FROM pricing.lastprice;
WITH srt AS (
SELECT
customer,
mold,
part,
version,
qty,
ROUND(sales_usd / qty, 5) AS price,
odate,
oseas,
ordnum,
quoten,
ROW_NUMBER() OVER (
PARTITION BY customer, mold, part, version
ORDER BY odate DESC
) AS rn
FROM rlarp.osm_stack
WHERE
--quotes can't be integrated until we have datasegment or correct part code
version IN ('Actual'/*,'Quotes'*/) AND
customer IS NOT NULL AND
fs_line = '41010' AND
calc_status <> 'CANCELLED' AND
qty <> 0 AND
mold <> ''
),
json_rows AS (
SELECT
customer,
mold,
part,
version,
CONCAT(
'"', part, '":',
(
SELECT version, qty, price, odate, ordnum, quoten
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
)
) AS part_json
FROM srt
WHERE rn = 1
)
,onerow AS (
SELECT
customer,
mold,
CONCAT('{', STRING_AGG(part_json, ','), '}') AS part_stats
FROM json_rows
GROUP BY customer, mold
)
INSERT INTO pricing.lastprice SELECT * FROM onerow;
--CREATE UNIQUE INDEX lastprice_cust_mold ON pricing.lastprice(customer, mold);

View File

@ -1,52 +0,0 @@
CREATE TABLE pricequote.lastprice AS (
WITH
--------SORT--------
srt AS (
SELECT
customer
,partgroup
,dataseg
,qtyord
,ROUND(sales_usd/qty,5) price
,odate
,oseas
,ordnum
,quoten
,row_number() OVER (PARTITION BY customer, partgroup, dataseg, version ORDER BY odate DESC) seq
,version
FROM
rlarp.osm_stack
WHERE
version IN ('Actual','Quotes')
AND customer IS NOT NULL
AND fs_line = '41010'
AND calc_status <> 'CANCELLED'
-- AND customer = 'ALTMAN PLANTS'
AND qty <> 0
AND partgroup <> ''
AND version = 'Actual'
-- LIMIT 10000
)
,onerow AS (
SELECT
customer,
partgroup,
-- Latest per-dataseg sales wrapped as JSONB object
jsonb_object_agg(
dataseg,
to_jsonb(srt)
ORDER BY odate DESC
) AS dataseg_stats
FROM
srt
WHERE
seq = 1
-- AND customer = 'ALTMAN PLANTS'
-- AND partgroup ~ 'XPR15CS'
GROUP BY customer, partgroup
-- ORDER BY customer, partgroup
)
SELECT * FROM onerow --WHERE customer = 'ALTMAN PLANTS' AND partgroup = 'XPR15CS1'
) WITH DATA;
SELECT * FROM pricequote.lastprice

View File

@ -1,222 +0,0 @@
CREATE OR ALTER PROCEDURE pricing.batch_price_stack
AS
BEGIN
SET NOCOUNT ON;
--------------------------------------------------------------------------------
-- Step 1: Seed temp table from rlarp.osm_stack
--------------------------------------------------------------------------------
SELECT
bill,
ship,
part,
stlc,
v1ds,
vol,
NULL AS chan,
NULL AS cust,
NULL AS tier,
NULL AS pltq,
NULL AS plevel,
NULL AS hist,
NULL AS last_price,
NULL AS last_date,
NULL AS last_order,
NULL AS last_quote,
NULL AS tprice,
NULL AS guidance_price,
NULL AS guidance_reason,
'{}' AS expl,
NULL AS list_price,
NULL AS list_code
INTO #queue
FROM rlarp.osm_stack;
--------------------------------------------------------------------------------
-- Step 2: Enrich
--------------------------------------------------------------------------------
UPDATE q
SET
chan =
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN
CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN 'WHS'
ELSE 'DRP'
END
ELSE 'DIR'
END,
tier =
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIR' THEN bc.tier
ELSE ISNULL(sc.tier, bc.tier)
END,
cust =
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN
CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN bc.dba
ELSE sc.dba
END
ELSE q.bill
END,
pltq = i.mpck,
plevel =
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN
CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN sc.plevel
ELSE bc.plevel
END
ELSE bc.plevel
END
FROM #queue q
LEFT JOIN rlarp.cust bc ON bc.code = q.bill
LEFT JOIN rlarp.cust sc ON sc.code = q.ship
LEFT JOIN CMSInterfaceIn.[CMS.CUSLG].itemm i ON i.item = q.part;
--------------------------------------------------------------------------------
-- Step 3: Apply target price and embed JSON
--------------------------------------------------------------------------------
UPDATE q
SET
tprice = tp.price,
expl = (
SELECT
'target price' AS [source],
tp.price AS [target_price],
FLOOR(q.vol / NULLIF(q.pltq, 0)) AS [calculated_pallets],
CAST(ROUND(q.vol / NULLIF(q.pltq, 0), 5) AS NUMERIC(20,5)) AS [exact_pallets],
CONCAT(tp.lower_bound, '-', ISNULL(CAST(tp.upper_bound AS VARCHAR), '')) AS [volume range],
q.cust AS [customer],
q.chan AS [channel],
TRIM(q.tier) AS [tier],
JSON_QUERY(tp.math) AS [target math]
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
)
FROM #queue q
INNER JOIN pricing.target_prices tp ON
q.stlc = tp.stlc
AND q.v1ds = tp.ds
AND q.chan = tp.chan
AND q.tier = tp.tier
AND FLOOR(q.vol / NULLIF(q.pltq, 0)) >= tp.lower_bound
AND (
tp.upper_bound IS NULL OR FLOOR(q.vol / NULLIF(q.pltq, 0)) < tp.upper_bound
);
--------------------------------------------------------------------------------
-- Step 4: Pull last sale data
--------------------------------------------------------------------------------
UPDATE q
SET
hist = JSON_MODIFY('{}', '$.full_history', JSON_QUERY(lp.part_stats)),
last_price = j.price,
last_date = j.odate,
last_order = j.ordnum,
last_quote = j.quoten,
expl = JSON_MODIFY(
JSON_MODIFY(
JSON_MODIFY(
JSON_MODIFY(
ISNULL(q.expl, '{}'),
'$.last_price', j.price
),
'$.last_date', CONVERT(NVARCHAR(10), j.odate, 23)
),
'$.last_order', j.ordnum
),
'$.last_quote', j.quoten
)
FROM #queue q
JOIN pricing.lastprice lp
ON lp.customer = q.cust
AND lp.mold = SUBSTRING(q.part, 1, 8)
OUTER APPLY (
SELECT TOP 1 *
FROM OPENJSON(lp.part_stats) AS p
OUTER APPLY OPENJSON(p.value)
WITH (
qty NUMERIC(20,5),
price NUMERIC(20,5),
odate DATE,
ordnum INT,
quoten INT
) AS j
WHERE p.[key] COLLATE SQL_Latin1_General_CP1_CI_AS = q.part
ORDER BY j.odate DESC
) AS j;
--------------------------------------------------------------------------------
-- Step 5: Add list price info
--------------------------------------------------------------------------------
WITH ranked_prices AS (
SELECT
q.bill, q.ship, q.part, q.stlc, q.v1ds, q.vol,
CAST(p.price AS NUMERIC(20,5)) AS price,
p.jcplcd,
ROW_NUMBER() OVER (
PARTITION BY q.bill, q.ship, q.part, q.stlc, q.v1ds, q.vol
ORDER BY p.price ASC
) AS rn
FROM #queue q
INNER JOIN CMSInterfaceIn."CMS.CUSLG".IPRCBHC i
ON TRIM(i.jbplvl) = TRIM(q.plevel)
AND CAST(GETDATE() AS DATE) BETWEEN i.jbfdat AND i.jbtdat
INNER JOIN pricing.pricelist_ranged p
ON p.jcplcd = TRIM(i.jbplcd)
AND p.jcpart = q.part
AND q.vol >= p.vb_from
AND (p.vb_to IS NULL OR q.vol < p.vb_to)
)
UPDATE q
SET
list_price = rp.price,
list_code = rp.jcplcd,
expl = JSON_MODIFY(
JSON_MODIFY(
ISNULL(q.expl, '{}'),
'$.list_price', rp.price
),
'$.list_code', rp.jcplcd
)
FROM #queue q
JOIN ranked_prices rp
ON q.bill = rp.bill
AND q.ship = rp.ship
AND q.part = rp.part
AND q.stlc = rp.stlc
AND q.v1ds = rp.v1ds
AND q.vol = rp.vol
AND rp.rn = 1;
--------------------------------------------------------------------------------
-- Step 6: Apply guidance logic
--------------------------------------------------------------------------------
UPDATE q
SET
guidance_price = g.guidance_price,
guidance_reason = g.guidance_reason,
expl = JSON_MODIFY(
JSON_MODIFY(
ISNULL(q.expl, '{}'),
'$.guidance_reason',
g.guidance_reason
),
'$.guidance_price',
g.guidance_price
)
FROM #queue q
CROSS APPLY pricing.guidance_logic(
CAST(JSON_VALUE(q.expl, '$.target_price') AS NUMERIC(20,5)),
CAST(JSON_VALUE(q.expl, '$.last_price') AS NUMERIC(20,5)),
CAST(JSON_VALUE(q.expl, '$.list_price') AS NUMERIC(20,5))
) g;
--------------------------------------------------------------------------------
-- Final output (to result table, or SELECT)
--------------------------------------------------------------------------------
SELECT * FROM #queue;
END;

View File

@ -1,268 +0,0 @@
-- Drop and recreate the target table
DROP TABLE IF EXISTS pricequote.queue;
CREATE TABLE pricequote.queue (
bill TEXT,
ship TEXT,
part TEXT,
stlc TEXT,
v1ds TEXT,
vol NUMERIC,
chan TEXT,
cust TEXT,
tier TEXT,
pltq NUMERIC,
plevel TEXT,
last_price NUMERIC,
last_date DATE,
last_order TEXT,
last_quote TEXT,
tprice NUMERIC,
list_price NUMERIC,
list_code TEXT,
guidance_price NUMERIC,
guidance_reason TEXT,
expl JSONB,
this JSONB,
partgroup TEXT
);
CREATE INDEX idx_osm_stack_merge
ON rlarp.osm_stack (
bill_cust,
ship_cust,
part,
stlc,
dataseg,
qtyord
);
CREATE INDEX idx_queue_merge
ON pricequote.queue (
bill,
ship,
part,
stlc,
v1ds,
vol
);
--DROP PROCEDURE IF EXISTS pricequote.process_queue;
CREATE OR REPLACE PROCEDURE pricequote.process_queue()
LANGUAGE plpgsql
AS $$
BEGIN
-----------------------------------------------------------------------
-- Step 1: Seed the queue table with distinct pricing scenarios
-----------------------------------------------------------------------
DELETE FROM pricequote.queue;
INSERT INTO pricequote.queue (bill, ship, part, stlc, v1ds, vol, expl)
SELECT DISTINCT
o.bill_cust AS bill,
o.ship_cust AS ship,
o.part,
o.stlc,
o.dataseg AS v1ds,
o.qtyord AS vol,
'{}'::jsonb AS expl
FROM rlarp.osm_stack o
WHERE
o.fs_line = '41010'
AND o.calc_status <> 'CANCELLED'
AND o.version IN ('Actual', 'Forecast', 'Quotes')
AND o.part IS NOT NULL
AND substring(o.glec, 1, 1) <= '2';
-----------------------------------------------------------------------
-- Step 2: Enrich customer, tier, channel, pack quantity, and level
-----------------------------------------------------------------------
MERGE INTO pricequote.queue q
USING (
SELECT
q.ctid,
-- Determine sales channel
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN 'WHS'
ELSE 'DRP'
END
ELSE 'DIR'
END AS chan,
-- Determine pricing tier
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIR' THEN bc.tier
ELSE COALESCE(sc.tier, bc.tier)
END AS tier,
-- Resolve customer DBA name
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN bc.dba
ELSE sc.dba
END
ELSE bc.dba
END AS cust,
-- Pack quantity
i.mpck AS pltq,
-- Price level
CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN sc.plevel
ELSE bc.plevel
END
ELSE bc.plevel
END AS plevel,
i.partgroup
FROM pricequote.queue q
JOIN rlarp.cust bc ON bc.code = q.bill
LEFT JOIN rlarp.cust sc ON sc.code = q.ship
LEFT JOIN "CMS.CUSLG".itemm i ON i.item = q.part
) src
ON (q.ctid = src.ctid)
WHEN MATCHED THEN
UPDATE SET
chan = src.chan,
tier = src.tier,
cust = src.cust,
pltq = src.pltq,
plevel = src.plevel,
partgroup = src.partgroup;
-----------------------------------------------------------------------
-- Step 3: Apply target prices and embed target metadata
-----------------------------------------------------------------------
UPDATE pricequote.queue q
SET
tprice = tp.price,
expl = q.expl || jsonb_build_object(
'target_price', tp.price,
'calculated_pallets', FLOOR(q.vol / NULLIF(q.pltq, 0)),
'exact_pallets', ROUND(q.vol / NULLIF(q.pltq, 0), 5),
'volume range', tp.vol::TEXT,
'customer', q.cust,
'channel', q.chan,
'tier', TRIM(q.tier),
'target math', tp.math
)
FROM pricequote.target_prices tp
WHERE
tp.stlc = q.stlc
AND tp.ds = q.v1ds
AND tp.chan = q.chan
AND tp.tier = q.tier
AND FLOOR(q.vol / NULLIF(q.pltq, 0))::int <@ tp.vol;
-----------------------------------------------------------------------
-- Step 4: Lookup most recent price history and embed it
-----------------------------------------------------------------------
UPDATE pricequote.queue q
SET
last_price = ((lp.dataseg_stats -> q.v1ds)::jsonb ->> 'price')::numeric,
last_date = ((lp.dataseg_stats -> q.v1ds)::jsonb ->> 'odate')::date,
last_order = (lp.dataseg_stats -> q.v1ds)::jsonb ->> 'ordnum',
last_quote = (lp.dataseg_stats -> q.v1ds)::jsonb ->> 'quoten',
expl = q.expl || jsonb_build_object(
'last_price', ((lp.dataseg_stats -> q.v1ds)::jsonb ->> 'price')::numeric,
'last_date', (lp.dataseg_stats -> q.v1ds)::jsonb ->> 'odate',
'last_order', (lp.dataseg_stats -> q.v1ds)::jsonb ->> 'ordnum',
'last_quote', (lp.dataseg_stats -> q.v1ds)::jsonb ->> 'quoten'
)
FROM pricequote.lastprice lp
WHERE
lp.customer = q.cust
AND lp.partgroup = SUBSTRING(q.part, 1, 8);
-----------------------------------------------------------------------
-- Step 5: Resolve best list price and insert it with list code
-----------------------------------------------------------------------
WITH ranked_prices AS (
SELECT
q.ctid,
pr.price,
pr.jcplcd,
ROW_NUMBER() OVER (PARTITION BY q.ctid ORDER BY pr.price ASC) AS rn
FROM pricequote.queue q
JOIN "CMS.CUSLG".IPRCBHC i
ON TRIM(i.jbplvl) = TRIM(q.plevel)
AND CURRENT_DATE BETWEEN i.jbfdat AND i.jbtdat
JOIN pricequote.pricelist_ranged pr
ON pr.jcplcd = TRIM(i.jbplcd)
AND pr.jcpart = q.part
AND q.vol >= pr.vb_from
AND q.vol < pr.vb_to
),
best_price AS (
SELECT * FROM ranked_prices WHERE rn = 1
)
UPDATE pricequote.queue q
SET
list_price = p.price,
list_code = p.jcplcd,
expl = q.expl || jsonb_build_object(
'list_price', p.price,
'list_code', p.jcplcd
)
FROM best_price p
WHERE q.ctid = p.ctid;
-----------------------------------------------------------------------
-- Step 6: Compute guidance price using logic function
-----------------------------------------------------------------------
UPDATE pricequote.queue q
SET
guidance_price = g.guidance_price,
guidance_reason = g.guidance_reason,
expl = q.expl || jsonb_build_object(
'guidance_price', g.guidance_price,
'guidance_reason', g.guidance_reason
)
FROM (
SELECT
q.ctid,
g.guidance_price,
g.guidance_reason
FROM pricequote.queue q
JOIN LATERAL pricequote.guidance_logic(
q.tprice,
q.last_price,
q.list_price,
q.last_date
) g ON TRUE
) g
WHERE q.ctid = g.ctid;
-----------------------------------------------------------------------
-- Step 7: merge the results back into sales matrix
-----------------------------------------------------------------------
UPDATE rlarp.osm_stack o
SET pricing = pricing || q.expl
FROM pricequote.queue q
WHERE
o.bill_cust = q.bill
AND o.ship_cust IS NOT DISTINCT FROM q.ship
AND o.part = q.part
AND o.stlc = q.stlc
AND o.dataseg = q.v1ds
AND o.qtyord = q.vol
AND o.fs_line = '41010'
AND o.calc_status <> 'CANCELLED'
AND o.version IN ('Actual', 'Forecast', 'Quotes')
AND o.part IS NOT NULL
AND substring(o.glec, 1, 1) <= '2';
-----------------------------------------------------------------------
-- Done
-----------------------------------------------------------------------
RAISE NOTICE 'Queue processing complete.';
END;
$$;

View File

@ -1,184 +0,0 @@
--XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-----------------------------------------------------------traverse unit of measure graph-----------------------------------------------------------------------
--XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-------------setup table to hold target conversions---------------------
SELECT DISTINCT
jcpart partn
,jcunit fu
,'PC' tu
,cast(null as numeric) factor
INTO
#anchor
FROM
cmsinterfacein.lgdat.iprcc
WHERE
1=1;
--SELECT * FROM #anchor
-------pre-build punit stacked on itself with the columns flipped so you can go either direction per join---------
SELECT
*
INTO
#g
FROM
(
SELECT
IHPART IHPART,
rtrim(IHUNT1) IHUNT1,
rtrim(IHUNT2) IHUNT2,
IHCNV1 IHCNV1,
IHCNV2 IHCNV2
FROM
CMSInterfaceIN.LGDAT.PUNIT pu
--only deal with parts in the anchor table or the &&global parts
INNER JOIN (
SELECT DISTINCT partn FROM #anchor
) items ON
items.partn = pu.ihpart
OR pu.ihpart = '&&GLOBAL'
UNION
SELECT
IHPART IHPART,
rtrim(IHUNT2) IHUNT1,
rtrim(IHUNT1) IHUNT2,
IHCNV2 IHCNV1,
IHCNV1 IHCNV2
FROM
CMSInterfaceIN.LGDAT.PUNIT pu
--only deal with parts in the anchor table or the &&global parts
INNER JOIN (
SELECT DISTINCT partn FROM #anchor
) items ON
items.partn = pu.ihpart
OR pu.ihpart = '&&GLOBAL'
) x ;
CREATE INDEX g_idx on #g(ihpart,ihunt1);
WITH
--------do the expansion on all paths until the target uom is matched----------------------------------------------
--(complains about types not matching between anchor and recursion, explicitly just casting everything)
uom (partn, partx, lvl, mastf, mastt, xf, xt, factor, xfactor, xnum, xden, id, uom_list) AS
(
SELECT
cast(partn as varchar(20)) --partn
,cast(partn as varchar(20)) --partx
,cast(0 as int) --lvl
,fu --mastf
,tu --mastt
,cast(fu as varchar(3)) --xf
,cast(fu as varchar(3)) --xt
,CAST(1 AS FLOAT) --factor
,CAST(1 AS FLOAT) --xfactor
,CAST(1 AS FLOAT) --xnum
,CAST(1 AS FLOAT) --xden
,format(row_number() over (ORDER BY partn),'000000')
,cast(trim(fu) as varchar(max))
FROM
#anchor
UNION ALL
SELECT
cast(uom.partn as varchar(20)) --partn
,cast(ihpart as varchar(20)) --partx
,CAST(uom.lvl + 1 AS INT) --lvl
,uom.mastf --mastf
,uom.mastt --mastt
,cast(p.ihunt1 as varchar(3)) --xf
,cast(p.ihunt2 as varchar(3)) --xt
,CAST(p.ihcnv2/p.ihcnv1 AS FLOAT) --factor
,CAST(p.ihcnv2/p.ihcnv1 AS FLOAT) * uom.xfactor --xfactor
,p.ihcnv2 * uom.xnum --xnum
,p.ihcnv1 * uom.xden --xden
,uom.id + '.' + format(row_number() over (PARTITION BY uom.id ORDER BY partn),'00')
,uom.uom_list + '.' + trim(p.ihunt2)
FROM
uom
INNER JOIN #g p ON
p.ihpart IN (uom.partn,'&&GLOBAL')
AND p.ihunt1 = uom.xt
WHERE
1=1
--AND p.ihunt2 not in ('BD','BG','BU','BX','CA','CS','PA','PL','SL','C','K','DOZ','PR')
AND p.ihunt1 <> uom.mastt
--prevent recursion: newest joined UOM can't be in the history
AND charindex(p.ihunt2,uom.uom_list) = 0
)
--SELECT COUNT(*) FROM UOM
--------------uom is going to have multiple rows per requested conversion, need to use row_number to pick the best row------------------------------
,sorted AS (
SELECT
partn, mastf from_uom, xt to_uom, xfactor factor, lvl steps, row_number() OVER (PARTITION BY partn, mastf, mastt ORDER BY lvl ASC, factor ASC) rn
FROM
uom
WHERE
xt = mastt
)
SELECT * INTO #uom FROM sorted WHERE rn = 1;
--so far so good
drop table #anchor;
drop table #g;
TRUNCATE TABLE pricing.pricelist_ranged;
WITH
conv AS (
SELECT
p.jcplcd,
p.jcpart,
p.jcunit,
p.jcvoll,
p.jcpric,
u.factor,
-- Normalize volume and price to PC
p.jcvoll * u.factor AS vol_pc,
p.jcpric / u.factor AS price_pc
FROM
cmsinterfacein.lgdat.iprcc p
INNER JOIN #uom u
ON u.partn = p.jcpart
AND u.from_uom = p.jcunit
AND u.to_uom = 'PC'
),
sorted AS (
SELECT
c.*,
ROW_NUMBER() OVER (PARTITION BY c.jcplcd, c.jcpart ORDER BY vol_pc ASC) AS rn
FROM conv c
),
ranged AS (
SELECT
curr.jcplcd,
curr.jcpart,
curr.jcunit,
curr.jcvoll,
curr.jcpric,
curr.vol_pc,
curr.price_pc,
curr.vol_pc AS vb_from,
COALESCE(next.vol_pc, 9999999.0) AS vb_to
FROM
sorted curr
LEFT JOIN sorted next
ON curr.jcplcd = next.jcplcd
AND curr.jcpart = next.jcpart
AND curr.rn + 1 = next.rn
)
INSERT INTO
pricing.pricelist_ranged
SELECT
RTRIM(jcplcd) jcplcd,
RTRIM(jcpart) jcpart,
jcunit,
jcvoll,
jcpric,
vb_from,
vb_to,
price_pc AS price
FROM
ranged;
--CREATE INDEX pricelist_ranged_idx ON pricing.pricelist_ranged(jcpart, jcplcd, vb_from, vb_to);

View File

@ -1,13 +0,0 @@
-- FAnalysis.PRICING.lastprice definition
-- Drop table
-- DROP TABLE FAnalysis.PRICING.lastprice;
CREATE TABLE pricing.lastprice (
customer varchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
mold varchar(255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
part_stats nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
);
CREATE UNIQUE NONCLUSTERED INDEX lastprice_cust_mold ON FAnalysis.PRICING.lastprice (customer ASC, mold ASC) ;

View File

@ -1,14 +0,0 @@
DROP TABLE pricing.pricelist_ranged;
CREATE TABLE pricing.pricelist_ranged (
jcplcd varchar(5) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
jcpart varchar(20) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
jcunit varchar(3) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
jcvoll numeric(12,5) NOT NULL,
jcpric numeric(12,5) NOT NULL,
vb_from float NULL,
vb_to float NULL,
price float NOT NULL
);
CREATE NONCLUSTERED INDEX pricelist_ranged_idx ON FAnalysis.PRICING.pricelist_ranged ( jcpart ASC , jcplcd ASC , vb_from ASC , vb_to ASC ) ;

View File

@ -1,101 +0,0 @@
DROP TABLE IF EXISTS uomc;
CREATE TEMP TABLE uomc AS (
WITH
uom AS (
SELECT
uom.p part
,uom.f fu
,uom.t tu
,uom.nm/uom.dm conv
FROM
(
SELECT
jsonb_agg(row_to_json(d)::jsonb) jdoc
FROM
(
select distinct
jcpart partn
, jcunit fu
, 'PC' tu
from
lgdat.iprcc
WHERE
jcpart <> ''
) d
) c
JOIN LATERAL rlarp.uom_array(c.jdoc) uom ON TRUE
)
SELECT * FROM uom
) WITH DATA;
CREATE INDEX uom_idx ON uomc (part, fu, tu);
-- Clear the output table
TRUNCATE TABLE pricequote.pricelist_ranged;
--DROP TABLE pricequote.pricelist_ranged;
-- Compute normalized volume/price and ranges
--CREATE TABLE pricequote.pricelist_ranged AS (
WITH
conv AS (
SELECT
p.jcplcd,
p.jcpart,
p.jcunit,
p.jcvoll,
p.jcpric,
u.conv,
(p.jcvoll * u.conv) AS vol_pc,
(p.jcpric / NULLIF(u.conv, 0)) AS price_pc
FROM
lgdat.iprcc p
INNER JOIN uomc u
ON u.part = p.jcpart
AND u.fu = p.jcunit
AND u.tu = 'PC'
),
--SELECT * FROM conv LIMIT 1000
sorted AS (
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY jcplcd, jcpart ORDER BY vol_pc ASC) AS rn
FROM conv
),
ranged AS (
SELECT
curr.jcplcd,
curr.jcpart,
curr.jcunit,
curr.jcvoll,
curr.jcpric,
curr.vol_pc,
curr.price_pc price,
curr.vol_pc AS vb_from,
COALESCE(next.vol_pc, 9999999.0) AS vb_to
FROM
sorted curr
LEFT JOIN sorted next
ON curr.jcplcd = next.jcplcd
AND curr.jcpart = next.jcpart
AND curr.rn + 1 = next.rn
)
--SELECT * FROM ranged
INSERT INTO pricequote.pricelist_ranged (
jcplcd, jcpart, jcunit, jcvoll, jcpric, vb_from, vb_to, price
)
SELECT
jcplcd,
jcpart,
jcunit,
jcvoll,
jcpric,
vb_from,
vb_to,
price
FROM ranged;
CREATE INDEX pricelist_ranged_idx ON pricequote.pricelist_ranged ( jcpart ASC , jcplcd ASC , vb_from ASC , vb_to ASC ) ;

View File

@ -1,18 +0,0 @@
DROP TABLE pricing.target_prices;
CREATE TABLE pricing.target_prices (
stlc nvarchar(8) NOT NULL,
ds nvarchar(20) NOT NULL,
chan nvarchar(3) NOT NULL,
tier nvarchar(1) NOT NULL,
vol nvarchar(20) NOT NULL,
lower_bound int NOT NULL,
upper_bound int NULL,
price numeric(28,6) NOT NULL,
math nvarchar(MAX) NULL
);
ALTER TABLE pricing.target_prices
ADD CONSTRAINT uq_target_prices_unique_combo
UNIQUE (stlc, ds, chan, tier, vol, lower_bound);

View File

@ -1,14 +0,0 @@
DROP TABLE pricequote.target_prices CASCADE;
CREATE TABLE pricequote.target_prices (
stlc TEXT NOT NULL,
ds TEXT NOT NULL,
chan TEXT NOT NULL,
tier TEXT NOT NULL,
vol INT4RANGE NOT NULL,
price NUMERIC,
math TEXT[],
PRIMARY KEY (stlc, ds, chan, tier, vol)
);
GRANT SELECT, INSERT, UPDATE, DELETE ON pricequote.target_prices TO PUBLIC;

View File

@ -1,11 +0,0 @@
CREATE or REPLACE VIEW pricequote.target_prices_view AS
SELECT
stlc
,ds
,chan
,tier
,vol::text vol
,price
,to_jsonb(math)::text AS math
FROM
pricequote.target_prices;

View File

@ -1,23 +0,0 @@
DELETE FROM pricing.target_prices;
INSERT INTO
pricing.target_prices
SELECT
stlc,
ds,
chan,
tier,
vol,
-- Extract lower bound: text between '[' and ','
TRY_CAST(SUBSTRING(vol, 2, CHARINDEX(',', vol) - 2) AS INT) AS lower_bound,
-- Extract upper bound: text between ',' and ')'
CASE
WHEN RIGHT(vol, 2) = ',)' THEN NULL
ELSE TRY_CAST(SUBSTRING(vol, CHARINDEX(',', vol) + 1, LEN(vol) - CHARINDEX(',', vol) - 1) AS INT)
END AS upper_bound,
price,
math
FROM
usmidsap02.ubm.pricequote.target_prices_view;
--SELECT COUNT(*) FROM pricing.target_prices

View File

@ -1,55 +0,0 @@
--SELECT * INTO rlarp.target_prices FROM usmidsap02.ubm.pricequote.target_prices_view
--DROP TABLE pricing.target_prices
DELETE FROM pricing.target_prices
SELECT
stlc,
ds,
chan,
tier,
vol,
-- Extract lower bound: text between '[' and ','
TRY_CAST(SUBSTRING(vol, 2, CHARINDEX(',', vol) - 2) AS INT) AS lower_bound,
-- Extract upper bound: text between ',' and ')'
CASE
WHEN RIGHT(vol, 2) = ',)' THEN NULL
ELSE TRY_CAST(SUBSTRING(vol, CHARINDEX(',', vol) + 1, LEN(vol) - CHARINDEX(',', vol) - 1) AS INT)
END AS upper_bound,
price,
math
INTO
pricing.target_prices
FROM
usmidsap02.ubm.pricequote.target_prices_view;
INSERT INTO
pricing.target_prices
SELECT
stlc,
ds,
chan,
tier,
vol,
-- Extract lower bound: text between '[' and ','
TRY_CAST(SUBSTRING(vol, 2, CHARINDEX(',', vol) - 2) AS INT) AS lower_bound,
-- Extract upper bound: text between ',' and ')'
CASE
WHEN RIGHT(vol, 2) = ',)' THEN NULL
ELSE TRY_CAST(SUBSTRING(vol, CHARINDEX(',', vol) + 1, LEN(vol) - CHARINDEX(',', vol) - 1) AS INT)
END AS upper_bound,
price,
math
FROM
usmidsap02.ubm.pricequote.target_prices_view;
SELECT TOP 100 * FROM rlarp.target_prices;
SELECT * FROM rlarp.target_prices tp
WHERE
stlc = 'XNS0T1G3'
AND ds = 'v1:T..PLT..'
AND chan = 'DIR'
AND tier = 1
AND 1.01 >= lower_bound
AND (1.01 < upper_bound OR upper_bound IS NULL);

View File

@ -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
// };
//}

View File

@ -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$;

View File

@ -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 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'];

View File

@ -1,5 +1,5 @@
SELECT
(select gg.d from rlarp.get_guidance_dseg('DIAM0004','DIAM0004','AMK06000','v1:B..PLT..',5000,2026) gg(d))
rlarp.get_guidance(lq.billto, lq.shipto, lq.part, lq.units_each, 2024)
FROM
pricequote.live_quotes lq
LIMIT 1
LIMIT 100

View File

@ -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$;

View File

@ -1,2 +1,2 @@
-- select gg.d from rlarp.get_guidance_dseg('DIAM0004','DIAM0004','AMK06000','v1:B..PLT..',5000,2026) gg(d);
--select gg.d from rlarp.get_guidance('DIAM0004','DIAM0004','AMK06000G18B054',5000,2024) gg(d);
SELECT gg.d doc FROM rlarp.get_guidance_dseg($1,$2, $3,$4, $5, 2024) gg(d);

View File

@ -42,7 +42,7 @@ BEGIN
INTO
_mold,_stlc,_v1ds , _v0ds, _iidx
FROM
"CMS.CUSLG".itemm i
"CMS.CUSLG".itemmv i
INNER JOIN rlarp.molds m ON
m.stlc = i.stlc
WHERE

View File

@ -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)
RETURNS jsonb
LANGUAGE plpgsql AS
@ -10,34 +10,23 @@ DECLARE
--_ship text;
--_qty numeric;
--_seas int;
_prem jsonb;
_mold text;
_item text;
_unti text;
_pltq numeric;
_cstd numeric;
_cstdina numeric;
_fstd numeric;
_fstdina numeric;
_cust text;
_curr text;
_rate numeric;
_v1ds text;
_v0ds text;
_v1tp jsonb;
_v0tp jsonb;
_chan text;
_regn text;
_rslt jsonb;
_targ jsonb;
_list jsonb;
_iidx jsonb;
_itemr text;
_input jsonb;
_product jsonb;
_customer jsonb;
_hist jsonb;
_pricing jsonb;
_prem jsonb;
_mold text;
_item text;
_cust text;
_curr text;
_rate numeric;
_v1ds text;
_v0ds text;
_v1tp jsonb;
_v0tp jsonb;
_chan text;
_regn text;
_rslt jsonb;
_targ jsonb;
_list jsonb;
_iidx jsonb;
_itemr text;
BEGIN
--_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;
_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--------------------------------
SELECT
part_group
,item
,stlc
,idxk
,prefer
,pltq
,curstdus
,curstdus_ina
,futstdus
,futstdus_ina
INTO
_mold
,_item
,_stlc
,_iidx
,_itemr
,_pltq
,_cstd
,_cstdina
,_fstd
,_fstdina
FROM
(
SELECT
i.partgroup part_group
m.part_group
,min(i.item) item
,i.stlc
,i.v1ds
,_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
,i.v0ds
,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
"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
"CMS.CUSLG".itemmv i
INNER JOIN rlarp.molds m ON
m.stlc = i.stlc
WHERE
i.stlc = _stlc
GROUP BY
i.partgroup
m.part_group
,i.stlc
,i.v1ds
,_ds.dataseg
,i.mpck
,i.v0ds
,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
ORDER BY
prefer DESC
LIMIT 1;
_product :=
jsonb_build_object(
'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);
_rslt := jsonb_build_object('mold',_mold,'v1ds',_v1ds,'v0ds',_v0ds,'stlc',_stlc,'item',_item,'item rel',_itemr,'desg',_dseg)||_iidx;
RAISE NOTICE 'item data %', _iidx;
----------------channel-------------------------------------
SELECT rlarp.get_cust(_bill, _ship) INTO _customer;
--_customer := jsonb_build_object('chan',_chan);
SELECT rlarp.channel_code(_bill, _ship) INTO _chan;
_rslt := _rslt||jsonb_build_object('chan',_chan);
RAISE NOTICE '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
-- )
--);
--RAISE NOTICE 'cust %', jsonb_pretty(_customer);
_rslt = _rslt||jsonb_build_object('cust',_cust,'curr',_curr,'fxrate',_rate);
RAISE NOTICE 'cust %', _cust;
----------------price history-------------------------------
--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);
SELECT _rslt||jsonb_build_object('hist',rlarp.get_hist(_mold, _v1ds, _cust, substring(_chan,1,1))) INTO _rslt ;
RAISE NOTICE 'result %', _rslt;
----------------target pricing------------------------------
SELECT
jsonb_build_object(
'v0tp',
target_price,
'v0stdv',
'stdv',
stdev_price
)
INTO
@ -194,14 +132,14 @@ BEGIN
mold = _stlc
AND season = _seas
AND data_segment = _v0ds
AND region = 'ALL'
AND chan = _customer->'customer'->>'chantp';
AND region = 'ALL';
_rslt := _rslt||COALESCE(_v0tp,'{}'::jsonb);
----------------target pricing------------------------------
SELECT
jsonb_build_object(
'v1tp',
target_price,
'v1stdv',
'stdv',
stdev_price
)
INTO
@ -212,12 +150,12 @@ BEGIN
mold = _stlc
AND season = _seas
AND data_segment = _dseg
AND region = 'ALL'
AND chan = _customer->'customer'->>'chantp';
AND region = 'ALL';
--RAISE NOTICE 'target: %', jsonb_pretty(_targ);
_pricing := (COALESCE(_v0tp,'{}'::jsonb)||COALESCE(_v1tp,'{}'::jsonb));
_rslt := _rslt||COALESCE(_v1tp,'{}'::jsonb);
----------------inflation index-----------------------------
RAISE NOTICE 'infaltion : %', jsonb_pretty(_iidx);
SELECT
jsonb_build_object(
'iidx'
@ -238,21 +176,17 @@ BEGIN
)
GROUP BY
priority;
_pricing := _pricing||COALESCE(_iidx,'{}'::jsonb);
--RAISE NOTICE 'add targets: %', jsonb_pretty(_pricing);
_rslt := _rslt||COALESCE(_iidx,'{}'::jsonb);
----------------list pricing---------------------------------
SELECT coalesce(rlarp.get_list(_bill, _ship, _item, _qty),'{}'::jsonb) INTO _list;
_pricing := _pricing||_list;
--RAISE NOTICE 'add list: %', jsonb_pretty(_pricing);
_rslt := _rslt||_list;
--RAISE NOTICE 'list: %', jsonb_pretty(_list);
----------------get premium for quote hist gap--------------
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);
_rslt := _input||_product||_customer||_pricing||_hist;
SELECT coalesce(rlarp.get_premium(_stlc, _seas, (SELECT xchan FROM _chx WHERE chan = _chan),_rslt->'hist'->'cust'->>'ds', _v1ds),'{}'::jsonb) INTO _prem;
_rslt := _rslt||_prem;
--RAISE NOTICE 'list: %', jsonb_pretty(_list);
RETURN _rslt;

View File

@ -16,9 +16,8 @@ sort AS (
,gset.*
,row_number() OVER (PARTITION BY p.agglevel ORDER BY avgunits DESC) rn
,stats.*
,season
FROM
rlarp.price_pool p
rlarp.price_pool_dev p
JOIN LATERAL jsonb_to_record(gset) AS gset(
chan text
,mold text
@ -38,8 +37,6 @@ sort AS (
,early_price numeric
,recent_season int
,recent_price numeric
,last_season int
,last_price numeric
) ON TRUE
WHERE
gset @> jsonb_build_object(
@ -98,9 +95,6 @@ SELECT
,early_price
,recent_season
,recent_price
,last_season
,last_price
,season
FROM
sort
)
@ -110,7 +104,7 @@ FROM
,('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
,('customer v1ds vol' ,2)
,('market exact' ,4)
,('market v0ds other' ,9)
,('market v0ds vol' ,5)
@ -136,16 +130,13 @@ FROM
,'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' ,row_number() OVER (PARTITION BY flag.source ORDER BY rel.prefer ASC)
,'pricinghistory' ,season
,'rank'
,row_number() OVER (PARTITION BY flag.source ORDER BY rel.prefer ASC)
)
)
) doc
,row_number() OVER (PARTITION BY flag.source ORDER BY rel.prefer ASC) rnk
,season
FROM
flag
LEFT OUTER JOIN rel ON

View File

@ -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 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;

View File

@ -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$;

View File

@ -25,7 +25,7 @@ BEGIN
stats,
(SELECT doc FROM getj) AS gdoc
FROM
rlarp.price_pool p
rlarp.price_pool_dev p
WHERE
gset @> jsonb_build_object(
'mold', (SELECT doc->>'mold' FROM getj),

View File

@ -1,5 +1,5 @@
WITH
sel AS (select 'v1:B..PLT..' _v1ds, 'ALTMAN PLANTS' _cust, 'XPR15CS1' _mold, 'D' _chan)
sel AS (select 'v1:P.P.PLT..' _v1ds, 'ALTMAN PLANTS' _cust, 'TFR001G0' _mold, 'D' _chan)
,sort AS (
SELECT
p.agglevel
@ -10,7 +10,7 @@ sel AS (select 'v1:B..PLT..' _v1ds, 'ALTMAN PLANTS' _cust, 'XPR15CS1' _mold, 'D'
,row_number() OVER (PARTITION BY p.agglevel ORDER BY avgunits DESC) rn
,stats.*
FROM
rlarp.price_pool p
rlarp.price_pool_dev p
CROSS JOIN sel
JOIN LATERAL jsonb_to_record(gset) AS gset(
chan text

View File

@ -1,23 +0,0 @@
-- DELETE FROM pricequote.price_queue;
--
-- ALTER SEQUENCE pricequote.price_queue_id_seq RESTART WITH 1;
--
-- INSERT INTO
-- pricequote.price_queue (bill, ship, part, stlc, v1ds, vol, chan, tier)
-- SELECT DISTINCT
-- bill_cust, ship_cust, part, stlc, dataseg, qty, chan, customer_tier
-- FROM
-- rlarp.osm_stack;
UPDATE
pricequote.price_queue q
SET
expl = COALESCE(q.expl, '{}'::jsonb) || jsonb_build_object('price history', l.dataseg_stats)
FROM
pricequote.lastprice l
WHERE
q.cust = l.customer
AND q.stlc = l.partgroup;

View File

@ -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 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

View File

@ -1,9 +1,9 @@
--CREATE OR REPLACE PROCEDURE rlarp.price_pool()
--LANGUAGE plpgsql AS
--$func$
--BEGIN;
DROP MATERIALIZED VIEW IF EXISTS rlarp.price_pool CASCADE;
CREATE MATERIALIZED VIEW rlarp.price_pool AS (
--BEGIN
DROP TABLE IF EXISTS rlarp.price_pool_dev;
CREATE TABLE IF NOT EXISTS rlarp.price_pool_dev AS (
WITH
agg AS (
SELECT
@ -11,13 +11,13 @@ CREATE MATERIALIZED VIEW rlarp.price_pool AS (
,substring(o.version,1,1) version
,o.chanwide
,o.nursery_region
,o.greenhouse_region
,o.partgroup baseitem
,o.majgd
,o.assc
,o.coltierd
,o.dataseg v1dataseg
,o.v0dataseg v0dataseg
,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
,o.oseas oseas
,round(sum(o.qty),0) units
,round(sum(o.sales_usd),0) sales_usd
@ -25,104 +25,52 @@ CREATE MATERIALIZED VIEW rlarp.price_pool AS (
,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 = o.stlc
AND tp.mold = i.stlc
AND tp.chan = 'DISTRIB DROP SHIP'
AND tp.data_segment = o.dataseg
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 = o.stlc
AND tq.mold = i.stlc
AND tq.chan = 'DISTRIB DROP SHIP'
AND tq.data_segment = o.v0dataseg
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.oseas >= 2015
AND o.mingd <> 'B52'
--AND o.part like 'SQL035%'
--AND o.calc_status <> 'CANCELED'
AND o.fs_line = '41010'
--AND o.dsm <> 'PW'
--AND i.coltierd <> 'C'
GROUP BY
o.customer
,substring(o.version,1,1)
,o.chanwide
,o.nursery_region
,o.greenhouse_region
,o.partgroup
,o.majgd
,o.assc
,o.coltierd
,o.dataseg
,o.v0dataseg
,o.oseas
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
,o.greenhouse_region
,o.partgroup baseitem
,o.majgd
,o.assc
,o.coltierd
,o.dataseg v1dataseg
,o.v0dataseg 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
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 = o.stlc
AND tp.chan = 'DISTRIB DROP SHIP'
AND tp.data_segment = o.dataseg
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 = o.stlc
AND tq.chan = 'DISTRIB DROP SHIP'
AND tq.data_segment = o.v0dataseg
WHERE
o.version IN ('Actual','Quotes')
AND o.odate >= current_date - '4 months'::interval
AND o.mingd <> 'B52'
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.coltierd <> 'C'
--AND i.coltier <> 'C'
GROUP BY
o.customer
,substring(o.version,1,1)
,o.chanwide
,o.nursery_region
,o.greenhouse_region
,o.partgroup
,o.majgd
,o.assc
,o.coltierd
,o.dataseg
,o.v0dataseg
,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
@ -148,7 +96,7 @@ CREATE MATERIALIZED VIEW rlarp.price_pool AS (
,sum(sales_usd) sales_usd
,round(sum(sales_usd )/sum(units),5) price_usd
,round(sum(target_price)/sum(units) FILTER (WHERE COALESCE(target_price,0) <> 0 ),5) target_price
,jsonb_agg(DISTINCT coltierd) coltierd
,jsonb_agg(DISTINCT coltier) coltier
,count(DISTINCT customer) custcount
,sum(ordcount) ordcount
FROM
@ -176,9 +124,8 @@ CREATE MATERIALIZED VIEW rlarp.price_pool AS (
,round(avg(ordcount) ,1) avgordcount
,round(avg(units) ,0) avgunits
,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
,max(oseas) FILTER (WHERE oseas >= 2020)::text last_season
--,oseas
--,units
--,sales_usd
@ -212,15 +159,10 @@ CREATE MATERIALIZED VIEW rlarp.price_pool AS (
,recent_season::int
,'recent_price'
,(season->recent_season->>'price_usd')::numeric
,'last_season'
,last_season::int
,'last_price'
,(season->last_season->>'price_usd')::numeric
) stats
FROM
find_stats
--LIMIT 1000
) WITH DATA;
create index ppd_gset on rlarp.price_pool using gin (gset);
--END;
create index ppd_gset on rlarp.price_pool_dev using gin (gset);

View File

@ -1,168 +0,0 @@
-- set work_mem TO '4GB';
--
DROP VIEW IF EXISTS rlarp.quote_review;
CREATE VIEW rlarp.quote_review AS
WITH
---------------------get quote lines from SQL Server---------------------
lq AS MATERIALIZED (
SELECT
lq.*
,substring(lq.part,1,8) mold
FROM
pricequote.live_quotes lq
WHERE
qstat LIKE '%Submitted%'
)
---------------------guidance logic---------------------------------------
,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
,CASE lq.qchan WHEN 'DIR' THEN bc.tier ELSE sc.tier END customer_tier
,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
,nt.price qtarget_price
,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 >= 2*mpck THEN lq.upperpricelimit
-- if more than a pallet use the target price
ELSE lq.upperpricelimit * 1.05
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
,pl.price pricelist
,pl.listcode
,row_number() OVER (PARTITION BY qid, qline ORDER BY pl.price ASC) bestprice
-- ,(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
LEFT OUTER JOIN rlarp.cust bc ON
bc.code = lq.billto
LEFT OUTER JOIN rlarp.cust sc ON
sc.code = lq.shipto
LEFT OUTER JOIN rlarp.plcore_fullcode_ranged pl ON
pl.item = lq.part
AND jsonb_build_array(pl.listcode) <@ (COALESCE(sc.lists,bc.lists))
AND (
lq.units_each >= pl.vb_f
AND lq.units_each < pl.vb_t
)
LEFT OUTER JOIN pricequote.target_prices nt ON
nt.stlc = i.stlc
AND nt.ds = lq.v1ds
AND nt.chan = lq.qchan
AND nt.tier = CASE lq.qchan WHEN 'DIR' THEN bc.tier ELSE sc.tier END
AND floor(lq.units_each/i.mpck)::int <@ nt.vol
WHERE
lq.qstat ~ 'Submitted'
)
-- SELECT * FROM lqg where bestprice <> 1
-- SELECT * FROM lqg WHERE qid = 109352
---------------------------link in sales history----------------------------------------------
,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
WHERE
COALESCE(g.bestprice,1) = 1
)
SELECT * FROM hist --WHERE qid = 108655