374 lines
10 KiB
Markdown
374 lines
10 KiB
Markdown
# 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调用和响应处理
|