poh and poi were full truncate-reloads: 187k rows / 30 s and 529k / 75 s. Both now pull only changed POs -- 1,201 rows / 5.5 s and 3,660 / 10 s -- and reconcile.py --quick reads IN SYNC on all 115 / 120 metrics. POH turns out to carry its own change stamp in its "future" fields: KAFUT12 is Date Created and KAFUT20 is Date Updated, both CHAR(10) ISO text. Predicate is those two against the watermark, plus the open hot set KACRCM = '1' -- 1,035 of 187k headers, and KACRCM leads most of POH's logicals, so it is a keyed read. POI has no change stamp of its own, so it joins the header's changed set at PO grain; its merge key is kbpo#, so staging only the changed lines would drop the rest of the PO. CMS logs this family (POHL, POIL), but both are redundant for change detection: over 7 days POHL and the KAFUT20/12 window agree exactly, and POIL reports no PO that POHL does not, so a line edit always stamps the header. The logs' one unique contribution is deletes, which an incremental merge structurally cannot see -- delete-by-key only touches staged keys, so a purged PO would sit in the dest forever (~88 POs/yr). poh_deleted closes that: DQ0ACTN = '3' is the delete action, and the NOT EXISTS against live POH makes the list exact rather than a guess about action ordering, since a re-used PO number is back in POH and drops out on its own. Three dest hooks, in order -- clearing the tombstone of any PO that is live again must happen before the deletes, or the second hook could remove a row poh had just refreshed. Whenever these are scheduled, run order must be poh -> poi -> poh_deleted: poi's watermark resolves off cms.poh, and poh_deleted's first hook reads cms.poh expecting it to be fresh. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
114 lines
3.3 KiB
SQL
114 lines
3.3 KiB
SQL
WITH changed AS (
|
|
-- Same predicate as poh (module 138) -- POI carries no change stamp of its
|
|
-- own (every KBFUT* is either blank or a business attribute), so it learns
|
|
-- of change only through its header. Verified 2026-08-18 against
|
|
-- LGDAT.POIL (CMS's own item audit log): over a 7-day window POIL reports
|
|
-- 0 POs that POHL does not already report, i.e. a line edit always stamps
|
|
-- the header.
|
|
SELECT "KAPO#" AS po FROM LGDAT.POH WHERE KAFUT20 >= '{poi_wm}'
|
|
UNION
|
|
SELECT "KAPO#" FROM LGDAT.POH WHERE KAFUT12 >= '{poi_wm}'
|
|
UNION
|
|
SELECT "KAPO#" FROM LGDAT.POH WHERE KACRCM = '1'
|
|
UNION
|
|
-- 4 open lines hang off headers already marked complete; without this they
|
|
-- would never refresh.
|
|
SELECT "KBPO#" FROM LGDAT.POI WHERE KBCRCM = '1'
|
|
)
|
|
SELECT
|
|
"KBPO#" AS "kbpo#",
|
|
"KBITM#" AS "kbitm#",
|
|
KBQTYO AS kbqtyo,
|
|
KBQTYR AS kbqtyr,
|
|
KBQTYA AS kbqtya,
|
|
KBQTYJ AS kbqtyj,
|
|
RTRIM(KBOUNT) AS kbount,
|
|
RTRIM("KBPT#") AS "kbpt#",
|
|
RTRIM("KBVPT#") AS "kbvpt#",
|
|
KBUPRC AS kbuprc,
|
|
RTRIM(KBPUNT) AS kbpunt,
|
|
CASE WHEN KBRDAT IN (DATE('0001-01-01'), DATE('9999-12-31')) THEN NULL ELSE KBRDAT END AS kbrdat,
|
|
CASE WHEN KBCDAT IN (DATE('0001-01-01'), DATE('9999-12-31')) THEN NULL ELSE KBCDAT END AS kbcdat,
|
|
RTRIM(KBREQR) AS kbreqr,
|
|
"KBREQ#" AS "kbreq#",
|
|
"KBGL#" AS "kbgl#",
|
|
RTRIM("KBJOB#") AS "kbjob#",
|
|
"KBSEQ#" AS "kbseq#",
|
|
RTRIM("KBPRJ#") AS "kbprj#",
|
|
RTRIM(KBDEPT) AS kbdept,
|
|
RTRIM(KBCGST) AS kbcgst,
|
|
RTRIM(KBCPST) AS kbcpst,
|
|
RTRIM(KBISTS) AS kbists,
|
|
RTRIM(KBITYP) AS kbityp,
|
|
RTRIM(KBISTR) AS kbistr,
|
|
RTRIM(KBOSTR) AS kbostr,
|
|
KBEXTN AS kbextn,
|
|
KBGSTA AS kbgsta,
|
|
KBPSTA AS kbpsta,
|
|
RTRIM(KBPRGR) AS kbprgr,
|
|
RTRIM(KBCRCM) AS kbcrcm,
|
|
RTRIM(KBOTYP) AS kbotyp,
|
|
RTRIM(KBTOS) AS kbtos,
|
|
RTRIM(KBTAXG) AS kbtaxg,
|
|
RTRIM(KBTAXR) AS kbtaxr,
|
|
RTRIM(KBDPRC) AS kbdprc,
|
|
RTRIM(KBPLNT) AS kbplnt,
|
|
RTRIM(KBFUT1) AS kbfut1,
|
|
RTRIM(KBFUT2) AS kbfut2,
|
|
RTRIM(KBFUT3) AS kbfut3,
|
|
RTRIM(KBFUT4) AS kbfut4,
|
|
RTRIM(KBFUT5) AS kbfut5,
|
|
RTRIM(KBFUT6) AS kbfut6,
|
|
RTRIM(KBFUT7) AS kbfut7,
|
|
RTRIM(KBFUT8) AS kbfut8,
|
|
RTRIM(KBFUT9) AS kbfut9,
|
|
RTRIM(KBFUT10) AS kbfut10,
|
|
RTRIM(KBFUT11) AS kbfut11,
|
|
RTRIM(KBFUT12) AS kbfut12,
|
|
RTRIM(KBFUT13) AS kbfut13,
|
|
RTRIM(KBFUT14) AS kbfut14,
|
|
RTRIM(KBFUT15) AS kbfut15,
|
|
RTRIM(KBFUT16) AS kbfut16,
|
|
RTRIM(KBFUT17) AS kbfut17,
|
|
RTRIM(KBFUT18) AS kbfut18,
|
|
RTRIM(KBFUT19) AS kbfut19,
|
|
RTRIM(KBFUT20) AS kbfut20,
|
|
RTRIM(KBFUT21) AS kbfut21,
|
|
RTRIM(KBFUT22) AS kbfut22,
|
|
RTRIM(KBFUT23) AS kbfut23,
|
|
RTRIM(KBFUT24) AS kbfut24,
|
|
RTRIM(KBFUT25) AS kbfut25,
|
|
RTRIM(KBFUT26) AS kbfut26,
|
|
RTRIM(KBFUT27) AS kbfut27,
|
|
RTRIM(KBFUT28) AS kbfut28,
|
|
KBFUT29 AS kbfut29,
|
|
KBFUT30 AS kbfut30,
|
|
KBFUT31 AS kbfut31,
|
|
KBFUT32 AS kbfut32,
|
|
KBFUT33 AS kbfut33,
|
|
KBFUT34 AS kbfut34,
|
|
KBFUT35 AS kbfut35,
|
|
KBFUT36 AS kbfut36,
|
|
RTRIM(KBUSR1) AS kbusr1,
|
|
RTRIM(KBUSR2) AS kbusr2,
|
|
RTRIM(KBUSR3) AS kbusr3,
|
|
RTRIM(KBUSR4) AS kbusr4,
|
|
RTRIM(KBUSR5) AS kbusr5,
|
|
RTRIM(KBUSR6) AS kbusr6,
|
|
RTRIM(KBUSR7) AS kbusr7,
|
|
RTRIM(KBCORG) AS kbcorg,
|
|
RTRIM(KBROHD) AS kbrohd,
|
|
KBORDN AS kbordn,
|
|
KBOITM AS kboitm,
|
|
RTRIM(KBPPRT) AS kbpprt,
|
|
RTRIM(KBCSTC) AS kbcstc,
|
|
RTRIM(KBCSTT) AS kbcstt,
|
|
RTRIM(KBSRIN) AS kbsrin,
|
|
KBUNTFR AS kbuntfr,
|
|
KBSRGPC AS kbsrgpc,
|
|
KBFFRTC AS kbffrtc,
|
|
RTRIM(KBPGRP) AS kbpgrp
|
|
FROM LGDAT.POI i
|
|
INNER JOIN changed c
|
|
ON c.po = i."KBPO#"
|