ETest-Vue-FastAPI/.kiro/specs/sample-to-workorder/design.md

374 lines
10 KiB
Markdown
Raw Normal View History

2026-01-07 01:10:51 +08:00
# Design Document
## Overview
本设计文档描述了从样品库直接生成测试工单的功能实现。该功能将简化原有的"订单→产品→工单"流程,改为"样品→工单"的直接流程。
核心变化:
- 前端:在样品管理页面添加"生成工单"功能
- 后端创建新的API接口直接从样品信息生成工单
- 数据关联工单的test_eut_id字段将直接关联warehouse_sample表的sample_id
## Architecture
### 系统架构
```
前端层 (Vue.js)
└── 样品管理页面 (warehouse/sample/index.vue)
├── 样品列表展示
├── 样品选择(多选)
└── 生成工单对话框
├── 测试流程选择
├── 工单名称输入
└── 备注输入
API层 (FastAPI)
└── 样品工单控制器 (warehouse_sample_controller.py)
└── POST /warehouse/sample/generate_work_orders
├── 接收样品ID列表
├── 接收测试流程ID
└── 返回生成结果
服务层 (Service)
└── 样品工单服务 (warehouse_sample_service.py)
└── generate_work_orders_from_samples()
├── 验证样品状态
├── 获取测试流程配置
├── 为每个样品创建工单
└── 更新样品状态
数据层 (DAO)
└── 工单数据访问 (test_work_order_dao.py)
└── 批量创建工单记录
```
### 数据流
```
用户选择样品 → 选择测试流程 → 提交请求
验证样品状态 → 获取流程配置 → 查询测试单元
创建工单记录 → 更新样品状态 → 返回结果
```
## Components and Interfaces
### 前端组件
#### 1. 样品管理页面增强 (warehouse/sample/index.vue)
**新增数据字段:**
```javascript
{
// 工单生成对话框
workOrderDialogVisible: false,
// 工单表单
workOrderForm: {
sampleIds: [], // 选中的样品ID列表
testFlowId: null, // 测试流程ID
workOrderName: '', // 工单名称
memo: '' // 备注
},
// 测试流程选项
testFlowOptions: [],
// 测试流程标签
testFlowTags: []
}
```
**新增方法:**
```javascript
// 打开生成工单对话框
handleGenerateWorkOrder()
// 加载测试流程选项
loadTestFlowOptions()
// 获取测试流程标签
fetchTestFlowTags(flowId)
// 提交工单生成
submitWorkOrderGeneration()
```
### 后端接口
#### 1. 样品工单生成API
**端点:** `POST /warehouse/sample/generate_work_orders`
**请求体:**
```json
{
"sampleIds": [1, 2, 3],
"testFlowId": 1,
"workOrderName": "批次测试",
"memo": "紧急测试"
}
```
**响应:**
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"successCount": 3,
"failedCount": 0,
"workOrderIds": [101, 102, 103],
"failedSamples": []
}
}
```
#### 2. 测试流程查询API复用现有
**端点:** `GET /system/test_flow/list`
**响应:**
```json
{
"code": 200,
"data": [
{
"id": 1,
"name": "标准测试流程",
"tags": [...]
}
]
}
```
## Data Models
### 样品工单生成请求模型
```python
class GenerateWorkOrderFromSampleModel(BaseModel):
"""从样品生成工单的请求模型"""
model_config = ConfigDict(alias_generator=to_camel)
sample_ids: List[int] = Field(description='样品ID列表')
test_flow_id: int = Field(description='测试流程ID')
work_order_name: Optional[str] = Field(default=None, description='工单名称')
memo: Optional[str] = Field(default=None, description='备注')
```
### 工单生成响应模型
```python
class WorkOrderGenerationResponseModel(BaseModel):
"""工单生成响应模型"""
model_config = ConfigDict(alias_generator=to_camel)
success_count: int = Field(description='成功数量')
failed_count: int = Field(description='失败数量')
work_order_ids: List[int] = Field(description='生成的工单ID列表')
failed_samples: List[dict] = Field(description='失败的样品信息')
```
### 数据库表关系
```
warehouse_sample (样品表)
├── sample_id (主键)
├── receipt_id (入库单ID)
├── sample_sn (样品SN号)
├── sample_model (样品型号)
├── hardware_version (硬件版本)
└── status (状态: 0-待测试, 1-测试中, 2-已完成, 3-已退回)
test_work_order (测试工单表)
├── id (主键)
├── test_eut_id (产品ID) → 关联 warehouse_sample.sample_id
├── test_category_id (测试类别ID)
├── test_item_id (测试单元ID)
├── tester_id (测试人ID)
├── reviewer_id (审核人ID)
├── test_status (测试状态)
└── test_step (测试步骤)
test_flow (测试流程表)
├── id (主键)
└── name (流程名称)
test_flow_tags (流程标签关联表)
├── test_flow_id (流程ID)
└── test_category_id (测试类别ID)
test_item (测试单元表)
├── id (主键)
├── test_category_id (测试类别ID)
└── eut_type_id (产品类型ID)
```
## Correctness Properties
*A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
### Property 1: 工单创建完整性
*For any* 有效的样品ID列表和测试流程ID系统应为每个样品创建与测试流程中测试类别数量相等的工单数
**Validates: Requirements 2.3**
### Property 2: 样品状态一致性
*For any* 成功生成工单的样品,其状态应从"待测试"(0)更新为"测试中"(1)
**Validates: Requirements 4.4**
### Property 3: 工单数据关联正确性
*For any* 生成的工单其test_eut_id字段应等于对应样品的sample_id
**Validates: Requirements 3.2**
### Property 4: 测试类别映射正确性
*For any* 测试流程生成的工单的test_category_id应属于该流程的test_flow_tags集合
**Validates: Requirements 2.2**
### Property 5: 批量操作原子性
*For any* 样品列表中的单个样品工单创建失败,不应影响其他样品的工单创建
**Validates: Requirements 2.4**
### Property 6: 工单命名规则一致性
*For any* 未指定工单名称的请求,生成的工单名称应遵循"样品SN + 测试类别"的格式
**Validates: Requirements 5.5**
## Error Handling
### 错误类型
1. **样品不存在错误**
- 错误码404
- 消息样品ID不存在
- 处理:跳过该样品,继续处理其他样品
2. **样品状态错误**
- 错误码400
- 消息:样品状态不允许生成工单
- 处理:记录失败原因,继续处理其他样品
3. **测试流程不存在错误**
- 错误码404
- 消息:测试流程不存在
- 处理:终止整个操作,返回错误
4. **测试单元未配置错误**
- 错误码400
- 消息:该样品型号未配置测试单元
- 处理:跳过该样品,记录警告
5. **数据库操作错误**
- 错误码500
- 消息:工单创建失败
- 处理:回滚事务,返回错误详情
### 错误响应格式
```json
{
"code": 400,
"msg": "部分样品工单生成失败",
"data": {
"successCount": 2,
"failedCount": 1,
"workOrderIds": [101, 102],
"failedSamples": [
{
"sampleId": 3,
"sampleSn": "SN003",
"reason": "样品状态不允许生成工单"
}
]
}
}
```
## Testing Strategy
### Unit Tests
1. **样品状态验证测试**
- 测试待测试状态样品可以生成工单
- 测试其他状态样品被正确拒绝
2. **测试流程配置查询测试**
- 测试正确获取流程的测试类别
- 测试流程不存在时的错误处理
3. **工单数据构造测试**
- 测试工单字段正确映射样品信息
- 测试工单命名规则
### Property-Based Tests
使用Python的`hypothesis`库进行属性测试:
1. **Property 1测试工单创建完整性**
```python
@given(
sample_ids=st.lists(st.integers(min_value=1), min_size=1, max_size=10),
test_flow_id=st.integers(min_value=1)
)
async def test_work_order_creation_completeness(sample_ids, test_flow_id):
"""测试为每个样品创建正确数量的工单"""
# 生成工单
result = await generate_work_orders_from_samples(sample_ids, test_flow_id)
# 获取流程的测试类别数量
category_count = await get_test_category_count(test_flow_id)
# 验证:成功的样品数 * 测试类别数 = 工单数
assert len(result.work_order_ids) == result.success_count * category_count
```
2. **Property 2测试样品状态一致性**
```python
@given(sample_ids=st.lists(st.integers(min_value=1), min_size=1))
async def test_sample_status_consistency(sample_ids):
"""测试成功生成工单后样品状态更新"""
# 生成工单
result = await generate_work_orders_from_samples(sample_ids, test_flow_id=1)
# 验证:所有成功的样品状态都是"测试中"
for sample_id in sample_ids[:result.success_count]:
sample = await get_sample_by_id(sample_id)
assert sample.status == '1'
```
3. **Property 3测试工单数据关联正确性**
```python
@given(sample_id=st.integers(min_value=1))
async def test_work_order_sample_association(sample_id):
"""测试工单正确关联样品"""
# 生成工单
result = await generate_work_orders_from_samples([sample_id], test_flow_id=1)
# 验证所有工单的test_eut_id都等于sample_id
for work_order_id in result.work_order_ids:
work_order = await get_work_order_by_id(work_order_id)
assert work_order.test_eut_id == sample_id
```
### Integration Tests
1. **端到端工单生成测试**
- 创建测试样品
- 调用工单生成API
- 验证工单创建成功
- 验证样品状态更新
2. **批量操作测试**
- 创建多个测试样品
- 批量生成工单
- 验证部分失败场景
3. **前端集成测试**
- 测试对话框打开和关闭
- 测试表单验证
- 测试API调用和响应处理