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

374 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 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调用和响应处理