feat(schemas): 扩充 Task/Product Pydantic Schema

Task Schema:
- TaskResponse 新增 is_rework, reject_reason, received_at, completed_at, records, product_sn
- 新增 TaskRejectRequest, TaskTransferRequest, TaskRecordCreate, TaskRecordResponse
- TaskRecordResponse 含 json.loads 反序列化 images

Product Schema:
- ProductResponse/ProductScanResponse 新增 external_serial, current_location_id, overall_status
- ProductScanResponse 新增 task_tree (递归任务树)
- ProductCreate 改为 material_id/material_name/spec_model + external_serial + order_no 自由文本
- ProductUpdate 新增 order_no
This commit is contained in:
2026-08-05 14:00:32 +08:00
parent e0c01a562f
commit f9e10a7dd1
2 changed files with 64 additions and 8 deletions

View File

@ -6,10 +6,17 @@ from pydantic import BaseModel, Field
class ProductCreate(BaseModel):
"""创建产品"""
serial_number: str = Field(..., min_length=16, max_length=16, description="产品序列号(16位)")
order_id: uuid.UUID = Field(..., description="所属订单ID")
material_id: str | None = Field(None, max_length=64, description="物料ID(逻辑外键→老系统)")
"""创建产品 — serial_number 由后端自动生成 16 位 HEX"""
# MOM 物料挂载(必填)
material_id: str = Field(..., max_length=64, description="MOM物料ID(必选)")
material_name: str = Field("", max_length=255, description="物料名称")
spec_model: str = Field("", max_length=255, description="规格型号")
category: str = Field("", max_length=100, description="物料类别")
material_type: str = Field("", max_length=100, description="物料类型")
# 可选
external_serial: str | None = Field(None, max_length=64, description="产品序列号(用户自定义,选填)")
order_id: uuid.UUID | None = Field(None, description="所属订单ID(选填)")
order_no: str | None = Field(None, max_length=64, description="订单号(自由键入,选填)")
parent_product_id: uuid.UUID | None = Field(None, description="父产品ID")
model_config = {"from_attributes": True}
@ -18,7 +25,11 @@ class ProductCreate(BaseModel):
class ProductUpdate(BaseModel):
"""更新产品"""
serial_number: str | None = Field(None, min_length=16, max_length=16)
external_serial: str | None = Field(None, max_length=64)
material_id: str | None = Field(None, max_length=64)
material_name: str | None = Field(None, max_length=255)
spec_model: str | None = Field(None, max_length=255)
order_no: str | None = Field(None, max_length=64, description="订单号")
status: str | None = Field(None, max_length=50, description="产品状态")
parent_product_id: uuid.UUID | None = Field(None)
@ -29,10 +40,17 @@ class ProductResponse(BaseModel):
"""产品响应"""
id: uuid.UUID
serial_number: str
order_id: uuid.UUID
external_serial: str | None = None
order_id: uuid.UUID | None = None
order_no: str = ""
material_id: str | None
material_name: str | None = None
spec_model: str | None = None
category: str | None = None
material_type: str | None = None
parent_product_id: uuid.UUID | None
current_location_id: str | None = None
overall_status: str | None = None
status: str
created_at: datetime
@ -43,11 +61,17 @@ class ProductScanResponse(BaseModel):
"""扫码查询响应 — 产品信息 + 完整任务树(递归嵌套)"""
id: uuid.UUID
serial_number: str
order_id: uuid.UUID
external_serial: str | None = None
order_id: uuid.UUID | None = None
order_no: str = ""
material_id: str | None
material_name: str | None = None
spec_model: str | None = None
category: str | None = None
material_type: str | None = None
parent_product_id: uuid.UUID | None
current_location_id: str | None = None
overall_status: str | None = None
status: str
created_at: datetime
top_level_tasks: list[TaskSummaryResponse] = []
@ -56,6 +80,6 @@ class ProductScanResponse(BaseModel):
model_config = {"from_attributes": True}
# 延迟导入,避免循环引用 — TaskSummaryResponse 在 tasks.py 中定义
from app.schemas.task import TaskSummaryResponse # noqa: E402
# 延迟导入,避免循环引用
from app.schemas.task import TaskSummaryResponse, TaskResponse # noqa: E402
ProductScanResponse.model_rebuild()