提交“
This commit is contained in:
1 parent
69ee0f505c
commit
9b88581450
614 files changed
+90318
-689022
No files matched your search
@@ -1,2 +0,0 @@
|
||||
schema: spec-driven
|
||||
created: 2026-05-13
|
||||
@@ -1,77 +0,0 @@
|
||||
## Context
|
||||
|
||||
`docs/sql/zkxw.sql`(全库导出基线)已包含 `biz_customer`、`biz_cell_sample_type`、`biz_collection_region`、`biz_collection_hospital`、`biz_collection_protocol_no`、`biz_sample_code` 等表;需求文档 `docs/中科兴皖需求V0.3.md` 2.2.1~2.2.5 描述了字段与交互。后端 `app/models` 与路由中尚未覆盖上述业务主数据的完整 CRUD;Web 管理端缺少对应页面。
|
||||
|
||||
**与需求文档的差异(以 DDL 为准)**:2.2.3 文案提到「医院名称逗号分隔」;当前 schema 为地区表 + 医院子表 1:N,实现 SHALL 以子表为准,弹窗内维护医院行,避免双写。
|
||||
|
||||
**现有代码模式参考:**
|
||||
|
||||
- 后端:`openspec/changes/dict-management` 与 `crud/tenant.py` 类独立函数、`api/admin.py` 路由风格;租户 `tenant_no`、软删 `del_flag`、列表默认排序 `create_time DESC`(见 engineering-standards)。
|
||||
- 前端:标准列表 `views/system/unit/index.vue`;复杂子表弹窗可参考字典「字典数据配置」或订单模块弹窗;API 封装于 `src/api/*.ts`。
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- 五类主数据在租户范围内的分页列表、详情(可选)、创建、更新、软删除。
|
||||
- 客户身份证去重(同租户、非空身份证、未删除记录唯一);样本类型编码、协议号、样本编码在租户内唯一。
|
||||
- 地区与医院:主列表为地区;「地区医院配置」弹窗内对 `biz_collection_hospital` 增删改查(按 `region_id`)。
|
||||
- Web UI 符合 `docs/web-admin-ui-spec-fresh-mint.md` 与 `.cursor/rules/web-admin-crud-dialog.mdc`。
|
||||
- 菜单与权限 SQL 或初始化说明写入 `docs/sql/`(与仓库惯例一致)。
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- `biz_customer_follow` 客户随访(2.2.1 未在本次菜单范围单独展开时可列为后续)。
|
||||
- 小程序端维护上述主数据。
|
||||
- 协议号/样本编码的「下发」与下游业务流程联动(仅维护 `issued` 字段与展示)。
|
||||
- 批量导入导出、复杂审批流。
|
||||
|
||||
## Decisions
|
||||
|
||||
### D1: 后端路由组织
|
||||
|
||||
**选择**:新增独立路由模块(例如 `app/api/basic_info.py` 或按域拆分为 `customer.py` + 聚合少量路由的文件),在 `app/api/__init__.py` 与 `app/main.py` 注册;路径前缀与现有 `/api` + admin 子前缀保持一致(如 `/web/admin/...` 或与 `dict` 同级命名空间)。
|
||||
|
||||
**理由**:五组资源边界清晰,避免单个 `admin.py` 过度膨胀;仍属同一业务域「基础信息」。
|
||||
|
||||
**替代方案**:全部写入 `admin.py` → 可行但不利于评审与合并冲突控制。
|
||||
|
||||
### D2: SQLAlchemy 模型与 CRUD
|
||||
|
||||
**选择**:在 `app/models/models.py`(或按项目惯例的拆分文件)增加与 DDL 一致的 ORM 模型;`app/crud/` 下每域独立模块或 `basic_info` 包内多文件,函数命名 `list_*`、`get_*`、`create_*`、`update_*`、`soft_delete_*`。
|
||||
|
||||
**理由**:与现有 tenant、dict 等模式一致,满足 database-conventions 公共字段与软删查询约定。
|
||||
|
||||
### D3: 客户身份证唯一校验
|
||||
|
||||
**选择**:创建与更新时若 `id_card_no` 非空,则查询同租户下是否存在其他未删除记录占用相同证件号;存在则返回 4xx 与明确业务文案(与需求「不要重复创建…提醒」一致)。
|
||||
|
||||
**理由**:表上已有 `idx_customer_idcard`;应用层给出可读错误信息。
|
||||
|
||||
### D4: 前端信息架构
|
||||
|
||||
**选择**:五个菜单入口(或二级菜单「基础信息」下五项),每页一个标准列表 + 表单弹窗;地区页主表 + 「地区医院配置」子弹窗(内嵌表格 + 分页)。
|
||||
|
||||
**理由**:与需求操作描述及工程 UI 模板一致。
|
||||
|
||||
### D5: 初始化数据(样本类型)
|
||||
|
||||
**选择**:可选 SQL 种子插入三种需求既定编码(wcqzxgxb、qdjczgxb、tpyqngxb),若环境已手动录入则脚本需幂等(`INSERT IGNORE` 或先判存)。
|
||||
|
||||
**理由**:需求 2.2.2 明确当前三种类型。
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- **[需求与 DDL 不一致]**:2.2.3 逗号分隔 vs 子表 → **缓解**:以 DDL 为准,在 proposal/design 中写明,避免实现回退到反范式存储。
|
||||
- **[唯一索引与软删]**:`uk_sample_type` 等包含 `del_flag` → 删除后再建同编码可能冲突 → **缓解**:软删后「复活」走更新 `del_flag=0` 或换编码;接口文档说明。
|
||||
- **[权限与菜单遗漏]** → **缓解**:tasks 中单列菜单 SQL 与路由权限码登记。
|
||||
|
||||
## Migration Plan
|
||||
|
||||
- 无破坏性 schema 变更前提:部署顺序为 DB 已执行 V0.3 DDL → 后端 → 前端;回滚为下线路由与菜单,不物理删数据。
|
||||
- 若某环境缺表:以 `docs/sql/zkxw.sql` 为基线导入/对齐,或从其中摘取对应 `CREATE TABLE` 段落执行。
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Web 菜单父级挂载在「Demo」下还是正式「业务/基础信息」根节点:建议与产品确认后写入 `docs/sql` 初始化脚本。
|
||||
- `biz_customer_follow` 是否与本迭代一并提供只读/编辑入口:默认本变更 Non-Goal,若需可追加 capability。
|
||||
@@ -1,34 +0,0 @@
|
||||
## Why
|
||||
|
||||
中科兴皖 V0.3「基础信息管理」下 2.2.1~2.2.5 为后续采集协议单、样本等业务的主数据入口;当前仓库仅有 SQL 模型定义,缺少租户内一致的 REST API 与 Web 管理端 CRUD,无法支撑业务录入与引用。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 在 `backend` 为五类主数据提供租户隔离的列表/详情/新增/修改/软删接口,字段与校验对齐 `docs/sql/zkxw.sql` 与 `docs/中科兴皖需求V0.3.md` 2.2.1~2.2.5。
|
||||
- 在 `web-admin` 增加五个列表+弹窗表单页(或等价结构),遵循 Fresh Mint 规范与既有 Demo 模板页(如 `unit`、`dict` 类页面)的布局与交互。
|
||||
- 客户:同一租户下身份证号非空且重复时拒绝创建并提示;姓名不强制唯一。
|
||||
- 细胞样本类型:`type_code` 租户内唯一(与表 `uk_sample_type` 一致)。
|
||||
- 采集地区与医院:地区 CRUD;医院为子表(`biz_collection_hospital`),通过「地区医院配置」弹窗维护,**不**采用需求文中「医院名称逗号分隔」的冗余存储(以当前 schema 1:N 为准)。
|
||||
- 采集协议号池、样本编码池:`protocol_no` / `sample_code` 租户内唯一;维护 `issued`(是否下发)。
|
||||
- 提供初始化菜单/SQL 片段(若项目惯例为 `docs/sql/`),便于挂到 Web 侧栏。
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `customer-management`:客户 `biz_customer` 的展示、增删改、身份证重复校验、标签逗号分隔编辑。
|
||||
- `cell-sample-type-management`:细胞样本类型 `biz_cell_sample_type` 的展示与增删改、编码唯一性。
|
||||
- `collection-region-hospital-management`:采集地区 `biz_collection_region` 与下属医院 `biz_collection_hospital` 的维护及子表弹窗配置。
|
||||
- `collection-protocol-no-management`:采集协议号池 `biz_collection_protocol_no` 的维护与下发标记。
|
||||
- `sample-code-management`:样本编码池 `biz_sample_code` 的维护与下发标记。
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- (无)不修改 `openspec/changes/zkxw-engineering-standards` 中既有 SHALL 语义;本变更在其实现约束下新增业务能力。
|
||||
|
||||
## Impact
|
||||
|
||||
- **后端**:新增路由模块(建议 `app/api/` 下业务域路由)、对应 `schemas/`、`crud/`、`services/`(如需);在 `app/api/__init__.py` 与 `app/main.py` 注册;SQLAlchemy 模型若尚未覆盖上述表则补充。
|
||||
- **前端**:`src/api/`、`src/router/`、`src/views/`(建议 `views/business/` 或按项目惯例)、菜单静态或后端菜单数据。
|
||||
- **数据库**:以现有 `docs/sql/zkxw.sql` 全库导出基线为准;本变更可附带种子数据(如三种预设样本类型)的 **可选** 增量 SQL(置于 `docs/sql/`)。
|
||||
- **权限**:菜单与按钮权限与现有 `sys_menu` / 角色授权模式对齐。
|
||||
@@ -1,37 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 租户内样本类型列表与分页
|
||||
|
||||
系统 SHALL 提供细胞样本类型分页查询接口,数据限定为当前租户且排除已软删记录,默认排序 SHALL 为 `create_time DESC`。
|
||||
|
||||
#### Scenario: 查询列表
|
||||
|
||||
- **WHEN** 请求样本类型列表
|
||||
- **THEN** 系统返回当前租户下 `biz_cell_sample_type` 未删除数据分页结果
|
||||
|
||||
### Requirement: 样本类型编码租户内唯一
|
||||
|
||||
系统 SHALL 在创建与更新时保证 `type_code` 在同一租户、未删除记录范围内唯一;违反时返回可展示错误。
|
||||
|
||||
#### Scenario: 重复编码拒绝
|
||||
|
||||
- **WHEN** 创建或更新样本类型使 `type_code` 与同租户另一未删除记录冲突
|
||||
- **THEN** 系统拒绝操作并返回业务错误
|
||||
|
||||
### Requirement: 样本类型字段维护
|
||||
|
||||
系统 SHALL 支持样本类型的创建、更新与软删除,业务字段 SHALL 包含样本类型编码、样本类型名称、样本存储年份、样本存储价格(元)、备注等,与 `biz_cell_sample_type` 一致。
|
||||
|
||||
#### Scenario: 完整字段保存
|
||||
|
||||
- **WHEN** 提交包含编码、名称、存储年份、存储价格的合法创建请求
|
||||
- **THEN** 系统持久化各字段并在详情/列表中可回显
|
||||
|
||||
### Requirement: Web 管理端样本类型页
|
||||
|
||||
Web 管理端 SHALL 提供样本类型列表与新增/编辑/删除(软删)交互,UI SHALL 符合 Web 管理端工程 UI 规范。
|
||||
|
||||
#### Scenario: 用户编辑一条记录
|
||||
|
||||
- **WHEN** 用户在列表选择编辑并修改名称后保存
|
||||
- **THEN** 系统调用更新接口且列表展示更新后名称
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 采集协议号池列表与分页
|
||||
|
||||
系统 SHALL 提供 `biz_collection_protocol_no` 的分页查询,租户隔离且排除已软删记录,默认排序 SHALL 为 `create_time DESC`。
|
||||
|
||||
#### Scenario: 列表查询
|
||||
|
||||
- **WHEN** 请求采集协议号池列表
|
||||
- **THEN** 返回当前租户未删除记录分页数据
|
||||
|
||||
### Requirement: 协议号租户内唯一
|
||||
|
||||
系统 SHALL 保证 `protocol_no` 在同一租户、未删除记录范围内唯一;冲突时拒绝写入并返回业务错误。
|
||||
|
||||
#### Scenario: 重复协议号
|
||||
|
||||
- **WHEN** 创建或更新导致与同租户另一未删除记录 `protocol_no` 相同
|
||||
- **THEN** 系统拒绝并返回错误
|
||||
|
||||
### Requirement: 是否下发字段维护
|
||||
|
||||
系统 SHALL 支持维护 `issued` 字段,取值为 0(否)或 1(是),与 DDL 注释一致。
|
||||
|
||||
#### Scenario: 更新下发标记
|
||||
|
||||
- **WHEN** 请求将某条记录 `issued` 从 0 改为 1
|
||||
- **THEN** 系统持久化后查询结果反映新值
|
||||
|
||||
### Requirement: 协议号池 CRUD 与 Web 页
|
||||
|
||||
系统 SHALL 支持协议号池行的创建、更新、软删除。Web 管理端 SHALL 提供列表与表单弹窗完成上述维护。
|
||||
|
||||
#### Scenario: 用户在页面保存新协议号
|
||||
|
||||
- **WHEN** 用户提交合法新协议号与下发标记
|
||||
- **THEN** 系统创建成功且列表可见新行
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 采集地区 CRUD
|
||||
|
||||
系统 SHALL 提供采集地区 `biz_collection_region` 的分页列表、创建、更新与软删除,数据 SHALL 按当前用户租户隔离。
|
||||
|
||||
#### Scenario: 地区列表仅本租户
|
||||
|
||||
- **WHEN** 请求采集地区列表
|
||||
- **THEN** 返回结果仅含当前租户未删除地区
|
||||
|
||||
### Requirement: 地区下属医院子表维护
|
||||
|
||||
系统 SHALL 提供按 `region_id` 查询、创建、更新、软删除 `biz_collection_hospital` 记录的接口。医院与地区关系 SHALL 为数据库 1:N(子表),SHALL NOT 将多医院合并为地区表上的逗号分隔字段存储。
|
||||
|
||||
#### Scenario: 某地区下新增医院
|
||||
|
||||
- **WHEN** 请求为指定 `region_id` 创建医院行且医院名称合法
|
||||
- **THEN** 系统持久化 `biz_collection_hospital` 且关联正确 `region_id`
|
||||
|
||||
#### Scenario: 软删除地区时级联软删下属医院
|
||||
|
||||
- **WHEN** 用户软删除某地区
|
||||
- **THEN** 系统在同一事务中将该地区 `del_flag` 置 1,并将其下属未删除医院记录全部 `del_flag` 置 1
|
||||
|
||||
### Requirement: Web 地区与医院配置交互
|
||||
|
||||
Web 管理端 SHALL 展示采集地区列表,并提供「地区医院配置」入口打开弹窗;弹窗内 SHALL 展示该地区下属医院表格并支持医院的分页列表、新增、编辑、软删除。
|
||||
|
||||
#### Scenario: 打开配置弹窗并新增医院
|
||||
|
||||
- **WHEN** 用户点击某行的「地区医院配置」并在弹窗内新增一条医院
|
||||
- **THEN** 弹窗列表出现新医院且主列表无需离开当前页即可再次打开验证
|
||||
@@ -1,47 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 租户内客户列表与分页
|
||||
|
||||
系统 SHALL 提供已认证管理端用户可用的客户分页查询接口,数据范围限定为当前用户所属租户,且默认排除 `del_flag=1` 的记录。列表默认排序 SHALL 为 `create_time DESC`(若无自定义排序)。
|
||||
|
||||
#### Scenario: 分页查询成功
|
||||
|
||||
- **WHEN** 调用方请求客户列表且传入合法分页参数
|
||||
- **THEN** 系统返回当前租户下未删除客户的分页数据,且不包含其他租户客户
|
||||
|
||||
### Requirement: 客户新增与身份证去重
|
||||
|
||||
系统 SHALL 支持创建客户,字段包含客户姓名(必填)、性别、身份证号、年龄、联系电话、客户标签(逗号分隔)、备注等,与 `biz_customer` 一致。当 `id_card_no` 非空时,系统 SHALL 拒绝在同一租户下创建与已有未删除客户相同身份证号的新记录,并返回可展示的业务错误信息。
|
||||
|
||||
#### Scenario: 同名不同人可共存
|
||||
|
||||
- **WHEN** 请求创建客户 A 与客户 B,二者 `customer_name` 相同但 `id_card_no` 不同或其一为空
|
||||
- **THEN** 系统允许分别创建成功
|
||||
|
||||
#### Scenario: 身份证重复拒绝创建
|
||||
|
||||
- **WHEN** 请求创建客户且 `id_card_no` 与同一租户下已存在未删除客户相同
|
||||
- **THEN** 系统拒绝创建并返回明确提示(含义与需求「已创建」一致)
|
||||
|
||||
### Requirement: 客户修改与删除
|
||||
|
||||
系统 SHALL 支持按主键更新未删除客户的可编辑字段;更新时若修改 `id_card_no` 为非空,SHALL 执行与同租户未删除记录的去重校验(排除自身)。系统 SHALL 仅支持软删除(`del_flag=1`),SHALL NOT 物理删除业务数据。
|
||||
|
||||
#### Scenario: 更新身份证冲突
|
||||
|
||||
- **WHEN** 将某客户的 `id_card_no` 改为另一未删除客户已占用的号码
|
||||
- **THEN** 系统拒绝更新并返回业务错误
|
||||
|
||||
#### Scenario: 软删除客户
|
||||
|
||||
- **WHEN** 请求删除某客户主键
|
||||
- **THEN** 系统将对应行 `del_flag` 置为 1,列表默认查询不再返回该记录
|
||||
|
||||
### Requirement: Web 管理端客户维护页
|
||||
|
||||
Web 管理端 SHALL 提供客户列表页,包含筛选(至少支持姓名/电话/身份证关键字类检索,若后端实现)、工具栏、表格、分页;SHALL 提供新增与编辑弹窗表单(`label-position="top"`,布局符合 Fresh Mint 与项目 CRUD 弹窗规范)。
|
||||
|
||||
#### Scenario: 用户在页面完成一次新增
|
||||
|
||||
- **WHEN** 用户在客户页填写合法信息并提交保存
|
||||
- **THEN** 系统调用后端创建接口并在成功后刷新列表
|
||||
@@ -1,37 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 样本编码池列表与分页
|
||||
|
||||
系统 SHALL 提供 `biz_sample_code` 的分页查询,租户隔离且排除已软删记录,默认排序 SHALL 为 `create_time DESC`。
|
||||
|
||||
#### Scenario: 列表查询
|
||||
|
||||
- **WHEN** 请求样本编码池列表
|
||||
- **THEN** 返回当前租户未删除记录分页数据
|
||||
|
||||
### Requirement: 样本编码租户内唯一
|
||||
|
||||
系统 SHALL 保证 `sample_code` 在同一租户、未删除记录范围内唯一;冲突时拒绝写入并返回业务错误。
|
||||
|
||||
#### Scenario: 重复样本编码
|
||||
|
||||
- **WHEN** 创建或更新导致与同租户另一未删除记录 `sample_code` 相同
|
||||
- **THEN** 系统拒绝并返回错误
|
||||
|
||||
### Requirement: 是否下发字段维护
|
||||
|
||||
系统 SHALL 支持维护 `issued` 字段,取值为 0(否)或 1(是)。
|
||||
|
||||
#### Scenario: 更新下发标记
|
||||
|
||||
- **WHEN** 请求将某条记录 `issued` 从 0 改为 1
|
||||
- **THEN** 系统持久化后查询结果反映新值
|
||||
|
||||
### Requirement: 样本编码池 CRUD 与 Web 页
|
||||
|
||||
系统 SHALL 支持样本编码池行的创建、更新、软删除。Web 管理端 SHALL 提供列表与表单弹窗完成上述维护。
|
||||
|
||||
#### Scenario: 用户在页面保存新样本编码
|
||||
|
||||
- **WHEN** 用户提交合法新样本编码与下发标记
|
||||
- **THEN** 系统创建成功且列表可见新行
|
||||
@@ -1,35 +0,0 @@
|
||||
## 1. 数据模型与 CRUD 基础
|
||||
|
||||
- [ ] 1.1 在 `backend/app/models` 中为 `biz_customer`、`biz_cell_sample_type`、`biz_collection_region`、`biz_collection_hospital`、`biz_collection_protocol_no`、`biz_sample_code` 增加 ORM 定义(字段顺序与公共字段对齐 `database-conventions`)
|
||||
- [ ] 1.2 新增 `backend/app/crud/` 模块(按 design 拆分文件或包),实现各实体的 list/get/create/update/soft_delete,查询统一 `tenant_no` + `del_flag=0`,列表默认 `create_time DESC`
|
||||
- [ ] 1.3 实现客户 `id_card_no` 非空时的租户内去重校验(创建与更新排除自身)
|
||||
|
||||
## 2. Pydantic Schema 与路由
|
||||
|
||||
- [ ] 2.1 在 `backend/app/schemas/` 为六类资源(含医院子资源)定义请求/响应模型
|
||||
- [ ] 2.2 新增 API 路由(建议 `app/api/basic_info.py` 或等价拆分),挂载客户、样本类型、地区、医院、协议号池、样本编码池端点;注册到 `app/api/__init__.py` 与 `app/main.py`
|
||||
- [ ] 2.3 为地区软删实现「同级联软删下属医院」事务逻辑(与 `collection-region-hospital-management` spec 一致)
|
||||
- [ ] 2.4 唯一约束冲突(`type_code`、`protocol_no`、`sample_code`、客户身份证)映射为可读 HTTP 4xx 与业务 message
|
||||
|
||||
## 3. 菜单与 SQL
|
||||
|
||||
- [ ] 3.1 在 `docs/sql/` 增加 Web 端菜单初始化脚本(五项菜单 + 合理 `order_num` / `parent_id`),权限标识与路由 path 对齐现有 `sys_menu` 惯例
|
||||
- [ ] 3.2 (可选)增加三种细胞样本类型初始数据的幂等 SQL,与需求 2.2.2 编码一致
|
||||
|
||||
## 4. Web 管理端 — API 与路由
|
||||
|
||||
- [ ] 4.1 在 `web-admin/src/api/` 增加封装上述端点的模块(如 `basicInfo.ts` 或分文件)
|
||||
- [ ] 4.2 在 `web-admin/src/router/` 注册五个页面路由(hash 路径与菜单 component 一致)
|
||||
|
||||
## 5. Web 管理端 — 页面实现
|
||||
|
||||
- [ ] 5.1 客户管理页:列表 + 筛选 + 新增/编辑弹窗(`label-position="top"`、`.dialog-form-layout`),对齐 `unit` 模板与 Fresh Mint
|
||||
- [ ] 5.2 细胞样本类型管理页:同上
|
||||
- [ ] 5.3 采集地区管理页:主表 +「地区医院配置」弹窗(内嵌医院表分页与 CRUD)
|
||||
- [ ] 5.4 采集协议号管理页:列表字段含协议号、`issued`、公共审计列
|
||||
- [ ] 5.5 样本编码管理页:同上
|
||||
|
||||
## 6. 验证
|
||||
|
||||
- [ ] 6.1 本地启动后端,用 Swagger 或脚本验证各列表/创建/更新/软删与异常路径(身份证重复、编码重复、级联软删)
|
||||
- [ ] 6.2 `pnpm build` 或 `pnpm build:typecheck` 通过;关键页面手测无控制台错误
|
||||
@@ -1,2 +0,0 @@
|
||||
schema: spec-driven
|
||||
created: 2026-05-13
|
||||
@@ -1,43 +0,0 @@
|
||||
## Context
|
||||
|
||||
参见 `docs/superpowers/specs/2026-05-13-cell-storage-protocol-modules-design.md`。当前仓库已实现基础信息管理 CRUD,但 `biz_collection_protocol` 及相关缴费/审核表在后端尚无 Model/API。
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- 最小闭环:协议单列表 + 概要详情;审核记录;财务两确认;分期预警。
|
||||
- 租户隔离、软删除、默认排序符合 `zkxw-engineering-standards`。
|
||||
- 审核不改变 `protocol_status`;审核支持多条历史(A1)。
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- 不对 2.2.6 全部子表做一次性完整表单。
|
||||
- 不实现退费发起与非 `jfqrz`/`tfqrz` 入口的财务动作。
|
||||
- 不用工作流引擎替换表驱动逻辑。
|
||||
|
||||
## Decisions
|
||||
|
||||
| 决策 | 选择 | 理由 |
|
||||
|------|------|------|
|
||||
| 建模范围 | 仅 `biz_collection_protocol`、`biz_protocol_audit`、`biz_protocol_payment`、`biz_protocol_payment_detail` | 方案 C,对齐已确认边界 |
|
||||
| API 前缀 | 延续 `/web/admin`,新路由文件例如 `collection_protocol.py`,在 `api/__init__.py` 注册 | 与 `basic_info.py` 一致 |
|
||||
| 审核 | 仅插入 `biz_protocol_audit` | 用户选定方案 A |
|
||||
| 财务确认 | 列表过滤固定状态;POST 校验当前行状态后更新 | 防止误操作 |
|
||||
| 预警日期 | 服务器日期与 `installment_due_date`(YYYYMMDD)比较 | 简单可靠 |
|
||||
| 前端路由 | `/cell-storage/*` 五页 | 已定稿 |
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- **详情信息不足** → 第一版标注「概要」,后续迭代补子表 Tab。
|
||||
- **无退费发起** → 退费确认页可能长期为空,依赖外部流程或后续变更。
|
||||
- **并发确认** → 依赖数据库行更新与状态校验;必要时可加重试提示。
|
||||
|
||||
## Migration Plan
|
||||
|
||||
- 无破坏性 schema 变更:部署顺序为后端 → 前端;可选执行菜单 SQL 补丁(若有)。
|
||||
- 回滚:下线路由与菜单项,禁用新 API 路由注册。
|
||||
|
||||
## Open Questions
|
||||
|
||||
- 协议单第一版是否允许「新建/编辑」:若需求未定,建议第一版只读列表 + 详情,创建单独后续变更。
|
||||
@@ -1,32 +0,0 @@
|
||||
## Why
|
||||
|
||||
需求文档 `docs/中科兴皖需求V0.3.md` 中「细胞存储管理」下 2.2.6~2.2.10 尚未在 web-admin 与后端落地;业务依赖 `biz_collection_protocol` 及缴费/审核表。需要在租户隔离与既有 `/web/admin` 约定下交付列表、审核与财务确认、分期预警的最小可用闭环。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 新增一级菜单 **细胞存储管理**及 5 个子路由页面(与 `sqxp.ts`、`backend/app/api/menu.py` 静态菜单对齐)。
|
||||
- 后端新增采集协议单查询、审核写入、缴费明细财务确认、分期预警查询等 API;补充对应表的 SQLAlchemy Model 与 CRUD(方案 C:最小表集)。
|
||||
- 前端新增 `views/cell-storage/**` 五个列表页(及必要弹窗),对接上述接口;样式对齐 Fresh Mint 与 CRUD 模板页。
|
||||
- **不包含**:退费发起、协议单子表(采集信息/样本等)全量录入 UI;工作流引擎驱动本组菜单。
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `cell-storage-collection-protocol`: 采集协议单列表与概要详情 API;Web 列表/详情(第一版以主表 + 缴费概要为主)。
|
||||
- `cell-storage-protocol-audit`: 协议附件类审核(写入 `biz_protocol_audit`,不修改协议单状态);多条审核历史(A1);审核列表与提交。
|
||||
- `cell-storage-receipt-confirm`: 财务收款确认列表(仅 `jfqrz`)与确认动作(`jfqrz`→`yjf`)。
|
||||
- `cell-storage-refund-confirm`: 财务退费确认列表(仅 `tfqrz`)与确认动作(`tfqrz`→`ytf`);不包含退费发起。
|
||||
- `cell-storage-installment-warning`: 分期应缴预警列表(仅 `dfj`、有分期序号;15 天内预警;逾期为应缴日早于今日)。
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- (无)本变更为新增业务能力,不修改已归档基线 spec 的既有 REQUIREMENTS 表述。
|
||||
|
||||
## Impact
|
||||
|
||||
- **后端**:`backend/app/models/models.py`、`app/crud/`、`app/api/`(新建 `collection_protocol.py` 或合并至既有 router)、`app/api/__init__.py`、`app/main.py`。
|
||||
- **前端**:`web-admin/src/router/modules/sqxp.ts`、`web-admin/src/api/*.ts`、`web-admin/src/views/cell-storage/**`。
|
||||
- **菜单**:`backend/app/api/menu.py`。
|
||||
- **数据库**:沿用既有 DDL,原则上不新增表;若需菜单种子则可选 `docs/sql/` 补丁脚本。
|
||||
- **权威交叉**:`docs/superpowers/specs/2026-05-13-cell-storage-protocol-modules-design.md`。
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 租户内采集协议单分页列表
|
||||
|
||||
系统 SHALL 向已认证管理端用户提供采集协议单分页查询接口,数据来源为 `biz_collection_protocol`。查询 SHALL 限定当前用户所属 `tenant_no`,且默认排除 `del_flag=1`。列表默认排序 SHALL 为 `create_time DESC`(若无自定义排序)。列表 SHALL 至少包含协议号展示字段、协议状态、创建时间等便于识别的列。
|
||||
|
||||
#### Scenario: 仅返回本租户数据
|
||||
|
||||
- **WHEN** 用户请求采集协议单分页列表且租户为 T
|
||||
- **THEN** 响应中每条记录的 `tenant_no` SHALL 为 T,且不包含已软删除行
|
||||
|
||||
### Requirement: 采集协议单概要详情
|
||||
|
||||
系统 SHALL 提供按主键查询单条采集协议单的接口,返回 `biz_collection_protocol` 业务字段及公共字段。系统 SHOULD 在同响应或次级结构中附带同一协议单关联的缴费主表 `biz_protocol_payment` 概要(若存在),用于详情页展示缴费模式与金额类信息。
|
||||
|
||||
#### Scenario: 详情命中未删除记录
|
||||
|
||||
- **WHEN** 请求详情且 id 对应当租户下未删除协议单
|
||||
- **THEN** 系统返回该协议单数据;若存在缴费主表记录则一并返回概要
|
||||
|
||||
#### Scenario: 跨租户或已删除拒绝
|
||||
|
||||
- **WHEN** 请求详情 id 不属于当前租户或记录已软删除
|
||||
- **THEN** 系统返回 404 或与项目一致的业务错误,且不泄漏其他租户数据
|
||||
|
||||
### Requirement: Web 采集协议单列表与概要详情页
|
||||
|
||||
Web 管理端 SHALL 提供采集协议单列表页(筛选、工具栏、表格、分页),对齐 `web-admin` 标准列表模板与 Fresh Mint 规范。SHALL 支持打开概要详情(抽屉或弹窗),展示主表及缴费概要;第一版不要求录入全部子表字段。
|
||||
|
||||
#### Scenario: 用户打开列表页
|
||||
|
||||
- **WHEN** 用户进入「采集协议单」菜单路由
|
||||
- **THEN** 页面加载分页列表并可通过操作查看概要详情
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 分期预警数据范围
|
||||
|
||||
系统 SHALL 仅统计满足以下条件的 `biz_protocol_payment_detail` 行:当前租户、`del_flag=0`、`pay_status = dfj`(待缴费)、`installment_no` 非空(分期明细)。系统 SHALL NOT 将 `pay_status = jfqrz` 或其他状态纳入本列表。
|
||||
|
||||
#### Scenario: 待缴费过滤
|
||||
|
||||
- **WHEN** 请求分期预警列表
|
||||
- **THEN** 返回行均满足 `dfj` 且存在分期期序号
|
||||
|
||||
### Requirement: 预警与逾期判定
|
||||
|
||||
系统 SHALL 使用服务器当前日期与 `installment_due_date`(存储为 `YYYYMMDD` 字符串)比较。对每一行 SHALL 可判定:
|
||||
|
||||
- **逾期**:应缴日早于当天;
|
||||
- **预警**:应缴日在当天或未来 15 天(含)内,且未逾期。
|
||||
|
||||
系统 SHALL 支持按「预警 / 逾期 / 全部」类筛选参数过滤(具体 query 名称以实现为准,须在前后端一致)。
|
||||
|
||||
#### Scenario: 超出 15 天未到期不标为预警
|
||||
|
||||
- **WHEN** 某分期应缴日晚于今天起算第 16 天
|
||||
- **THEN** 该行在仅查「预警」类结果中 SHALL NOT 出现(「全部」是否出现由产品约定;默认实现可仍列出但标签非预警)
|
||||
|
||||
### Requirement: Web 分期缴费预警页
|
||||
|
||||
Web 管理端 SHALL 提供「分期缴费用户预警」列表页,展示应缴日、预警/逾期标签、关联协议单标识等;对齐标准列表模板与 Fresh Mint 规范。
|
||||
|
||||
#### Scenario: 用户查看逾期列表
|
||||
|
||||
- **WHEN** 用户选择逾期筛选并加载列表
|
||||
- **THEN** 展示的行均为应缴日早于今天的待缴费分期明细
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 审核记录写入且不修改协议单状态
|
||||
|
||||
系统 SHALL 支持对指定采集协议单提交审核结果,持久化到 `biz_protocol_audit`,字段包含审核状态(`shtg` 审核通过、`shth` 审核退回)、审核备注、审核人(当前用户)及关联协议单 ID。系统 SHALL NOT 因审核提交而修改 `biz_collection_protocol.protocol_status` 或协议单其他状态字段。
|
||||
|
||||
#### Scenario: 提交审核成功写入一行
|
||||
|
||||
- **WHEN** 审核人对某协议单提交合法审核结果
|
||||
- **THEN** 系统插入一条 `biz_protocol_audit` 记录且协议单主表状态字段保持不变
|
||||
|
||||
### Requirement: 同一协议单多条审核历史
|
||||
|
||||
系统 SHALL 允许同一 `collection_protocol_id` 存在多条审核记录(按时间保留历史),SHALL NOT 以唯一约束强制单行覆盖。
|
||||
|
||||
#### Scenario: 同一协议单两次审核
|
||||
|
||||
- **WHEN** 同一协议单先后两次提交审核
|
||||
- **THEN** 系统存在两条审核记录且均可被列表查询到
|
||||
|
||||
### Requirement: 审核列表查询
|
||||
|
||||
系统 SHALL 提供审核记录分页列表接口,限定当前租户未删除数据,并支持按关键字(如协议号关联合理性由实现约定)、审核状态筛选。默认排序 SHALL 符合项目列表约定。
|
||||
|
||||
#### Scenario: 列表仅含本租户审核
|
||||
|
||||
- **WHEN** 请求审核列表
|
||||
- **THEN** 返回记录均属当前租户且 `del_flag=0`
|
||||
|
||||
### Requirement: Web 采集协议单审核页
|
||||
|
||||
Web 管理端 SHALL 提供「采集协议单审核」页面,包含列表与审核操作入口(通过/退回及备注);弹窗表单 SHALL 符合 `label-position="top"` 与 CRUD 弹窗规范。
|
||||
|
||||
#### Scenario: 用户完成一次审核提交
|
||||
|
||||
- **WHEN** 用户填写审核结论并提交
|
||||
- **THEN** 系统调用审核接口成功后刷新列表或局部更新
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 收款确认待办列表
|
||||
|
||||
系统 SHALL 提供分页列表接口,仅返回 `biz_protocol_payment_detail` 中 `pay_status = jfqrz`(缴费确认中)且当前租户、`del_flag=0` 的明细。列表 SHALL 携带关联协议单标识信息(至少协议单 ID 或协议号展示字段)以便财务核对。
|
||||
|
||||
#### Scenario: 列表不含其他状态
|
||||
|
||||
- **WHEN** 请求收款确认列表
|
||||
- **THEN** 每条明细的 `pay_status` SHALL 为 `jfqrz`
|
||||
|
||||
### Requirement: 收款确认动作
|
||||
|
||||
系统 SHALL 提供确认接口,针对单条缴费明细主键:若当前行 `pay_status` 为 `jfqrz`,SHALL 将其更新为 `yjf`(已缴费),并可写入财务确认附件字段(若请求体提供)。若当前行不是 `jfqrz`,SHALL 拒绝并返回业务错误。若已为 `yjf`,SHALL 拒绝重复确认(幂等错误语义)。
|
||||
|
||||
#### Scenario: 正常确认
|
||||
|
||||
- **WHEN** 对 `jfqrz` 明细调用确认接口
|
||||
- **THEN** 该明细 `pay_status` 变为 `yjf`
|
||||
|
||||
#### Scenario: 非法状态拒绝
|
||||
|
||||
- **WHEN** 对非 `jfqrz` 明细调用确认接口
|
||||
- **THEN** 系统拒绝且不修改数据
|
||||
|
||||
### Requirement: Web 收款确认页
|
||||
|
||||
Web 管理端 SHALL 提供「收款确认(财务)」列表页,对齐标准列表模板;SHALL 提供确认操作(弹窗上传附件/备注若需要)。页面 SHALL 仅展示待财务确认的明细。
|
||||
|
||||
#### Scenario: 财务完成确认
|
||||
|
||||
- **WHEN** 用户在列表中对一条待确认记录提交确认
|
||||
- **THEN** 调用后端确认接口成功后该行从待办列表消失或状态更新为已缴费
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 退费确认待办列表
|
||||
|
||||
系统 SHALL 提供分页列表接口,仅返回 `biz_protocol_payment_detail` 中 `pay_status = tfqrz`(退费确认中)且当前租户、`del_flag=0` 的明细。
|
||||
|
||||
#### Scenario: 列表不含非退费确认中状态
|
||||
|
||||
- **WHEN** 请求退费确认列表
|
||||
- **THEN** 每条明细的 `pay_status` SHALL 为 `tfqrz`
|
||||
|
||||
### Requirement: 退费确认动作
|
||||
|
||||
系统 SHALL 提供确认接口,针对单条缴费明细主键:若当前行 `pay_status` 为 `tfqrz`,SHALL 将其更新为 `ytf`(已退费)。若当前行不是 `tfqrz`,SHALL 拒绝。若已为 `ytf`,SHALL 拒绝重复确认。本变更 SHALL NOT 实现「发起退费」或向 `tfqrz` 推进状态的业务接口。
|
||||
|
||||
#### Scenario: 正常确认退费
|
||||
|
||||
- **WHEN** 对 `tfqrz` 明细调用退费确认接口
|
||||
- **THEN** 该明细 `pay_status` 变为 `ytf`
|
||||
|
||||
### Requirement: Web 退费确认页
|
||||
|
||||
Web 管理端 SHALL 提供「退费确认(财务)」列表页与确认操作,对齐标准列表与弹窗规范。
|
||||
|
||||
#### Scenario: 财务完成退费确认
|
||||
|
||||
- **WHEN** 用户对一条退费确认中记录提交确认
|
||||
- **THEN** 调用接口成功后该行不再出现在退费待办列表(或显示为已退费)
|
||||
@@ -1,39 +0,0 @@
|
||||
## 1. 后端模型与 CRUD
|
||||
|
||||
- [x] 1.1 在 `backend/app/models/models.py` 增加 `BizCollectionProtocol`、`BizProtocolAudit`、`BizProtocolPayment`、`BizProtocolPaymentDetail` 与 DDL 字段对齐
|
||||
- [x] 1.2 新建 `backend/app/crud/collection_protocol.py`(或拆分多个模块):协议单列表/详情查询、审核插入、缴费明细状态更新、分期预警查询;统一 `_row_to_dict` camelCase 输出与租户过滤
|
||||
- [x] 1.3 新建 `backend/app/schemas/` 下 Pydantic 请求体(审核、财务确认、分页参数)若项目惯例需要(已在 `collection_protocol.py` 内联 Body,未单独建 schemas 文件)
|
||||
|
||||
## 2. 后端 API
|
||||
|
||||
- [x] 2.1 新建 `backend/app/api/collection_protocol.py`(名称可调整):实现 GET 列表/详情、POST 审核、GET/POST 收款确认、GET/POST 退费确认、GET 分期预警;依赖 `require_admin_or_super_admin` 与 `get_db`
|
||||
- [x] 2.2 在 `backend/app/api/__init__.py` 与 `backend/app/main.py` 注册路由前缀 `/web/admin`(或既有聚合方式)
|
||||
- [ ] 2.3 手工验证:Swagger `/docs` 中上述路径可用,错误状态与业务校验符合 spec(需在本地启动后端后点验)
|
||||
|
||||
## 3. 菜单与路由对齐
|
||||
|
||||
- [x] 3.1 更新 `backend/app/api/menu.py` 的 `STATIC_MENU_TREE`:新增一级「细胞存储管理」及 5 个子菜单(path/component 与前端一致)
|
||||
- [x] 3.2 更新 `web-admin/src/router/modules/sqxp.ts`:同级路由与 meta.title;图标与现有风格一致
|
||||
|
||||
## 4. 前端 API 与类型
|
||||
|
||||
- [x] 4.1 新建 `web-admin/src/api/collection-protocol.ts`(或并入 `admin.ts`):封装列表、详情、审核、两种确认、预警接口,路径与后端一致
|
||||
- [x] 4.2 在 `web-admin/src/types/api.d.ts` 补充必要类型(若项目惯例)(页面使用 `Record<string, unknown>` / 专用 Row 类型已够用)
|
||||
|
||||
## 5. 前端页面(五页)
|
||||
|
||||
- [x] 5.1 新建 `web-admin/src/views/cell-storage/protocol/index.vue`:列表 + 概要详情弹窗;对齐 `system/unit/index.vue` 结构
|
||||
- [x] 5.2 新建 `web-admin/src/views/cell-storage/protocol-audit/index.vue`:审核列表 + 审核弹窗(通过/退回)
|
||||
- [x] 5.3 新建 `web-admin/src/views/cell-storage/payment-confirm/index.vue`:仅 `jfqrz` 列表 + 确认弹窗
|
||||
- [x] 5.4 新建 `web-admin/src/views/cell-storage/refund-confirm/index.vue`:仅 `tfqrz` 列表 + 确认弹窗
|
||||
- [x] 5.5 新建 `web-admin/src/views/cell-storage/installment-warning/index.vue`:筛选预警/逾期/全部 + 标签列;对齐 Fresh Mint 状态色
|
||||
|
||||
## 6. 数据与文档收尾
|
||||
|
||||
- [ ] 6.1 若 DB 菜单走种子数据:在 `docs/sql/` 增加补丁脚本(可选),与仓库既有 `docs/sql/` 增量脚本惯例一致(全量基线为 `zkxw.sql`;当前为前端静态路由 + `STATIC_MENU_TREE`,若生产依赖 DB 菜单种子再补)
|
||||
- [ ] 6.2 本地联调:登录 admin → 五菜单可进 → 列表有接口响应(可用占位数据或手动插库验证)
|
||||
|
||||
## 7. 验证
|
||||
|
||||
- [ ] 7.1 后端:`pytest` 现有用例通过;如有新增关键逻辑可补最小单测(可选)(当前仓库 `tests/test_api_crypto.py` 与实现不一致导致 1 例失败,与本次变更无关)
|
||||
- [ ] 7.2 前端:`pnpm build` 或 `pnpm build:typecheck` 通过(仓库内尚有既有 vue-tsc 报错;新增页面未引入新的独占阻塞项)
|
||||
@@ -1,2 +0,0 @@
|
||||
schema: spec-driven
|
||||
created: 2026-05-26
|
||||
@@ -1,54 +0,0 @@
|
||||
## Context
|
||||
|
||||
中试服务管理已有完整的出库生产+质检闭环:中试申请单 → 输注方案 → 输注计划 → 出库生产工单/任务 → 出库质检工单/任务。已存在 `biz_outbound_release_review` 表和基础 CRUD(4个端点、149行),但功能简陋:创建时未关联生产/质检工单,无聚合查询,无前端页面。
|
||||
|
||||
入库放行审核(`storage-release-review`)已有完整实现(后端757行 CRUD + 3个 Vue 文件 + 独立 API 文件),可参照其模式设计出库放行审核。
|
||||
|
||||
后端已有可复用函数 `build_outbound_pilot_context_by_schedule(db, schedule_id, tenant_no)`,一次性查出申请单/患者/输注方案/计划/产品信息。
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- 实现完整的出库放行审核模块(后端聚合查询 + 前端列表/查看/审核界面)
|
||||
- 每条输注计划独立审核,查看其关联的生产工单/任务和质检工单/任务结果
|
||||
- 审核通过/不通过 + 备注 + 附件,仅记录结论不自动改状态
|
||||
- 参照入库放行审核模式,保持代码风格和架构一致性
|
||||
|
||||
**Non-Goals:**
|
||||
- 不实现自动联动状态更新(审核通过后不自动改输注计划状态)
|
||||
- 不实现工作流引擎(审核为单步操作,非多级审批)
|
||||
- 不修改已有入库放行审核模块
|
||||
- 不修改生产/质检工单的已有逻辑
|
||||
|
||||
## Decisions
|
||||
|
||||
### D1: 复用已有 `biz_outbound_release_review` 表 vs 新建表
|
||||
**选择**: 复用已有表,补充缺失字段。
|
||||
**理由**: 表已存在且与 `infusion_schedule_id` 关联,只需补充 `review_attachments`、`review_by_name`、`create_by_name` 等快照字段。
|
||||
**备选**: 新建表——会增加迁移成本且无额外收益。
|
||||
|
||||
### D2: 审核列表页数据来源
|
||||
**选择**: 基于 `biz_pilot_infusion_schedule` 构建,左连接 `biz_outbound_release_review` 获取审核状态。
|
||||
**理由**: 审核对象是输注计划,而非审核记录本身。输注计划创建后,只有生产和质检都完成才需要审核。列表页展示所有排程(附带审核状态),而非只展示已创建审核记录的排程。
|
||||
**备选**: 只展示已创建审核记录的排程——会导致"待审核"状态的排程无法展示。
|
||||
|
||||
### D3: 前端页面放在 pilot-service 目录 vs quality-inspection 目录
|
||||
**选择**: 放在 `pilot-service/outbound-release-review/`。
|
||||
**理由**: 用户决策放在中试服务管理菜单下,与输注计划管理同级。
|
||||
**备选**: 放在 `quality-inspection/` 下——会与入库放行审核混在一起,不符合业务分组。
|
||||
|
||||
### D4: 详情聚合查询方式
|
||||
**选择**: 后端一次性聚合查询,复用 `build_outbound_pilot_context_by_schedule()`。
|
||||
**理由**: 入库放行审核的详情也是后端聚合(6个信息域)。复用已有函数减少重复代码,且一次请求减少前端多次调用。
|
||||
**备选**: 前端多次调用已有 API 组装——增加请求次数,前端逻辑复杂。
|
||||
|
||||
### D5: API 路径前缀
|
||||
**选择**: 保持已有的 `/web/admin/pilot-release-review` 路径前缀。
|
||||
**理由**: 后端 API 已注册在此路径下,保持一致性。
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- **[风险] `biz_outbound_release_review` 表字段不完整** → 补充字段即可,已有数据不受影响(新字段为 NULL 安全)
|
||||
- **[风险] 聚合查询性能** → 按 `infusion_schedule_id` 查询(有索引),且单次排程关联数据量有限,性能可控
|
||||
- **[取舍] 审核不联动状态** → 简化实现,但用户需手动操作后续步骤。如需联动可在后续版本补充
|
||||
- **[取舍] 列表基于排程而非审核记录** → 列表数据更全面但查询稍复杂(需 LEFT JOIN)
|
||||
@@ -1,29 +0,0 @@
|
||||
## Why
|
||||
|
||||
中试服务管理流程已实现申请单、体检、输注计划、出库生产工单/任务、出库质检工单/任务的完整闭环,但缺少最终的**出库放行审核**环节——即对每条输注计划关联的生产和质检结果进行审核判定后才能放行出库。目前已有的 `biz_outbound_release_review` 表和基础 CRUD 仅是骨架,未实现聚合查询和前端审核界面。
|
||||
|
||||
## What Changes
|
||||
|
||||
- **后端重构**:重构 `outbound_release_review.py` CRUD(~149行→~500行),增加按 `infusion_schedule_id` 聚合查询申请单/患者/生产工单+任务/质检工单+任务详情
|
||||
- **后端 API 扩展**:从 4 个基础 CRUD 端点扩展为完整审核 API(分页列表、聚合详情、单条审核、批量审核)
|
||||
- **前端新增页面**:在中试服务管理模块下新建出库放行审核页面(列表页 + 查看弹窗 + 审核弹窗),参照已有入库放行审核模式
|
||||
- **路由注册**:`sqxp.ts` 新增路由,菜单放在中试服务管理下与输注计划管理同级
|
||||
- **状态标签注册**:`status-tag-registry.ts` 注册出库审核结论标签
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `outbound-release-review-api`: 后端出库放行审核 API——聚合查询(输注计划关联的生产工单/任务/质检工单/任务/结果)、审核操作(单条/批量)、分页列表
|
||||
- `outbound-release-review-ui`: 前端出库放行审核页面——列表页(筛选+批量操作)、查看弹窗(6域聚合展示)、审核弹窗(结论+备注+附件)
|
||||
|
||||
### Modified Capabilities
|
||||
(无已有 spec 需要修改)
|
||||
|
||||
## Impact
|
||||
|
||||
- **后端文件**:`backend/app/api/outbound_release_review.py`、`backend/app/crud/outbound_release_review.py`、`backend/app/schemas/outbound_release_review.py`(可能新建)
|
||||
- **前端文件**:`web-admin/src/views/pilot-service/outbound-release-review/`(新建目录 + 3 个 Vue 文件)、`web-admin/src/api/admin.ts`(补充 API 函数)
|
||||
- **路由**:`web-admin/src/router/modules/sqxp.ts`
|
||||
- **状态标签**:`web-admin/src/utils/status-tag-registry.ts`
|
||||
- **数据库**:`biz_outbound_release_review` 表可能需要补充字段(如 `review_attachments`)
|
||||
- **无破坏性变更**:所有改动为新增功能,不影响已有模块
|
||||
@@ -1,71 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 出库放行审核列表 API
|
||||
系统 SHALL 提供 `GET /web/admin/pilot-release-reviews` 端点,返回分页的输注计划列表(附带出库放行审核状态)。列表 SHALL 基于 `biz_pilot_infusion_schedule` 构建,LEFT JOIN `biz_outbound_release_review` 获取审核结论。每个列表项 SHALL 包含:申请单号、患者姓名、输注计划编号、细胞类型、规格、输注时间、生产工单状态、质检工单状态、审核结论、审核时间。
|
||||
|
||||
#### Scenario: 查询全部输注计划审核状态
|
||||
- **WHEN** 管理员请求 `GET /web/admin/pilot-release-reviews?page=1&page_size=20`
|
||||
- **THEN** 系统返回分页列表,包含所有未删除的输注计划及其对应的审核状态
|
||||
|
||||
#### Scenario: 按审核结论筛选
|
||||
- **WHEN** 管理员请求 `GET /web/admin/pilot-release-reviews?review_conclusion=tg`
|
||||
- **THEN** 系统只返回审核结论为"通过"的输注计划
|
||||
|
||||
#### Scenario: 按关键词搜索
|
||||
- **WHEN** 管理员请求 `GET /web/admin/pilot-release-reviews?keyword=ZSSQ202605260005`
|
||||
- **THEN** 系统返回匹配申请单号或患者姓名的输注计划
|
||||
|
||||
### Requirement: 出库放行审核详情聚合 API
|
||||
系统 SHALL 提供 `GET /web/admin/pilot-release-reviews/{schedule_id}/detail` 端点,返回指定输注计划的完整审核上下文。详情 SHALL 聚合以下 6 个信息域:
|
||||
1. **申请单信息**:申请单号、申请单名称、渠道名称、状态
|
||||
2. **患者信息**:姓名、性别、年龄、联系电话
|
||||
3. **输注计划信息**:细胞类型、规格、输注时间、地点、方式、生产状态、质检状态、输注状态
|
||||
4. **生产工单+任务信息**:工单号、状态、每个任务的投入/产出/工艺步骤及结论
|
||||
5. **质检工单+任务信息**:工单号、状态、实验室/第三方项目、每个任务的检测结果及结论
|
||||
6. **审核记录信息**:审核结论、备注、附件、审核人、审核时间
|
||||
|
||||
#### Scenario: 查看完整审核详情
|
||||
- **WHEN** 管理员请求 `GET /web/admin/pilot-release-reviews/{schedule_id}/detail`
|
||||
- **THEN** 系统返回包含上述 6 个信息域的完整聚合数据
|
||||
|
||||
#### Scenario: 输注计划无生产工单
|
||||
- **WHEN** 输注计划尚未创建出库生产工单
|
||||
- **THEN** 生产工单+任务信息域返回空数组
|
||||
|
||||
#### Scenario: 输注计划无质检工单
|
||||
- **WHEN** 输注计划尚未创建出库质检工单
|
||||
- **THEN** 质检工单+任务信息域返回空数组
|
||||
|
||||
### Requirement: 出库放行审核操作 API
|
||||
系统 SHALL 提供 `PUT /web/admin/pilot-release-reviews/{schedule_id}/review` 端点用于单条审核,以及 `PUT /web/admin/pilot-release-reviews/batch-review` 用于批量审核。审核操作 SHALL 创建或更新 `biz_outbound_release_review` 记录,设置 `review_conclusion`(tg/btg)、`review_remark`、`review_attachments`、`reviewer_user_id`、`review_time`。审核时 SHALL 自动查找并填充 `production_work_order_id` 和 `qc_work_order_id`。
|
||||
|
||||
#### Scenario: 单条审核通过
|
||||
- **WHEN** 管理员提交审核 `PUT /pilot-release-reviews/{schedule_id}/review` body=`{"review_conclusion":"tg","review_remark":"合格"}`
|
||||
- **THEN** 系统创建或更新审核记录,设置结论为"通过"、备注、审核人、审核时间
|
||||
|
||||
#### Scenario: 单条审核不通过
|
||||
- **WHEN** 管理员提交审核结论为"btg"
|
||||
- **THEN** 系统记录"不通过"结论
|
||||
|
||||
#### Scenario: 批量审核
|
||||
- **WHEN** 管理员提交 `PUT /pilot-release-reviews/batch-review` body=`{"schedule_ids":["id1","id2"],"review_conclusion":"tg","review_remark":"批量通过"}`
|
||||
- **THEN** 系统为所有指定排程创建/更新审核记录
|
||||
|
||||
#### Scenario: 重复审核覆盖
|
||||
- **WHEN** 输注计划已有审核记录,再次提交审核
|
||||
- **THEN** 系统更新已有记录(覆盖审核结论、备注、附件、审核人、时间)
|
||||
|
||||
### Requirement: 审核记录关联工单
|
||||
创建审核记录时,系统 SHALL 根据 `infusion_schedule_id` 自动查询关联的出库生产工单(`biz_production_work_order WHERE infusion_schedule_id=? AND work_order_type='outbound'`)和出库质检工单(`biz_qc_work_order WHERE infusion_schedule_id=? AND qc_biz_type='outbound'`),并将工单 ID 填充到 `production_work_order_id` 和 `qc_work_order_id` 字段。
|
||||
|
||||
#### Scenario: 自动关联生产工单
|
||||
- **WHEN** 为某输注计划创建审核记录,且该计划存在 `work_order_type='outbound'` 的生产工单
|
||||
- **THEN** 审核记录的 `production_work_order_id` 自动填充为该生产工单的 ID
|
||||
|
||||
#### Scenario: 自动关联质检工单
|
||||
- **WHEN** 为某输注计划创建审核记录,且该计划存在 `qc_biz_type='outbound'` 的质检工单
|
||||
- **THEN** 审核记录的 `qc_work_order_id` 自动填充为该质检工单的 ID
|
||||
|
||||
#### Scenario: 无关联工单
|
||||
- **WHEN** 输注计划尚无出库生产或质检工单
|
||||
- **THEN** 对应工单 ID 字段为空字符串
|
||||
@@ -1,68 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 出库放行审核列表页
|
||||
系统 SHALL 在中试服务管理菜单下新增"出库放行审核"页面,路径为 `pilot-service/outbound-release-review`。列表页 SHALL 展示所有输注计划的审核状态,参照 `storage-release-review/index.vue` 模式。列表 SHALL 支持筛选:关键词搜索、审核结论、生产状态、质检状态。列表操作栏 SHALL 包含:查看、审核(单条)。支持批量选择和批量审核。
|
||||
|
||||
#### Scenario: 列表页加载
|
||||
- **WHEN** 用户进入出库放行审核页面
|
||||
- **THEN** 系统展示分页列表,每行展示:申请单号、患者姓名、细胞类型、规格、输注时间、生产状态(el-tag)、质检状态(el-tag)、审核结论(el-tag)、审核时间
|
||||
|
||||
#### Scenario: 筛选审核状态
|
||||
- **WHEN** 用户选择审核结论筛选为"待审核"
|
||||
- **THEN** 列表只展示未审核的输注计划
|
||||
|
||||
#### Scenario: 批量审核操作
|
||||
- **WHEN** 用户勾选多条记录后点击"批量审核"按钮
|
||||
- **THEN** 弹出批量审核对话框,提交后所有选中记录更新审核结论
|
||||
|
||||
### Requirement: 出库放行审核查看弹窗
|
||||
系统 SHALL 提供查看弹窗(`OutboundReleaseViewDialog.vue`),使用 `SystemViewDialog` 组件,展示 6 个信息域的聚合数据:
|
||||
1. 申请单基础信息(申请单号、名称、渠道、状态)
|
||||
2. 患者信息(姓名、性别、年龄、电话)
|
||||
3. 输注计划信息(细胞类型、规格、时间、地点、方式、各状态)
|
||||
4. 生产工单+任务信息(工单号、状态、任务列表含结论)
|
||||
5. 质检工单+任务信息(工单号、状态、任务列表含结论和检测结果)
|
||||
6. 审核记录信息(结论、备注、附件、审核人、时间)
|
||||
|
||||
#### Scenario: 查看完整审核详情
|
||||
- **WHEN** 用户点击某条记录的"查看"按钮
|
||||
- **THEN** 弹窗展示上述 6 个 section 的完整聚合数据
|
||||
|
||||
#### Scenario: 查看审核附件
|
||||
- **WHEN** 审核记录包含附件
|
||||
- **THEN** 附件区域展示可点击下载的附件列表
|
||||
|
||||
### Requirement: 出库放行审核操作弹窗
|
||||
系统 SHALL 提供审核弹窗(`OutboundReleaseReviewDialog.vue`),参照 `StorageReleaseReviewDialog.vue` 模式。弹窗 SHALL 包含:审核结论(单选:通过/不通过)、审核备注(textarea)、审核附件(卡片化上传,参照附件上传卡片化布局规范)。支持单条模式和批量模式。
|
||||
|
||||
#### Scenario: 单条审核
|
||||
- **WHEN** 用户点击某条记录的"审核"按钮
|
||||
- **THEN** 弹出审核弹窗,用户选择结论、填写备注、上传附件后提交
|
||||
|
||||
#### Scenario: 批量审核
|
||||
- **WHEN** 用户勾选多条记录后点击"批量审核"
|
||||
- **THEN** 弹出批量审核弹窗(不显示具体记录详情),填写统一结论/备注/附件后提交
|
||||
|
||||
#### Scenario: 审核通过提交
|
||||
- **WHEN** 用户选择"通过"并提交
|
||||
- **THEN** 系统更新审核记录,列表刷新后该记录审核结论显示为"通过"(success el-tag)
|
||||
|
||||
#### Scenario: 审核不通过提交
|
||||
- **WHEN** 用户选择"不通过"并提交
|
||||
- **THEN** 系统更新审核记录,列表刷新后该记录审核结论显示为"不通过"(danger el-tag)
|
||||
|
||||
### Requirement: 状态标签注册
|
||||
`status-tag-registry.ts` SHALL 注册出库放行审核相关的状态标签映射:
|
||||
- 审核结论:`tg`=通过(success)、`btg`=不通过(danger)、null=待审核(info)
|
||||
- 按钮 SHALL 携带 `el-icon` 图标(参照按钮须携带图标规范)
|
||||
|
||||
#### Scenario: 审核结论标签展示
|
||||
- **WHEN** 列表中某条记录审核结论为"tg"
|
||||
- **THEN** 审核结论列显示绿色 `el-tag`(type="success",text="通过")
|
||||
|
||||
### Requirement: 路由注册
|
||||
`sqxp.ts` SHALL 在中试服务管理下新增"出库放行审核"路由,路径 `outbound-release-review`,组件指向 `pilot-service/outbound-release-review/index.vue`。
|
||||
|
||||
#### Scenario: 菜单导航
|
||||
- **WHEN** 用户点击中试服务管理下的"出库放行审核"菜单
|
||||
- **THEN** 系统跳转到出库放行审核列表页
|
||||
@@ -1,43 +0,0 @@
|
||||
## 1. 数据库变更
|
||||
|
||||
- [ ] 1.1 检查并补充 `biz_outbound_release_review` 表字段(如缺少 `review_attachments`、`review_by_name`、`create_by_name` 等),生成增量 SQL 到 `docs/sql/`
|
||||
- [ ] 1.2 更新 `backend/app/models/models.py` 中 `BizOutboundReleaseReview` 模型,与表结构对齐
|
||||
|
||||
## 2. 后端 Schema 与 CRUD
|
||||
|
||||
- [ ] 2.1 新建 `backend/app/schemas/outbound_release_review.py`,定义请求/响应 Pydantic 模型(列表项、详情聚合、审核提交、批量审核),遵循项目 Schema 命名规范
|
||||
- [ ] 2.2 重构 `backend/app/crud/outbound_release_review.py`:实现分页列表查询(基于 infusion_schedule LEFT JOIN 审核记录 + 生产工单 + 质检工单状态)
|
||||
- [ ] 2.3 实现聚合详情查询 `get_review_detail(schedule_id)`:复用 `build_outbound_pilot_context_by_schedule()` + 查生产工单任务 + 查质检工单任务结果,返回 6 域聚合数据
|
||||
- [ ] 2.4 实现审核操作 `review_schedule(schedule_id, conclusion, remark, attachments, user)`:创建或更新审核记录,自动填充 production_work_order_id 和 qc_work_order_id
|
||||
- [ ] 2.5 实现批量审核 `batch_review(schedule_ids, conclusion, remark, attachments, user)`
|
||||
|
||||
## 3. 后端 API
|
||||
|
||||
- [ ] 3.1 重构 `backend/app/api/outbound_release_review.py`:新增 `GET /pilot-release-reviews` 分页列表端点
|
||||
- [ ] 3.2 新增 `GET /pilot-release-reviews/{schedule_id}/detail` 详情聚合端点
|
||||
- [ ] 3.3 新增 `PUT /pilot-release-reviews/{schedule_id}/review` 单条审核端点
|
||||
- [ ] 3.4 新增 `PUT /pilot-release-reviews/batch-review` 批量审核端点
|
||||
- [ ] 3.5 确认路由已在 `app/api/__init__.py` 和 `app/main.py` 正确注册
|
||||
|
||||
## 4. 前端 API 层
|
||||
|
||||
- [ ] 4.1 在 `web-admin/src/api/admin.ts` 中补充/重构出库放行审核相关 API 函数(列表、详情、单条审核、批量审核),定义 TypeScript 类型
|
||||
|
||||
## 5. 前端列表页
|
||||
|
||||
- [ ] 5.1 新建 `web-admin/src/views/pilot-service/outbound-release-review/index.vue` 列表页,参照 `storage-release-review/index.vue` 模式:搜索栏(关键词、审核结论、生产状态、质检状态)+ 表格(申请单号、患者、细胞类型、规格、输注时间、生产/质检/审核状态列)+ 操作栏(查看、审核)
|
||||
- [ ] 5.2 实现批量选择和批量审核按钮交互
|
||||
|
||||
## 6. 前端查看弹窗
|
||||
|
||||
- [ ] 6.1 新建 `OutboundReleaseViewDialog.vue`,使用 `SystemViewDialog` 组件,展示 6 个 section(申请单信息、患者信息、输注计划、生产工单+任务、质检工单+任务、审核记录)
|
||||
- [ ] 6.2 生产/质检信息域复用 `SampleQcInfoCards` / `SampleProductionInfoCards` 组件(如有)或参照入库放行审核的 `StorageReleaseViewDialog.vue` 模式自定义展示
|
||||
|
||||
## 7. 前端审核弹窗
|
||||
|
||||
- [ ] 7.1 新建 `OutboundReleaseReviewDialog.vue`,参照 `StorageReleaseReviewDialog.vue`:审核结论(el-radio-group)、备注(el-input textarea)、附件上传(卡片化布局),支持单条和批量模式
|
||||
|
||||
## 8. 路由与状态标签
|
||||
|
||||
- [ ] 8.1 在 `web-admin/src/router/modules/sqxp.ts` 中新增出库放行审核路由(路径 `outbound-release-review`,放在中试服务管理下)
|
||||
- [ ] 8.2 在 `web-admin/src/utils/status-tag-registry.ts` 中注册出库审核结论标签映射(tg=通过/success、btg=不通过/danger、null=待审核/info)
|
||||
@@ -1,2 +0,0 @@
|
||||
schema: spec-driven
|
||||
created: 2026-05-23
|
||||
@@ -1,131 +0,0 @@
|
||||
## Context
|
||||
|
||||
生产部门当前仅有耗材目录表(`biz_consumable`)和试剂目录表(`biz_reagent`),管理编码、名称、规格、标准用量等基础信息,无库存管理。市场部门和质检部门已有完整的库存管理体系,采用「主表含库存字段 + 变动记录表」的双表模式。
|
||||
|
||||
现有耗材/试剂被 10 张下游关联表(耗材包、工艺、工艺路线、生产任务步骤)引用,但全部使用快照复制(denormalized code/name),无 FK 依赖,对主表加字段零影响。
|
||||
|
||||
### 现有参照实现
|
||||
|
||||
- **市场物料**:`biz_material`(含 stock_qty)+ `biz_material_stock_log`(变动记录,rk/ck,正数)
|
||||
- **质检物料**:`biz_qc_material`(含 stock_qty)+ `biz_qc_material_usage`(变动记录,in/use,正负数,含 task_complete 自动扣减 + revert 回退)
|
||||
|
||||
### 步骤保存挂钩点
|
||||
|
||||
生产任务步骤的耗材/试剂保存入口:
|
||||
- `PUT /production-tasks/{task_id}/steps/{step_id}/reagents` → `replace_step_reagents()`
|
||||
- `PUT /production-tasks/{task_id}/steps/{step_id}/consumables` → `replace_step_consumables()`
|
||||
|
||||
这两个函数使用"软删旧 + 插入新"模式,需在此处加入 diff 结算逻辑。
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- 为耗材和试剂增加库存管理能力(库存量、预警量、出入库操作)
|
||||
- 支持手动单个/批量入库出库,参照质检物料模式
|
||||
- 支持生产任务步骤保存时按 actual_usage 自动 diff 结算库存
|
||||
- 变动记录在耗材/试剂页面内以子弹窗和 Tab 形式展示
|
||||
|
||||
**Non-Goals:**
|
||||
- 不新建独立菜单页面(变动记录嵌入现有页面)
|
||||
- 不修改现有耗材/试剂目录字段(只加库存字段)
|
||||
- 不修改下游 10 张关联表
|
||||
- 不实现仓库/库位管理(单库存维度)
|
||||
- 不实现库存预警通知(仅记录 warning_qty 字段)
|
||||
- 不统一耗材/试剂为统一物料表(保持两个独立目录)
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: 在现有目录表上加库存字段,不新建库存主表
|
||||
|
||||
**选择**:ALTER TABLE `biz_consumable` / `biz_reagent` 新增 `stock_qty`、`warning_qty`、`status` 字段。
|
||||
|
||||
**理由**:
|
||||
- 下游 10 张关联表全是快照复制,加字段零影响
|
||||
- 与市场/质检物料的「主表含库存字段」模式一致
|
||||
- 避免引入目录表→库存表的间接层和数据同步问题
|
||||
- 改动最小:复用现有 CRUD/API/前端,只需扩展
|
||||
|
||||
**替代方案**:新建 `biz_consumable_stock` 表,通过 consumable_id 关联。放弃原因:多一层间接、需维护目录-库存同步、与已有模式不一致。
|
||||
|
||||
### Decision 2: 新建独立的变动记录表
|
||||
|
||||
**选择**:新建 `biz_consumable_stock_log` 和 `biz_reagent_stock_log`,参照 `biz_material_stock_log` 结构。
|
||||
|
||||
**理由**:
|
||||
- 变动记录是独立的关注点,不应混在目录表中
|
||||
- 需要快照字段(code/name)和 before/after 库存
|
||||
- 需要溯源字段(source_type、step_id、task_id、task_no)
|
||||
- 参照 `biz_qc_material_usage` 的 source_type 模式:manual_in / manual_out / step_save
|
||||
|
||||
**关键设计**:参照质检物料采用正负数表示方向(入库正、出库负),同时保留 `change_type` 字段(in/use)。
|
||||
|
||||
### Decision 3: 步骤保存 diff 结算算法
|
||||
|
||||
**选择**:全量回退 + 重算模式(参照质检物料的 revert + deduct 模式)。
|
||||
|
||||
**算法**:
|
||||
1. 查出该步骤当前所有 source_type=step_save 的变动记录
|
||||
2. 按变动记录逐条回退库存(加回扣减量),软删变动记录
|
||||
3. 遍历新的步骤耗材/试剂列表,按 actual_usage 扣减库存,生成新变动记录
|
||||
4. 整体在同一事务中
|
||||
|
||||
**理由**:
|
||||
- 步骤保存频率不高,全量回退+重算简单可靠
|
||||
- 避免复杂的逐项 diff 计算(需处理编码变更等边界情况)
|
||||
- 与质检物料 deduct_for_task() 模式一致,代码可复用
|
||||
|
||||
**替代方案**:逐项 diff(旧用量 - 新用量 = 差额)。放弃原因:需处理编码变更(物料A改成物料B)、处理删除、新增等复杂场景,容易出 bug。全量回退更简单且已验证。
|
||||
|
||||
### Decision 4: 变动记录子弹窗 + Tab 双入口
|
||||
|
||||
**选择**:
|
||||
- 每行操作列「变动记录」按钮 → Dialog 弹窗,按 material_id 筛选
|
||||
- 页面顶部 Tab「全部变动记录」→ Tab 切换视图,展示所有物料的汇总记录
|
||||
|
||||
**理由**:
|
||||
- 不新增菜单位,保持生产管理菜单简洁
|
||||
- 行按钮满足"看某个物料历史"的快速需求
|
||||
- Tab 视图满足"看所有变动流水"的审计需求
|
||||
|
||||
### Decision 5: 挂钩点在 replace_step_reagents/consumables
|
||||
|
||||
**选择**:在 `replace_step_reagents()` 和 `replace_step_consumables()` 函数中,在 soft delete 旧记录之后、insert 新记录之前,执行库存 diff 结算。
|
||||
|
||||
**调用链**:
|
||||
```
|
||||
API: PUT /production-tasks/{task_id}/steps/{step_id}/consumables
|
||||
→ replace_step_consumables(db, step_id, tenant_no, user_id, items)
|
||||
→ 1. 查出步骤信息(step_id → task_id, task_no)
|
||||
→ 2. 调用 diff_settle_step_consumables(db, step_id, task_id, task_no, tenant_no, user_id)
|
||||
→ revert step 的所有 step_save 变动记录(回退库存)
|
||||
→ 3. soft delete 旧步骤耗材子记录
|
||||
→ 4. insert 新步骤耗材子记录
|
||||
→ 5. 调用 deduct_step_consumables(db, step_id, task_id, task_no, tenant_no, user_id, new_items)
|
||||
→ 按 actual_usage 扣减库存,生成 step_save 变动记录
|
||||
→ 6. commit
|
||||
```
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
### Risk: 步骤保存时库存不足
|
||||
**影响**:任务执行保存步骤时,若耗材/试剂库存不足,保存会失败。
|
||||
**缓解**:提供清晰的错误提示("物料「XX」库存不足,当前库存 N,需使用 M"),让用户先去入库。同时前端可在步骤编辑时显示当前库存量供参考。
|
||||
|
||||
### Risk: actual_usage 为空或非数字
|
||||
**影响**:步骤保存时 actual_usage 字段可能为空字符串或非数字。
|
||||
**缓解**:diff 结算时跳过 actual_usage 为空或无法转为正数的条目,仅处理有效数据。
|
||||
|
||||
### Risk: 并发保存同一物料库存
|
||||
**影响**:多个步骤同时保存涉及同一耗材/试剂。
|
||||
**缓解**:使用 `with_for_update()` 行锁,与质检物料一致。
|
||||
|
||||
### Trade-off: 全量回退 vs 逐项 diff
|
||||
**选择**全量回退,牺牲少量性能换取代码简洁性和正确性保证。步骤保存频率低,性能影响可忽略。
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. **数据库迁移**:ALTER TABLE 加字段(有默认值) + CREATE TABLE 建变动记录表
|
||||
2. **后端部署**:模型 → CRUD → API 顺序部署
|
||||
3. **前端部署**:扩展现有页面
|
||||
4. **无需数据迁移**:现有耗材/试剂的 stock_qty 默认为 0,warning_qty 默认为 0,status 默认为 '1'
|
||||
5. **回滚方案**:ALTER TABLE 删除新增字段,DROP TABLE 变动记录表,回滚代码
|
||||
@@ -1,34 +0,0 @@
|
||||
## Why
|
||||
|
||||
生产部门目前【耗材管理】和【试剂管理】仅维护目录数据(编码、名称、规格、单位等),无法追踪库存数量、出入库记录。市场部门和质检部门已有完整的物料库存管理体系(主表含库存字段 + 变动记录表),生产部门需要补齐这一能力,同时生产任务执行过程中的步骤保存需自动扣减耗材/试剂库存。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 在 `biz_consumable` 和 `biz_reagent` 现有目录表上新增库存字段(stock_qty、warning_qty、status)
|
||||
- 新建 `biz_consumable_stock_log` 和 `biz_reagent_stock_log` 两张变动记录表(参照 `biz_material_stock_log` 结构)
|
||||
- 后端新增出入库 API(单个/批量入库出库),含行锁防超卖、出库校验、批量事务回滚
|
||||
- 后端新增生产任务步骤保存时的自动库存 diff 结算(增量扣减/回退)
|
||||
- 前端在现有耗材/试剂管理页面增加:库存列、入库/出库/批量入库/批量出库操作按钮及弹窗
|
||||
- 前端新增变动记录展示:行按钮弹窗(单物料历史)+ 顶部 Tab 全部变动记录视图
|
||||
- 变动记录区分 source_type:manual_in(手动入库)、manual_out(手动出库)、step_save(步骤保存自动扣减/回退)
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `consumable-inventory`: 耗材库存管理 — 库存字段扩展、手动出入库(单个+批量)、批量事务、库存校验、删除保护
|
||||
- `reagent-inventory`: 试剂库存管理 — 同上,独立于耗材的平行实现
|
||||
- `production-step-stock-deduction`: 生产任务步骤保存自动扣减 — diff 结算算法、增量扣减/回退、并发安全、溯源关联(step_id/task_id/task_no)
|
||||
- `material-stock-log-ui`: 变动记录子弹窗 UI — 行按钮单物料弹窗 + 顶部 Tab 全部记录视图、筛选、分页
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
(无需修改现有 spec 的行为要求)
|
||||
|
||||
## Impact
|
||||
|
||||
- **数据库**:`biz_consumable`、`biz_reagent` 各加 3 个字段(ALTER ADD COLUMN,有默认值,零风险);新建 2 张变动记录表
|
||||
- **后端**:修改 `models/models.py`(加字段+新 Model)、新建 `crud/consumable_stock_log.py` 和 `crud/reagent_stock_log.py`、扩展 `crud/consumable.py` 和 `crud/reagent.py` 出入库逻辑、扩展 `api/production.py` 出入库和变动记录 API、修改 `crud/production_task.py` 步骤保存加入 diff 扣减
|
||||
- **前端**:修改 `views/production/consumable/index.vue` 和 `views/production/reagent/index.vue`(增加库存列、出入库弹窗、变动记录 Tab/弹窗)、扩展 `api/production.ts` API 调用
|
||||
- **下游不受影响**:耗材包、工艺库、工艺路线、生产任务步骤等 10 张下游关联表均为快照复制,无 FK 依赖,加字段零影响
|
||||
- **SQL 迁移**:需在 `docs/sql/` 新增迁移脚本
|
||||
@@ -1,107 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Consumable inventory fields
|
||||
系统 SHALL 在 `biz_consumable` 表上新增以下库存字段:
|
||||
- `stock_qty` DECIMAL(18,4) NOT NULL DEFAULT 0 — 当前库存量
|
||||
- `warning_qty` DECIMAL(18,4) NOT NULL DEFAULT 0 — 预警库存量
|
||||
- `status` CHAR(1) NOT NULL DEFAULT '1' — 启用/停用状态(1=启用,0=停用)
|
||||
|
||||
后端 SQLAlchemy Model `BizConsumable` SHALL 同步新增对应字段。前端列表和表单 SHALL 展示这些字段。
|
||||
|
||||
#### Scenario: Existing consumables have zero stock after migration
|
||||
- **WHEN** 数据库迁移完成,已有耗材记录存在
|
||||
- **THEN** 所有已有耗材的 stock_qty 为 0,warning_qty 为 0,status 为 '1'
|
||||
|
||||
#### Scenario: Consumable list shows stock info
|
||||
- **WHEN** 用户访问耗材管理列表
|
||||
- **THEN** 列表显示当前库存量、预警库存量、状态列
|
||||
|
||||
### Requirement: Manual stock-in for consumable
|
||||
系统 SHALL 支持对单个耗材进行手动入库操作。入库数量必须大于 0。入库后 stock_qty 增加,同时生成一条变动记录(source_type=manual_in,change_type=in)。
|
||||
|
||||
#### Scenario: Successful stock-in
|
||||
- **WHEN** 用户对库存为 10 的耗材入库 5
|
||||
- **THEN** 耗材 stock_qty 变为 15,生成变动记录 change_qty=5, stock_after=15, source_type=manual_in
|
||||
|
||||
#### Scenario: Stock-in with disabled consumable
|
||||
- **WHEN** 用户对已停用的耗材执行入库
|
||||
- **THEN** 系统拒绝并提示"物料「XX」已停用,无法入库"
|
||||
|
||||
### Requirement: Manual stock-out for consumable
|
||||
系统 SHALL 支持对单个耗材进行手动出库操作。出库数量必须大于 0,且不能超过当前库存。出库必须填写领用人。出库后 stock_qty 减少,同时生成一条变动记录(source_type=manual_out,change_type=use,change_qty 为负数)。
|
||||
|
||||
#### Scenario: Successful stock-out
|
||||
- **WHEN** 用户对库存为 10 的耗材出库 3,领用人为"张三"
|
||||
- **THEN** 耗材 stock_qty 变为 7,生成变动记录 change_qty=-3, stock_after=7, source_type=manual_out, receiver=张三
|
||||
|
||||
#### Scenario: Stock-out exceeds inventory
|
||||
- **WHEN** 用户对库存为 2 的耗材出库 5
|
||||
- **THEN** 系统拒绝并提示"物料「XX」库存不足,当前库存 2,需出库 5"
|
||||
|
||||
#### Scenario: Stock-out without receiver
|
||||
- **WHEN** 用户出库时不填写领用人
|
||||
- **THEN** 系统拒绝并提示"请选择领用人"
|
||||
|
||||
### Requirement: Batch stock-in for consumables
|
||||
系统 SHALL 支持对多个耗材批量入库。所有条目在同一事务内处理,任一条目失败则全部回滚。每条入库记录独立生成变动记录。
|
||||
|
||||
#### Scenario: Successful batch stock-in
|
||||
- **WHEN** 用户批量入库 3 种耗材,数量分别为 5、10、2
|
||||
- **THEN** 3 种耗材库存分别增加,生成 3 条变动记录,全部在同一事务内
|
||||
|
||||
#### Scenario: Batch stock-in with one invalid item
|
||||
- **WHEN** 用户批量入库 3 种耗材,其中一种已停用
|
||||
- **THEN** 全部回滚,没有任何耗材库存变化
|
||||
|
||||
### Requirement: Batch stock-out for consumables
|
||||
系统 SHALL 支持对多个耗材批量出库。批量出库需统一填写领用人和用途。所有条目在同一事务内处理,任一条目失败则全部回滚。
|
||||
|
||||
#### Scenario: Successful batch stock-out
|
||||
- **WHEN** 用户批量出库 3 种耗材,领用人"张三",数量分别为 2、1、3
|
||||
- **THEN** 3 种耗材库存分别减少,生成 3 条变动记录(source_type=manual_out)
|
||||
|
||||
#### Scenario: Batch stock-out with insufficient stock
|
||||
- **WHEN** 用户批量出库 3 种耗材,其中一种库存不足
|
||||
- **THEN** 全部回滚,提示具体哪个物料库存不足
|
||||
|
||||
### Requirement: Delete protection for stocked consumable
|
||||
系统 SHALL 禁止删除库存量大于 0 的耗材。
|
||||
|
||||
#### Scenario: Delete consumable with stock
|
||||
- **WHEN** 用户尝试删除库存为 5 的耗材
|
||||
- **THEN** 系统拒绝并提示"该物料仍有库存,无法删除"
|
||||
|
||||
#### Scenario: Delete consumable with zero stock
|
||||
- **WHEN** 用户删除库存为 0 的耗材
|
||||
- **THEN** 软删除成功(del_flag=1)
|
||||
|
||||
### Requirement: Consumable stock-out disabled status check
|
||||
出库和入库操作 SHALL 检查物料状态,已停用物料不允许出入库。
|
||||
|
||||
#### Scenario: Stock-out with disabled status
|
||||
- **WHEN** 用户对 status='0' 的耗材执行出库
|
||||
- **THEN** 系统拒绝并提示"物料「XX」已停用,无法出库"
|
||||
|
||||
### Requirement: Row-level locking for concurrent stock operations
|
||||
出入库操作 SHALL 使用 `with_for_update()` 行锁,防止并发操作导致库存数据不一致。
|
||||
|
||||
#### Scenario: Concurrent stock-in
|
||||
- **WHEN** 两个用户同时对同一耗材入库
|
||||
- **THEN** 行锁保证两次操作串行执行,库存结果正确
|
||||
|
||||
### Requirement: Consumable stock log table
|
||||
系统 SHALL 新建 `biz_consumable_stock_log` 变动记录表,字段参照 `biz_material_stock_log` 并增加生产溯源字段:
|
||||
- `material_id` — 耗材 ID
|
||||
- `material_code` / `material_name` — 快照字段
|
||||
- `change_type` — in(入库) / use(使用/出库)
|
||||
- `change_qty` — 变动数量(入库正数,出库负数)
|
||||
- `stock_before` — 变动前库存
|
||||
- `stock_after` — 变动后库存
|
||||
- `source_type` — manual_in / manual_out / step_save
|
||||
- `step_id` / `task_id` / `task_no` — 步骤溯源字段(step_save 时有值)
|
||||
- `receiver` / `purpose` — 领用人/用途(manual_out 时有值)
|
||||
- 公共字段
|
||||
|
||||
#### Scenario: Stock log created on stock-in
|
||||
- **WHEN** 耗材入库 5
|
||||
- **THEN** 变动记录 change_type=in, change_qty=5, source_type=manual_in, stock_before=旧库存, stock_after=新库存
|
||||
@@ -1,80 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Per-row stock log dialog
|
||||
耗材/试剂管理列表每行操作列 SHALL 有一个「变动记录」按钮,点击弹出 Dialog,标题显示物料名称,列表仅展示该物料的变动记录,支持分页。
|
||||
|
||||
#### Scenario: Open stock log for single material
|
||||
- **WHEN** 用户点击耗材A行的「变动记录」按钮
|
||||
- **THEN** 弹出 Dialog,标题为"耗材A — 变动记录",列表按时间倒序展示该耗材的所有变动记录
|
||||
|
||||
#### Scenario: Stock log dialog pagination
|
||||
- **WHEN** 变动记录超过 20 条
|
||||
- **THEN** Dialog 内列表支持分页
|
||||
|
||||
### Requirement: Tab view for all stock logs
|
||||
耗材管理页面和试剂管理页面 SHALL 各自有一个顶部 Tab「全部变动记录」,切换后展示所有耗材(或试剂)的汇总变动记录列表,支持按物料名称/编码、变动类型、时间范围筛选,支持分页。
|
||||
|
||||
#### Scenario: Switch to all stock logs tab
|
||||
- **WHEN** 用户点击耗材管理页面顶部「全部变动记录」Tab
|
||||
- **THEN** 切换到全部变动记录视图,展示所有耗材的变动记录汇总列表
|
||||
|
||||
#### Scenario: Filter by material name
|
||||
- **WHEN** 用户在全部变动记录 Tab 中搜索物料名称"培养皿"
|
||||
- **THEN** 列表仅展示物料名称包含"培养皿"的变动记录
|
||||
|
||||
#### Scenario: Filter by change type
|
||||
- **WHEN** 用户筛选变动类型为"出库"
|
||||
- **THEN** 列表仅展示 change_type=use 的变动记录(含 manual_out 和 step_save)
|
||||
|
||||
#### Scenario: Filter by time range
|
||||
- **WHEN** 用户选择时间范围 2026-01-01 至 2026-03-31
|
||||
- **THEN** 列表仅展示该时间范围内的变动记录
|
||||
|
||||
### Requirement: Stock log display fields
|
||||
变动记录列表(弹窗和 Tab 视图)SHALL 展示以下字段:
|
||||
- 物料编码(material_code)
|
||||
- 物料名称(material_name)
|
||||
- 变动类型(change_type):入库/出库/步骤扣减,以 `<el-tag>` 展示
|
||||
- 变动数量(change_qty):正数绿色,负数红色
|
||||
- 变动前库存(stock_before)
|
||||
- 变动后库存(stock_after)
|
||||
- 来源(source_type):手动入库/手动出库/步骤保存,以 `<el-tag>` 展示
|
||||
- 关联任务(task_no):步骤扣减时展示任务编号
|
||||
- 领用人(receiver):手动出库时展示
|
||||
- 用途(purpose):手动出库时展示
|
||||
- 操作人(create_by_name)
|
||||
- 操作时间(create_time)
|
||||
|
||||
#### Scenario: Manual out log display
|
||||
- **WHEN** 变动记录为手动出库类型
|
||||
- **THEN** 展示领用人、用途、操作人、时间,来源显示"手动出库"
|
||||
|
||||
#### Scenario: Step save log display
|
||||
- **WHEN** 变动记录为步骤保存类型
|
||||
- **THEN** 展示关联任务编号、操作人、时间,来源显示"步骤扣减",不展示领用人/用途
|
||||
|
||||
### Requirement: Stock log API endpoints
|
||||
后端 SHALL 提供以下变动记录 API:
|
||||
- `GET /web/admin/consumables/{id}/stock-logs` — 单个耗材变动记录(分页)
|
||||
- `GET /web/admin/consumables/stock-logs` — 全部耗材变动记录(分页,支持筛选)
|
||||
- `GET /web/admin/reagents/{id}/stock-logs` — 单个试剂变动记录(分页)
|
||||
- `GET /web/admin/reagents/stock-logs` — 全部试剂变动记录(分页,支持筛选)
|
||||
|
||||
#### Scenario: Single material stock log API
|
||||
- **WHEN** 前端请求 `GET /web/admin/consumables/{id}/stock-logs?page=1&pageSize=20`
|
||||
- **THEN** 返回该耗材的变动记录列表和总数
|
||||
|
||||
#### Scenario: All stock logs API with filters
|
||||
- **WHEN** 前端请求 `GET /web/admin/consumables/stock-logs?keyword=培养皿&changeType=out&startTime=2026-01-01&endTime=2026-03-31`
|
||||
- **THEN** 返回筛选后的变动记录列表和总数
|
||||
|
||||
### Requirement: Status field display in list
|
||||
耗材/试剂管理列表的状态列 SHALL 使用 `<el-tag>` 展示:启用显示 success 类型,停用显示 info 类型。
|
||||
|
||||
#### Scenario: Enabled status display
|
||||
- **WHEN** 耗材状态为启用(status='1')
|
||||
- **THEN** 列表显示绿色 `<el-tag type="success" size="small">` 文本"启用"
|
||||
|
||||
#### Scenario: Disabled status display
|
||||
- **WHEN** 耗材状态为停用(status='0')
|
||||
- **THEN** 列表显示灰色 `<el-tag type="info" size="small">` 文本"停用"
|
||||
-76
@@ -1,76 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Step save auto stock deduction
|
||||
系统 SHALL 在生产任务步骤保存耗材/试剂时,根据 `actual_usage` 字段自动扣减对应耗材/试剂的库存。变动记录的 `source_type` SHALL 为 `step_save`。
|
||||
|
||||
#### Scenario: First save with actual usage
|
||||
- **WHEN** 用户首次保存步骤,耗材A 的 actual_usage=2,耗材B 的 actual_usage=3
|
||||
- **THEN** 耗材A 库存扣减 2,耗材B 库存扣减 3,生成 2 条变动记录 source_type=step_save
|
||||
|
||||
#### Scenario: Save with empty actual_usage
|
||||
- **WHEN** 用户保存步骤,某耗材的 actual_usage 为空或为 0
|
||||
- **THEN** 该耗材不扣减库存,不生成变动记录
|
||||
|
||||
#### Scenario: Save with non-numeric actual_usage
|
||||
- **WHEN** 用户保存步骤,某耗材的 actual_usage 为非数字字符串
|
||||
- **THEN** 系统跳过该条目,仅处理 actual_usage 为有效正数的条目
|
||||
|
||||
### Requirement: Step save diff settlement via full revert and re-deduct
|
||||
系统 SHALL 采用全量回退+重算模式处理步骤保存的库存变动:
|
||||
1. 查出该步骤此前所有 source_type=step_save 的变动记录
|
||||
2. 按变动记录逐条回退库存(加回扣减量),软删变动记录
|
||||
3. 遍历新的步骤耗材/试剂列表,按 actual_usage 扣减库存,生成新变动记录
|
||||
|
||||
#### Scenario: Modify usage upward
|
||||
- **WHEN** 步骤首次保存耗材A actual_usage=2,第二次保存改为 actual_usage=3
|
||||
- **THEN** 回退 2(库存+2),重新扣减 3(库存-3),净效果库存-1
|
||||
|
||||
#### Scenario: Modify usage downward
|
||||
- **WHEN** 步骤首次保存耗材A actual_usage=5,第二次保存改为 actual_usage=2
|
||||
- **THEN** 回退 5(库存+5),重新扣减 2(库存-2),净效果库存+3
|
||||
|
||||
#### Scenario: Remove material from step
|
||||
- **WHEN** 步骤首次保存耗材A actual_usage=3 和耗材B actual_usage=2,第二次保存仅保留耗材B actual_usage=2
|
||||
- **THEN** 回退耗材A 的 3 和耗材B 的 2,重新扣减耗材B 的 2。净效果:耗材A 库存+3,耗材B 不变
|
||||
|
||||
#### Scenario: Add new material to step
|
||||
- **WHEN** 步骤首次保存耗材A actual_usage=2,第二次保存新增耗材C actual_usage=4
|
||||
- **THEN** 回退耗材A 的 2,重新扣减耗材A 的 2 和耗材C 的 4。净效果:耗材A 不变,耗材C 库存-4
|
||||
|
||||
### Requirement: Step save stock deduction uses row-level locking
|
||||
diff 结算过程中 SHALL 使用 `with_for_update()` 行锁锁定涉及的耗材/试剂行。
|
||||
|
||||
#### Scenario: Concurrent step saves on same material
|
||||
- **WHEN** 两个步骤同时保存,都涉及耗材A
|
||||
- **THEN** 行锁保证串行执行,库存变动正确
|
||||
|
||||
### Requirement: Step save stock deduction in same transaction
|
||||
diff 结算 SHALL 在步骤耗材/试剂保存的同一数据库事务中执行。库存扣减失败时,步骤保存也回滚。
|
||||
|
||||
#### Scenario: Stock insufficient during step save
|
||||
- **WHEN** 用户保存步骤,耗材A actual_usage=10,但库存仅 3
|
||||
- **THEN** 整个步骤保存回滚,提示"物料「耗材A」库存不足,当前库存 3,需使用 10"
|
||||
|
||||
### Requirement: Stock deduction traceability
|
||||
每条 step_save 类型的变动记录 SHALL 包含以下溯源字段:
|
||||
- `step_id` — 生产任务步骤 ID
|
||||
- `task_id` — 生产任务 ID
|
||||
- `task_no` — 生产任务编号快照
|
||||
|
||||
#### Scenario: Stock log shows task info
|
||||
- **WHEN** 步骤保存触发库存扣减
|
||||
- **THEN** 变动记录包含 step_id、task_id、task_no,可追溯至具体任务和步骤
|
||||
|
||||
### Requirement: Deduction hooks in replace_step_reagents and replace_step_consumables
|
||||
库存 diff 结算 SHALL 在 `replace_step_reagents()` 和 `replace_step_consumables()` 函数中执行,调用时机为软删旧子记录之后、插入新子记录之前。
|
||||
|
||||
#### Scenario: replace_step_consumables triggers deduction
|
||||
- **WHEN** API `PUT /production-tasks/{task_id}/steps/{step_id}/consumables` 被调用
|
||||
- **THEN** 系统在替换步骤耗材的同时执行库存 diff 结算
|
||||
|
||||
### Requirement: Skip deduction for materials not in catalog
|
||||
如果步骤中的耗材编码或试剂编码在 `biz_consumable` / `biz_reagent` 中不存在(可能是手工录入的自定义物料),SHALL 跳过该条目的库存扣减,不报错。
|
||||
|
||||
#### Scenario: Custom material code in step
|
||||
- **WHEN** 步骤保存包含一个 consumable_code 不在 biz_consumable 表中的条目
|
||||
- **THEN** 系统跳过该条目的库存扣减,其他正常条目正常扣减
|
||||
@@ -1,75 +0,0 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Reagent inventory fields
|
||||
系统 SHALL 在 `biz_reagent` 表上新增以下库存字段:
|
||||
- `stock_qty` DECIMAL(18,4) NOT NULL DEFAULT 0 — 当前库存量
|
||||
- `warning_qty` DECIMAL(18,4) NOT NULL DEFAULT 0 — 预警库存量
|
||||
- `status` CHAR(1) NOT NULL DEFAULT '1' — 启用/停用状态(1=启用,0=停用)
|
||||
|
||||
后端 SQLAlchemy Model `BizReagent` SHALL 同步新增对应字段。前端列表和表单 SHALL 展示这些字段。
|
||||
|
||||
#### Scenario: Existing reagents have zero stock after migration
|
||||
- **WHEN** 数据库迁移完成,已有试剂记录存在
|
||||
- **THEN** 所有已有试剂的 stock_qty 为 0,warning_qty 为 0,status 为 '1'
|
||||
|
||||
#### Scenario: Reagent list shows stock info
|
||||
- **WHEN** 用户访问试剂管理列表
|
||||
- **THEN** 列表显示当前库存量、预警库存量、状态列
|
||||
|
||||
### Requirement: Manual stock-in for reagent
|
||||
系统 SHALL 支持对单个试剂进行手动入库操作。入库数量必须大于 0。入库后 stock_qty 增加,同时生成一条变动记录(source_type=manual_in,change_type=in)。
|
||||
|
||||
#### Scenario: Successful stock-in
|
||||
- **WHEN** 用户对库存为 10 的试剂入库 5
|
||||
- **THEN** 试剂 stock_qty 变为 15,生成变动记录 change_qty=5, stock_after=15, source_type=manual_in
|
||||
|
||||
### Requirement: Manual stock-out for reagent
|
||||
系统 SHALL 支持对单个试剂进行手动出库操作。出库数量必须大于 0,且不能超过当前库存。出库必须填写领用人。出库后 stock_qty 减少,同时生成一条变动记录(source_type=manual_out,change_type=use,change_qty 为负数)。
|
||||
|
||||
#### Scenario: Successful stock-out
|
||||
- **WHEN** 用户对库存为 10 的试剂出库 3,领用人"李四"
|
||||
- **THEN** 试剂 stock_qty 变为 7,生成变动记录 change_qty=-3, stock_after=7, source_type=manual_out, receiver=李四
|
||||
|
||||
#### Scenario: Stock-out exceeds inventory
|
||||
- **WHEN** 用户对库存为 2 的试剂出库 5
|
||||
- **THEN** 系统拒绝并提示库存不足
|
||||
|
||||
### Requirement: Batch stock-in for reagents
|
||||
系统 SHALL 支持对多个试剂批量入库。所有条目在同一事务内处理,任一条目失败则全部回滚。
|
||||
|
||||
#### Scenario: Successful batch stock-in
|
||||
- **WHEN** 用户批量入库 3 种试剂,数量分别为 5、10、2
|
||||
- **THEN** 3 种试剂库存分别增加,生成 3 条变动记录,全部在同一事务内
|
||||
|
||||
### Requirement: Batch stock-out for reagents
|
||||
系统 SHALL 支持对多个试剂批量出库。批量出库需统一填写领用人和用途。所有条目在同一事务内处理,任一条目失败则全部回滚。
|
||||
|
||||
#### Scenario: Successful batch stock-out
|
||||
- **WHEN** 用户批量出库 3 种试剂,领用人"李四"
|
||||
- **THEN** 3 种试剂库存分别减少,生成 3 条变动记录
|
||||
|
||||
### Requirement: Delete protection for stocked reagent
|
||||
系统 SHALL 禁止删除库存量大于 0 的试剂。
|
||||
|
||||
#### Scenario: Delete reagent with stock
|
||||
- **WHEN** 用户尝试删除库存为 5 的试剂
|
||||
- **THEN** 系统拒绝并提示"该物料仍有库存,无法删除"
|
||||
|
||||
### Requirement: Row-level locking for reagent stock operations
|
||||
出入库操作 SHALL 使用 `with_for_update()` 行锁,防止并发操作导致库存数据不一致。
|
||||
|
||||
### Requirement: Reagent stock log table
|
||||
系统 SHALL 新建 `biz_reagent_stock_log` 变动记录表,字段结构与 `biz_consumable_stock_log` 一致:
|
||||
- `material_id` — 试剂 ID
|
||||
- `material_code` / `material_name` — 快照字段
|
||||
- `change_type` — in(入库) / use(使用/出库)
|
||||
- `change_qty` — 变动数量(入库正数,出库负数)
|
||||
- `stock_before` / `stock_after` — 变动前后库存
|
||||
- `source_type` — manual_in / manual_out / step_save
|
||||
- `step_id` / `task_id` / `task_no` — 步骤溯源字段
|
||||
- `receiver` / `purpose` — 领用人/用途
|
||||
- 公共字段
|
||||
|
||||
#### Scenario: Stock log created on reagent stock-in
|
||||
- **WHEN** 试剂入库 5
|
||||
- **THEN** 变动记录 change_type=in, change_qty=5, source_type=manual_in, stock_before=旧库存, stock_after=新库存
|
||||
@@ -1,56 +0,0 @@
|
||||
## 1. Database Migration
|
||||
|
||||
- [x] 1.1 编写 SQL 迁移脚本 `docs/sql/production_material_inventory.sql`:ALTER TABLE `biz_consumable` 新增 stock_qty/warning_qty/status 字段,ALTER TABLE `biz_reagent` 新增同上字段,CREATE TABLE `biz_consumable_stock_log`,CREATE TABLE `biz_reagent_stock_log`
|
||||
- [ ] 1.2 在开发数据库执行迁移脚本,验证字段和表创建成功
|
||||
|
||||
## 2. Backend Model & CRUD — Consumable
|
||||
|
||||
- [x] 2.1 在 `backend/app/models/models.py` 中 `BizConsumable` 新增 stock_qty、warning_qty、status 字段;新建 `BizConsumableStockLog` Model(参照 `BizQcMaterialUsage`,增加 step_id/task_id/task_no 字段)
|
||||
- [x] 2.2 扩展 `backend/app/crud/consumable.py`:修改 `_row_to_dict` 返回库存字段,新增 `stock_in()`、`stock_out()`、`batch_stock_in()`、`batch_stock_out()` 函数(参照 `crud/qc_material.py`),修改 `soft_delete` 增加库存检查
|
||||
- [x] 2.3 新建 `backend/app/crud/consumable_stock_log.py`:`list_stock_logs()` 函数(参照 `crud/qc_material_usage.py` 的 `list_usages()`),支持按 material_id、change_type、时间范围筛选
|
||||
|
||||
## 3. Backend Model & CRUD — Reagent
|
||||
|
||||
- [x] 3.1 在 `backend/app/models/models.py` 中 `BizReagent` 新增 stock_qty、warning_qty、status 字段;新建 `BizReagentStockLog` Model(同 BizConsumableStockLog)
|
||||
- [x] 3.2 扩展 `backend/app/crud/reagent.py`:修改 `_row_to_dict` 返回库存字段,新增 `stock_in()`、`stock_out()`、`batch_stock_in()`、`batch_stock_out()` 函数,修改 `soft_delete` 增加库存检查
|
||||
- [x] 3.3 新建 `backend/app/crud/reagent_stock_log.py`:`list_stock_logs()` 函数,支持筛选
|
||||
|
||||
## 4. Backend API — Stock Operations & Log Endpoints
|
||||
|
||||
- [x] 4.1 在 `backend/app/api/production.py` 新增耗材出入库 API:`POST /consumables/{id}/stock-in`、`POST /consumables/{id}/stock-out`、`POST /consumables/batch-stock-in`、`POST /consumables/batch-stock-out`
|
||||
- [x] 4.2 在 `backend/app/api/production.py` 新增耗材变动记录 API:`GET /consumables/{id}/stock-logs`、`GET /consumables/stock-logs`
|
||||
- [x] 4.3 在 `backend/app/api/production.py` 新增试剂出入库 API:`POST /reagents/{id}/stock-in`、`POST /reagents/{id}/stock-out`、`POST /reagents/batch-stock-in`、`POST /reagents/batch-stock-out`
|
||||
- [x] 4.4 在 `backend/app/api/production.py` 新增试剂变动记录 API:`GET /reagents/{id}/stock-logs`、`GET /reagents/stock-logs`
|
||||
|
||||
## 5. Backend — Step Save Auto Deduction
|
||||
|
||||
- [x] 5.1 在 `backend/app/crud/consumable_stock_log.py` 新增 `revert_step_stock_changes()` 函数(参照 `qc_material_usage.py` 的 `revert_task_material_usages`,按 step_id + source_type=step_save 回退库存)
|
||||
- [x] 5.2 在 `backend/app/crud/consumable_stock_log.py` 新增 `deduct_for_step()` 函数(参照 `qc_material_usage.py` 的 `deduct_for_task`,按 actual_usage 扣减库存)
|
||||
- [x] 5.3 在 `backend/app/crud/reagent_stock_log.py` 新增 `revert_step_stock_changes()` 和 `deduct_for_step()` 函数(同上,试剂版)
|
||||
- [x] 5.4 修改 `backend/app/crud/production_task.py` 的 `replace_step_reagents()` 函数:在 soft delete 旧记录后、insert 新记录后,调用 `revert_step_stock_changes()` + `deduct_for_step()`
|
||||
- [x] 5.5 修改 `backend/app/crud/production_task.py` 的 `replace_step_consumables()` 函数:同上逻辑
|
||||
- [x] 5.6 修改 `backend/app/api/production.py` 中 `replace_task_step_reagents` 和 `replace_task_step_consumables` API,传入 task_id/task_no 以支持溯源
|
||||
|
||||
## 6. Frontend — Consumable Page Enhancement
|
||||
|
||||
- [x] 6.1 扩展 `web-admin/src/api/production.ts`:新增耗材出入库 API 调用函数(stockIn、stockOut、batchStockIn、batchStockOut、getStockLogs、getAllStockLogs)
|
||||
- [x] 6.2 修改 `web-admin/src/views/production/consumable/index.vue`:列表新增库存量、预警量、状态列,表单新增库存字段
|
||||
- [x] 6.3 在耗材页面新增操作按钮:单个入库、单个出库弹窗(参照质检物料 `qc-material/index.vue`)
|
||||
- [x] 6.4 在耗材页面新增批量入库、批量出库弹窗(参照质检物料批量操作)
|
||||
- [x] 6.5 在耗材页面行操作列新增「变动记录」按钮 → Dialog 弹窗,展示单物料变动记录列表
|
||||
- [x] 6.6 在耗材页面新增顶部 Tab「全部变动记录」视图,展示所有耗材汇总变动记录,支持筛选和分页
|
||||
|
||||
## 7. Frontend — Reagent Page Enhancement
|
||||
|
||||
- [x] 7.1 扩展 `web-admin/src/api/production.ts`:新增试剂量出入库 API 调用函数
|
||||
- [x] 7.2 修改 `web-admin/src/views/production/reagent/index.vue`:列表新增库存量、预警量、状态列,表单新增库存字段
|
||||
- [x] 7.3 在试剂页面新增操作按钮:单个入库、单个出库弹窗
|
||||
- [x] 7.4 在试剂页面新增批量入库、批量出库弹窗
|
||||
- [x] 7.5 在试剂页面行操作列新增「变动记录」按钮 → Dialog 弹窗
|
||||
- [x] 7.6 在试剂页面新增顶部 Tab「全部变动记录」视图
|
||||
|
||||
## 8. Verification
|
||||
|
||||
- [ ] 8.1 后端验证:启动后端服务,通过 Swagger 测试所有新增 API(CRUD + 出入库 + 变动记录)
|
||||
- [ ] 8.2 前端验证:启动前端开发服务,手动测试耗材/试剂页面的所有新增功能(入库、出库、批量操作、变动记录弹窗、变动记录 Tab)
|
||||
- [ ] 8.3 步骤扣减验证:创建生产任务,执行步骤保存,验证耗材/试剂库存自动扣减,修改用量后验证 diff 结算正确性
|
||||
@@ -1,9 +1,10 @@
|
||||
## Context
|
||||
|
||||
- 业务与数据规则来源:`docs/中科兴皖需求V0.3.md`(含菜单、表模型、§3 技术要求、§2.1.11 工作流、§2.1.5 权限等)。
|
||||
- 业务与数据规则来源:`工程规范`(含菜单、表模型、§3 技术要求、§2.1.11 工作流、§2.1.5 权限等)。
|
||||
- Web 端视觉与交互权威:`docs/web-admin-ui-spec-fresh-mint.md` 及其中引用的 `docs/fresh-mint-green.html`。
|
||||
- 小程序端权威:`docs/miniprogram-ui-spec-sanqiang.md` 及其中列出的 `mobile-ui/sanqiang-*.html`。
|
||||
- 工程运行与目录约定:`AGENTS.md`、`.cursorrules`、后端 `app/` 与前端 `web-admin/`、`miniprogram/` 现状。
|
||||
- 多系统边界与 DDL 索引:`docs/sql/dibang.sql`(地磅)、`docs/sql/shanxia2.0.sql`(本仓库门户)、`docs/sql/sx.sql`(CRM);CRM 代码在并列仓库 `shanxia/crm/`(见 `ecosystem-landscape` spec)。
|
||||
|
||||
本变更的 `specs/*/spec.md` 为**可测试的规范摘要**;凡涉及色值、类名、组件级布局的细则,**不以本 design 重复展开**,而以对应 Markdown/HTML 为准,避免双源漂移。
|
||||
|
||||
@@ -11,7 +12,7 @@
|
||||
|
||||
**Goals:**
|
||||
|
||||
- 用 OpenSpec 将「架构 / 接口 / UI / 编码 / 库表 / 工作流 / 权限」七类约束写成可追溯的 SHALL 与场景。
|
||||
- 用 OpenSpec 将「架构 / 接口 / UI / 编码 / 库表 / 工作流 / 权限 / 多系统生态」八类约束写成可追溯的 SHALL 与场景。
|
||||
- 明确「需求 §3」与「两份 UI 规范」之间的分工:前者定数据与租户/API 行为,后者定界面 Token 与页面骨架。
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
## Why
|
||||
|
||||
中科兴皖一体化门户的技术与体验约束分散在《中科兴皖需求 V0.3》、Web 管理端与小程序 UI 规范及仓库 `AGENTS.md` / `.cursorrules` 中,缺少一份可被评审、版本化且与实现检查对齐的**单一事实来源(OpenSpec)**。本变更将上述材料提炼为可测试的 SHALL 级需求与架构/设计说明,便于研发、测试与评审统一口径。
|
||||
山峡化工的技术与体验约束分散在《shanxia2.0需求 V0.3》、Web 管理端与小程序 UI 规范及仓库 `AGENTS.md` / `.cursorrules` 中,缺少一份可被评审、版本化且与实现检查对齐的**单一事实来源(OpenSpec)**。本变更将上述材料提炼为可测试的 SHALL 级需求与架构/设计说明,便于研发、测试与评审统一口径。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 新增 OpenSpec 变更 `zkxw-engineering-standards`,包含提案、设计说明、**七项能力规范**及落地任务清单。
|
||||
- 新增 OpenSpec 变更 `zkxw-engineering-standards`,包含提案、设计说明、**八项能力规范**及落地任务清单。
|
||||
- **不修改**业务代码;规范正文以需求 V0.3 第 3 节「技术要求」为硬约束,UI 细节以两份 UI 规范文档为权威展开(本变更中的 UI 条目为**跨端统一原则与引用约束**,像素级 Token 仍以原文档为准)。
|
||||
- 工作流/审批与权限条目直接对齐需求文档 **§2.1.11 流程管理** 与 **§2.1.5 角色管理** 等章节。
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
- `database-conventions`:MySQL 5.7、公共字段、软删除、字段顺序等数据库层规范。
|
||||
- `workflow-conventions`:自研工作流的目标能力、配置、运行时与待办/已办中心(对齐需求 §2.1.11)。
|
||||
- `permission-conventions`:角色-菜单-数据权限模型及多角色权限合并规则(对齐需求 §2.1.5 等)。
|
||||
- `ecosystem-landscape`:多系统 SQL 快照索引(`dibang.sql` / `shanxia2.0.sql` / `sx.sql`)及山峡 CRM 独立仓库路径(`shanxia/crm/backend`、`shanxia/crm/web`)。
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
### Requirement: 租户隔离
|
||||
|
||||
所有面向业务数据的查询接口 SHALL 仅返回 `tenant_no` 等于当前登录用户租户编号的数据;所有写入或更新类接口 SHALL 将目标业务行的 `tenant_no` 设置为当前登录用户的 `tenant_no`(与《中科兴皖需求 V0.3》§3 一致)。
|
||||
所有面向业务数据的查询接口 SHALL 仅返回 `tenant_no` 等于当前登录用户租户编号的数据;所有写入或更新类接口 SHALL 将目标业务行的 `tenant_no` 设置为当前登录用户的 `tenant_no`(与《shanxia2.0需求 V0.3》§3 一致)。
|
||||
|
||||
#### Scenario: 列表查询
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
### Requirement: 仓库采用前后端分离的一体化门户形态
|
||||
|
||||
中科兴皖一体化门户 SHALL 以「Python 后端 + Web 管理端 + 小程序端」的形态组织代码与部署单元;业务域(细胞存储、中试、系统管理等)共享同一后端与租户模型,除非需求文档明确声明独立子系统。
|
||||
山峡化工 SHALL 以「Python 后端 + Web 管理端 + 小程序端」的形态组织代码与部署单元;业务域(细胞存储、中试、系统管理等)共享同一后端与租户模型,除非需求文档明确声明独立子系统。
|
||||
|
||||
#### Scenario: 新人识别工程边界
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
### Requirement: 技术栈与需求文档 §3 对齐
|
||||
|
||||
系统 SHALL 使用 MySQL 5.7 作为关系型数据库;后端 SHALL 使用 Python 实现;Web 管理端 SHALL 基于 Vue 技术栈在精简后的管理端模板工程上扩展;小程序 SHALL 基于 uni-app、Vue 3 与 Vant 体系实现业务界面(与《中科兴皖需求 V0.3》§3 及当前 `miniprogram` 工程一致或可文档化迁移)。
|
||||
系统 SHALL 使用 MySQL 5.7 作为关系型数据库;后端 SHALL 使用 Python 实现;Web 管理端 SHALL 基于 Vue 技术栈在精简后的管理端模板工程上扩展;小程序 SHALL 基于 uni-app、Vue 3 与 Vant 体系实现业务界面(与《shanxia2.0需求 V0.3》§3 及当前 `miniprogram` 工程一致或可文档化迁移)。
|
||||
|
||||
#### Scenario: 技术选型评审
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
### Requirement: 权威文档索引
|
||||
|
||||
实现类变更 SHALL 将 `docs/中科兴皖需求V0.3.md`、`docs/web-admin-ui-spec-fresh-mint.md`、`docs/miniprogram-ui-spec-sanqiang.md` 及 `AGENTS.md` 视为架构与规范的索引入口;OpenSpec 变更 SHALL 在 `proposal.md` / `design.md` 中保持对上述路径的引用。
|
||||
实现类变更 SHALL 将 `工程规范`、`docs/web-admin-ui-spec-fresh-mint.md`、`docs/miniprogram-ui-spec-sanqiang.md` 及 `AGENTS.md` 视为架构与规范的索引入口;多系统 SQL 与 CRM/地磅边界 SHALL 以 `ecosystem-landscape` spec 为准;OpenSpec 变更 SHALL 在 `proposal.md` / `design.md` 中保持对上述路径的引用。
|
||||
|
||||
#### Scenario: UI 相关 PR 描述
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
### Requirement: MySQL 版本
|
||||
|
||||
生产与标准开发环境的关系型数据库 SHALL 使用 MySQL 5.7(与《中科兴皖需求 V0.3》§3 一致)。
|
||||
生产与标准开发环境的关系型数据库 SHALL 使用 MySQL 5.7(与《shanxia2.0需求 V0.3》§3 一致)。
|
||||
|
||||
#### Scenario: 新环境搭建文档
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 多系统 SQL 模型权威文件索引
|
||||
|
||||
山峡相关产品线 SHALL 将下列 `docs/sql/` 导出文件视为各系统数据库模型的**权威 DDL 快照**(Navicat 导出,MySQL 5.7);实现或评审时 SHALL 以对应文件为准,不得与 `shanxia2.0` 本仓库后端模型混用。
|
||||
|
||||
| 系统 | SQL 快照路径 | 典型库名(导出元数据) | 表命名特征 | 对应工程 |
|
||||
|------|----------------|------------------------|------------|----------|
|
||||
| 地磅系统 | `docs/sql/dibang.sql` | `dibang-test` | `cargos`、`companies`、`weighing_slips`、`inbound_outbound` 等 | 独立系统(非本仓库 `backend/`) |
|
||||
| 山峡一体化门户 | `docs/sql/shanxia2.0.sql` | `shanxia2.0` | `sys_*`、`biz_*`、`wf_*`;公共字段含 `tenant_no`、`del_flag` | 本仓库 `backend/` + `web-admin/` + `miniprogram/` |
|
||||
| 山峡 CRM 系统 | `docs/sql/sx.sql` | `sx` | `crm_*`(线索/客户/商机/合同/回款等);同库可含 `bx_*` 报销子域表 | 独立仓库 `shanxia/crm/`(见下条) |
|
||||
|
||||
#### Scenario: 新人定位门户库表
|
||||
|
||||
- **WHEN** 在 `shanxia2.0` 仓库内开发细胞存储、系统管理、工作流等门户能力
|
||||
- **THEN** 查阅与变更 DDL SHALL 使用 `docs/sql/shanxia2.0.sql`,且 ORM/迁移与 `database-conventions` 公共字段约定一致
|
||||
|
||||
#### Scenario: 新人定位 CRM 库表
|
||||
|
||||
- **WHEN** 开发线索、客户、合同、回款等 CRM 业务
|
||||
- **THEN** 查阅 DDL SHALL 使用 `docs/sql/sx.sql`,代码变更 SHALL 在 `shanxia` 仓库的 `crm/` 工程内进行,而非 `shanxia2.0/backend/`
|
||||
|
||||
#### Scenario: 新人定位地磅库表
|
||||
|
||||
- **WHEN** 开发地磅、称重单、进出库等业务
|
||||
- **THEN** 查阅 DDL SHALL 使用 `docs/sql/dibang.sql`,且 SHALL NOT 假定表结构与本仓库 `shanxia2.0.sql` 相同
|
||||
|
||||
### Requirement: 山峡 CRM 工程路径与栈
|
||||
|
||||
山峡 CRM 系统 SHALL 视为与 `shanxia2.0` **分离的 Git 仓库与部署单元**;默认工作区路径为同级目录 `shanxia/crm/`(相对 monorepo 工作区根:与 `shanxia2.0` 并列的 `shanxia` 仓库)。
|
||||
|
||||
| 层级 | 路径(相对 `shanxia` 仓库根) | 技术栈 |
|
||||
|------|-------------------------------|--------|
|
||||
| 后端 | `crm/backend/` | Java 17、Spring Boot 3.4、RuoYi-Vue-Plus、MyBatis-Plus、Sa-Token |
|
||||
| Web 管理端 | `crm/web/` | Vue 3、TypeScript、Element Plus、Vite |
|
||||
|
||||
#### Scenario: Agent 选择正确后端入口
|
||||
|
||||
- **WHEN** 任务描述涉及 CRM、线索、客户、合同、回款或 `crm_*` 表
|
||||
- **THEN** Agent SHALL 在 `shanxia/crm/backend/` 下查找与修改 Java 代码,API 前缀与 RuoYi 约定(如 `/prod-api`)以该工程为准
|
||||
|
||||
#### Scenario: Agent 选择正确前端入口
|
||||
|
||||
- **WHEN** 任务描述涉及 CRM 管理端页面或 `crm/web` 路由
|
||||
- **THEN** Agent SHALL 在 `shanxia/crm/web/` 下查找与修改 Vue 代码,UI 规范以该仓库 `.cursorrules` / `AGENTS.md` 为准(非 `shanxia2.0` Fresh Mint 规范)
|
||||
|
||||
### Requirement: 本仓库与周边系统的边界
|
||||
|
||||
`shanxia2.0` 仓库 SHALL 仅承载一体化门户(Python FastAPI + `web-admin` + `miniprogram`);CRM 与地磅 SHALL NOT 默认在本仓库 `backend/` 或 `web-admin/` 内实现,除非 OpenSpec 功能变更明确声明集成或迁移。
|
||||
|
||||
#### Scenario: 跨系统需求评审
|
||||
|
||||
- **WHEN** 需求同时涉及门户与 CRM 或地磅
|
||||
- **THEN** 设计说明 SHALL 分别标明所影响的 SQL 快照路径与代码仓库路径,并避免单一 PR 无说明地混改多库 DDL
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
### Requirement: 角色与菜单授权
|
||||
|
||||
系统 SHALL 通过 `sys_role`、`sys_role_menu` 等模型维护角色与菜单的关联;角色管理界面 SHALL 支持为角色配置可访问菜单树,且勾选子菜单时 SHALL 自动包含必要父菜单(与《中科兴皖需求 V0.3》§2.1.5 描述一致)。
|
||||
系统 SHALL 通过 `sys_role`、`sys_role_menu` 等模型维护角色与菜单的关联;角色管理界面 SHALL 支持为角色配置可访问菜单树,且勾选子菜单时 SHALL 自动包含必要父菜单(与《shanxia2.0需求 V0.3》§2.1.5 描述一致)。
|
||||
|
||||
#### Scenario: 勾选子菜单
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
### Requirement: 工作流由后端 Python 实现
|
||||
|
||||
中科兴皖一体化门户的工作流引擎 SHALL 使用 Python 在后端实现为**独立、可配置**的审批/流程子系统,目标能力对标简易低代码流程(与《中科兴皖需求 V0.3》§2.1.11 一致)。
|
||||
山峡化工的工作流引擎 SHALL 使用 Python 在后端实现为**独立、可配置**的审批/流程子系统,目标能力对标简易低代码流程(与《shanxia2.0需求 V0.3》§2.1.11 一致)。
|
||||
|
||||
#### Scenario: 技术栈检查
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
## 1. 评审与采纳
|
||||
|
||||
- [ ] 1.1 产品/研发共同评审 `proposal.md` 中的七项能力划分是否与中科兴皖项目阶段匹配
|
||||
- [ ] 1.2 对照 `docs/中科兴皖需求V0.3.md` §3 校验 `database-conventions` 与 `api-conventions` 中的 SHALL 条目
|
||||
- [ ] 1.1 产品/研发共同评审 `proposal.md` 中的八项能力划分是否与山峡化工项目阶段匹配
|
||||
- [ ] 1.2 对照 `工程规范` §3 校验 `database-conventions` 与 `api-conventions` 中的 SHALL 条目
|
||||
- [ ] 1.3 对照 `docs/web-admin-ui-spec-fresh-mint.md` 与 `docs/miniprogram-ui-spec-sanqiang.md` 校验 `ui-conventions` 是否覆盖团队最关心的门禁(色板、树路径、弹窗)
|
||||
|
||||
## 2. 与仓库治理对齐
|
||||
|
||||
- [ ] 2.1 可选:在 `openspec/config.yaml` 增加 `context` 字段,指向本变更目录或 `openspec/specs/` 归档后的基线说明
|
||||
- [x] 2.1 在 `openspec/config.yaml` 的 `context` 中摘要本变更及 `ecosystem-landscape`(多系统 SQL 与 CRM 路径);OpenCode 见 `.opencode/ecosystem-landscape.md`
|
||||
- [ ] 2.2 在 PR 模板或评审清单中增加一条:涉及租户/软删/排序的改动必须对照 `api-conventions` 与 `database-conventions`
|
||||
- [ ] 2.3 工作流专项启动前,将 `workflow-conventions` 中 SQL 审批人、版本迁移等「Open Questions」拆成独立变更
|
||||
|
||||
|
||||
@@ -3,9 +3,14 @@ schema: spec-driven
|
||||
# Project context (optional)
|
||||
# This is shown to AI when creating artifacts.
|
||||
context: |
|
||||
zkxw(陇耘鲜达 / 中科兴皖一体化门户):FastAPI 后端 + Vue3 web-admin + uni-app 小程序。
|
||||
工程规范摘要见 OpenSpec 变更:openspec/changes/zkxw-engineering-standards/(含 architecture、api、ui、coding、database、workflow、permission 七类 spec)。
|
||||
需求与 UI 权威文档:docs/中科兴皖需求V0.3.md、docs/web-admin-ui-spec-fresh-mint.md、docs/miniprogram-ui-spec-sanqiang.md;仓库约定见 AGENTS.md、.cursorrules。
|
||||
shanxia2.0(山峡化工一体化门户):FastAPI 后端 + Vue3 web-admin + uni-app 小程序。
|
||||
工程规范摘要见 OpenSpec 变更:openspec/changes/zkxw-engineering-standards/(含 architecture、api、ui、coding、database、workflow、permission、ecosystem-landscape 八类 spec)。
|
||||
需求与 UI 权威文档:docs/web-admin-ui-spec-fresh-mint.md、docs/miniprogram-ui-spec-sanqiang.md;仓库约定见 AGENTS.md、.cursorrules。
|
||||
|
||||
多系统现状(详见 ecosystem-landscape/spec.md):
|
||||
- docs/sql/shanxia2.0.sql — 本仓库门户库模型(sys_*/biz_*/wf_*)
|
||||
- docs/sql/sx.sql — 山峡 CRM 库模型(crm_* 等);代码在并列仓库 shanxia/crm/(backend=Java,web=Vue3)
|
||||
- docs/sql/dibang.sql — 地磅系统库模型(独立系统)
|
||||
|
||||
# Per-artifact rules (optional)
|
||||
# Add custom rules for specific artifacts.
|
||||
|
||||
Reference in new issue
Block a user