pipekit/config/modules/terms.sql
Paul Trowbridge dd9f89f4b5 feat: version-control pipeline definitions via export/apply
Add `pipekit export` / `pipekit apply` (pipekit/config_io.py) to serialise the
DB's config — drivers, connections, modules (+ columns, watermarks, hooks),
groups, schedules — to a git-trackable text tree under config/, and rehydrate
it. SQLite stays runtime state; definitions become diffable/reviewable/
revertible.

- config only: run_log/group_run/settings and per-run state columns excluded
- name-keyed refs (portable across databases); source_query in .sql sidecars;
  columns as real JSON arrays for line-by-line diffs
- newline-normalised so CRLF-vs-LF is never a spurious change
- apply is create/update by name; child collections fully synced; top-level
  deletes gated behind --prune; --dry-run prints the plan
- round-trip is identity (export -> apply --dry-run == nothing to do)

Commits the current config/ as the first baseline, capturing the freshly
populated columns_json for rm00101/rm00301/iv00101. Documented in SPEC.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 10:56:55 -04:00

31 lines
1.7 KiB
SQL

--source-side extract for cms.terms (pipekit CMS module)
--CMS terms live in the generic CODE table (A2 = 'NN'); the structured attributes are
--packed into the fixed-width CHAR column A215 at fixed byte offsets. Parse them HERE on
--DB2 where A215 is intact -- do NOT sync raw A215 and parse in Postgres: the transfer
--strips leading spaces on discount-bearing rows, which shifts every offset.
--offsets verified against the working query in sql/db2/CMS/AR/terms/Terms Codes.sql
--REPLACE(...,' ','0') guards each numeric field: unpopulated term types leave those
--positions blank, and a bare INT()/FLOAT() over a space would fail the whole extract.
SELECT
LTRIM(RTRIM(A9)) AS term
,LTRIM(RTRIM(A30)) AS descr
--discount % offered (e.g. 1.00 = 1%); A215 pos 102-105, scaled by 10000
,ROUND(FLOAT(REPLACE(SUBSTR(A215,102,4),' ','0')) / FLOAT(10000),2) AS disc_pct
--days within which the discount may be taken; A215 pos 84-86
,INT(REPLACE(SUBSTR(A215,84,3),' ','0')) AS disc_days
--net pay days; A215 pos 64-66
,INT(REPLACE(SUBSTR(A215,64,3),' ','0')) AS pay_days
--pay percent (rarely used split-term %); A215 pos 10-12
,FLOAT(REPLACE(SUBSTR(A215,10,3),' ','0')) AS pay_perc
--fixed pay date (seasonal/dated terms): A215 pos 28-33 packed MMDDYY -> YYYY-MM-DD
--emitted as ISO text (null when the date field is zero) so a malformed packed value
--cannot fail the extract; cast to date in Postgres on read
,CASE
WHEN INT(REPLACE(SUBSTR(A215,28,6),' ','0')) = 0 THEN CAST(NULL AS CHAR(10))
ELSE '20' || SUBSTR(A215,32,2) || '-' || SUBSTR(A215,28,2) || '-' || SUBSTR(A215,30,2)
END AS pay_date
FROM
LGDAT.CODE
WHERE
A2 = 'NN'