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

10 KiB
Raw Blame History

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

错误类型

  1. 样品不存在错误

    • 错误码404
    • 消息样品ID不存在
    • 处理:跳过该样品,继续处理其他样品
  2. 样品状态错误

    • 错误码400
    • 消息:样品状态不允许生成工单
    • 处理:记录失败原因,继续处理其他样品
  3. 测试流程不存在错误

    • 错误码404
    • 消息:测试流程不存在
    • 处理:终止整个操作,返回错误
  4. 测试单元未配置错误

    • 错误码400
    • 消息:该样品型号未配置测试单元
    • 处理:跳过该样品,记录警告
  5. 数据库操作错误

    • 错误码500
    • 消息:工单创建失败
    • 处理:回滚事务,返回错误详情

错误响应格式

{
  "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测试工单创建完整性
@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
  1. 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'
  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

  1. 端到端工单生成测试

    • 创建测试样品
    • 调用工单生成API
    • 验证工单创建成功
    • 验证样品状态更新
  2. 批量操作测试

    • 创建多个测试样品
    • 批量生成工单
    • 验证部分失败场景
  3. 前端集成测试

    • 测试对话框打开和关闭
    • 测试表单验证
    • 测试API调用和响应处理