fix: 三致命Bug—macro_status预计算+排除已完工脏读+flush落盘+递归深度限制10
This commit is contained in:
@ -384,6 +384,30 @@ async def get_all_products(
|
||||
location_ids = [p.current_location_id for p in products if p.current_location_id]
|
||||
name_map = _lookup_display_names(location_ids)
|
||||
|
||||
# 🔧 批量预计算 macro_status:一次性查出所有产品关联的任务状态
|
||||
product_ids = [p.id for p in products]
|
||||
macro_map: dict[uuid.UUID, str] = {}
|
||||
if product_ids:
|
||||
from sqlalchemy import case, func as sa_func
|
||||
task_stmt = (
|
||||
select(
|
||||
Task.product_id,
|
||||
sa_func.max(case(
|
||||
(Task.status == "WIP", 3),
|
||||
(Task.status == "PENDING", 2),
|
||||
(Task.status == "COMPLETED", 1),
|
||||
(Task.status == "ARCHIVED", 1),
|
||||
else_=0,
|
||||
)).label("prio"),
|
||||
)
|
||||
.where(Task.product_id.in_(product_ids))
|
||||
.group_by(Task.product_id)
|
||||
)
|
||||
task_result = await db.execute(task_stmt)
|
||||
prio_to_status = {3: "WIP", 2: "PENDING", 1: "COMPLETED", 0: None}
|
||||
for row in task_result:
|
||||
macro_map[row[0]] = prio_to_status.get(row[1], None)
|
||||
|
||||
return [
|
||||
ProductResponse(
|
||||
id=p.id,
|
||||
@ -403,6 +427,7 @@ 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,
|
||||
status=p.status,
|
||||
created_at=p.created_at,
|
||||
|
||||
@ -74,6 +74,7 @@ async def _recalc_product_location(db: AsyncSession, product_id: uuid.UUID, comp
|
||||
sa_select(Task).where(
|
||||
Task.product_id == product_id,
|
||||
Task.status == TASK_STATUS_WIP,
|
||||
Task.id != completed_task_id, # 🔧 排除刚刚完工的任务(避免脏读)
|
||||
).order_by(Task.created_at.desc())
|
||||
)
|
||||
wip_tasks = task_result.scalars().all()
|
||||
@ -94,6 +95,7 @@ async def _recalc_product_location(db: AsyncSession, product_id: uuid.UUID, comp
|
||||
|
||||
if product.current_location_id != new_location:
|
||||
product.current_location_id = new_location
|
||||
await db.flush() # 🔧 确保位置更新落盘到当前事务
|
||||
|
||||
|
||||
def _check_permission(task_assignee_id: str | None, operator_id: str | None, operator_role: str | None = None) -> None:
|
||||
|
||||
Reference in New Issue
Block a user