Commit Graph

13 Commits

Author SHA1 Message Date
5d5aea1015 refactor(outbound): 出库单据与领用物料合并成一张表
这两者本来就是同一件事(这台设备对应 MOM 的哪些出库单、领了哪些料),
却因为粒度不同被拆成两张表、界面上两张卡:用户要面对两个入口两个删除按钮,
还会问「我在那边挂的怎么这边看不见」。更糟的是**单据级那张没有 mom_line_id,
挂上去的料根本报不了废**。

- 新建 product_outbound_materials,统一到**明细级**(只有它带 mom_line_id,
  而报废要用它定位)。单据级信息(申请单号/备注/撤回)作为冗余列落在每条明细上。
  task_id 改为可空 —— 任务只是溯源信息,不再是组织维度,展示/报废/删除按设备走。
- 接口从 7 个收敛成 3 个(GET/POST/DELETE /products/{id}/outbound-materials,
  外加整单删 by-order)。任务级那套连同 TaskResponse.outbound_materials 一起删掉:
  保留第二个入口只会让「同一个东西两个地方」重新长出来。
- MOM 回调存档改为按 outbound_no 去 MOM **现查明细**逐行落 —— 不查的话
  这台设备「领了什么料」永远是空的,也就报不了废。查不到时退化成单据级存档,
  宁可显示「有这张单但看不到明细」,也不要静默丢掉这张单。
- 扫码响应补 outbound_materials(附「谁挂上去的」中文名,服务端解析)。
  ⚠️ 依赖 task_tree_loader 的 selectinload —— 异步 session 下懒加载会
  MissingGreenlet。
- 前端两张卡合并成一张:按出库单号分组、点开看明细,明细行才有报废/删除。
2026-09-23 15:18:06 +08:00
d666bbd4ed feat: 直接完结通道与报表口径收口(后端)
【直接完结:保留动作,剥离状态】
- transfer_task 权限硬拦截:仅 SUPER_ADMIN / SUPERVISOR。判据取签名保护的
  operator_role,刻意不用客户端可通过 ?operator_id= 伪造的 operator_id
- 直接完结【不再改写】overall_status —— 它只是任务闭环动作,不改变物理状态。
  已出库设备完结后依然是「已出库」,回归 WIP 矩阵的已出库列
- 物理终态保护:create_task / receive_task / transfer_task 三处写入点统一加
  _is_physical_terminal 守卫,禁止用任务名覆写 已入库/在库/已出库。
  历史缺陷:「发货测试」会把设备的「已出库」标识静默抹掉,跨报表口径随之打架

【位置与工序口径】
- _recalc_product_location:已出库且闲置 → 位置清空(货发走就离场)。
  只清「已出库」;已入库/在库的设备确实还在仓库里,位置必须保留
- MOM 出库回调同步清空 current_location_id
- 新增 ProductResponse.current_step:只认活跃主干任务,无活跃任务时返回
  宏观终态或空。不再让已 COMPLETED 的历史工序(扫码出库/测试…)冒充"当前工序"

【售后烙印去死锁】
- 拆分 OUTBOUND_QC_STEPS(发货测试) / AFTER_SALES_REPAIR_STEPS(售后维修)
- resolve_phase_for_step 与 _mark_after_sales_if_reactivated 双双改为仅
  「售后维修」触发 AFTER_SALES,解除「已出库 + 发货测试」被永久烙印的死锁
- PRODUCTION_OVERALL_STEPS 补入「发货测试」,使出厂质检在生产阶段合法
  (否则 _enforce_step_isolation 会把已出库设备的发货测试直接 400)

【游魂收口】
- get_wip_matrix / get_wip_matrix_detail 的 is_terminal 增加"名下再无任何活跃
  任务则视同终结态",让被直接完结的生产设备接受时间筛选,不再恒挂在看板上
  冒充在制。两处必须一字不差同步,否则会出现"矩阵有数、下钻为空"
2026-09-17 17:05:42 +08:00
1e6c006360 feat: MES/MOM 出入库状态解绑与直接完结通道(后端契约 + 移动端)
- TaskTransferRequest 新增 finish_directly 开关:闭环当前任务但不产生任何下游任务,
  产品 overall_status 保持原样,工人无需再借道「入库(virtual_warehouse)」来关闭任务,
  从根源上避免产品被误标「待仓库收货」而卡住 MOM 对账
- 空 assignees 分支加防呆校验:想直接完结必须显式传 finish_directly=true,
  杜绝漏填导致「转交」静默退化成「直接完结」的丢件级隐患
- 直接完结跳过 _mark_after_sales_if_reactivated:不产生新任务即不构成「回流返厂」信号,
  否则已出库设备的正常收官会把产品误翻成售后机(该标志单向不可回退)
- 补齐直接完结的独立响应文案,不再拼出「已创建 0 个下一道工序任务「None」」
- 移动端转交弹窗改为「转交个人 / 入库 / 直接完结」三选一互斥
2026-09-17 14:07:02 +08:00
71e660b428 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 字段
2026-09-15 10:57:35 +08:00
b8ade13b61 fix: TaskRecordResponse改用field_validator — 不再污染ORM对象导致图片列表写回VARCHAR报错
根因: model_validate直接obj.images=json.loads()把ORM对象的字符串改成列表
     SQLAlchemy autoflush时把列表写回VARCHAR列 → DataError
修复: field_validator(mode=before)在序列化层转换, 不修改ORM源对象
2026-08-13 09:03:17 +08:00
d8d42e9613 feat: 上游显示真实发送人 — 从task_logs追溯created_by 2026-08-12 17:52:35 +08:00
b71c5a2d07 feat: 双Token认证(Access 2h/Refresh 7d) + 通知系统(转交/驳回自动推送) 2026-08-07 11:44:04 +08:00
0d323e8181 血缘锚定法: task_type字段+迁移+三大接口写入+TreeCanvas基于task_type布局 2026-08-06 13:03:25 +08:00
7810097b39 全栈修复: remark字段全链路打通 — TaskCreate+TransferRequest+transfer_task+前端Payload 2026-08-05 15:59:20 +08:00
f736cf0c13 修复: TaskResponse补remark字段 + 记录按时间降序取最新一条(latestRecord) 2026-08-05 15:37:10 +08:00
22f7bb2f79 全栈: Task模型+remark字段 + 前端任务卡片初始说明展示区 2026-08-05 15:22:50 +08:00
f9e10a7dd1 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
2026-08-05 14:00:32 +08:00
cb97d390ad feat(schemas): 更新 Pydantic Schema,新增请求/响应模型
Task Schema 更新:
- TaskResponse/TaskSummaryResponse 新增 is_rework, reject_reason, received_at, completed_at 字段
- 新增 TaskRejectRequest (品质驳回请求, reason 必填)
- 新增 TaskTransferRequest (裂变转交请求, next_assignees + next_task_name 必填)
- 新增 TaskTransferResponse (裂变转交响应)
- TaskCreate 新增 is_rework 字段

Product Schema 更新:
- ProductResponse/ProductScanResponse 新增 current_location_id 字段
- ProductScanResponse 新增 task_tree 字段 (递归任务树,供十字矩阵树状图)
2026-08-04 17:03:29 +08:00