FSD m06 · 预诊断与方案(diagnosis)
本册覆盖代码域
internal/domain/diagnosis(无新表——医生输出落ticket列,状态变更走ticket.TransitionInTx唯一入口)。全局规则见 00-总则 §2。
m06 功能节目录
| ID | 名称 | 路由/入口 |
|---|---|---|
| F6.01 | 医生工作台(预诊+专家选人 dept 锚) | GET /api/diagnosis/pending、GET /api/diagnosis/experts、POST /api/diagnosis/:ticketId |
| F6.02 | 拒绝与重派 | POST /api/diagnosis/:ticketId/reject |
| F6.03 | 患者方案确认 | GET /pt/plan、POST /pt/plan/confirm |
F6.01 医生工作台(预诊+专家选人 dept 锚)
对应 SRS:F-DIAG-001(专家选人为 M10 扩展,SRS 未细化) | 实现落点:
internal/domain/diagnosis/service.go:47(PendingList)/:78(Submit)/:229(ExpertOptions)/main.go:259-262(路由) | 操作入口:web/admin/diagnosis医生待诊页(列表→病历预览 Modal→填意见/选专家→提交)
1 功能定义
医生查看 PREDIAGNOSING 工单待诊列表、在线预览病历(复用 F5.04 代理 blob 前端渲染)、按科室锚定查询 PUBLISHED 专家并选人(或手填)、提交预诊意见/方案/推荐科室/预估天数与费用。提交=写 ticket 列(version CAS)→ 流转 PLAN_CONFIRMING → 患者邮件(plan_ready)同事务 → Commit 后三 key SSE。
2 触发条件与前置状态
diag:write(仅 DOCTOR);工单须处于 PREDIAGNOSING(白名单前置校验+事务内兜底双重)。- 病历在线预览为纯前端(Modal 内 img/pdf 原生渲染,后端零改动——⚠ DIF-M6 ⑨)。
3 输入与校验
| 字段 | 类型 | 校验 |
|---|---|---|
| prediagnosis_summary | string | 必填语义(医生意见) |
| plan | string | 治疗方案文本 |
| dept_id | int64 | 推荐科室 |
| expert_id | int64 | 0=手填/存量哨兵;>0 时事务内一查两用(校验归属+上架态,取「姓名(职称)」快照) |
| expert | string | 手填推荐专家(’’ 允许;ExpertID>0 时被快照覆盖) |
| estimate_days | int | 预估停留天数(0 允许) |
| estimate_amount | float64 | 预估总费用(0=未填哨兵 → 定金回落固定额,payment.DepositCents 消费) |
| estimate_currency | string | 缺省服务端兜底 USD |
GET /api/diagnosis/experts?dept_id=:dept_id<=0 → 空列表;仅 status='PUBLISHED' 专家,ORDER BY sort,id。
4 处理流程
5 输出与结果状态
待诊列表/专家选项 JSON;提交 204;患者收 plan_ready 邮件 + /pt/plan 可见方案(F6.03)。
6 状态流转
PREDIAGNOSING → PLAN_CONFIRMING(A 轴正向边);ticket.hospital_id 自 M4 建单以来首次有写路径(选专家=确认院区,工单已绑院且与专家归属不符 → 409——ValidateExpertSelection 纯函数)。
7 边界与异常
| 场景 | 行为 |
|---|---|
| 专家不存在 | 404 ErrExpertNotFound(⚠ DIF-M10 ③ M10 核查 A3 收口:原 400 改 404 与 ErrOrderNotFound 同形,mapErr 同映) |
| 专家非 PUBLISHED / 归属院区与工单不符 | 409(ValidateExpertSelection) |
| 工单非 PREDIAGNOSING | 409 ErrInvalidTransition(白名单前置) |
| version 竞态 | 409(写列 CAS 命中 0 行) |
| 专家快照 | 不可变——专家改名/下架不回写历史方案(医疗记录语义,⚠ DIF-M10 ④) |
| estimate_amount=0 | 定金回落 config 固定额(M6 单测断言 200.0 兼容证明) |
8 权限与数据规则
diag:write(DOCTOR 专属);医生选人端点同挂 diag:write(14 码矩阵不扩——⚠ DIF-M10 ⑤ 权限面不蔓延);dept 锚设计根据=ticket.hospital_id 预诊前恒 0 不可作 JOIN 锚(M10 核查 B3/B5)。
F6.02 拒绝与重派
对应 SRS:F-TICK-002(「医生确认/拒绝」,M6 裁决 4 补齐) | 实现落点:
internal/domain/diagnosis/service.go:154(Reject)/main.go:262(路由) | 操作入口:web/admin/diagnosis待诊详情「拒绝」按钮
1 功能定义
医生拒绝预诊请求:状态机回退边 3(PREDIAGNOSING→PENDING_ASSIGN)+ INBOX 通知顾问重新分配(doctor_rejected 模板,同事务)。零写路径(拒绝只流转不写列)。
2 触发条件与前置状态
diag:write;工单须 PREDIAGNOSING;reason 必填。
3 输入与校验
| 字段 | 类型 | 校验 |
|---|---|---|
| reason | string | 必填(400);拼入 op_log reason「医生拒绝预诊请求:+reason」 |
4 处理流程
5 输出与结果状态
204;顾问 INBOX 收到重派待办(payload={ticket_no, reason});工单回到待分配。
6 状态流转
回退边 3(白名单内唯一由 DOCTOR 触发的回退边);lifecycle from/to 记录回退轨迹。
7 边界与异常
| 场景 | 行为 |
|---|---|
| 工单非 PREDIAGNOSING | 409(白名单前置) |
| reason 空 | 400 |
| version 竞态 | 409 |
8 权限与数据规则
diag:write;INBOX recipient=role:CONSULTANT(角色谓词待办)。
F6.03 患者方案确认
对应 SRS:F-DIAG-002 | 实现落点:
internal/domain/diagnosis/service.go:190(ConfirmByPatient)/:260(PatientPlan)/main.go:263-264(路由) | 操作入口:app H5#/pages/progress方案卡片(查看→确认)
1 功能定义
患者在确认前查看方案(/pt/plan——F-DIAG-002「确认方案前看方案」语义闭环,DIF-M7 ⑤ 补齐)、确认后进入支付(PLAN_CONFIRMING→PENDING_PAYMENT,「进入支付」,支付本身 M6 接续)。
2 触发条件与前置状态
pt JWT;本人最新工单(直查口径 WHERE patient_id=? ORDER BY id DESC LIMIT 1——越权不可能 claims 即身份,⚠ DIF-M6 ⑤);确认须 PLAN_CONFIRMING。
3 输入与校验
| 端点 | 输入 | 校验 |
|---|---|---|
| GET /pt/plan | 无 | 无工单 404;预诊前字段零值/nil(前端按 status 渲染) |
| POST /pt/plan/confirm | 无 | TransitionInTx 白名单(非 PLAN_CONFIRMING 409) |
4 处理流程
5 输出与结果状态
方案视图 JSON(含专家快照/预估天数/费用/币种);确认 204;SSE ticket 事件双端刷新。
6 状态流转
PLAN_CONFIRMING → PENDING_PAYMENT(A 轴正向边;actor=PATIENT id,op_log reason「患者在线确认诊疗方案」)。
7 边界与异常
| 场景 | 行为 |
|---|---|
| 无工单 | 404 |
| 非 PLAN_CONFIRMING(重复确认/未到阶段) | 409 |
| 回退边 1 触发后(支付失败重谈) | 工单回 PLAN_CONFIRMING,患者可再次确认 |
8 权限与数据规则
pt JWT + patient_id 直查(不走权限码);方案文本 prediagnosis_summary/plan 为 NULL 豁免列(「尚未发生」语义)。