fix(push): lookup 的 from 表缺席时从 PAC 库重建 —— 兑现「推送顺序无要求」
接入文档 channel-push.mdx §7.3 承诺「推送顺序无要求;业务数据先于患者主档到达时,
PAC 先建档、主档到达后补全同一人」。实际做不到:push 是**单表**请求,
ingestRawTables 只把被推那张表放进 tables
const tables = { [opts.source]: opts.rows };
for (const tf of transforms) if (tf.input && !tables[tf.input]) tables[tf.input] = [];
只兜底了 input,没兜底 lookup 的 from。于是 transform-engine 拿不到 from 表,
warn 一句就当空表、select 字段全填 null —— 换什么推送顺序都没用,单表请求里
from 表永远不在场。
2026-07-28 FRIDAY 开发推测试数据时踩到:
customer_referee_circle 的规则要 lookup customer_basic_info 取**对方性别**,
用来把关系码 3(本人是对方子女)拆成 father / mother。拿不到性别 → rel_sex_key="3|"
→ patient_relation.yaml 里码 3 唯独没配缺性别兜底 → 掉 _default: other。
实测(测试服):
friday 257 条关系边:father=0 mother=0 other=211
jvs-dw 76,999 条(走 cold-import,from 表齐全):father=6,837 mother=10,715(占 23%)
连带 family_structure 的「多代之家」系统性漏判 —— friday multigen 只剩 2 个,
且全靠 grandparent 撑,该识别成多代之家的都被压成 single。
改动:
- transforms.schema.ts:lookup 新增可选 push_fallback { entity, select{column,map} }。
不配 = 保持旧行为,存量 host 零影响。
- push-lookup-fallback.ts(新):按 input 行的 left_key 去 PAC patients 捞实体,
拼成"长得像 from 表"的合成行 { [right_key]: external_id, ...select }。
· source_unit 消歧:external_id 在集团型宿主跨品牌撞号(FRIDAY 22 个 source_unit,
实测 310 个 id 撞号)→ 捞取按 input 行解析出的 source_unit 圈定;仍落到多个品牌
则**整条跳过**填 null 走 _default,不硬猜。
· map 把 PAC 归一值反写回宿主原编码(male→'1'),保证 push 与 cold-import 产出
**同一个** rel_sex_key —— 否则两条通道各配一套 enum_mapping,迟早漂移。
· map 未命中 / 空串性别 一律当"取不到",不把 PAC 归一值漏给只认宿主编码的下游。
· IN 列表按 5000 分批(bind-var 32767 上限,存量补摄踩过)。
- cold-import.service.ts:transform 前调 hydratePushLookupTables。
只在 tables[from] 缺席或为空时接管 → cold-import / reparse 不受影响。
- friday manifest:给那条 lookup 配上 push_fallback。
残留(有意为之):对方**从未进过 PAC** 时仍取不到性别,落 other。这是"不知道"而不是
"猜错",且存量首推收尾跑一次 reparse 即可补齐(重放时库已全)。
验证:新增 7 个用例连着 runLookup 一起断言最终值(中间对了下游错了没意义);
647 tests / 41 suites 全过;service typecheck 通过。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Found errors in your .gitlab-ci.yml:
- jobs:openapi-drift config contains unknown keys: rules
| Status | Job ID | Name | Coverage |
|---|