Compare commits

..

No commits in common. "23b39623137ed61c4cb4529ea6a4345d8957a6db" and "49748383ff30b77adccb1a7849ee59f3576198ae" have entirely different histories.

View File

@ -1,260 +1,245 @@
-- Recreate queue with columns matching single_price_call outputs
DROP TABLE IF EXISTS pricequote.queue; DROP TABLE IF EXISTS pricequote.queue;
CREATE TABLE pricequote.queue ( CREATE TABLE pricequote.queue (
bill TEXT, bill TEXT,
ship TEXT, ship TEXT,
part TEXT, part TEXT,
stlc TEXT, stlc TEXT,
v1ds TEXT, v1ds TEXT,
vol NUMERIC, vol NUMERIC,
chan TEXT, chan TEXT,
cust TEXT, cust TEXT,
tier TEXT, tier TEXT,
pltq NUMERIC, pltq NUMERIC,
plevel TEXT, plevel TEXT,
partgroup TEXT, last_price NUMERIC,
part_v1ds TEXT, last_qty NUMERIC,
v0ds TEXT, last_dataseg TEXT,
curstd_orig NUMERIC, last_date DATE,
futstd_orig NUMERIC, last_order TEXT,
curstd NUMERIC, last_quote TEXT,
futstd NUMERIC, last_source TEXT,
curstd_last NUMERIC, tprice NUMERIC,
futstd_last NUMERIC, tmath JSONB,
customized TEXT, volume_range TEXT,
last_premium NUMERIC, list_price NUMERIC,
last_premium_method TEXT, list_code TEXT,
last_price_norm NUMERIC, guidance_price NUMERIC,
last_isdiff TEXT, guidance_reason TEXT,
last_v0ds TEXT, expl JSONB,
tprice_last NUMERIC, ui_json JSONB,
last_price NUMERIC, partgroup TEXT
last_qty NUMERIC,
last_dataseg TEXT,
last_date DATE,
last_order TEXT,
last_quote TEXT,
last_source TEXT,
hist JSONB,
tprice NUMERIC,
tmath JSONB,
volume_range TEXT,
listprice NUMERIC,
listcode TEXT,
listprice_eff NUMERIC,
list_relevance TEXT,
guidance_price NUMERIC,
guidance_reason TEXT,
expl JSONB,
ui_json JSONB
); );
CREATE INDEX IF NOT EXISTS idx_osm_stack_merge /*
ON rlarp.osm_stack (bill_cust, ship_cust, part, stlc, dataseg, qtyord); ====================================================================================
Script: matrix_guidance.pg.sql
Purpose: Batch pricing logic for sales matrix (PostgreSQL)
-----------------------------------------------------------------------------------
Description:
- Seeds a queue table with distinct pricing scenarios from rlarp.osm_stack
- Enriches each scenario with customer, channel, tier, pack quantity, and price level
- Looks up and applies target price, price history, list price, and guidance logic
- Builds a JSON explanation for each scenario
- Merges results back into the main sales matrix table
Inputs:
- Source table: rlarp.osm_stack
- Pricing reference tables: pricequote.target_prices, pricequote.lastpricedetail, pricequote.pricelist_ranged
- Customer/item reference: rlarp.cust, CMS.CUSLG.itemm, CMS.CUSLG.IPRCBHC
Outputs:
- Updates rlarp.osm_stack.pricing with a JSON explanation for each scenario
- All intermediate results are stored in pricequote.queue
Key Business Logic:
- Channel/tier/customer resolution based on bill/ship codes
- Target price and math lookup by segment, channel, tier, and volume
- Price history precedence and extraction via helper function
- List price selection: lowest valid price for the scenario
- Guidance logic: computed from target, last, and list prices
Dependencies:
- pricequote.guidance_logic (function)
- pricequote.pick_last_price_from_hist (function)
Notes:
- Designed for batch/matrix pricing updates
- Assumes all referenced tables and functions exist
- See also: single_price_call.pg.sql for single-row logic
====================================================================================
*/
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
);
CREATE INDEX IF NOT EXISTS idx_queue_merge
ON pricequote.queue (bill, ship, part, stlc, v1ds, vol);
-- Batch procedure mirroring single_price_call logic (4-space indentation)
--DROP PROCEDURE IF EXISTS pricequote.process_queue; --DROP PROCEDURE IF EXISTS pricequote.process_queue;
CREATE OR REPLACE PROCEDURE pricequote.process_queue() CREATE OR REPLACE PROCEDURE pricequote.process_queue()
LANGUAGE plpgsql LANGUAGE plpgsql
AS $$ AS $$
BEGIN BEGIN
--------------------------------------------------------------------
-- 1) Seed queue from matrix -----------------------------------------------------------------------
-------------------------------------------------------------------- -- Step 1: Seed the queue table with distinct pricing scenarios
-----------------------------------------------------------------------
DELETE FROM pricequote.queue; DELETE FROM pricequote.queue;
INSERT INTO pricequote.queue (bill, ship, part, stlc, v1ds, vol, expl, ui_json) INSERT INTO pricequote.queue (bill, ship, part, stlc, v1ds, vol, expl)
SELECT DISTINCT SELECT DISTINCT
o.bill_cust, o.bill_cust AS bill,
o.ship_cust, o.ship_cust AS ship,
o.part, o.part,
o.stlc, o.stlc,
o.dataseg, o.dataseg AS v1ds,
o.qtyord, o.qtyord AS vol,
'{}'::jsonb, '{}'::jsonb AS expl
'{}'::jsonb
FROM rlarp.osm_stack o FROM rlarp.osm_stack o
WHERE WHERE
o.fs_line = '41010' o.fs_line = '41010'
AND o.calc_status <> 'CANCELLED' AND o.calc_status <> 'CANCELLED'
AND o.version IN ('Actual', 'Forecast', 'Quotes') AND o.version IN ('Actual', 'Forecast', 'Quotes')
AND o.part IS NOT NULL AND o.part IS NOT NULL
AND SUBSTRING(o.glec, 1, 1) <= '2'; AND substring(o.glec, 1, 1) <= '2';
-- 46 seconds -- 44 seconds
--------------------------------------------------------------------
-- 2) Enrich: chan, tier, cust, pltq, plevel, partgroup (+stlc fix) -----------------------------------------------------------------------
-------------------------------------------------------------------- -- Step 2: Enrich customer, tier, channel, pack quantity, and level
-----------------------------------------------------------------------
MERGE INTO pricequote.queue q MERGE INTO pricequote.queue q
USING ( USING (
SELECT SELECT
q.ctid, q.ctid,
-- Determine sales channel
CASE SUBSTRING(bc.cclass, 2, 3) CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN CASE SUBSTRING(sc.cclass, 2, 3) WHEN 'DIS' THEN 'WHS' ELSE 'DRP' END WHEN 'DIS' THEN CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN 'WHS'
ELSE 'DRP'
END
ELSE 'DIR' ELSE 'DIR'
END AS chan, END AS chan,
-- Determine pricing tier
CASE SUBSTRING(bc.cclass, 2, 3) CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIR' THEN bc.tier WHEN 'DIR' THEN bc.tier
ELSE COALESCE(sc.tier, bc.tier) ELSE COALESCE(sc.tier, bc.tier)
END AS tier, END AS tier,
-- Resolve customer DBA name
CASE SUBSTRING(bc.cclass, 2, 3) CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN CASE SUBSTRING(sc.cclass, 2, 3) WHEN 'DIS' THEN bc.dba ELSE sc.dba END WHEN 'DIS' THEN CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN bc.dba
ELSE sc.dba
END
ELSE bc.dba ELSE bc.dba
END AS cust, END AS cust,
-- Pack quantity
i.mpck AS pltq, i.mpck AS pltq,
-- Price level
CASE SUBSTRING(bc.cclass, 2, 3) CASE SUBSTRING(bc.cclass, 2, 3)
WHEN 'DIS' THEN CASE SUBSTRING(sc.cclass, 2, 3) WHEN 'DIS' THEN sc.plevel ELSE bc.plevel END WHEN 'DIS' THEN CASE SUBSTRING(sc.cclass, 2, 3)
WHEN 'DIS' THEN sc.plevel
ELSE bc.plevel
END
ELSE bc.plevel ELSE bc.plevel
END AS plevel, END AS plevel,
i.partgroup AS partgroup, i.partgroup
SUBSTRING(q.part, 1, 8) AS stlc_fix
FROM pricequote.queue q FROM pricequote.queue q
JOIN rlarp.cust bc ON bc.code = q.bill JOIN rlarp.cust bc ON bc.code = q.bill
LEFT JOIN rlarp.cust sc ON sc.code = q.ship LEFT JOIN rlarp.cust sc ON sc.code = q.ship
LEFT JOIN "CMS.CUSLG".itemm i ON i.item = q.part LEFT JOIN "CMS.CUSLG".itemm i ON i.item = q.part
) s ) src
ON (q.ctid = s.ctid) ON (q.ctid = src.ctid)
WHEN MATCHED THEN UPDATE SET WHEN MATCHED THEN
chan = s.chan, UPDATE SET
tier = s.tier, chan = src.chan,
cust = s.cust, tier = src.tier,
pltq = s.pltq, cust = src.cust,
plevel = s.plevel, pltq = src.pltq,
partgroup = s.partgroup, plevel = src.plevel,
stlc = COALESCE(q.stlc, s.stlc_fix); partgroup = src.partgroup;
-- 16 seconds -- 17 seconds
-------------------------------------------------------------------- -----------------------------------------------------------------------
-- 3) Scenario fields from item master: part_v1ds, v0ds, orig costs -- Step 3: Apply target prices and embed target metadata
-- + customized flag -----------------------------------------------------------------------
--------------------------------------------------------------------
UPDATE pricequote.queue q
SET
part_v1ds = i0.v1ds,
v0ds = (CASE SUBSTRING(q.v1ds, 4, 1) WHEN 'B' THEN 'B' ELSE 'C' END)
|| (CASE SUBSTRING(q.v1ds, 6, 1) WHEN 'L' THEN 'L' WHEN 'P' THEN 'P' ELSE '' END),
curstd_orig = i0.curstdus,
futstd_orig = i0.futstdus,
customized = CASE
WHEN i0.v1ds IS NOT NULL AND q.v1ds IS NOT NULL AND i0.v1ds <> q.v1ds
THEN 'Customized'
ELSE ''
END
FROM "CMS.CUSLG".itemm i0
WHERE i0.item = q.part;
-- 16 seconds
--------------------------------------------------------------------
-- 4) History: store hist, extract last_* with precedence helper
--------------------------------------------------------------------
UPDATE pricequote.queue q
SET
hist = x.part_stats, -- from the correlated subquery
last_price = (j->>'price')::NUMERIC,
last_qty = (j->>'qty')::NUMERIC,
last_dataseg = j->>'datasegment',
last_date = (j->>'odate')::DATE,
last_order = j->>'ordnum',
last_quote = j->>'quoten',
last_source = j->>'source',
last_isdiff = CASE
WHEN (j->>'datasegment') IS NOT NULL
AND q.v1ds IS NOT NULL
AND (j->>'datasegment') <> q.v1ds
THEN 'Last Sale Diff Part'
END,
last_v0ds = (CASE SUBSTRING(j->>'datasegment', 4, 1)
WHEN 'B' THEN 'B' ELSE 'C' END)
|| (CASE SUBSTRING(j->>'datasegment', 6, 1)
WHEN 'L' THEN 'L'
WHEN 'P' THEN 'P'
ELSE '' END)
FROM (
SELECT
q2.ctid,
lp2.part_stats,
pricequote.pick_last_price_from_hist(lp2.part_stats, q2.v1ds) AS j
FROM pricequote.queue q2
JOIN pricequote.lastpricedetail lp2
ON lp2.customer = q2.cust
AND lp2.partgroup = q2.partgroup
) AS x
WHERE q.ctid = x.ctid;
-- 2 min 3 sec
--------------------------------------------------------------------
-- 5) Target (requested v1ds): tprice, tmath, volume_range
--------------------------------------------------------------------
UPDATE pricequote.queue q UPDATE pricequote.queue q
SET SET
tprice = tp.price, tprice = tp.price,
tmath = to_json(tp.math), expl = q.expl || jsonb_build_object(
volume_range = tp.vol::TEXT '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 FROM pricequote.target_prices tp
WHERE WHERE
tp.stlc = q.stlc tp.stlc = q.stlc
AND tp.ds = q.v1ds AND tp.ds = q.v1ds
AND tp.chan = q.chan AND tp.chan = q.chan
AND tp.tier = q.tier AND tp.tier = q.tier
AND FLOOR(q.vol / NULLIF(q.pltq, 0))::INT <@ tp.vol; AND FLOOR(q.vol / NULLIF(q.pltq, 0))::int <@ tp.vol;
-- 22 seconds -- 20 seconds
-------------------------------------------------------------------- -----------------------------------------------------------------------
-- 6) Target for last_dataseg (tprice_last) -- Step 4: Lookup price history and embed all relevant keys and precedence
-------------------------------------------------------------------- -----------------------------------------------------------------------
-- Use the helper function to extract last price precedence and build JSON explanation as in single_price_call
UPDATE pricequote.queue q UPDATE pricequote.queue q
SET SET
tprice_last = tp2.price last_price = (last_json->>'price')::numeric,
FROM pricequote.target_prices tp2 last_qty = (last_json->>'qty')::numeric,
WHERE last_dataseg = last_json->>'datasegment',
q.last_dataseg IS NOT NULL last_date = (last_json->>'odate')::date,
AND tp2.stlc = q.stlc last_order = last_json->>'ordnum',
AND tp2.ds = q.last_dataseg last_quote = last_json->>'quoten',
AND tp2.chan = q.chan last_source = last_json->>'source',
AND tp2.tier = q.tier expl = q.expl || jsonb_build_object(
AND FLOOR(q.vol / NULLIF(q.pltq, 0))::INT <@ tp2.vol; 'last_price', (last_json->>'price')::numeric,
-- 17 sec 'last_qty', (last_json->>'qty')::numeric,
'last_dataseg', last_json->>'datasegment',
'last_source', last_json->>'source',
'last_date', (last_json->>'odate')::date,
'last_order', last_json->>'ordnum',
'last_quote', last_json->>'quoten'
)
FROM (
SELECT q.ctid, pricequote.pick_last_price_from_hist(lp.part_stats, q.v1ds) AS last_json
FROM pricequote.queue q
JOIN pricequote.lastpricedetail lp
ON lp.customer = q.cust AND lp.partgroup = q.partgroup
) sub
WHERE q.ctid = sub.ctid;
-- 2 minutes 36 seconds
-------------------------------------------------------------------- -----------------------------------------------------------------------
-- 7) Cost data for requested v1ds and last_dataseg -- Step 5: Resolve best list price and insert it with list code
-------------------------------------------------------------------- -----------------------------------------------------------------------
UPDATE pricequote.queue q
SET
curstd = CASE WHEN COALESCE(q.customized,'') = '' THEN q.curstd_orig ELSE COALESCE(s.v1_cur, s.v0_cur) END,
futstd = CASE WHEN COALESCE(q.customized,'') = '' THEN q.futstd_orig ELSE COALESCE(s.v1_fut, s.v0_fut) END,
curstd_last = CASE WHEN COALESCE(q.last_isdiff,'') = '' THEN q.curstd_orig ELSE COALESCE(s.v1l_cur, s.v0l_cur) END,
futstd_last = CASE WHEN COALESCE(q.last_isdiff,'') = '' THEN q.futstd_orig ELSE COALESCE(s.v1l_fut, s.v0l_fut) END
FROM (
SELECT
q2.ctid,
v1.curstdus AS v1_cur,
v1.futstdus AS v1_fut,
v0.curstdus AS v0_cur,
v0.futstdus AS v0_fut,
v1l.curstdus AS v1l_cur,
v1l.futstdus AS v1l_fut,
v0l.curstdus AS v0l_cur,
v0l.futstdus AS v0l_fut
FROM pricequote.queue q2
LEFT JOIN rlarp.cost_v1ds v1
ON v1.stlc = q2.stlc AND v1.v1ds = q2.v1ds
LEFT JOIN rlarp.cost_v0ds v0
ON v0.stlc = q2.stlc AND v0.v0ds = q2.v0ds
LEFT JOIN rlarp.cost_v1ds v1l
ON v1l.stlc = q2.stlc AND v1l.v1ds = q2.last_dataseg
LEFT JOIN rlarp.cost_v0ds v0l
ON v0l.stlc = q2.stlc AND v0l.v0ds = q2.last_v0ds
) AS s
WHERE q.ctid = s.ctid;
-- 28 seconds
--------------------------------------------------------------------
-- 8) List price (lowest valid); allow open-ended ranges (vb_to IS NULL)
--------------------------------------------------------------------
WITH ranked_prices AS ( WITH ranked_prices AS (
SELECT SELECT
q.ctid, q.ctid,
@ -269,245 +254,56 @@ BEGIN
ON pr.jcplcd = TRIM(i.jbplcd) ON pr.jcplcd = TRIM(i.jbplcd)
AND pr.jcpart = q.part AND pr.jcpart = q.part
AND q.vol >= pr.vb_from AND q.vol >= pr.vb_from
AND (q.vol < pr.vb_to OR pr.vb_to IS NULL) AND q.vol < pr.vb_to
), ),
best_price AS ( best_price AS (
SELECT * FROM ranked_prices WHERE rn = 1 SELECT * FROM ranked_prices WHERE rn = 1
) )
UPDATE pricequote.queue q UPDATE pricequote.queue q
SET SET
listprice = p.price, list_price = p.price,
listcode = p.jcplcd list_code = p.jcplcd,
expl = q.expl || jsonb_build_object(
'list_price', p.price,
'list_code', p.jcplcd
)
FROM best_price p FROM best_price p
WHERE q.ctid = p.ctid; WHERE q.ctid = p.ctid;
-- 18 seconds -- 15 seconds
-------------------------------------------------------------------- -----------------------------------------------------------------------
-- 9) Normalize last (when last_dataseg != v1ds) + effective list flags -- Step 6: Compute guidance price using logic function
-------------------------------------------------------------------- -----------------------------------------------------------------------
UPDATE pricequote.queue q UPDATE pricequote.queue q
SET SET
last_premium = CASE guidance_price = g.guidance_price,
WHEN q.last_isdiff IS NOT NULL guidance_reason = g.guidance_reason,
AND q.tprice_last IS NOT NULL expl = q.expl || jsonb_build_object(
AND q.tprice IS NOT NULL 'guidance_price', g.guidance_price,
AND q.tprice_last <> 0 'guidance_reason', g.guidance_reason
THEN ROUND(q.tprice / q.tprice_last, 5) )
WHEN q.last_isdiff IS NOT NULL FROM (
AND q.curstd_last IS NOT NULL SELECT
AND q.curstd IS NOT NULL q.ctid,
AND q.curstd_last <> 0 g.guidance_price,
THEN q.curstd / q.curstd_last g.guidance_reason
END, FROM pricequote.queue q
last_premium_method = CASE JOIN LATERAL pricequote.guidance_logic(
WHEN q.last_isdiff IS NOT NULL q.tprice,
AND q.tprice_last IS NOT NULL q.last_price,
AND q.tprice IS NOT NULL q.list_price,
AND q.tprice_last <> 0 q.last_date
THEN 'Target Price Ratio' ) g ON TRUE
WHEN q.last_isdiff IS NOT NULL ) g
AND q.curstd_last IS NOT NULL WHERE q.ctid = g.ctid;
AND q.curstd IS NOT NULL -- 27 seconds
AND q.curstd_last <> 0
THEN 'Cost Ratio'
WHEN q.last_isdiff IS NOT NULL
THEN 'Unknown'
END,
last_price_norm = CASE
WHEN q.last_isdiff IS NOT NULL
AND q.tprice_last IS NOT NULL
AND q.tprice IS NOT NULL
AND q.tprice_last <> 0
THEN ROUND(q.last_price * (q.tprice / q.tprice_last), 5)
WHEN q.last_isdiff IS NOT NULL
AND q.curstd_last IS NOT NULL
AND q.curstd IS NOT NULL
AND q.curstd_last <> 0
THEN ROUND(q.last_price * (q.curstd / q.curstd_last), 5)
ELSE q.last_price
END,
listprice_eff = CASE WHEN q.customized <> '' THEN NULL ELSE q.listprice END,
list_relevance = CASE WHEN q.customized <> '' THEN 'Ignore - Customized' ELSE '' END;
-- 21 seconds
--------------------------------------------------------------------
-- 10) Guidance using normalized last + effective list
--------------------------------------------------------------------
UPDATE pricequote.queue q
SET
guidance_price = s.guidance_price,
guidance_reason = s.guidance_reason
FROM (
SELECT
q2.ctid,
g.guidance_price,
g.guidance_reason
FROM pricequote.queue q2
JOIN LATERAL pricequote.guidance_logic(
q2.tprice,
q2.last_price_norm,
q2.listprice_eff,
q2.last_date
) g ON TRUE
) s
WHERE q.ctid = s.ctid;
-- 31 seconds
-------------------------------------------------------------------- -----------------------------------------------------------------------
-- 11) Build expl and ui_json identical to single_price_call -- Step 7: merge the results back into sales matrix
-------------------------------------------------------------------- -----------------------------------------------------------------------
UPDATE pricequote.queue q
SET
expl = jsonb_build_object(
'last', jsonb_build_object(
'last_part', (pricequote.pick_last_price_from_hist(q.hist, q.v1ds)->>'part'),
'last_price', q.last_price,
'last_qty', q.last_qty,
'last_dataseg', q.last_dataseg,
'last_v0ds', q.last_v0ds,
'last_source', q.last_source,
'last_date', q.last_date,
'last_order', q.last_order,
'last_quote', q.last_quote,
'last_isdiff', q.last_isdiff,
'last_premium', q.last_premium,
'last_premium_method', q.last_premium_method,
'last_price_norm', q.last_price_norm,
'tprice_last', q.tprice_last
),
'scenario', jsonb_build_object(
'calculated_pallets', FLOOR(q.vol / NULLIF(q.pltq, 0)),
'exact_pallets', ROUND(q.vol / NULLIF(q.pltq, 0), 5),
'customer', q.cust,
'channel', q.chan,
'tier', TRIM(q.tier),
'v1ds', q.v1ds,
'v0ds', q.v0ds,
'part_v1ds', q.part_v1ds,
'customized', q.customized
),
'cost', jsonb_build_object(
'curstd_orig', q.curstd_orig,
'futstd_orig', q.futstd_orig,
'curstd_last', q.curstd_last,
'futstd_last', q.futstd_last,
'curstd', q.curstd,
'futstd', q.futstd
),
'targets', jsonb_build_object(
'target_price', q.tprice,
'target_math', q.tmath,
'volume_range', q.volume_range
),
'list', jsonb_build_object(
'listcode', q.listcode,
'listprice', q.listprice,
'listprice_eff', q.listprice_eff,
'list_relevance', q.list_relevance
),
'guidance_price', q.guidance_price,
'guidance_reason', q.guidance_reason
),
ui_json = jsonb_build_object(
'details', jsonb_build_array(
jsonb_build_object(
'label', 'History',
'details', jsonb_build_array(
jsonb_build_object(
'label', CASE WHEN q.last_price IS NOT NULL THEN 'Last Sale: ' || q.last_date ELSE 'No Recent' END,
'value', COALESCE(q.last_price, 0),
'type', 'currency',
'note', CASE WHEN q.last_price IS NOT NULL THEN
CASE q.last_source
WHEN 'mrq' THEN 'Recent similar ' || (pricequote.pick_last_price_from_hist(q.hist, q.v1ds)->>'part') || ' qty: ' || q.last_qty
WHEN 'mrs' THEN 'Recent similar ' || (pricequote.pick_last_price_from_hist(q.hist, q.v1ds)->>'part') || ' qty: ' || q.last_qty
WHEN 'dsq' THEN 'Last quote qty: ' || q.last_qty
WHEN 'dss' THEN 'Last sale qty: ' || q.last_qty
ELSE ''
END
|| CASE WHEN COALESCE(q.last_order, '0') = '0'
THEN ' Qt# ' || COALESCE(q.last_quote, '')
ELSE ' Ord# ' || COALESCE(q.last_order, '')
END
END
)
)
|| CASE WHEN COALESCE(q.last_premium, 1) <> 1 THEN
jsonb_build_array(
jsonb_build_object(
'label', 'Price Difference',
'value', q.last_premium,
'type', 'percent',
'note', q.last_premium_method
)
)
ELSE '[]'::jsonb END
|| CASE WHEN COALESCE(q.last_premium, 1) <> 1 THEN
jsonb_build_array(
jsonb_build_object(
'label', 'Adjusted Price',
'value', q.last_price_norm,
'type', 'currency',
'note', 'normalized to ' || q.v1ds
)
)
ELSE '[]'::jsonb END
),
jsonb_build_object(
'label', 'List',
'details', jsonb_build_array(
jsonb_build_object(
'label', 'List:' || COALESCE(q.listcode, ''),
'value', q.listprice,
'type', 'currency',
'note', q.list_relevance
)
)
),
jsonb_build_object(
'label', 'Target Calculation',
'details',
(
SELECT jsonb_agg(
jsonb_build_object(
'label', CASE WHEN v <> '' THEN RTRIM(SUBSTRING(v, 1, 18)) ELSE 'No Target' END,
'value', CASE WHEN v <> '' THEN SUBSTRING(v, 23, 7)::NUMERIC(20,5)
+ CASE SUBSTRING(v, 19, 1) WHEN '+' THEN 0 ELSE -1 END
ELSE 0 END,
'type', CASE WHEN v <> '' THEN CASE SUBSTRING(v, 19, 1) WHEN '+' THEN 'currency' ELSE 'Percent' END ELSE '' END,
'note', CASE WHEN v <> '' THEN CASE SUBSTRING(v, 19, 1) WHEN '+' THEN 'Price' ELSE 'Premium' END ELSE '' END
)
)
FROM jsonb_array_elements_text(COALESCE(q.tmath, '[""]'::jsonb)) AS t(v)
)
|| CASE WHEN q.tprice IS NULL THEN '[]'::jsonb
ELSE jsonb_build_object('label', 'Price', 'value', COALESCE(q.tprice, 0), 'type', 'currency', 'note', 'Total') END
),
jsonb_build_object(
'label', 'Guidance',
'details', jsonb_build_array(
jsonb_build_object(
'label', 'Price',
'value', COALESCE(q.guidance_price, 0),
'type', 'currency',
'note', COALESCE(q.guidance_reason, '')
)
)
)
),
'data', q.expl
);
-- 2 minutes 33 seconds
--------------------------------------------------------------------
-- 12) Merge back into matrix (store both expl and ui)
--------------------------------------------------------------------
UPDATE rlarp.osm_stack o UPDATE rlarp.osm_stack o
SET pricing = pricing SET pricing = pricing || q.expl
|| jsonb_build_object(
'expl', q.expl,
'ui', q.ui_json
)
FROM pricequote.queue q FROM pricequote.queue q
WHERE WHERE
o.bill_cust = q.bill o.bill_cust = q.bill
@ -520,9 +316,12 @@ BEGIN
AND o.calc_status <> 'CANCELLED' AND o.calc_status <> 'CANCELLED'
AND o.version IN ('Actual', 'Forecast', 'Quotes') AND o.version IN ('Actual', 'Forecast', 'Quotes')
AND o.part IS NOT NULL AND o.part IS NOT NULL
AND SUBSTRING(o.glec, 1, 1) <= '2'; AND substring(o.glec, 1, 1) <= '2';
-- 9 minutes 35 seconds -- 6 minutes 31 seconds
-----------------------------------------------------------------------
-- Done
-----------------------------------------------------------------------
RAISE NOTICE 'Queue processing complete.'; RAISE NOTICE 'Queue processing complete.';
END; END;
$$; $$;