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 增加"名下再无任何活跃 任务则视同终结态",让被直接完结的生产设备接受时间筛选,不再恒挂在看板上 冒充在制。两处必须一字不差同步,否则会出现"矩阵有数、下钻为空"
This commit is contained in:
@ -29,21 +29,35 @@ PHASE_LABELS = {
|
||||
}
|
||||
|
||||
# ============================================================
|
||||
# 售后专属工序名 — 一旦选中即代表设备进入售后生命周期
|
||||
# 售后专属工序名
|
||||
# ============================================================
|
||||
STEP_SHIP_TEST = "发货测试" # 售后返修后的出货测试
|
||||
STEP_SHIP_TEST = "发货测试" # 出厂 / 发货前测试
|
||||
STEP_AFTER_SALES_REPAIR = "售后维修" # 售后返修本体
|
||||
|
||||
# 售后区独立成列所用的两个工序名(前端分列 / 大屏返厂统计仍以它为准)
|
||||
AFTER_SALES_ONLY_STEPS = frozenset({STEP_SHIP_TEST, STEP_AFTER_SALES_REPAIR})
|
||||
|
||||
# 🔧 工序语义细分(2026-09-17)——「售后专属」不等于「回流返厂」:
|
||||
# · 出厂质检(发货测试):设备可能压根没回厂,只是补做发货前测试。
|
||||
# 它【不】构成回流信号,选中它不应把设备永久烙进售后生命周期。
|
||||
# · 明确修机指令(售后维修):设备确实是回厂返修 → 判定回流。
|
||||
# 历史缺陷:两者混为一谈,导致「已出库 + 发货测试」被打上不可回退的
|
||||
# AFTER_SALES 烙印(售后死锁),而「已出库」的物理终态也被抹掉。
|
||||
OUTBOUND_QC_STEPS = frozenset({STEP_SHIP_TEST})
|
||||
AFTER_SALES_REPAIR_STEPS = frozenset({STEP_AFTER_SALES_REPAIR})
|
||||
|
||||
# ============================================================
|
||||
# 各阶段合法的工序名 / 宏观状态名
|
||||
# ============================================================
|
||||
|
||||
# ── 生产制造阶段(原有词表,一字未改,保证存量流程不受影响)──
|
||||
# ── 生产制造阶段 ──
|
||||
# 🔧 2026-09-17 补入「发货测试」:出厂质检现在被允许在生产阶段执行
|
||||
# (设备的 lifecycle_phase 不再因选中它而翻成售后)。若不补,
|
||||
# _enforce_step_isolation 会把「已出库设备的发货测试」直接 400 掉。
|
||||
PRODUCTION_TASK_STEPS = ("备货", "生产", "测试", "维修", "在库")
|
||||
PRODUCTION_OVERALL_STEPS = (
|
||||
"备货", "生产", "测试", "维修", "在库", "待仓库收货", "已入库", "已出库",
|
||||
STEP_SHIP_TEST,
|
||||
)
|
||||
|
||||
# ── 售后回流阶段:只保留「发货测试 / 售后维修 / 入库出库」──
|
||||
@ -99,12 +113,15 @@ def is_placeholder_step(step: str | None) -> bool:
|
||||
|
||||
|
||||
def resolve_phase_for_step(current_phase: str | None, step: str | None) -> str:
|
||||
"""选定售后专属工序 → 设备进入售后生命周期(单向,不可回退)
|
||||
"""选定【明确修机指令】→ 设备进入售后生命周期(单向,不可回退)
|
||||
|
||||
这是"无历史记录的老设备"进入售后阶段的唯一入口:它首次选定
|
||||
「发货测试 / 售后维修」时即被判定为售后回流设备。
|
||||
⚠️ 只有「售后维修」触发,出厂质检(发货测试)【不】触发。
|
||||
「已出库的设备补做发货测试」不代表它回厂返修;若在此烙印,
|
||||
设备会被永久打成售后(该标志单向不可回退),这就是售后死锁的第二个入口。
|
||||
|
||||
这是"无历史记录的老设备"进入售后阶段的入口:首次选定「售后维修」即判定回流。
|
||||
"""
|
||||
if step and step.strip() in AFTER_SALES_ONLY_STEPS:
|
||||
if step and step.strip() in AFTER_SALES_REPAIR_STEPS:
|
||||
return LIFECYCLE_AFTER_SALES
|
||||
return current_phase or LIFECYCLE_PRODUCTION
|
||||
|
||||
|
||||
Reference in New Issue
Block a user