# PAC 底层事实模型建议

> 版本：v0.5  
> 对象：PAC 底层数据模型设计  
> 目的：明确 PAC 中 Transaction、Fact、Assessment、Plan 的边界。  
> 核心口径：PAC 底座采用 **CustomerTransaction + CustomerFact（Actual / Planned）+ Assessment + Plan**。

---

## 1. 总体模型

PAC 底层模型：

```text
CustomerTransaction  // 操作账本：记录操作事实如何发生
        ↓
CustomerFact         // 事实单元：记录患者事实中形成了什么
        ↓
Assessment / Persona // 评价：基于事实形成患者评价
        ↓
FollowupPlan         // 计划：基于评价形成召回计划
```

四层主语：

```text
Transaction：某个系统/人员做了什么操作
Fact：患者事实中存在什么事实单元
Assessment：PAC 对患者事实形成什么评价
Plan：PAC 形成什么行动计划
```

---

## 2. 三个 type 的定义

这里需要明确区分：

```text
transaction_type
subject_type
fact_type
```

三者不能混用。

---

### 2.1 transaction_type：动作事实

`transaction_type` 描述：

```text
发生了什么操作事实
```

它的主语是：

```text
某个系统 / 某个人 / 某个流程
```

表达方式：

```text
appointment_created
appointment_changed
visit_registered
patient_received
charge_order_submitted
payment_received
emr_submitted
```

示例：

```text
预约被创建
预约被变更
挂号发生
患者被接诊
收费单被提交
收款被确认
病历被提交
```

`transaction_type` 要尽可能贴近宿主真实动作，越细越好。

---

### 2.2 subject_type：被操作主体类型

`subject_type` 描述：

```text
这次操作作用在哪类主体上
```

它不表达动作，只表达对象类型。

示例：

```text
consultation
appointment
visit_registration
visit_reception
clinical_encounter
emr_document
charge_order
payment
refund
image_study
followup_plan
followup_execution
```

例如：

```text
transaction_type = appointment_created
subject_type = appointment

transaction_type = visit_registered
subject_type = visit_registration

transaction_type = patient_received
subject_type = visit_reception

transaction_type = doctor_encounter_started
subject_type = clinical_encounter
```

---

### 2.3 fact_type：患者事实单元类型

`fact_type` 描述：

```text
患者事实中形成了什么事实单元
```

它不表达操作过程，而表达患者事实的稳定单元。

示例：

```text
appointment_plan
visit_registration_record
patient_received_record
encounter_record
charge_order_record
payment_record
emr_record
image_record
followup_plan
followup_execution_record
```

例如：

```text
transaction_type = patient_received
subject_type = visit_reception

解析为：

fact_kind = actual
fact_type = patient_received_record
```

---

### 2.4 三者关系

```text
transaction_type = 动作事实，尽可能细节准确
subject_type     = 被操作主体类型，不表达动作
fact_type        = 患者事实单元类型，不表达操作过程
```

---

## 3. clinic_id 的字段归属

### 3.1 Patient 相关对象：到租户

Patient 相关对象包括：

```text
patients
patient_identity_refs
patient_profile
assessment / persona
assessment_features
```

数据边界：

```text
platform_id + tenant_id
```

不强制带 `clinic_id`。

定义：

```text
患者身份到 tenant。
患者资料到 tenant。
患者画像到 tenant。
患者评价到 tenant。
```

---

### 3.2 Transaction：必须有 clinic_id

Transaction 记录操作发生过程：

```text
谁，在什么时候，通过哪个系统，在哪个 clinic 上下文中，对哪个主体，做了什么操作。
```

Transaction 必须带 `clinic_id`。

`clinic_id` 表示：

```text
操作发生地点
操作归属诊所
业务现场上下文
计划创建所在诊所
收费发生诊所
病历提交诊所
预约创建/变更所在诊所
挂号发生诊所
患者接诊诊所
```

---

### 3.3 Actual Fact：到租户

Actual Fact 记录患者事实中已经形成的事实单元。

数据边界：

```text
platform_id + tenant_id + patient_id
```

Actual Fact 不强制带 `clinic_id`。

clinic 通过 evidence transaction 反查：

```text
actual_fact.evidence_transaction_ids -> customer_transactions.clinic_id
```

如果为了查询性能需要冗余 clinic，可使用：

```text
primary_clinic_id
```

该字段为派生字段，不作为隔离字段。

---

### 3.4 Planned Fact：必须有 clinic_id

Planned Fact 记录患者事实中已经形成的未来安排。

Planned Fact 必须有 `clinic_id`。

`clinic_id` 表示计划落点：

```text
预约目标诊所
回访执行诊所/团队
复查目标诊所
治疗计划执行诊所
待缴费归属诊所
```

---

## 4. clinic_id 字段归属总表

| 对象 | clinic_id | 说明 |
|---|---:|---|
| Patient | 否 | 患者身份到 tenant |
| Patient Identity / Profile | 否 | 患者资料到 tenant |
| Assessment / Persona | 否 | 患者评价到 tenant |
| Assessment Feature | 否 | 评价特征引用 facts |
| CustomerTransaction | 是 | 操作必须记录 clinic 上下文 |
| Actual Fact | 通常否 | 已发生事实到 tenant；clinic 由 evidence transaction 追溯 |
| Planned Fact | 是 | 计划事实必须记录目标诊所/执行诊所 |
| FollowupPlan | 是 | 计划需要目标诊所或执行团队 |
| PlanExecution | 是 | 执行记录需要执行地点/团队上下文 |
| AgentInvocation / ProcessorInvocation | 否或可选 | 可记录 related clinic，不作为主隔离 |

字段归属口径：

```text
Patient 到租户。
Transaction 必须有 clinic。
Actual Fact 到租户。
Planned Fact 必须有 clinic。
```

---

## 5. 宿主业务对象在 PAC 中的归属

以下宿主业务对象在 PAC 中不作为主权事实表：

```text
diagnoses
treatments
appointments
charges
touchpoints
```

这些对象在 PAC 中的承接方式：

```text
1. 作为 CustomerTransaction 的 subject snapshot
2. 作为 CustomerFact 的 fact_content_json
3. 作为 Assessment 的 evidence 来源
```

### 5.1 宿主对象归属表

| 宿主对象 | PAC 中的承接方式 |
|---|---|
| diagnosis | 进入病历/临床类 transaction snapshot；必要时解析为 fact 内容 |
| treatment | 进入治疗计划/治疗动作类 transaction snapshot；必要时解析为 planned / actual fact |
| appointment | 进入预约创建/变更/取消 transaction；解析为 appointment_plan 等 fact |
| charge | 进入收费单/收费/退费 transaction；解析为 charge_order_record / payment_record / refund_record 等 fact |
| touchpoint | 进入触达/回访 transaction；解析为 followup_execution_record 或 followup_plan 等 fact |

PAC 记录的表达方式：

```text
宿主在某个时间提交了一份包含某些内容的记录。
```

PAC 事实表达方式：

```text
患者事实中存在一条由该宿主记录解析形成的事实单元。
```

---

## 6. Transaction 和 Fact 的边界

### 6.1 Transaction 是操作账本

Transaction 回答：

```text
某个系统/人员做了什么操作？
```

示例：

```text
400 创建咨询记录
预约被创建
预约被变更
预约被取消
患者到店签到
挂号发生
患者被接诊
医生开始接诊
收费单被提交
收款被确认
退费被创建
病历被提交
病历被打回
影像被上传
回访计划被创建
回访被执行
```

Transaction 的性质：

```text
不可变操作记录
append-only
```

---

### 6.2 Fact 是事实单元

Fact 回答：

```text
患者事实中存在什么？
```

示例：

```text
患者事实中存在一条咨询记录
患者事实中存在一条预约计划
患者事实中存在一条挂号记录
患者事实中存在一条患者被接诊记录
患者事实中存在一条医生接诊记录
患者事实中存在一条收费单记录
患者事实中存在一条收款记录
患者事实中存在一条退费记录
患者事实中存在一条病历记录
患者事实中存在一条病历质控记录
患者事实中存在一条影像资料记录
患者事实中存在一条影像分析结果
患者事实中存在一条回访计划
患者事实中存在一条回访执行记录
```

Fact 的性质：

```text
由 transaction 解析、切块、归一、AI 处理后形成的可证据化事实单元。
```

---

## 7. Fact 分为 Actual Fact 与 Planned Fact

PAC 中的 Fact 分为两类：

```text
Actual Fact   已发生事实
Planned Fact  计划事实
```

---

### 7.1 Actual Fact：已发生事实

Actual Fact 回答：

```text
患者事实中已经存在什么已发生事实？
```

典型 fact：

```text
患者事实中存在一条咨询记录
患者事实中存在一条挂号记录
患者事实中存在一条患者被接诊记录
患者事实中存在一条医生接诊记录
患者事实中存在一条收费单提交记录
患者事实中存在一条收款记录
患者事实中存在一条退费记录
患者事实中存在一条病历记录
患者事实中存在一条病历质控记录
患者事实中存在一条影像资料记录
患者事实中存在一条回访执行记录
```

Actual Fact 的核心时间字段：

```text
occurred_at
```

Actual Fact 的主边界：

```text
platform_id + tenant_id + patient_id
```

Actual Fact 不强制 `clinic_id`。

---

### 7.2 Planned Fact：计划事实

Planned Fact 回答：

```text
患者事实中已经存在什么未来安排？
```

典型 fact：

```text
患者事实中存在一条预约计划
患者事实中存在一条回访计划
患者事实中存在一条治疗计划
患者事实中存在一条医嘱复查计划
患者事实中存在一条待缴费计划
```

Planned Fact 的核心字段：

```text
clinic_id
planned_for
valid_from
valid_until
plan_status
```

Planned Fact 的边界：

```text
platform_id + tenant_id + patient_id + clinic_id
```

这里的 clinic 是计划落点，不是 patient 隔离维度。

定义：

```text
Planned Fact 是某个系统或人员已经创建出的未来安排事实。
```

---

## 8. Appointment / Visit / Follow-up 的模型

Appointment、Visit、Follow-up 都需要区分：

```text
1. 操作：创建、变更、取消、挂号、接诊、执行
2. 事实内容：患者事实中形成的事实单元
```

---

### 8.1 预约创建

#### Transaction：预约被创建

```json
{
  "transaction_type": "appointment_created",
  "subject_type": "appointment",
  "subject_id": "apt_001",
  "operation": "created",
  "clinic_id": "clinic_A",
  "transaction_time": "2026-05-10T10:00:00+08:00",
  "after_snapshot": {
    "scheduled_at": "2026-05-20T10:00:00+08:00",
    "clinic_id": "clinic_A",
    "doctor_name": "张医生",
    "appointment_type": "复查",
    "source": "400",
    "purpose": "根管复查"
  }
}
```

#### Fact：患者事实中形成预约计划

```json
{
  "fact_kind": "planned",
  "fact_type": "appointment_plan",
  "clinic_id": "clinic_A",
  "planned_for": "2026-05-20T10:00:00+08:00",
  "status": "active",
  "fact_summary": "患者事实中存在一条 2026-05-20 10:00 到 clinic_A 复查的预约计划",
  "evidence_transaction_ids": ["tx_001"]
}
```

---

### 8.2 预约变更

#### Transaction：预约被变更

```json
{
  "transaction_type": "appointment_changed",
  "subject_type": "appointment",
  "subject_id": "apt_001",
  "operation": "changed",
  "clinic_id": "clinic_A",
  "before_snapshot": {
    "scheduled_at": "2026-05-20T10:00:00+08:00"
  },
  "after_snapshot": {
    "scheduled_at": "2026-05-22T15:00:00+08:00"
  }
}
```

#### Fact 变化

```text
旧 appointment_plan fact -> superseded
新 appointment_plan fact -> active
新 fact 保留 clinic_id
```

---

### 8.3 挂号

#### Transaction：挂号发生

```json
{
  "transaction_type": "visit_registered",
  "subject_type": "visit_registration",
  "subject_id": "reg_001",
  "operation": "created",
  "clinic_id": "clinic_A",
  "transaction_time": "2026-05-22T14:40:00+08:00",
  "after_snapshot": {
    "registration_no": "R20260522001",
    "appointment_id": "apt_001",
    "department": "口腔综合",
    "doctor_name": "张医生"
  }
}
```

#### Fact：患者事实中形成挂号记录

```json
{
  "fact_kind": "actual",
  "fact_type": "visit_registration_record",
  "occurred_at": "2026-05-22T14:40:00+08:00",
  "fact_summary": "患者事实中存在一条 2026-05-22 14:40 的挂号记录",
  "evidence_transaction_ids": ["tx_002"]
}
```

---

### 8.4 患者被接诊

#### Transaction：患者被接诊

```json
{
  "transaction_type": "patient_received",
  "subject_type": "visit_reception",
  "subject_id": "recv_001",
  "operation": "received",
  "clinic_id": "clinic_A",
  "transaction_time": "2026-05-22T14:55:00+08:00",
  "after_snapshot": {
    "registration_id": "reg_001",
    "appointment_id": "apt_001",
    "received_by": "前台A"
  }
}
```

#### Fact：患者事实中形成被接诊记录

```json
{
  "fact_kind": "actual",
  "fact_type": "patient_received_record",
  "occurred_at": "2026-05-22T14:55:00+08:00",
  "fact_summary": "患者事实中存在一条 2026-05-22 14:55 在 clinic_A 被接诊的记录",
  "evidence_transaction_ids": ["tx_003"]
}
```

说明：

```text
patient_received_record 是 actual fact。
clinic 可由 tx_003 反查。
```

同时：

```text
appointment_plan fact -> fulfilled
```

---

### 8.5 医生接诊

#### Transaction：医生开始接诊

```json
{
  "transaction_type": "doctor_encounter_started",
  "subject_type": "clinical_encounter",
  "subject_id": "enc_001",
  "operation": "started",
  "clinic_id": "clinic_A",
  "transaction_time": "2026-05-22T15:05:00+08:00",
  "after_snapshot": {
    "doctor_name": "张医生",
    "registration_id": "reg_001",
    "appointment_id": "apt_001"
  }
}
```

#### Fact：患者事实中形成医生接诊记录

```json
{
  "fact_kind": "actual",
  "fact_type": "encounter_record",
  "occurred_at": "2026-05-22T15:05:00+08:00",
  "fact_summary": "患者事实中存在一条 2026-05-22 15:05 的医生接诊记录",
  "evidence_transaction_ids": ["tx_004"]
}
```

---

### 8.6 回访计划

Transaction：

```text
followup_plan_created
followup_plan_changed
followup_plan_cancelled
followup_executed
```

Fact：

```text
planned fact: followup_plan，保留 clinic_id
actual fact: followup_execution_record，clinic 可由 evidence transaction 反查
```

定义：

```text
回访计划是 Planned Fact。
回访执行结果是 Actual Fact。
```

---

## 9. CustomerTransaction 建议结构

表名：

```text
customer_transactions
```

建议字段：

```text
id
platform_id
tenant_id
patient_id

transaction_type
transaction_time
received_at

source_system          // 5i5ya / 400 / friday / pac / manual
source_module          // appointment / visit / emr / charge / followup / image
source_object_type
source_object_id
source_event_id        // 如果宿主有事件 ID，优先用于幂等
source_actor_id
source_actor_role

clinic_id              // 必填：操作业务现场 / 计划归属诊所 / 来源诊所

subject_type           // consultation / appointment / visit_registration / visit_reception / clinical_encounter / emr_document / charge_order / payment / refund / image_study / followup_plan / followup_execution
subject_id             // 宿主侧主体 ID
operation              // created / changed / cancelled / submitted / rejected / paid / refunded / executed / registered / received / started

before_snapshot        // 可空，宿主能给就保存
after_snapshot         // 当次操作后的主体内容
raw_payload            // 原始入参快照
payload_hash

ingest_id
created_at
```

---

### 9.1 幂等键

优先使用：

```text
platform_id + tenant_id + source_event_id
```

如果宿主没有 source_event_id，再退化为：

```text
platform_id + tenant_id + source_system + subject_type + subject_id + operation + transaction_time + payload_hash
```

同一个业务主体可能被多次修改，因此不使用：

```text
fact_type + external_ref
```

作为唯一幂等依据。

---

## 10. CustomerFact 建议结构

表名：

```text
customer_facts
```

建议字段：

```text
id
platform_id
tenant_id
patient_id

fact_kind              // actual | planned
fact_type              // appointment_plan / visit_registration_record / patient_received_record / emr_record / charge_record / image_analysis_result ...

fact_status            // active / superseded / cancelled / fulfilled / expired / invalidated
version

occurred_at            // actual fact 使用
planned_for            // planned fact 使用
valid_from
valid_until

clinic_id              // planned fact 必填；actual fact 可空
primary_clinic_id      // actual fact 如需性能冗余，可用该字段，不作为隔离

fact_title
fact_summary
fact_content_json

source_kind            // host_transaction / pac_processor / ai_processor / manual_correction
evidence_transaction_ids
evidence_fact_ids
processor_invocation_ids

confidence
superseded_by
created_at
updated_at
```

---

### 10.1 字段约束

```text
if fact_kind = 'planned':
    clinic_id must not be null
    planned_for should usually not be null

if fact_kind = 'actual':
    occurred_at should not be null
    clinic_id may be null
```

---

## 11. 初始 CustomerTransaction 类型

| transaction_type | 中文名 | subject_type | clinic 要求 | 典型结果 |
|---|---|---|---|---|
| `consultation_created` | 咨询记录被创建 | consultation | 必填/可用目标诊所 | actual fact: consultation_record |
| `appointment_created` | 预约被创建 | appointment | 必填 | planned fact: appointment_plan |
| `appointment_changed` | 预约被变更 | appointment | 必填 | 新 planned fact，旧 fact superseded |
| `appointment_cancelled` | 预约被取消 | appointment | 必填 | actual fact: appointment_cancel_record；planned fact cancelled |
| `patient_arrived` | 患者到店/签到 | visit_reception | 必填 | transaction，可参与解析 patient_received_record |
| `visit_registered` | 挂号发生 | visit_registration | 必填 | actual fact: visit_registration_record |
| `patient_received` | 患者被接诊 | visit_reception | 必填 | actual fact: patient_received_record |
| `doctor_encounter_started` | 医生接诊开始 | clinical_encounter | 必填 | actual fact: encounter_record |
| `charge_order_submitted` | 收费单被提交 | charge_order | 必填 | planned fact: payment_plan / actual fact: charge_order_record |
| `payment_received` | 收款被确认 | payment | 必填 | actual fact: payment_record |
| `refund_created` | 退费被创建 | refund | 必填 | actual fact: refund_record |
| `emr_submitted` | 病历被提交 | emr_document | 必填 | actual fact: emr_record |
| `emr_rejected` | 病历被打回 | emr_document | 必填 | actual fact: emr_quality_record |
| `image_uploaded` | 影像被上传 | image_study | 必填 | actual fact: image_record |
| `followup_plan_created` | 回访计划被创建 | followup_plan | 必填 | planned fact: followup_plan |
| `followup_plan_changed` | 回访计划被变更 | followup_plan | 必填 | 新 planned fact，旧 fact superseded |
| `followup_plan_cancelled` | 回访计划被取消 | followup_plan | 必填 | planned fact cancelled |
| `followup_executed` | 回访被执行 | followup_execution | 必填 | actual fact: followup_execution_record |

---

## 12. 初始 CustomerFact 类型

### 12.1 Actual Fact

```text
consultation_record          咨询记录
visit_registration_record    挂号记录
patient_received_record      患者被接诊记录
encounter_record             医生接诊记录
charge_order_record          收费单提交记录
payment_record               收款记录
refund_record                退费记录
emr_record                   病历记录
emr_quality_record           病历质控记录
image_record                 影像资料记录
image_analysis_result        影像分析结果
followup_execution_record    回访执行记录
```

这些 fact 主边界到 tenant，不强制 clinic_id。

---

### 12.2 Planned Fact

```text
appointment_plan             预约计划
followup_plan                回访计划
treatment_plan               治疗计划
review_plan                  医嘱复查计划
payment_plan                 待缴费计划
```

这些 fact 必须有 clinic_id。

---

## 13. Image AI / EMR AI 等解析结果的归属

例如：

```text
image_uploaded transaction
```

可触发影像 AI：

```text
processor_invocation
```

然后形成：

```text
fact_kind = actual
fact_type = image_analysis_result
```

该 fact 引用：

```text
evidence_transaction_ids = [image_uploaded_tx]
processor_invocation_ids = [image_ai_call_id]
```

边界：

```text
Fact = 对 transaction / 原始材料的解析结果
Assessment = 对 facts 的业务评价
```

例如：

| 内容 | 层级 |
|---|---|
| 某张片子被上传 | Transaction |
| 影像 AI 对片子的分析结果 | Fact |
| 基于影像、病历、收费形成患者治疗意向评价 | Assessment |
| 形成客服回访计划 | Plan |

---

## 14. Assessment / Persona 的位置

Assessment 基于 facts 生成。

它回答：

```text
PAC 对患者事实形成什么评价？
```

例如：

```text
患者价值评价
复查未完成风险评价
治疗意向评价
投诉/体验风险评价
近期不宜打扰评价
推荐回访角色评价
```

Assessment 消费：

```text
customer_facts
```

每个 assessment feature 引用：

```text
evidence_fact_ids
```

必要时再间接追溯到 transaction。

Assessment 不带 clinic_id 作为主隔离；若需要形成“某诊所视角下的评价”，可使用 assessment_scope 或 feature context。

---

## 15. FollowupPlan 的位置

FollowupPlan 是 PAC 的行动计划。

它可以基于：

```text
customer_facts
assessment_features
rules
agent output
```

生成。

FollowupPlan 需要目标诊所或执行诊所：

```text
target_clinic_id
execution_clinic_id / team_id
```

PAC 生成的 FollowupPlan 可作为 planned fact 回写到 fact 层：

```text
fact_kind = planned
fact_type = followup_plan
```

PlanExecution 可形成 actual fact：

```text
fact_kind = actual
fact_type = followup_execution_record
source_system = pac
```

clinic 来自执行 transaction。

---

## 16. 与原表的对应关系

| 原表/概念 | 建议归属 |
|---|---|
| `patient_fact_events` | `customer_transactions`，操作账本，必须有 clinic_id |
| `diagnoses` | 临床/病历类 transaction snapshot；必要时解析为 fact 内容 |
| `treatments` | 治疗计划/治疗动作类 transaction snapshot；必要时解析为 planned / actual fact |
| `appointments` | 预约创建/变更/取消 transaction；解析为 appointment_plan 等 fact |
| `charges` | 收费单、收费、退费 transaction；解析为 charge_order_record / payment_record / refund_record fact |
| `touchpoints` | 宿主触达和 PAC 执行 transaction；解析为 followup_execution_record 或 followup_plan fact |
| `personas` | Assessment 层，到 tenant，不带 clinic 主隔离 |
| `followup_plans` | Plan 层，带 target_clinic_id / execution context |
| `agent_invocations` | 可扩展为 processor_invocations，覆盖 AI 解析、LLM 生成等 |

---

## 17. 设计约束

### 17.1 Patient 到租户

```text
Patient / Persona / Assessment 只到 platform + tenant。
clinic 不切分患者和画像。
```

### 17.2 Transaction 必须有 clinic

```text
每个 transaction 必须记录 clinic 上下文。
```

### 17.3 transaction_type 表达动作事实

```text
transaction_type 描述操作发生了什么。
命名应尽可能贴近宿主真实动作。
```

### 17.4 subject_type 表达被操作主体

```text
subject_type 只表达对象类型，不表达动作。
```

### 17.5 fact_type 表达患者事实单元

```text
fact_type 表达患者事实中形成的事实单元，不表达操作过程。
```

### 17.6 Actual Fact 到租户

```text
Actual Fact 主边界到 tenant。
clinic 通过 evidence transaction 追溯。
如冗余 clinic，只能作为 derived field，不是隔离字段。
```

### 17.7 Planned Fact 必须有 clinic

```text
预约计划、回访计划、治疗计划、复查计划、待缴费计划都必须有 clinic_id。
```

### 17.8 宿主对象不作为 PAC 主权对象

```text
PAC 不拥有宿主 diagnosis / treatment / appointment / charge。
PAC 记录宿主对这些主体做过什么操作，以及当时的内容快照。
```

### 17.9 Transaction append-only

```text
Transaction 不更新、不删除。
错误通过 correction transaction 修正。
```

### 17.10 Fact 必须可追溯

```text
每个 fact 必须追溯到 transaction、raw payload、processor invocation。
```

### 17.11 Planned Fact 也是事实

```text
预约计划、回访计划、治疗计划、复查计划都是 planned fact。
它们是已经形成的未来安排。
```

### 17.12 Assessment 是评价

```text
患者价值、治疗意向、投诉风险、回访优先级属于 Assessment。
```

---

## 18. 建议下一步

下一步先完成以下设计：

1. 定义 `customer_transactions` 表。
2. 定义 `customer_facts` 表。
3. 梳理首批 transaction_type。
4. 梳理首批 subject_type。
5. 梳理首批 fact_type，并区分 actual / planned。
6. 明确 clinic_id 字段归属规则。
7. 定义 transaction → fact 的解析器协议。
8. 再讨论 Assessment / Plan 如何消费 facts。

首批链路：

```text
400咨询
预约创建 / 变更 / 取消
患者到店 / 挂号 / 被接诊
医生接诊
提交收费单
收费
退费
提交病历
病历打回
影像上传
回访计划创建 / 变更 / 取消
回访执行
```

尘锋 SCRM 可后续作为 external_signal 接入。

---

## 19. 一句话总结

PAC 的底层模型：

```text
CustomerTransaction：操作发生的证据链，必须有 clinic_id
CustomerFact：操作解析出的事实单元，分 Actual Fact 和 Planned Fact
Actual Fact：已发生事实，到 tenant，clinic 从 transaction 追溯
Planned Fact：计划事实，必须有 clinic_id
Assessment：对事实的业务评价，到 tenant
FollowupPlan：基于评价生成的行动计划，必须有执行/目标 clinic
```

核心区分：

```text
transaction_type = 动作事实
subject_type     = 被操作主体
fact_type        = 患者事实单元
```

目标形态：

```text
Customer Transaction Based Assessment & Follow-up Planning Engine
```
