feat: 驳回图片改为选填,驳回原因/转交备注落库留痕
业务调整:车间驳回不必须拍照(编号错误、选错工序等场景无需照片举证)。 - schemas/task.py: TaskRejectRequest.images 由必填(min_length=1)改为 default_factory=list,保留 max_length=9 与 URL 总长保护;reason 增加 mode="before" 的 strip 校验器,堵住纯空格凑长度绕过 min_length 的口子 (顺带保证落库的 reject_reason 不带首尾空白) - task_service.py: 驳回时把原因+图片写入 TaskRecord 挂到被驳回任务下, 修复前端时间线看不到驳回详情的问题;转交时把交接备注也挂一条记录到 下家任务,补齐接手人的上下文视角 - task_service.py: create_task / receive_task 写入 overall_status 后调用 sync_product_status 对齐 status 字段
This commit is contained in:
@ -49,8 +49,31 @@ class SubtaskCreate(BaseModel):
|
||||
|
||||
|
||||
class TaskRejectRequest(BaseModel):
|
||||
"""品质驳回请求"""
|
||||
"""品质驳回请求 — 驳回原因必填;异常图片【选填】
|
||||
(编号错误、工序选错等场景无需拍照举证,故不强制传图)"""
|
||||
reason: str = Field(..., min_length=1, max_length=500, description="驳回原因(必填)")
|
||||
images: list[str] = Field(
|
||||
default_factory=list, max_length=9,
|
||||
description="异常图片 URL 列表(选填,可传空数组,最多 9 张)",
|
||||
)
|
||||
|
||||
@field_validator("reason", mode="before")
|
||||
@classmethod
|
||||
def _strip_reason(cls, v):
|
||||
"""先 strip 再交给 min_length 校验:否则纯空格(' ')能凑够长度绕过必填。
|
||||
顺带保证落库的 Task.reject_reason / TaskRecord.remark 不带首尾空白。
|
||||
非字符串原样返回,让 Pydantic 抛出正常的类型错误。"""
|
||||
return v.strip() if isinstance(v, str) else v
|
||||
|
||||
@field_validator("images")
|
||||
@classmethod
|
||||
def _validate_images(cls, v: list[str]) -> list[str]:
|
||||
"""剥离空串(前端可能提交 [''] 之类的占位),并做总长度上限校验,
|
||||
避免落库时才撞上 TaskRecord.images 的 String(4000) 上限。图片选填,允许为空。"""
|
||||
urls = [u.strip() for u in v if u and u.strip()]
|
||||
if sum(len(u) for u in urls) > 3500:
|
||||
raise ValueError("异常图片 URL 总长度超限,请减少图片数量")
|
||||
return urls
|
||||
|
||||
|
||||
class TaskTransferBranch(BaseModel):
|
||||
|
||||
Reference in New Issue
Block a user