feat: 宏观状态动态从主干任务获取+任务树assignee中文姓名映射(后端+前端)
This commit is contained in:
@ -108,6 +108,17 @@ async def get_product_by_serial(db: AsyncSession, serial_number: str) -> Product
|
||||
# 获取完整任务树(递归嵌套,供前端渲染十字矩阵树状图)
|
||||
task_tree = await _load_task_tree(db, product.id)
|
||||
|
||||
# 🔧 收集任务树中所有 assignee_id → 查中文姓名映射
|
||||
assignee_ids: set[str] = set()
|
||||
def _collect_ids(tasks):
|
||||
for t in tasks:
|
||||
if t.assignee_id: assignee_ids.add(t.assignee_id)
|
||||
if t.child_tasks: _collect_ids(t.child_tasks)
|
||||
for t in top_tasks:
|
||||
if t.assignee_id: assignee_ids.add(t.assignee_id)
|
||||
_collect_ids(task_tree)
|
||||
assignee_names = _lookup_display_names(list(assignee_ids))
|
||||
|
||||
return ProductScanResponse(
|
||||
id=product.id,
|
||||
serial_number=product.serial_number,
|
||||
@ -128,6 +139,7 @@ async def get_product_by_serial(db: AsyncSession, serial_number: str) -> Product
|
||||
TaskSummaryResponse.model_validate(t) for t in top_tasks
|
||||
],
|
||||
task_tree=task_tree,
|
||||
assignee_names=assignee_names, # 🔧 username→中文姓名
|
||||
)
|
||||
|
||||
|
||||
@ -408,6 +420,53 @@ async def get_all_products(
|
||||
for row in task_result:
|
||||
macro_map[row[0]] = prio_to_status.get(row[1], None)
|
||||
|
||||
# 🔧 动态宏观状态:只从主干任务中获取最高优先级任务的 task_name
|
||||
overall_names: dict[uuid.UUID, str] = {}
|
||||
if product_ids:
|
||||
from sqlalchemy import func as sa_func2, case as sa_case2
|
||||
# 先找每个产品中优先级最高的主干任务ID
|
||||
main_prio_stmt = (
|
||||
select(
|
||||
Task.product_id,
|
||||
sa_func2.max(sa_case2(
|
||||
(Task.status == "WIP", 3),
|
||||
(Task.status == "PENDING", 2),
|
||||
(Task.status == "COMPLETED", 1),
|
||||
else_=0,
|
||||
)).label("prio"),
|
||||
)
|
||||
.where(
|
||||
Task.product_id.in_(product_ids),
|
||||
sa_func2.or_(
|
||||
Task.parent_task_id.is_(None),
|
||||
Task.task_type.in_(["TRANSFER", "RECOVERY"]),
|
||||
),
|
||||
)
|
||||
.group_by(Task.product_id)
|
||||
).subquery()
|
||||
# 再 join 回去拿 task_name
|
||||
name_stmt = (
|
||||
select(Task.product_id, Task.task_name)
|
||||
.join(main_prio_stmt, sa_func2.and_(
|
||||
Task.product_id == main_prio_stmt.c.product_id,
|
||||
sa_case2(
|
||||
(Task.status == "WIP", 3),
|
||||
(Task.status == "PENDING", 2),
|
||||
(Task.status == "COMPLETED", 1),
|
||||
else_=0,
|
||||
) == main_prio_stmt.c.prio,
|
||||
sa_func2.or_(
|
||||
Task.parent_task_id.is_(None),
|
||||
Task.task_type.in_(["TRANSFER", "RECOVERY"]),
|
||||
),
|
||||
))
|
||||
.order_by(Task.created_at.desc())
|
||||
.limit(1)
|
||||
)
|
||||
name_result = await db.execute(name_stmt)
|
||||
for row in name_result:
|
||||
overall_names[row[0]] = row[1]
|
||||
|
||||
return [
|
||||
ProductResponse(
|
||||
id=p.id,
|
||||
@ -427,8 +486,8 @@ async def get_all_products(
|
||||
else name_map.get(p.current_location_id) if p.current_location_id
|
||||
else None
|
||||
),
|
||||
macro_status=macro_map.get(p.id) or p.status, # 优先任务树状态,兜底产品状态
|
||||
overall_status=p.overall_status,
|
||||
macro_status=macro_map.get(p.id) or p.status,
|
||||
overall_status=overall_names.get(p.id) or p.overall_status, # 🔧 动态主干任务名优先
|
||||
status=p.status,
|
||||
created_at=p.created_at,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user