bring func up to speed

This commit is contained in:
Paul Trowbridge 2025-08-07 23:35:09 -04:00
parent 4602db59bb
commit af5e4d202b

View File

@ -1,228 +1,230 @@
DROP FUNCTION pricing.single_price_call_fn; DROP FUNCTION IF EXISTS pricing.single_price_call_fn;
GO
CREATE FUNCTION pricing.single_price_call_fn ( CREATE FUNCTION pricing.single_price_call_fn (
@bill VARCHAR(100), @bill VARCHAR(100),
@ship VARCHAR(100), @ship VARCHAR(100),
@part VARCHAR(100), @part VARCHAR(100),
@v1ds VARCHAR(100), @v1ds VARCHAR(100),
@vol NUMERIC(18,6) @vol NUMERIC(18,6)
) )
RETURNS @queue TABLE ( RETURNS @queue TABLE (
bill VARCHAR(100), bill VARCHAR(100),
ship VARCHAR(100), ship VARCHAR(100),
part VARCHAR(100), part VARCHAR(100),
stlc VARCHAR(100), stlc VARCHAR(100),
v1ds VARCHAR(100), v1ds VARCHAR(100),
vol NUMERIC(18,6), vol NUMERIC(18,6),
chan VARCHAR(50), chan VARCHAR(50),
cust VARCHAR(100), cust VARCHAR(100),
tier VARCHAR(50), tier VARCHAR(50),
pltq NUMERIC(18,6), pltq NUMERIC(18,6),
volume_range TEXT, volume_range TEXT,
plevel NVARCHAR(20), plevel NVARCHAR(20),
listprice NUMERIC(20,5), listprice NUMERIC(20,5),
listcode VARCHAR(10), listcode VARCHAR(10),
hist NVARCHAR(MAX), hist NVARCHAR(MAX),
last_price NUMERIC(20,5), last_price NUMERIC(20,5),
last_date DATE, last_date DATE,
last_order NVARCHAR(10), last_order NVARCHAR(10),
last_quote NVARCHAR(10), last_quote NVARCHAR(10),
tprice NUMERIC(20,5), tprice NUMERIC(20,5),
guidance_price NUMERIC(20,5), tmath NVARCHAR(MAX),
guidance_reason NVARCHAR(MAX), guidance_price NUMERIC(20,5),
expl NVARCHAR(MAX), guidance_reason NVARCHAR(MAX),
ui_json NVARCHAR(MAX) expl NVARCHAR(MAX),
ui_json NVARCHAR(MAX),
partgroup VARCHAR(100)
) )
AS AS
BEGIN BEGIN
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Step 1: Seed the queue with input row -- Step 1: Seed the queue with input row
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
INSERT INTO @queue (bill, ship, part, v1ds, vol, expl) INSERT INTO @queue (bill, ship, part, v1ds, vol, expl)
VALUES (@bill, @ship, @part, @v1ds, @vol, '{}'); VALUES (@bill, @ship, @part, @v1ds, @vol, '{}');
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Step 2: Enrich with channel, tier, customer, pack quantity, and price level -- Step 2: Enrich with channel, tier, customer, pack quantity, and price level
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
UPDATE q UPDATE q
SET SET
chan = chan =
CASE SUBSTRING(bc.cclass, 2, 3) CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN WHEN 'DIS' THEN
CASE SUBSTRING(sc.cclass, 2, 3) CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN 'WHS' WHEN 'DIS' THEN 'WHS'
ELSE 'DRP' ELSE 'DRP'
END END
ELSE 'DIR' ELSE 'DIR'
END, END,
tier = tier =
CASE SUBSTRING(bc.cclass, 2, 3) CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIR' THEN bc.tier WHEN 'DIR' THEN bc.tier
ELSE ISNULL(sc.tier, bc.tier) ELSE ISNULL(sc.tier, bc.tier)
END, END,
cust = cust =
CASE SUBSTRING(bc.cclass, 2, 3) CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN WHEN 'DIS' THEN
CASE SUBSTRING(sc.cclass, 2, 3) CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN bc.dba WHEN 'DIS' THEN bc.dba
ELSE sc.dba ELSE sc.dba
END END
ELSE q.bill ELSE q.bill
END, END,
pltq = i.mpck, pltq = i.mpck,
plevel = plevel =
CASE SUBSTRING(bc.cclass, 2, 3) CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN WHEN 'DIS' THEN
CASE SUBSTRING(sc.cclass, 2, 3) CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN sc.plevel WHEN 'DIS' THEN sc.plevel
ELSE bc.plevel ELSE bc.plevel
END END
ELSE bc.plevel ELSE bc.plevel
END, END,
stlc = substring(q.part,1,8) stlc = substring(q.part,1,8),
FROM @queue q partgroup = i.partgroup
LEFT JOIN rlarp.cust bc ON bc.code = q.bill FROM @queue q
LEFT JOIN rlarp.cust sc ON sc.code = q.ship LEFT JOIN rlarp.cust bc ON bc.code = q.bill
LEFT JOIN CMSInterfaceIn.[CMS.CUSLG].itemm i ON i.item = q.part; 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 -- Step 3: Apply target price and embed metadata as JSON
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
UPDATE q UPDATE q
SET SET
tprice = tp.price, tprice = tp.price
expl = ( ,tmath = JSON_QUERY(tp.math)
SELECT ,volume_range = CONCAT(tp.lower_bound, '-', ISNULL(CAST(tp.upper_bound AS VARCHAR), ''))
'target price' AS [source], FROM @queue q
tp.price AS [target_price], INNER JOIN pricing.target_prices tp ON
FLOOR(q.vol / NULLIF(q.pltq, 0)) AS [calculated_pallets], q.stlc = tp.stlc
CAST(ROUND(q.vol / NULLIF(q.pltq, 0), 5) AS NUMERIC(20,5)) AS [exact_pallets], AND q.v1ds = tp.ds
CONCAT(tp.lower_bound, '-', ISNULL(CAST(tp.upper_bound AS VARCHAR), '')) AS [volume_range], AND q.chan = tp.chan
q.cust AS [customer], AND q.tier = tp.tier
q.chan AS [channel], AND FLOOR(q.vol / NULLIF(q.pltq, 0)) >= tp.lower_bound
TRIM(q.tier) AS [tier], AND (
JSON_QUERY(tp.math) AS [target_math] tp.upper_bound IS NULL OR FLOOR(q.vol / NULLIF(q.pltq, 0)) < tp.upper_bound
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 -- Step 4: Pull last sale data and embed in columns and JSON
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
UPDATE q UPDATE q
SET SET
hist = JSON_MODIFY('{}', '$.full_history', JSON_QUERY(lp.part_stats)), hist = lp.part_stats
last_price = j.price, FROM @queue q
last_date = j.odate, JOIN pricing.lastpricedetail lp
last_order = j.ordnum, ON lp.customer = q.cust AND lp.partgroup = q.partgroup;
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 -- Step 4b.1: Populate composite fields from precedence chain using JSON-based helper
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
WITH ranked_prices AS ( -- Use new helper to select best last price, source, and date directly from JSON
SELECT UPDATE q
q.bill, q.ship, q.part, q.stlc, q.v1ds, q.vol, SET
CAST(p.price AS NUMERIC(20,5)) AS price, last_price = b.price,
p.jcplcd, last_source = b.source,
ROW_NUMBER() OVER ( last_date = b.odate,
PARTITION BY q.bill, q.ship, q.part, q.stlc, q.v1ds, q.vol last_qty = b.qty,
ORDER BY p.price ASC last_dataseg = b.dataseg,
) AS rn last_order = b.ord,
FROM @queue q last_quote = b.quote
INNER JOIN CMSInterfaceIn."CMS.CUSLG".IPRCBHC i FROM @queue q
ON TRIM(i.jbplvl) = TRIM(q.plevel) CROSS APPLY (
AND CAST(GETDATE() AS DATE) BETWEEN i.jbfdat AND i.jbtdat SELECT TOP 1 price, source, odate, qty, dataseg, ord, quote
INNER JOIN pricing.pricelist_ranged p FROM pricing.pick_last_price_from_hist_json(q.hist, q.v1ds)
ON p.jcplcd = TRIM(i.jbplcd) ) b;
AND p.jcpart = q.part
AND q.vol >= p.vb_from --------------------------------------------------------------------------------
AND (p.vb_to IS NULL OR q.vol < p.vb_to) -- Step 4b.2: Build JSON explanation object from populated columns
) --------------------------------------------------------------------------------
UPDATE q UPDATE q
SET expl = JSON_MODIFY( SET expl = (
JSON_MODIFY( SELECT
ISNULL(q.expl, '{}'), q.last_price AS last_price,
'$.list_price', rp.price q.last_qty AS last_qty,
), q.last_dataseg AS last_dataseg,
'$.list_code', rp.jcplcd q.last_source AS last_source,
) FORMAT(q.last_date, 'yyyy-MM-dd') AS last_date,
,listcode = rp.jcplcd q.tprice AS [target_price],
,listprice = rp.price JSON_QUERY(q.tmath) AS [target_math],
FROM @queue q FLOOR(q.vol / NULLIF(q.pltq, 0)) AS [calculated_pallets],
JOIN ranked_prices rp CAST(ROUND(q.vol / NULLIF(q.pltq, 0), 5) AS NUMERIC(20,5)) AS [exact_pallets],
ON q.bill = rp.bill q.cust AS [customer],
AND q.ship = rp.ship q.chan AS [channel],
AND q.part = rp.part TRIM(q.tier) AS [tier]
AND q.stlc = rp.stlc -- JSON_QUERY(hist) AS [history]
AND q.v1ds = rp.v1ds FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
AND q.vol = rp.vol )
AND rp.rn = 1; FROM @queue q;
--------------------------------------------------------------------------------
-- 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 -- Step 6: Compute guidance price and logic, and embed in JSON
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
UPDATE q UPDATE q
SET SET
guidance_price = g.guidance_price, guidance_price = g.guidance_price,
guidance_reason = g.guidance_reason, guidance_reason = g.guidance_reason,
expl = JSON_MODIFY( expl = JSON_MODIFY(
JSON_MODIFY( JSON_MODIFY(
ISNULL(q.expl, '{}'), ISNULL(q.expl, '{}'),
'$.guidance_reason', '$.guidance_reason',
g.guidance_reason g.guidance_reason
), ),
'$.guidance_price', '$.guidance_price',
g.guidance_price g.guidance_price
) )
FROM @queue q FROM @queue q
CROSS APPLY pricing.guidance_logic( CROSS APPLY pricing.guidance_logic(
CAST(JSON_VALUE(q.expl, '$.target_price') AS NUMERIC(20,5)), 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, '$.last_price') AS NUMERIC(20,5)),
CAST(JSON_VALUE(q.expl, '$.list_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) CAST(last_date AS DATE)
) g; ) g;
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -230,79 +232,84 @@ BEGIN
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
UPDATE q UPDATE q
SET ui_json = ( SET ui_json = (
SELECT SELECT
panel.label, (
JSON_QUERY(panel.details) AS details SELECT
FROM ( panel.label,
-- History Panel JSON_QUERY(panel.details) AS details
SELECT FROM (
'History' AS label, -- History Panel
( SELECT
SELECT 'History' AS label,
'Last Sale: ' + CAST(q.last_date AS varchar(10)) AS label, (
q.last_price AS value, SELECT
'currency' AS type, 'Last Price' AS label,
'Ord# ' + q.last_order AS note q.last_price AS value,
FOR JSON PATH 'currency' AS type,
) AS details CONCAT(
'Source: ', ISNULL(q.last_source, 'N/A'),
' | Date: ', ISNULL(CONVERT(varchar(10), q.last_date, 120), 'N/A'),
' | Order: ', ISNULL(q.last_order, 'N/A'),
' | Quote: ', ISNULL(q.last_quote, 'N/A'),
' | Dataseg: ', ISNULL(q.last_dataseg, 'N/A'),
' | Qty: ', ISNULL(CAST(q.last_qty AS varchar(32)), 'N/A')
) AS note
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
) AS details
UNION ALL UNION ALL
-- List Panel -- List Panel
SELECT SELECT
'List' AS label, 'List' AS label,
( (
SELECT SELECT
'List:' + q.listcode AS label, 'List:' + q.listcode AS label,
q.listprice AS value, q.listprice AS value,
'currency' AS type, 'currency' AS type,
q.plevel AS note q.plevel AS note
FOR JSON PATH FOR JSON PATH
) )
UNION ALL UNION ALL
-- Target Support Panel -- Target Support Panel
SELECT SELECT
'Target Support' AS label, 'Target Support' AS label,
( (
SELECT SELECT
-- parse each item in target_math RTRIM(SUBSTRING(value,1,18)) AS label,
RTRIM(SUBSTRING(value,1,18)) label, TRY_CAST(SUBSTRING(value,23,7) AS NUMERIC(20,5))
TRY_CAST(SUBSTRING(value,23,7) AS NUMERIC(20,5)) + CASE SUBSTRING(value,19,1) WHEN '+' THEN 0 ELSE -1 END AS value, + CASE SUBSTRING(value,19,1) WHEN '+' THEN 0 ELSE -1 END AS value,
CASE SUBSTRING(value,19,1) WHEN '+' THEN 'currency' ELSE 'percentage' END AS type, CASE SUBSTRING(value,19,1) WHEN '+' THEN 'currency' ELSE 'percentage' END AS type,
SUBSTRING(value,19,1) AS note CASE SUBSTRING(value,19,1) WHEN '+' THEN 'Price' ELSE 'Premium' END AS note
FROM OPENJSON(q.expl, '$.target_math') FROM OPENJSON(q.expl, '$.target_math')
WITH (value NVARCHAR(MAX) '$') WITH (value NVARCHAR(MAX) '$')
FOR JSON PATH FOR JSON PATH
) AS details ) AS details
UNION ALL UNION ALL
-- Guidance Panel -- Guidance Panel
SELECT SELECT
'Guidance' AS label, 'Guidance' AS label,
( (
SELECT SELECT
'Last Price Capped' AS label, 'Price' AS label,
q.guidance_price AS value, q.guidance_price AS value,
'currency' AS type, 'currency' AS type,
CONCAT( q.guidance_reason AS note
'Last price ', q.last_price, FOR JSON PATH
' capped at ', )
ROUND((q.last_price - q.guidance_price) / NULLIF(q.last_price, 0) * 100, 2), ) AS panel
'%' FOR JSON PATH
) AS note ) AS details,
FOR JSON PATH JSON_QUERY(q.expl) AS data -- 👈 adds the full expl content as a JSON object
) FOR JSON PATH, WITHOUT_ARRAY_WRAPPER -- 👈 make it a single JSON object
) AS panel
FOR JSON PATH, ROOT('details')
) )
FROM @queue q; FROM @queue q;
--------------------------------------------------------------------------------
-- Final: Return the enriched result row
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Final: Return the enriched result row RETURN;
--------------------------------------------------------------------------------
RETURN;
END; END;