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( -- Step 4b.1: Populate composite fields from precedence chain using JSON-based helper
JSON_MODIFY( --------------------------------------------------------------------------------
JSON_MODIFY( -- Use new helper to select best last price, source, and date directly from JSON
ISNULL(q.expl, '{}'), UPDATE q
'$.last_price', j.price SET
), last_price = b.price,
'$.last_date', CONVERT(NVARCHAR(10), j.odate, 23) last_source = b.source,
), last_date = b.odate,
'$.last_order', j.ordnum last_qty = b.qty,
), last_dataseg = b.dataseg,
'$.last_quote', j.quoten last_order = b.ord,
) last_quote = b.quote
FROM @queue q FROM @queue q
JOIN pricing.lastprice lp CROSS APPLY (
ON lp.customer = q.cust SELECT TOP 1 price, source, odate, qty, dataseg, ord, quote
AND lp.mold = SUBSTRING(q.part, 1, 8) FROM pricing.pick_last_price_from_hist_json(q.hist, q.v1ds)
OUTER APPLY ( ) b;
SELECT TOP 1 *
FROM OPENJSON(lp.part_stats) AS p --------------------------------------------------------------------------------
OUTER APPLY OPENJSON(p.value) -- Step 4b.2: Build JSON explanation object from populated columns
WITH ( --------------------------------------------------------------------------------
qty NUMERIC(20,5), UPDATE q
price NUMERIC(20,5), SET expl = (
odate DATE, SELECT
ordnum INT, q.last_price AS last_price,
quoten INT q.last_qty AS last_qty,
) AS j q.last_dataseg AS last_dataseg,
WHERE p.[key] COLLATE SQL_Latin1_General_CP1_CI_AS = q.part q.last_source AS last_source,
ORDER BY j.odate DESC FORMAT(q.last_date, 'yyyy-MM-dd') AS last_date,
) AS j; q.tprice AS [target_price],
JSON_QUERY(q.tmath) AS [target_math],
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],
q.cust AS [customer],
q.chan AS [channel],
TRIM(q.tier) AS [tier]
-- JSON_QUERY(hist) AS [history]
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
)
FROM @queue q;
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Step 5: Add list price info from external pricelist -- Step 5: Add list price info from external pricelist
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
WITH ranked_prices AS ( WITH ranked_prices AS (
SELECT SELECT
q.bill, q.ship, q.part, q.stlc, q.v1ds, q.vol, q.bill, q.ship, q.part, q.stlc, q.v1ds, q.vol,
CAST(p.price AS NUMERIC(20,5)) AS price, CAST(p.price AS NUMERIC(20,5)) AS price,
p.jcplcd, p.jcplcd,
ROW_NUMBER() OVER ( ROW_NUMBER() OVER (
PARTITION BY q.bill, q.ship, q.part, q.stlc, q.v1ds, q.vol PARTITION BY q.bill, q.ship, q.part, q.stlc, q.v1ds, q.vol
ORDER BY p.price ASC ORDER BY p.price ASC
) AS rn ) AS rn
FROM @queue q FROM @queue q
INNER JOIN CMSInterfaceIn."CMS.CUSLG".IPRCBHC i INNER JOIN CMSInterfaceIn."CMS.CUSLG".IPRCBHC i
ON TRIM(i.jbplvl) = TRIM(q.plevel) ON TRIM(i.jbplvl) = TRIM(q.plevel)
AND CAST(GETDATE() AS DATE) BETWEEN i.jbfdat AND i.jbtdat AND CAST(GETDATE() AS DATE) BETWEEN i.jbfdat AND i.jbtdat
INNER JOIN pricing.pricelist_ranged p INNER JOIN pricing.pricelist_ranged p
ON p.jcplcd = TRIM(i.jbplcd) ON p.jcplcd = TRIM(i.jbplcd)
AND p.jcpart = q.part AND p.jcpart = q.part
AND q.vol >= p.vb_from AND q.vol >= p.vb_from
AND (p.vb_to IS NULL OR q.vol < p.vb_to) AND (p.vb_to IS NULL OR q.vol < p.vb_to)
) )
UPDATE q UPDATE q
SET expl = JSON_MODIFY( SET expl = JSON_MODIFY(
JSON_MODIFY( JSON_MODIFY(
ISNULL(q.expl, '{}'), ISNULL(q.expl, '{}'),
'$.list_price', rp.price '$.list_price', rp.price
), ),
'$.list_code', rp.jcplcd '$.list_code', rp.jcplcd
) )
,listcode = rp.jcplcd ,listcode = rp.jcplcd
,listprice = rp.price ,listprice = rp.price
FROM @queue q FROM @queue q
JOIN ranked_prices rp JOIN ranked_prices rp
ON q.bill = rp.bill ON q.bill = rp.bill
AND q.ship = rp.ship AND q.ship = rp.ship
AND q.part = rp.part AND q.part = rp.part
AND q.stlc = rp.stlc AND q.stlc = rp.stlc
AND q.v1ds = rp.v1ds AND q.v1ds = rp.v1ds
AND q.vol = rp.vol AND q.vol = rp.vol
AND rp.rn = 1; 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
-- Target Support Panel UNION ALL
SELECT
'Target Support' AS label,
(
SELECT
-- parse each item in target_math
RTRIM(SUBSTRING(value,1,18)) label,
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 'currency' ELSE 'percentage' END AS type,
SUBSTRING(value,19,1) AS note
FROM OPENJSON(q.expl, '$.target_math')
WITH (value NVARCHAR(MAX) '$')
FOR JSON PATH
) AS details
UNION ALL -- Target Support Panel
SELECT
'Target Support' AS label,
(
SELECT
RTRIM(SUBSTRING(value,1,18)) AS label,
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 'currency' ELSE 'percentage' END AS type,
CASE SUBSTRING(value,19,1) WHEN '+' THEN 'Price' ELSE 'Premium' END AS note
FROM OPENJSON(q.expl, '$.target_math')
WITH (value NVARCHAR(MAX) '$')
FOR JSON PATH
) AS details
-- Guidance Panel UNION ALL
SELECT
'Guidance' AS label, -- Guidance Panel
( SELECT
SELECT 'Guidance' AS label,
'Last Price Capped' AS label, (
q.guidance_price AS value, SELECT
'currency' AS type, 'Price' AS label,
CONCAT( q.guidance_price AS value,
'Last price ', q.last_price, 'currency' AS type,
' capped at ', q.guidance_reason AS note
ROUND((q.last_price - q.guidance_price) / NULLIF(q.last_price, 0) * 100, 2), FOR JSON PATH
'%' )
) AS note ) AS panel
FOR JSON PATH FOR JSON PATH
) ) AS details,
) AS panel JSON_QUERY(q.expl) AS data -- 👈 adds the full expl content as a JSON object
FOR JSON PATH, ROOT('details') FOR JSON PATH, WITHOUT_ARRAY_WRAPPER -- 👈 make it a single JSON object
) )
FROM @queue q; FROM @queue q;
--------------------------------------------------------------------------------
-- Final: Return the enriched result row
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Final: Return the enriched result row RETURN;
-------------------------------------------------------------------------------- END;
RETURN;
END;