# PAC 数据库结构 — 提议响应确认单(对应 db-review §21)

> **状态**:待确认
> **目的**:对建议文档(db-suggest-after-review.md)的所有提议,逐项确认我们的响应(采纳 / 部分采纳 / 不采纳)
> **范围**:仅限提议带来的改动,不含 PAC 已有规则
> **流程**:本文确认 → 敲定 schema 字段 → 出"枚举值确认单"二轮

---

## 一、第三层 Plan 响应

### 1.1 提议 §15:FollowupPlan 需要 `target_clinic_id` + `execution_clinic_id`

- [ ] **采纳**:`followup_plans` 加 `target_clinic_id`(nullable,业务字段,创建锁定不更新);`null` = 集团统一客服池(VIP 中心 / 中央营销 / 流失挽回)
- [ ] **采纳**:`plan_executions.clinic_id` 改名 **`executor_clinic_id`**(必填,事实字段)
- [ ] **配套**:两者**允许不一致**(代办场景:A 归属 B 代办)

### 1.2 提议 §15:Plan / PlanExecution 回写 fact 层

- [ ] **拒绝**:Plan 不回写(主语是 PAC 不是患者,创造循环自反馈)
- [ ] **拒绝**:PlanExecution 不回写(算事实但跟同步引擎拉回的 Touchpoint 重复,熔断阈值翻倍风险)
- [ ] **根因澄清**:提议 §16 把 `touchpoints` 错等同于"宿主触达 + PAC 执行 transaction",混了接口 1/2

## 二、第二层 Persona 响应

### 2.1 提议 §14:改名 Persona → Assessment

- [ ] **拒绝改名**:PDF §6.4 钦定术语是 Persona,改名破坏 PDF / 代码 / 文档对齐

### 2.2 提议 §14 + PDF §6.4:feature_key 候选范围

逐项确认(对齐业务边界,枚举值不在 schema 强约束,应用层校验即可):

- [ ] `value`(患者价值)
- [ ] `treatment_chain_status`(治疗链状态)
- [ ] `incomplete_treatment`(未完成治疗)
- [ ] `recall_risk`(复查风险)
- [ ] `engagement`(触达活跃度)
- [ ] `do_not_contact_status`(不打扰状态)
- [ ] `recommended_role`(推荐回访角色)
- [ ] `referral_relation`(推荐关系)
- [ ] `doctor_relation`(医生关系)
- [ ] `communication_preference`(沟通偏好)
- [ ] `customer_experience_risk`(客户体验风险)
- [ ] `treatment_intent`(治疗意向)
- [ ] `family_social_relation`(家庭社会关系)

### 2.3 提议 §14:`assessment_scope` 字段(某诊所视角评价 hook)

- [ ] **拒绝**:v1 集团统一运营,业务上无诊所视角差异;Phase 6+ 真出现"加盟诊所自看自评"再加

## 三、第一层 fact 重构

### 3.1 提议 §6-§10:拆 Transaction + Fact 双表

- [ ] **采纳**:**消灭 5 张事实镜像表**(diagnoses / treatments / appointments / charges / touchpoints)
- [ ] **采纳**:**拆 `patient_transactions`(append-only,操作账本)+ `patient_facts`(版本流,事实单元)双表**
- [ ] **命名**:用 `patient_*` 前缀(不用提议的 `customer_*`)— 跟现有项目定义PAC（不偏运营向） / `patients` 风格统一
- [ ] **`patients` 主档保留**(身份对象,不属事实单元)

### 3.2 提议 §3.1:`patient_identity_refs` / `patient_profile` 拆表

- [ ] **拒绝建 `patient_identity_refs`**(v1 接入契约假设 external_id 唯一,Phase 6+ 跨平台合并再加)
- [ ] **拒绝建 `patient_profile`**(v1 patients 字段可控 ~10 个,Phase 6+ 字段膨胀再拆)

### 3.3 提议 §2:三类 type 严格区分

- [ ] **采纳**:`transaction_type`(动作事实,push 主导)/ `subject_type`(被操作主体,pull 主导)/ `fact_type`(事实单元,parser 解析后下游统一)
- [ ] **采纳 push/pull 摄入路径分工**:transaction_type 跟 push 推送对应 / subject_type 跟 pull 资源对应

### 3.4 提议 §7:Fact 分 Actual / Planned

- [ ] **采纳**:`fact_kind` 字段区分(同表),不拆两张表

### 3.5 提议 §10:`patient_facts` 字段

- [ ] **采纳版本流写入模式**:每版本独立 UUID + `subject_id` 跨版本稳定 + partial UNIQUE active
- [ ] **采纳 `evidence_transaction_ids` 数组**(GIN 索引)
- [ ] **`clinic_id` 立柱但 nullable**(actual / planned 字段统一,**与提议"planned 必填" 差异**;反例:中央客服 400 接咨询 / 集团总部群发触达;必填性 per fact_type 应用层校验)
- [ ] **拒绝 `source_kind` 字段**(只装宿主事实,该字段永远 `host_transaction`)
- [ ] **拒绝 `processor_invocation_ids`**(AI 产物归 `agent_invocations.output`,不进 fact)
- [ ] **拒绝 `evidence_fact_ids`(fact 引用 fact)**(引用关系在 transaction 维度)
- [ ] **拒绝 `confidence`**(AI 置信度,不属宿主事实)
- [ ] **拒绝 `primary_clinic_id` 性能冗余**(nullable 后不需要)

### 3.6 提议 §9:`patient_transactions` 幂等键

- [ ] **采纳 `source_event_id`(nullable)** 作为幂等键 — 宿主原生事件 ID 或 adapter 合成 hash
- [ ] **拒绝提议合成键(组合 5 字段)** — 用 `source_event_id` 单字段更简洁
- [ ] **Push 路径硬要求带 `source_event_id`**,无则拒收
- [ ] **Pull 路径 adapter 合成**:`hash(externalRef, occurredAt, payloadDigest)`

### 3.7 数据流单向 — 已剔除项

- [ ] **采纳剔除**:按"Plan / PlanExecution / AI 产物不回写 fact"决议,从提议 enum 中剔除 `followup_plan_*` / `followup_executed` 4 个 transaction_type、`followup_plan` / `followup_execution` 2 个 subject_type、`followup_plan` / `followup_execution_record` / `image_analysis_result` 3 个 fact_type

### 3.8 保留枚举值逐项确认(对齐业务边界)

> 起步候选,不在 schema 强约束(应用层 zod 校验);本节确认业务范围。
> **起步策略**:transaction_type 14 个最小起步(原版);fact_type actual 12 个 = 原 10 + `treatment_record` + `diagnosis_record`(后两个由 adapter parser 从 encounter / emr / charge 衍生)。
> **后期可补**:`treatment_started/completed/cancelled` / `diagnosis_added` / `patient_registered/updated` 等专门 transaction_type(精度提升时)。
> **触达数据**:PAC 跟宿主回访模块互斥(有回访的宿主不接 PAC),无 touchpoint 类 fact;Persona engagement 应用层显式 join `plan_executions` 消费。

**transaction_type(14 个)**:

- [ ] `consultation_created`(咨询记录创建)
- [ ] `appointment_created`(预约创建)
- [ ] `appointment_changed`(预约变更)
- [ ] `appointment_cancelled`(预约取消)
- [ ] `patient_arrived`(到店签到)
- [ ] `visit_registered`(挂号)
- [ ] `patient_received`(被接诊)
- [ ] `doctor_encounter_started`(医生接诊)
- [ ] `charge_order_submitted`(收费单提交)
- [ ] `payment_received`(收款)
- [ ] `refund_created`(退费)
- [ ] `emr_submitted`(病历提交)
- [ ] `emr_rejected`(病历打回)
- [ ] `image_uploaded`(影像上传)

**subject_type(10 个)**:

- [ ] `consultation`(咨询)
- [ ] `appointment`(预约)
- [ ] `visit_registration`(挂号)
- [ ] `visit_reception`(接诊登记)
- [ ] `clinical_encounter`(医生接诊)
- [ ] `emr_document`(病历文档)
- [ ] `charge_order`(收费单)
- [ ] `payment`(收款)
- [ ] `refund`(退费)
- [ ] `image_study`(影像资料)

**fact_type — Actual Fact(12 个,已发生事实)**:

- [ ] `consultation_record`(咨询记录)
- [ ] `visit_registration_record`(挂号记录)
- [ ] `patient_received_record`(患者被接诊记录)
- [ ] `encounter_record`(医生接诊记录)
- [ ] `diagnosis_record`(诊断记录 — adapter parser 衍生)
- [ ] `treatment_record`(治疗记录 ⭐ 召回核心 — adapter parser 衍生)
- [ ] `charge_order_record`(收费单提交记录)
- [ ] `payment_record`(收款记录)
- [ ] `refund_record`(退费记录)
- [ ] `emr_record`(病历记录)
- [ ] `emr_quality_record`(病历质控记录)
- [ ] `image_record`(影像资料记录)

**fact_type — Planned Fact(4 个,未来安排)**:

- [ ] `appointment_plan`(预约计划)
- [ ] `treatment_plan`(治疗计划,由 encounter parser 衍生)
- [ ] `review_plan`(医嘱复查计划,由 encounter parser 衍生)
- [ ] `payment_plan`(待缴费计划)

> 注:**patient 不进 fact 层**(patient 主档 + transaction 流够);**treatment_plan / review_plan 来自 encounter_record 内容解析**,不增加单独 transaction_type。

## 四、跨表字段响应

### 4.1 evidence 字段是否立柱

- [ ] **维持 JSONB 不立柱**(personas / persona_features / followup_plans / plan_scripts / plan_summaries 上的 `evidence`)— 跟提议 §10 的 `evidence_transaction_ids` 等独立列方向**不同**
- [ ] 形态可演进(Phase 5+ 加 promptVersion / scenarioConfigVersion 等),立柱要持续 migration
- [ ] 真出现"某 fact 影响了哪些 plan"反查热点,按需建 GIN 索引(不进 v1 默认)

## 五、衍生能力 — 影像 AI 识别

### 5.1 提议加 `image_uploaded` / `image_analysis_result` 等影像 fact_type

- [ ] **采纳**`image_uploaded` transaction + `image_record` actual fact(接收影像事实)
- [ ] **拒绝**`image_analysis_result` 作为 fact(AI 产物归 `agent_invocations.output`,见 §3.7)
- [ ] **演进路径**:Phase 5+ 多模态 Agent(GPT-4V / Claude 3 / Qwen-VL)消费宿主侧影像 URL,输出落 `Persona.features` / `PlanSummary`
- [ ] **边界**:PAC 不做主权影像 AI / 不复制存储原文件 / 输出不回写 fact

---

## 六、其他业务枚举字段(可补充 / 后续可调)

> 以下字段 schema 用 String 不强约束,应用层 zod enum 标注。下方为建议起步值 — **能确定的可以直接给,没把握的留空,试点反馈后调整**(改 zod enum 常量即可,不动 schema)。

### 6.1 `scenario`(召回场景 — `plan_reasons.scenario`,v2 移到子表)

PAC v1 两条主战场:
- `treatment_aftercare_recall`(治疗链已完成患者的疗效保障召回 — 主战场,#3 种植年度复查 / #4 牙周维护 已就位)
- `treatment_initiation_recall`(启治召回 — 漏治新链,W3+ 数据足够后启用)

⏳ 待业务拍板:
- 链内中断(#1 根管未戴冠 / #2 正畸保持期)— 算 PAC 还是 host 治疗中提醒?
- 漏诊(影像有医生没看)— W6+ AI 影像才做

将来候选:`sleeping_customer_activation`(沉睡客户激活)/ `vip_followup`(高价值客户跟进)/ `complaint_followup`(投诉后安抚)

### 6.2 `outcome`(执行结果 — `plan_executions`,**强枚举**驱动 Plan 状态机)

建议:
- `abandoned`(客服放弃 → Plan abandoned)
- `no_answer`(无应答 → Plan 仍 active 等下次)
- `scheduled_next`(约定下次回访 → Plan 仍 assigned)
- `success_appointed`(成功转化为新预约 → Plan completed)

### 6.3 `abandon_reasons`(放弃原因多选 — `plan_executions`)

建议(待业务确认):
- `wrong_number`(号码错误)
- `patient_refused`(患者明确拒绝)
- `out_of_service_area`(已搬离服务范围)
- `treated_elsewhere`(已在他处治疗)
- `not_interested`(无意向)
- `do_not_contact_request`(患者要求不再联系 → 自动加 dnc)
- `other`(其他,配合 `abandon_other` 文本)

### 6.4 `script_type`(话术类型 — `plan_scripts`)

建议:
- `opening`(开场白)
- `follow_up`(跟进话术)
- `objection_handling`(异议处理)

将来候选:`closing`(收尾)/ `scheduling_confirm`(预约确认)

### 6.5 `summary_type`(摘要类型 — `plan_summaries`)

建议:
- `one_page`(One Page Summary,客服打电话前快读)
- `medical_record`(病历摘要,引用 EMR 关键内容)
- `treatment_chain`(治疗链概览,跨次治疗梳理)

### 6.6 `agent_kind`(Agent 类型 — `agent_invocations`)

建议:
- `SCRIPT`(话术生成)
- `SUMMARY`(摘要生成)
- `PERSONA_FEATURE`(画像特征推断)
- `RANKING`(召回排序辅助)
- `MEDICAL_SUMMARY`(deprecated,改用 SUMMARY + summary_type)

### 6.7 `recommended_role`(推荐回访角色 — `followup_plans`)

建议(跟 RBAC 角色集对齐):
- `staff`(一线客服)
- `leader`(主管)
- `admin`(管理员)— 极少回访,仅留 hook

将来候选:`doctor_assistant`(医助)/ `vip_specialist`(VIP 客服)

### 6.8 `recommended_channel`(推荐触达渠道 — `followup_plans`)+ `channel`(实际触达渠道 — `touchpoints`)

两字段共用同一组取值。建议:
- `phone`(电话回访)
- `wecom`(企业微信)
- `sms`(短信)
- `other`(其他,配合自由文本)

将来候选:`wechat`(个微)/ `email` / `app_push`

### 6.9 `direction`(触达方向 — `touchpoints`)

建议:
- `inbound`(患者主动来电 / 来消息)
- `outbound`(宿主或 PAC 主动外呼 / 外推)
- `unknown`(无法判定,兜底)

### 6.10 `do_not_contact_reason`(不打扰原因 — `patients`,合规相关)

建议:
- `complaint`(投诉过)
- `opt_out`(主动要求不联系)
- `treated_elsewhere`(已转他处)
- `deceased`(已故,但通常用 `deceased` 字段)
- `legal_hold`(法律纠纷)
- `other`(其他)

---

# 下一步

**本确认单(§1-§5 决议 + §2.2 / §3.8 业务边界 + §6 业务枚举)**:按所有结论敲定 `patient_transactions` / `patient_facts` 等 schema 字段(prisma + 索引)及应用层 zod enum,直接进 Phase 1 重构。

请逐项打勾(§1-§5 / §2.2 / §3.8)或在 §6 各项下直接给出最终业务取值,反馈即可。
