锁定缴费校验失败时整单回滚,避免样本半成功落库;前端禁止删除锁定缴费样本,改码走更正编码。同步落地样本更正、采集微信通知、OA提及未读、细胞产品套餐与相关迁移文档。 Co-authored-by: Cursor <cursoragent@cursor.com>
138 lines
4.5 KiB
Markdown
138 lines
4.5 KiB
Markdown
# 样本编码全链路纠错 — 设计
|
||
|
||
> 日期:2026-10-22
|
||
> 状态:已确认(实现默认)
|
||
> 关联:采集协议单 / 科研捐赠;质检接收与工单;生产工单;储存证 / 保险 / 客服
|
||
|
||
---
|
||
|
||
## 1. 范围决策
|
||
|
||
| 项 | 决定 |
|
||
|----|------|
|
||
| 交付形态 | **产品化能力**:预览 + 事务级联更正 + 审计日志(非一次性手工 SQL) |
|
||
| 细胞产品码 | **不自动修改** `biz_cell_product.product_code` / 出库快照;预览可提示「同名产品码条数」供人工评估 |
|
||
| 实验室入库码 | **不修改** `lab_storage_code` |
|
||
| 来源 | 支持 `cell_storage` 与 `research_donation` |
|
||
|
||
---
|
||
|
||
## 2. 目标与非目标
|
||
|
||
### 2.1 目标
|
||
|
||
- 将错误样本编码 `oldCode` 更正为 `newCode`,在同一租户、同一来源下级联更新所有以 `sample_code` 为匹配键或快照的业务表。
|
||
- 更正前可预览各表影响行数与阻断原因。
|
||
- 写入审计日志(操作人、时间、旧→新、影响明细、原因)。
|
||
- 入口挂在「样本信息管理 / 客户服务」列表操作列。
|
||
|
||
### 2.2 非目标
|
||
|
||
- 不批量改多条样本编码。
|
||
- 不改短信历史正文、附件内容。
|
||
- 不自动改细胞产品码、出库产品快照。
|
||
- 不通过「编辑协议单换码再保存」实现纠错(该路径不回写下游快照)。
|
||
|
||
---
|
||
|
||
## 3. 关联键与校验
|
||
|
||
- 权威键:`tenant_no` + `sample_code`(OpenSpec api-conventions)。
|
||
- 来源:`reception_source` ∈ {`cell_storage`, `research_donation`};无来源列的表仅在对应来源下更新。
|
||
- 旧码必须存在于对应 SoT 样本表(`biz_protocol_sample` 或 `biz_research_donation_sample`,`del_flag=0`)。
|
||
- 新码不得已被其它活跃样本占用(协议 + 捐赠共用命名空间);允许等于旧码时直接拒绝。
|
||
- UNIQUE 表(储存证 / 保险 / 客服 / 储存证 QC)若已存在 `newCode` 行且不是本样本迁移目标,则阻断。
|
||
|
||
### 编码池(细胞存储)
|
||
|
||
1. 若 `newCode` 已在 `biz_sample_code`:将样本的 `sample_code_id` 指向该池行,并标记 `issued=1`;若旧池行不再被其它活跃样本引用,可释放 `issued=0`。
|
||
2. 否则若样本当前绑定池行:将该池行的 `sample_code` 字符串就地改为 `newCode`。
|
||
3. 否则仅更新样本行文本码(捐赠场景常见)。
|
||
|
||
---
|
||
|
||
## 4. 级联表清单
|
||
|
||
### 4.1 SoT
|
||
|
||
- `biz_protocol_sample`(cell_storage)
|
||
- `biz_research_donation_sample`(research_donation)
|
||
- `biz_sample_code`(按上节策略)
|
||
|
||
### 4.2 市场附属(主要为 cell_storage)
|
||
|
||
- `biz_protocol_sample_payment`
|
||
- `biz_protocol_payment_schedule`
|
||
- `biz_protocol_payment_transfer`
|
||
- `biz_protocol_sample_transport`
|
||
- `biz_research_donation_sample_transport`(research_donation)
|
||
- `biz_sample_freight_item`
|
||
|
||
### 4.3 质检 / 生产(按 `reception_source` 过滤,无该列则仅按租户+码)
|
||
|
||
- `biz_sample_reception`
|
||
- `biz_qc_work_order`
|
||
- `biz_qc_task`
|
||
- `biz_storage_release_review`
|
||
- `biz_sample_storage_cert_qc`(UNIQUE;细胞存储)
|
||
- `biz_sample_production_reception`
|
||
- `biz_production_work_order`
|
||
- `biz_production_task_input`(`input_type=sample` 且 `input_code=oldCode`)
|
||
|
||
### 4.4 扩展 UNIQUE(细胞存储)
|
||
|
||
- `biz_sample_storage_cert`
|
||
- `biz_sample_insurance`
|
||
- `biz_sample_customer_service`
|
||
|
||
### 4.5 明确不改
|
||
|
||
- `lab_storage_code`、`biz_cell_product.product_code`、`biz_outbound_release_cell`、附件与短信正文。
|
||
|
||
---
|
||
|
||
## 5. API
|
||
|
||
前缀:`/web/admin/sample-code-corrections`
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| POST | `/preview` | 校验 + 返回各表影响行数、阻断原因、可选同名产品码提示 |
|
||
| POST | `/apply` | 事务内级联更新 + 写审计日志 |
|
||
|
||
请求体:
|
||
|
||
```json
|
||
{
|
||
"receptionSource": "cell_storage",
|
||
"oldSampleCode": "OLD",
|
||
"newSampleCode": "NEW",
|
||
"newSampleCodeId": null,
|
||
"reason": "客户填错编码"
|
||
}
|
||
```
|
||
|
||
权限:运营端登录 + 严格菜单码(细胞存储或科研捐赠样本信息 list 任一即可预览/执行;前端按钮随当前 Tab 展示)。
|
||
|
||
---
|
||
|
||
## 6. 审计
|
||
|
||
表 `biz_sample_code_correction_log`:记录租户、来源、旧码、新码、影响 JSON、原因、操作人、公共字段。
|
||
|
||
---
|
||
|
||
## 7. UI
|
||
|
||
样本信息页操作列增加「更正编码」→ 弹窗录入新码与原因 → 先预览 → 确认后 apply → 刷新列表。
|
||
|
||
---
|
||
|
||
## 8. 事务顺序
|
||
|
||
1. 锁/读取 SoT 旧码行,校验新码空闲与 UNIQUE 冲突
|
||
2. 更新编码池策略
|
||
3. 更新 UNIQUE 扩展表
|
||
4. 更新 SoT 与全部快照表
|
||
5. 写审计日志并 commit
|