Commit 8b556c4a by luoqi

feat(sync/friday): 患者关系边 + 咨询接入;退费第三轨 200 单补摄收口

- patient_relation ← customer_referee_circle(10,169 行,双向成对存):患者-患者边进
  patient_relations 独立表(同 jvs-dw 契约,电话簿语义不冒充关系边)。
  ️ 关系码字典 DB 无表(疑代码硬编码)→ 统计推断解码(互逆对+年龄差+性别三重证据,
  依据全在 yaml 注释):1=spouse(92%异性同龄)/8,7=friend/3=父母按对方性别拆
  father,mother(transforms lookup 对方 sex 拼"码|性别"键)/2,10=child(儿×女)/
  17,16=grandparent,grandchild/4,9=sibling/其余 other。待 FRIDAY 官方枚举校正,
  改 enum_mapping 重摄即覆盖。
- consultation ← customer_consult(64 行):意向 potential_treatment + FRIDAY 独有
  未成交原因 unsettled_reason(强召回信号)passthrough 进 content。
- 落库:关系边 7,996 条(friend 3511/other 2322/spouse 639/child 630/mother 349/
  father 266/sibling 229/祖孙 50),100% linked(对方均在册患者)→ guardian 链路
  (儿童触达取家长真名真号)对 FRIDAY 直接激活;consultation 64;failed=0。
- 退费第三轨(status=3 负额 200 单)测试库恢复后补摄完成:refund_record 齐 880
  (99 整单反向+581 行级+200 负额冲减),全程幂等。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
parent f608db9a
# consult — FRIDAY 咨询主体(customer_consult → consultation_record)
# 比 jvs-dw 富:除意向(potential_treatment)外还有 未成交原因(unsettled_reason)——
# 强召回信号(咨询未成交=有意愿没转化),passthrough 进 fact.content 供 scenario/LLM 消费。
# 测试库仅 45 行(结构真实);生产量待接入后观测。
canonical: consultation
emits:
action: consultation_created
subjectType: consultation
occurredAtField: occurredAt
primary:
table: customer_consult
key: id
dedup_by: id
field_mapping:
externalId: id
updatedAt: updated_gmt_at
createdAt: created_gmt_at
patientExternalId: customer_id
clinicId: organization_id
occurredAt: created_gmt_at
intentRaw: potential_treatment # 意向(自由文本;jvs-dw 同名语义 parser 解析)
taskDirector: task_director # 跟进人
# FRIDAY 独有信号(passthrough 进 content):
treatmentPlanText: treatment_plan # 咨询时聊到的治疗方案
unsettledReason: unsettled_reason # 未成交原因(分类值)
unsettledReasonDetail: unsettled_reason_description
preferentialWay: preferential_way # 优惠方式
# patient_relation — FRIDAY 患者-患者关系边(customer_referee_circle → patient_relations 独立表)
#
# 源表双向成对存储(A→B 与 B→A 各一行,互为视角),referee_relationship 是宿主字典 id
# (DB 无对应字典表,疑似代码硬编码)。upsert 资源(无 emits),同 jvs-dw patient_relation。
#
# ⚠️ 关系码解码 = 统计推断(2026-07-19,测试库 10,147 行,互逆对+年龄差+性别三重证据):
# 码 互逆 年龄差(本人-对方) 性别组合 → 推断
# 1 1↔1 +0.2 同龄 92% 异性 → spouse(高置信)
# 8 8↔8 +0.7 同龄 混合(最大量6118对) → friend(高置信)
# 3 3↔10/2 -26.8(对方大27) — → 对方是父母:按对方性别拆 father/mother
# 10 10↔3 +27.5(对方小27) 对方偏女 → child(女儿)
# 2 2↔3 +26.1(对方小26) 对方偏男 → child(儿子)
# 17 17↔16 -38.5(对方大38) — → grandparent
# 16 16↔17 (17 互逆) — → grandchild
# 4 4↔4 -0.6 同龄 偏双男 → sibling(兄弟)
# 9 9↔9 +0.6 同龄 偏双女 → sibling(姊妹)
# 7 7↔7 -0.1 同龄 偏同性 → friend(低置信,或 sibling 变体)
# 5/6/12/13/14/NULL(量小或证据不足) → other
# 待 FRIDAY 提供官方枚举后校正(改这里 enum_mapping 即可,重摄 upsert 覆盖)。
#
# transforms 已 lookup 对方性别拼成 "码|性别" 键(码 3 需性别消歧 father/mother)。
canonical: patient_relation
primary:
table: patient_relation_rows
key: customer_id # 非真 PK;去重靠 PatientRelation @@unique(patientId, relatedExternalId, relationship)
field_mapping:
patientExternalId: customer_id
relatedExternalId: referee_patient_id
relationship: rel_sex_key # "码|性别" → 下方 enum_mapping 归一
enum_mapping:
relationship:
# spouse(1:对称同龄 92% 异性)
"1|1": spouse
"1|2": spouse
"1|": spouse
# friend(8 高置信;7 低置信)
"8|1": friend
"8|2": friend
"8|": friend
"7|1": friend
"7|2": friend
"7|": friend
# 父母(3:对方大 27 岁,按对方性别拆;性别缺 → other 不硬猜)
"3|1": father
"3|2": mother
# 子女(10=女儿,2=儿子 → PAC 统一 child)
"10|1": child
"10|2": child
"10|": child
"2|1": child
"2|2": child
"2|": child
# 祖辈/孙辈(17:对方大 38;16 为其互逆)
"17|1": grandparent
"17|2": grandparent
"17|": grandparent
"16|1": grandchild
"16|2": grandchild
"16|": grandchild
# 兄弟姊妹(4 偏男/9 偏女,对称同龄)
"4|1": sibling
"4|2": sibling
"4|": sibling
"9|1": sibling
"9|2": sibling
"9|": sibling
# 量小/证据不足/NULL 码 → other
_default: other
...@@ -66,6 +66,10 @@ mysql_csv "SELECT uuid,tenant_id AS brand_id,organization_id,patient_id,doctor_i ...@@ -66,6 +66,10 @@ mysql_csv "SELECT uuid,tenant_id AS brand_id,organization_id,patient_id,doctor_i
mysql_csv "SELECT id,tenant_id AS brand_id,organization_id,patient_id,settlement_id,cure_name,service_project_name,receivable_this,net_receipts_this,is_refund,created_gmt_at,updated_gmt_at FROM \`arrail-settlement-server\`.patient_settlement_spec WHERE is_refund=1" patient_settlement_spec_refund.csv mysql_csv "SELECT id,tenant_id AS brand_id,organization_id,patient_id,settlement_id,cure_name,service_project_name,receivable_this,net_receipts_this,is_refund,created_gmt_at,updated_gmt_at FROM \`arrail-settlement-server\`.patient_settlement_spec WHERE is_refund=1" patient_settlement_spec_refund.csv
# 支付通道长表(每单×通道一行;lookup 挑金额最大者为主导通道) # 支付通道长表(每单×通道一行;lookup 挑金额最大者为主导通道)
mysql_csv "SELECT id,tenant_id AS brand_id,settlement_id,modes_name,money,created_gmt_at,updated_gmt_at FROM \`arrail-settlement-server\`.settlement_modes" settlement_modes.csv mysql_csv "SELECT id,tenant_id AS brand_id,settlement_id,modes_name,money,created_gmt_at,updated_gmt_at FROM \`arrail-settlement-server\`.settlement_modes" settlement_modes.csv
# 转介绍圈(患者-患者关系边,双向成对存;referee_relationship 为宿主字典 id,PAC 侧统计推断解码)
mysql_csv "SELECT id,tenant_id AS brand_id,organization_id,customer_id,referee_patient_id,referee_relationship,type,created_gmt_at,updated_gmt_at FROM customer.customer_referee_circle" customer_referee_circle.csv
# 咨询(意向 potential_treatment/未成交原因;测试库仅 45 行,结构真实)
mysql_csv "SELECT id,tenant_id AS brand_id,organization_id,customer_id,task_director_id,task_director,treatment_plan,preferential_way,unsettled_reason,unsettled_reason_description,other_conditions,potential_treatment,data_sources,created_gmt_at,updated_gmt_at FROM customer.customer_consult" customer_consult.csv
echo "── Mongo 导出(med_emr_info,status∈{3,4} 正式病历)──" echo "── Mongo 导出(med_emr_info,status∈{3,4} 正式病历)──"
# 不用 mongoexport:Extended JSON 会把 Date/Long 包成 {$date}/{$numberLong} 对象,破坏平铺契约。 # 不用 mongoexport:Extended JSON 会把 Date/Long 包成 {$date}/{$numberLong} 对象,破坏平铺契约。
......
...@@ -44,6 +44,8 @@ tables: ...@@ -44,6 +44,8 @@ tables:
- { table: patient_settlement_refund, file: patient_settlement_refund.csv } # 整单退费(status=4 或 3 负额) - { table: patient_settlement_refund, file: patient_settlement_refund.csv } # 整单退费(status=4 或 3 负额)
- { table: patient_settlement_spec_refund, file: patient_settlement_spec_refund.csv } # 行级退费明细(is_refund=1) - { table: patient_settlement_spec_refund, file: patient_settlement_spec_refund.csv } # 行级退费明细(is_refund=1)
- { table: settlement_modes, file: settlement_modes.csv } # 支付通道长表 - { table: settlement_modes, file: settlement_modes.csv } # 支付通道长表
- { table: customer_referee_circle, file: customer_referee_circle.csv } # 转介绍圈(患者-患者边)
- { table: customer_consult, file: customer_consult.csv } # 咨询(意向/未成交原因)
transforms: transforms:
# ── 患者:把 1:N 联系方式归约成 patient.phone 标量(无需源侧 join)── # ── 患者:把 1:N 联系方式归约成 patient.phone 标量(无需源侧 join)──
...@@ -326,6 +328,26 @@ transforms: ...@@ -326,6 +328,26 @@ transforms:
# ── S.2 退费①:整单冲减(status=4 或 status=3 负金额;导出侧 WHERE 已切分,assembler 直读 # ── S.2 退费①:整单冲减(status=4 或 status=3 负金额;导出侧 WHERE 已切分,assembler 直读
# patient_settlement_refund 表;金额负值由 refund parser Math.abs 归一)── # patient_settlement_refund 表;金额负值由 refund parser Math.abs 归一)──
# ═══════════ 患者关系链(customer_referee_circle → patient_relations 独立表)═══════════
# 宿主 referee_relationship 是字典 id(DB 无字典表,疑似代码硬编码)。解码 = 统计推断
# (2026-07-19,互逆对+年龄差+性别三重证据,详见 patient_relation.yaml)——需要对方性别
# 参与消歧(码 3=父母,father/mother 按对方性别拆)→ lookup 对方 sex 后拼 "码|性别" 键。
- kind: lookup
input: customer_referee_circle
output: _referee_with_sex
from: customer_basic_info
left_key: referee_patient_id
right_key: id
select:
referee_sex: sex
- kind: derive
input: _referee_with_sex
output: patient_relation_rows
fields:
rel_sex_key:
op: concat
parts: ['${referee_relationship}', '|', '${referee_sex}']
assemblers: assemblers:
- { file: assemblers/patient.yaml } - { file: assemblers/patient.yaml }
- { file: assemblers/appointment.yaml } - { file: assemblers/appointment.yaml }
...@@ -340,3 +362,5 @@ assemblers: ...@@ -340,3 +362,5 @@ assemblers:
- { file: assemblers/payment.yaml } - { file: assemblers/payment.yaml }
- { file: assemblers/refund_full.yaml } - { file: assemblers/refund_full.yaml }
- { file: assemblers/refund_item.yaml } - { file: assemblers/refund_item.yaml }
- { file: assemblers/patient_relation.yaml }
- { file: assemblers/consult.yaml }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment