Files
zkxw/docs/superpowers/specs/2026-06-10-basic-experiment-design.md
T
2026-06-11 15:42:58 +08:00

456 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 基础实验业务 — 功能设计文档
> 日期:2026-06-10
> 状态:已确认(2026-06-10:一产品一售卖计划)
> 模块:基础实验(新增一级菜单,独立于中试服务 / 临床应用)
> 需求来源:客户新增「基础实验」业务线(细胞产品售卖给客户做基础实验)
---
## 1. 背景与目标
### 1.1 业务定义
**基础实验**:将细胞产品售卖给客户用于基础实验。与中试服务(渠道 B 端)、临床应用(患者 C 端输注)不同,属于 **B2B 一次性售卖 + 出库交付** 模式。
### 1.2 与现有业务对比
| 维度 | 中试服务 | 临床应用(已隐藏) | 基础实验 |
|------|---------|-------------------|---------|
| `biz_type` | `pilot_service` | `clinical_application` | `basic_experiment` |
| 申请单号前缀 | `ZSSQ` | `LCSQ` | **`JCSY`** |
| 渠道 | 必选 + 服务订单扣费 | 选渠道,不绑订单 | **无** |
| 知情同意书 / 其他附件 | 有 | 有 | **无** |
| 标准附件 | — | — | **有(单上传区,图片/PDF)** |
| 患者信息 | 有 | 有 | **无** |
| 客户信息 | 走渠道 | 走渠道 | **自由填写:客户名称/联系人/联系方式** |
| 课题名称 | — | — | **有** |
| 方案语义 | 输注方案(多疗程) | 输注方案(多疗程) | **售卖方案(一次性多产品)** |
| 计划粒度 | 每疗程一条输注计划 | 每疗程一条输注计划 | **每个细胞产品一条售卖计划(独立提货时间)** |
| 产品费用 | 协议价/订单持仓 | 手填 | **从细胞产品价格体系带入,可修改** |
| 体检 | 有 | 无 | **无** |
| 缴费 / 财务确认 | 渠道扣费 | 独立缴费闭环 | **独立缴费闭环(同临床模式)** |
| 交付确认 | 有 | 有 | **有** |
| 输注确认 | 有 | 有 | **无** |
| 出库生产/质检工单 | 有 | 有 | **有** |
| 出库放行审核 | 有 | 有 | **有** |
| 出库交接 | 有 | 有 | **有** |
### 1.3 目标
1. 在现有 `biz_pilot_*` 表结构与出库链路上,通过 `biz_type=basic_experiment` 新增第三条业务变体。
2. 最大化复用中试/临床已验证的页面、API、出库组件;UI 文案按「售卖 / 提货 / 交付」映射,代码层可保留 `infusion_*` 命名。
3. 前端采用 `bizType` 策略配置,避免 `ApplicationFormDialog.vue` 继续堆叠 `if` 分支。
### 1.4 非目标(本期不做)
- 客户主数据关联(`biz_customer`)
- 渠道、体检、输注确认
- 小程序端(若需要,另开需求)
---
## 2. 核心业务流程
```
基础实验申请单(JCSY,课题/客户/标准附件)
└─ 售卖方案:多种细胞产品(价格可改)
└─ 每个产品 → 一条售卖计划(独立提货时间)
├─ 自动:出库生产工单 + 出库质检工单(biz_type 继承)
├─ 自动:缴费记录(biz_pilot_payment,pay_status=dfj)
├─ 生产 / 质检执行
├─ 出库物料准备
├─ 出库交接
├─ 出库放行审核
└─ 交付确认(biz_pilot_delivery,无输注确认)
```
### 2.1 售卖计划粒度(已确认)
- **一个申请单** 对应 **一个售卖方案**(多产品行)。
- **每个细胞产品** 独立生成 **一条售卖计划**(复用 `biz_pilot_infusion_schedule`),各自拥有:
- 独立 **提货时间**(映射 `infusion_time`)
- 独立 **费用**(映射 `amount`,由产品价格带入后可改)
- 独立 **出库生产/质检工单、缴费、交付、放行** 链路
> 说明:与「一个批次共用一个提货时间」不同;当前采用产品级提货时间,故以「一产品一计划」驱动下游工单,避免单计划多提货时间的生产调度歧义。
---
## 3. 数据库变更
### 3.1 ALTER `biz_pilot_application` — 扩展 `biz_type` 与客户字段
```sql
-- biz_type 注释扩展(值域新增 basic_experiment)
ALTER TABLE biz_pilot_application
MODIFY COLUMN biz_type VARCHAR(20) NOT NULL DEFAULT 'pilot_service'
COMMENT '业务类型: pilot_service=中试服务, clinical_application=临床应用, basic_experiment=基础实验';
ALTER TABLE biz_pilot_application
ADD COLUMN project_title VARCHAR(200) DEFAULT NULL COMMENT '课题名称(基础实验)' AFTER application_name,
ADD COLUMN customer_name VARCHAR(200) DEFAULT NULL COMMENT '客户名称(基础实验,自由文本)' AFTER project_title,
ADD COLUMN customer_contact VARCHAR(100) DEFAULT NULL COMMENT '客户联系人(基础实验)' AFTER customer_name,
ADD COLUMN customer_phone VARCHAR(32) DEFAULT NULL COMMENT '客户联系方式(基础实验)' AFTER customer_contact;
```
**字段使用约定(`basic_experiment`)**
| 字段 | 用法 |
|------|------|
| `channel_id` / `channel_name` / `channel_service_order_id` | 留空,不校验 |
| `consent_form_urls` | 不使用 |
| `attachment_urls` | 承载 **标准附件**(单上传区,逗号分隔 URL) |
| `project_title` | 课题名称,必填 |
| `customer_name` / `customer_contact` / `customer_phone` | 客户信息,必填 |
| `application_name` | 可选,申请单名称 |
### 3.2 `biz_pilot_infusion_plan` — 售卖方案容器
不新增表。基础实验创建申请单时自动创建 **一条** `biz_pilot_infusion_plan` 作为售卖方案容器:
- `total_course_count` 固定为产品行数或 `1`(实现时取产品行数,便于统计)
- `course_interval` / `infusion_start_date` / `infusion_route` 留空
- UI 不展示「疗程」概念
### 3.3 `biz_pilot_infusion_schedule` — 售卖计划(一产品一条)
复用现有表,语义映射:
| DB 字段 | 基础实验 UI 文案 |
|---------|-----------------|
| `infusion_time` | 提货时间 |
| `amount` | 售卖金额(元) |
| `cell_type` / `spec_text` | 取自产品行 |
| `infusion_location` / `infusion_method` | 不展示(可留空) |
| `schedule_status` | 待生产 / 已生产 / 已交付 / 已取消(文案可映射为「待出库」等,码值不变) |
| `infusion_status` | **基础实验不使用输注确认**;列表/查看态映射为「—」或隐藏 |
| `qc_status` | 同中试/临床 |
### 3.4 `biz_pilot_infusion_schedule_product` — 产品明细
每条 schedule 关联 **一条** product 记录(一产品一计划)。价格字段:
- `price_id` → `biz_cell_product_price.id`
- `agreement_price` → 价格体系参考价(带入)
- `actual_price` → 用户可修改的实际单价
- `quantity` → 份数,默认 1
### 3.5 `biz_pilot_payment` — 缴费记录
复用 `biz_pilot_payment`,扩展 `biz_type` 支持 `basic_experiment`:
```sql
ALTER TABLE biz_pilot_payment
MODIFY COLUMN biz_type VARCHAR(20) NOT NULL DEFAULT 'clinical_application'
COMMENT '业务类型: clinical_application=临床应用, basic_experiment=基础实验';
```
- 每个售卖计划(schedule)创建时自动插入一条 `pay_status=dfj` 记录。
- `amount` 取自对应 schedule 的 `amount`。
### 3.6 不使用的表(`basic_experiment`)
| 表 | 说明 |
|----|------|
| `biz_pilot_patient` | 不创建 |
| `biz_pilot_checkup` | 不创建 |
| `biz_pilot_infusion_confirm` | 不创建、不展示 |
### 3.7 复用的出库/交付表
| 表 | 关联键 | 说明 |
|----|--------|------|
| `biz_production_work_order` | `infusion_schedule_id`, `biz_type=basic_experiment` | 出库生产工单 |
| `biz_qc_work_order` | `infusion_schedule_id`, `biz_type=basic_experiment` | 出库质检工单 |
| `biz_outbound_release_review` | `infusion_schedule_id` | 出库放行审核 |
| `biz_outbound_release_material` | 放行审核 | 出库物料 |
| `biz_outbound_handover` | 交接 | 出库交接 |
| `biz_pilot_delivery` | `infusion_schedule_id` | 交付确认 |
---
## 4. 后端 API 设计
### 4.1 申请单 / 售卖计划 — 扩展 `pilot_application` CRUD
**文件**:`backend/app/crud/pilot_application.py`、`backend/app/api/pilot_application.py`
| 变更点 | 说明 |
|--------|------|
| `_generate_application_no` | `biz_type=basic_experiment` → 前缀 `JCSY` |
| `create_application` | 跳过渠道/服务订单校验;校验课题/客户/标准附件;不写 patient |
| `update_application` | 支持 `projectTitle/customerName/customerContact/customerPhone` |
| `_row_to_dict_application` | 输出新字段 |
| 售卖计划创建 | 按产品行批量创建 schedule + product + 工单 + payment |
| `list` / `get` | `bizType=basic_experiment` 过滤 |
**售卖计划创建规则**
1. 用户在一个表单中维护多行产品(细胞产品、参考价、实际价、份数、提货时间)。
2. 保存时:每个产品行 → 1 条 `BizPilotInfusionSchedule` + 1 条 `BizPilotInfusionScheduleProduct`。
3. 每条 schedule 自动调用现有:
- `create_outbound_production_work_order(..., biz_type='basic_experiment')`
- `create_outbound_qc_work_order(..., biz_type='basic_experiment')`
- `clinical_payment.auto_create_payment`(扩展支持 `basic_experiment`)
**产品选型**:从 `biz_cell_product_price` 加载(同临床),`actual_price` 默认等于 `unit_price`,前端可改。
### 4.2 缴费 API — 扩展 `clinical_payment`
**文件**:`backend/app/crud/clinical_payment.py`(或重命名为 `pilot_payment`)、`backend/app/api/clinical_payment.py`
- 列表/详情/确认/退费接口增加 `bizType` 查询参数,默认不过滤;基础实验菜单请求时传 `bizType=basic_experiment`。
- `auto_create_payment`:`biz_type in ('clinical_application', 'basic_experiment')` 时创建。
- 列表列:基础实验展示 **课题名称、客户名称** 替代患者/渠道。
### 4.3 出库放行审核 — 扩展 `outbound_release_review`
- `_BIZ_TYPE_LABELS` 增加 `basic_experiment: 基础实验`。
- 列表 `bizType=basic_experiment` 过滤(已有模式)。
- 详情聚合:申请单新字段 + 售卖计划(提货时间、金额)+ 产品明细;**不返回患者**。
### 4.4 出库工单查看 — 扩展 QC / 生产 CRUD
**文件**:`qc_work_order.py`、`production_work_order.py`、`pilot_infusion_schedule_mgmt.py`
- 出库详情接口返回 `application` 时包含 `projectTitle/customerName/...`。
- `patient` 对 `basic_experiment` 返回 `null`。
- `infusionPlan` 可返回简化字段或 `null`(查看弹窗按 variant 决定是否展示)。
### 4.5 交付 API — 复用 `pilot_delivery`
- 不按 `biz_type` 限制;基础实验在申请单详情 / 售卖计划操作中进入「交付确认」。
- 每条 schedule 独立维护 `biz_pilot_delivery`(与中试一致)。
- **不调用** `pilot_infusion_confirm` 相关接口。
### 4.6 状态同步 — 扩展 `pilot_outbound_status_sync`
`_OUTBOUND_BIZ_TYPES` 增加 `basic_experiment`。
---
## 5. 前端设计
### 5.1 菜单结构
```
基础实验(一级菜单)
├── 基础实验申请单 menuCode: basic-experiment:application:list
├── 缴退费财务确认 menuCode: basic-experiment:payment-confirm:list
└── 出库放行审核 menuCode: basic-experiment:outbound-release-review:list
```
路由模块 `sqxp.ts`(`props.bizType: 'basic_experiment'`):
| 路由 name | path | 组件 |
|-----------|------|------|
| `BasicExperiment` | `/basic-experiment` | layout |
| `BasicExperimentApplication` | `application` | `pilot-application/index` |
| `BasicExperimentPaymentConfirm` | `payment-confirm` | `clinical-payment-confirm/index`(传 bizType) |
| `BasicExperimentOutboundRelease` | `outbound-release-review` | `outbound-release-review/index` |
缴费信息 Tab 内嵌于申请单页(同临床),不单独做侧栏菜单;旧路径可做重定向。
### 5.2 申请单页 Tab 结构
| Tab | 组件 | 说明 |
|-----|------|------|
| 基础实验申请单 | `PilotApplicationTab` | 列表 + 新增/编辑/查看 |
| 售卖计划管理 | `InfusionScheduleTab` | 文案改为「售卖计划」;列含提货时间、金额、缴费状态 |
| 缴费信息 | `ClinicalPaymentTab` 或抽取共用 Tab | `bizType=basic_experiment` |
**不展示**:体检 Tab、输注确认相关入口。
### 5.3 `bizType` 策略配置(推荐新建)
新建 `web-admin/src/config/pilot-biz-type.ts`(名称可调整),集中定义:
```ts
export type PilotBizType = 'pilot_service' | 'clinical_application' | 'basic_experiment'
export interface PilotBizTypeConfig {
applicationNoPrefix: string
showChannel: boolean
showPatient: boolean
showConsent: boolean
showOtherAttachments: boolean
showStandardAttachments: boolean
showCheckup: boolean
showInfusionConfirm: boolean
showDelivery: boolean
showPayment: boolean
planLabel: string // 输注方案 / 售卖方案
scheduleLabel: string // 输注计划 / 售卖计划
pickupTimeLabel: string // 输注时间 / 提货时间
// ...
}
```
`ApplicationFormDialog.vue`、`ApplicationViewDialog.vue`、`InfusionScheduleTab.vue` 等读取配置,替代散落 `isClinical`。
### 5.4 申请单表单字段(`basic_experiment`)
**申请单区块**
| 字段 | 必填 | 说明 |
|------|------|------|
| 申请单号 | 自动 | `JCSY` + 日期 + 序号 |
| 申请单名称 | 否 | |
| 课题名称 | 是 | `projectTitle` |
| 客户名称 | 是 | 自由文本 |
| 客户联系人 | 是 | |
| 客户联系方式 | 是 | |
| 标准附件 | 否 | 单上传区,图片/PDF,卡片布局同规范 |
| 备注 | 否 | |
**隐藏**:渠道、服务订单、知情同意书、其他附件、患者信息整块。
**售卖方案区块**(原输注方案 Tab 内)
| 列 | 说明 |
|----|------|
| 细胞产品 | 从 `biz_cell_product_price` 选择 |
| 规格 | 随产品带入 |
| 参考单价 | 只读 |
| 实际单价 | 可编辑,默认=参考单价 |
| 份数 | 默认 1 |
| 提货时间 | 每行独立 `datetime` |
| 金额 | 可 `实际单价 × 份数` 自动算,可改(写入 schedule.amount) |
保存逻辑:N 行产品 → N 条 schedule(见 §4.1)。
### 5.5 出库质检 / 生产工单 — 查看弹窗
扩展 `outbound-qc-pilot-view-sections.ts`:
```ts
export type OutboundViewContextVariant =
| 'pilot_service'
| 'clinical_application'
| 'basic_experiment'
```
**`basic_experiment` 展示区块**
1. **基础实验申请信息**:申请单号、课题名称、客户名称、联系人、联系方式、申请单状态
2. **售卖计划信息**:提货时间、售卖金额、计划/质检状态
3. **细胞产品明细**:项目、规格、参考价、实际价、份数
**不展示**:患者信息、输注方案(疗程)、输注地点/方式。
使用处:
- `qc-work-order/OutboundQcViewDialog.vue`
- `production-work-order/index.vue` 出库查看
- `outbound-release-review` 查看弹窗(若共用 section builder)
### 5.6 缴退费财务确认
复用 `clinical-payment-confirm/index.vue` + `RefundConfirmTab.vue`:
- 路由 `props: { bizType: 'basic_experiment' }`
- 列表 API 带 `bizType=basic_experiment`
- 表格列:申请单号、课题名称、客户名称、细胞产品、提货时间、金额、缴费状态
### 5.7 交付确认
复用 `ApplicationDetailDialog.vue` 内交付 Tab / 交付弹窗逻辑:
- `basic_experiment` 显示「交付信息」Tab
- 隐藏「输注确认」Tab(若有)
- 交付操作粒度:**按售卖计划(schedule)**,与中试一致
### 5.8 状态标签
`status-tag-registry.ts` 增加:
```ts
basic_experiment: { label: '基础实验', tagType: 'primary' } // 色值待定,勿与中试重复语义
```
---
## 6. 权限与菜单码
| menuCode | 菜单 |
|----------|------|
| `basic-experiment:application:list` | 基础实验申请单 |
| `basic-experiment:payment-confirm:list` | 缴退费财务确认 |
| `basic-experiment:outbound-release-review:list` | 出库放行审核 |
角色授权需同步 `sys_menu`(SQL 迁移脚本)。
---
## 7. 实现策略与文件清单
### 7.1 推荐方案
**`biz_type` 扩展 + 前端 `bizType` 策略配置**(参见临床应用设计,避免独立建表)。
### 7.2 改动清单(按优先级)
| 优先级 | 层级 | 文件/模块 |
|--------|------|-----------|
| P0 | SQL | `docs/sql/migrations/2026-06-10-basic-experiment.sql` |
| P0 | Model | `backend/app/models/models.py` |
| P0 | CRUD | `pilot_application.py`, `clinical_payment.py` |
| P0 | API Schema | `pilot_application` Create/Update body |
| P0 | 路由 | `sqxp.ts`, `menu.py` |
| P0 | 前端配置 | `pilot-biz-type.ts`(新) |
| P0 | 表单/列表 | `ApplicationFormDialog.vue`, `PilotApplicationTab.vue`, `InfusionScheduleTab.vue` |
| P1 | 出库查看 | `outbound-qc-pilot-view-sections.ts`, QC/生产查看弹窗 |
| P1 | 放行审核 | `outbound-release-review/*` |
| P1 | 缴费 | `clinical-payment-confirm/*`, `ClinicalPaymentTab.vue` |
| P1 | 交付 | `ApplicationDetailDialog.vue` |
| P1 | 状态同步 | `pilot_outbound_status_sync.py`, `outbound_release_review.py` |
| P2 | 字段一致性 | `check_field_consistency.py` |
| P2 | 测试 | 申请单创建、多产品多计划、工单/auto payment 联动 |
### 7.3 风险与缓解
| 风险 | 缓解 |
|------|------|
| `ApplicationFormDialog.vue` 过大 | 本期引入 `pilot-biz-type.ts` 配置;后续可拆子表单组件 |
| `infusion_*` 命名与售卖语义不符 | UI 全面使用「售卖/提货」;DB/代码保留旧名 |
| 一产品一计划导致列表行数多 | 售卖计划 Tab 按产品行展示,申请单列表仍按申请单聚合 |
| 缴费模块命名 `clinical_*` | API 层扩展 `bizType` 参数,暂不 rename 模块 |
---
## 8. 验收标准
1. 侧栏可见「基础实验」一级菜单及三个二级菜单;临床应用仍隐藏。
2. 可创建 `JCSY` 前缀申请单,填写课题/客户/标准附件,无渠道与患者字段。
3. 售卖方案可添加多行细胞产品,每行独立提货时间与可改价格;保存后生成 N 条售卖计划。
4. 每条售卖计划自动产生出库生产工单、出库质检工单、待缴费记录。
5. 出库质检/生产工单「查看」弹窗展示基础实验申请信息 + 售卖计划 + 产品明细,无患者区块。
6. 出库放行审核、出库交接、交付确认可按 schedule 正常操作。
7. 缴费信息 + 缴退费财务确认流程与临床一致(状态机 `dfj→jfqrz→yjf→tfqrz→ytf`),数据按 `biz_type` 隔离。
8. 中试/临床列表不出现 `JCSY` 申请单;基础实验列表不出现 `ZSSQ`/`LCSQ`。
---
## 9. 已确认需求摘要(2026-06-10)
| 问题 | 结论 |
|------|------|
| 缴费/财务确认 | 需要 |
| 体检 | 无 |
| 交付/输注确认 | 有交付确认,无输注确认 |
| 申请单号前缀 | `JCSY` |
| 客户信息 | 自由文本 |
| 售卖计划粒度 | 每细胞产品一个提货时间 → **一产品一售卖计划** |
| 标准附件 | 单上传区,图片/PDF,卡片布局 |
| 产品费用 | 从细胞产品价格体系带入,可修改 |
| 客户主数据 | 不关联 |
---
## 10. 后续步骤
1. **用户审阅本 spec** — 确认后进入实现计划(`writing-plans`)。
2. 编写 `docs/superpowers/plans/2026-06-10-basic-experiment.md` 任务拆解。
3. 按 P0 → P1 分期实现与联调。