10 KiB
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)
新增数据字段:
{
// 工单生成对话框
workOrderDialogVisible: false,
// 工单表单
workOrderForm: {
sampleIds: [], // 选中的样品ID列表
testFlowId: null, // 测试流程ID
workOrderName: '', // 工单名称
memo: '' // 备注
},
// 测试流程选项
testFlowOptions: [],
// 测试流程标签
testFlowTags: []
}
新增方法:
// 打开生成工单对话框
handleGenerateWorkOrder()
// 加载测试流程选项
loadTestFlowOptions()
// 获取测试流程标签
fetchTestFlowTags(flowId)
// 提交工单生成
submitWorkOrderGeneration()
后端接口
1. 样品工单生成API
端点: POST /warehouse/sample/generate_work_orders
请求体:
{
"sampleIds": [1, 2, 3],
"testFlowId": 1,
"workOrderName": "批次测试",
"memo": "紧急测试"
}
响应:
{
"code": 200,
"msg": "操作成功",
"data": {
"successCount": 3,
"failedCount": 0,
"workOrderIds": [101, 102, 103],
"failedSamples": []
}
}
2. 测试流程查询API(复用现有)
端点: GET /system/test_flow/list
响应:
{
"code": 200,
"data": [
{
"id": 1,
"name": "标准测试流程",
"tags": [...]
}
]
}
Data Models
样品工单生成请求模型
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='备注')
工单生成响应模型
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
错误类型
-
样品不存在错误
- 错误码:404
- 消息:样品ID不存在
- 处理:跳过该样品,继续处理其他样品
-
样品状态错误
- 错误码:400
- 消息:样品状态不允许生成工单
- 处理:记录失败原因,继续处理其他样品
-
测试流程不存在错误
- 错误码:404
- 消息:测试流程不存在
- 处理:终止整个操作,返回错误
-
测试单元未配置错误
- 错误码:400
- 消息:该样品型号未配置测试单元
- 处理:跳过该样品,记录警告
-
数据库操作错误
- 错误码:500
- 消息:工单创建失败
- 处理:回滚事务,返回错误详情
错误响应格式
{
"code": 400,
"msg": "部分样品工单生成失败",
"data": {
"successCount": 2,
"failedCount": 1,
"workOrderIds": [101, 102],
"failedSamples": [
{
"sampleId": 3,
"sampleSn": "SN003",
"reason": "样品状态不允许生成工单"
}
]
}
}
Testing Strategy
Unit Tests
-
样品状态验证测试
- 测试待测试状态样品可以生成工单
- 测试其他状态样品被正确拒绝
-
测试流程配置查询测试
- 测试正确获取流程的测试类别
- 测试流程不存在时的错误处理
-
工单数据构造测试
- 测试工单字段正确映射样品信息
- 测试工单命名规则
Property-Based Tests
使用Python的hypothesis库进行属性测试:
- Property 1测试:工单创建完整性
@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
- Property 2测试:样品状态一致性
@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'
- Property 3测试:工单数据关联正确性
@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
-
端到端工单生成测试
- 创建测试样品
- 调用工单生成API
- 验证工单创建成功
- 验证样品状态更新
-
批量操作测试
- 创建多个测试样品
- 批量生成工单
- 验证部分失败场景
-
前端集成测试
- 测试对话框打开和关闭
- 测试表单验证
- 测试API调用和响应处理