fix: 位置回溯父任务优先 + Tab筛选改为本地calcProductStatus过滤

This commit is contained in:
2026-08-09 18:10:13 +08:00
parent 3c4c16a1cc
commit f33396b9f1
2 changed files with 59 additions and 29 deletions

View File

@ -34,19 +34,42 @@ VIRTUAL_WAREHOUSE = "virtual_warehouse"
ADMIN_ROLES = {"SUPER_ADMIN", "SUPERVISOR"}
async def _recalc_product_location(db: AsyncSession, product_id: uuid.UUID) -> None:
async def _recalc_product_location(db: AsyncSession, product_id: uuid.UUID, completed_task_id: uuid.UUID | None = None) -> None:
"""
任务完工/结束时触发:沿任务树向上回溯,
将产品 current_location 更新为最近一个 WIP 任务负责人
若无进行中任务,位置置空。
任务完工/结束时触发:位置回溯 父任务优先 策略。
① 如果完工任务有父任务且父任务未完成 → 强制回溯到父任务负责人
② 否则查找所有 WIP 任务 → 最新 WIP 负责人
③ 无 WIP → 兜底最后完工者
④ 全结束 → 置空
"""
from sqlalchemy import select as sa_select
# ① 父任务优先:如果有父任务且未完成 → 位置给父任务负责人
if completed_task_id:
task_result = await db.execute(
sa_select(Task).where(Task.id == completed_task_id)
)
current_task = task_result.scalar_one_or_none()
if current_task and current_task.parent_task_id:
parent_result = await db.execute(
sa_select(Task).where(Task.id == current_task.parent_task_id)
)
parent = parent_result.scalar_one_or_none()
if parent and parent.status not in (TASK_STATUS_COMPLETED, TASK_STATUS_REJECTED, TASK_STATUS_CANCELED, TASK_STATUS_ARCHIVED):
product_result = await db.execute(
sa_select(Product).where(Product.id == product_id)
)
product = product_result.scalar_one_or_none()
if product and product.current_location_id != parent.assignee_id:
product.current_location_id = parent.assignee_id
return
# ② 无父任务/父任务已完工 → 查找其他 WIP 任务
product_result = await db.execute(sa_select(Product).where(Product.id == product_id))
product = product_result.scalar_one_or_none()
if not product:
return
# 查找所有 WIP 状态的任务
task_result = await db.execute(
sa_select(Task).where(
Task.product_id == product_id,
@ -56,7 +79,6 @@ async def _recalc_product_location(db: AsyncSession, product_id: uuid.UUID) -> N
wip_tasks = task_result.scalars().all()
if wip_tasks:
# 有进行中的任务 → 位置更新为最新WIP任务的负责人
latest_wip = wip_tasks[0]
new_location = latest_wip.assignee_id or product.current_location_id
else:
@ -364,8 +386,8 @@ async def end_task(
await _create_task_log(db, task_id, action_type="end",
operator_id=operator_id, remark=f"分支「{task.task_name}」已终止(无下游)")
# 🔧 位置回溯:分支结束后重新计算产品当前位置
await _recalc_product_location(db, task.product_id)
# 🔧 位置回溯:分支结束后优先回溯到父任务负责人
await _recalc_product_location(db, task.product_id, task.id)
await db.commit()
await db.refresh(task)
@ -806,9 +828,9 @@ async def transfer_task(
product.current_location_id = real_branches[0][1]
product.overall_status = real_branches[0][0]
# 🔧 位置回溯:如果有新任务创建,优先新任务负责人;否则回溯到上级WIP任务
# 🔧 位置回溯:如果有新任务创建,优先新任务负责人;否则回溯到任务
if not real_branches and not has_warehouse:
await _recalc_product_location(db, task.product_id)
await _recalc_product_location(db, task.product_id, task_id)
await db.commit()
@ -908,8 +930,8 @@ async def complete_task(
remark=f"由任务「{task.task_name}」完成后转交创建",
)
# 🔧 位置回溯:老接口也触发
await _recalc_product_location(db, task.product_id)
# 🔧 位置回溯:老接口也触发(父任务优先)
await _recalc_product_location(db, task.product_id, task_id)
await db.commit()