feat(透视表): 工序分布包含在库/完成 + 增加时间筛选

- wip-matrix 去掉状态过滤,全量分布,工序包含「在库」(生产完成)
- 后端加 since/until 按任务接手/创建时间过滤
- 前端 MatrixBoard 加 RangePicker 日期筛选 + 全部清除
This commit is contained in:
2026-08-28 16:32:01 +08:00
parent fdd7465afb
commit 41dd257260
4 changed files with 50 additions and 15 deletions

View File

@ -104,10 +104,14 @@ async def user_operations_detail(
@router.get("/wip-matrix", response_model=list[WipMatrixRow])
async def wip_matrix(
dimension: str = Query("assignee", description="聚合维度: assignee(人员) / task_name(工序)"),
since: str | None = Query(None, description="起始日期 ISO"),
until: str | None = Query(None, description="截止日期 ISO"),
db: AsyncSession = Depends(get_db),
):
"""在制品分布透视表 — 规格型号 × 人员/工序 的设备数量交叉聚合"""
return await get_wip_matrix(db, dimension=dimension)
"""生产分布透视表 — 规格型号 × 人员/工序 的设备数量交叉聚合(含在库/完成)"""
since_dt = datetime.fromisoformat(since) if since else None
until_dt = datetime.fromisoformat(until) if until else None
return await get_wip_matrix(db, dimension=dimension, since=since_dt, until=until_dt)
@router.get("/people-workload", response_model=list[PersonWorkload])

View File

@ -607,14 +607,19 @@ async def get_user_operations(
async def get_wip_matrix(
db: AsyncSession,
dimension: str = "assignee",
since: datetime | None = None,
until: datetime | None = None,
) -> list[WipMatrixRow]:
"""在制品交叉聚合Y=规格型号X=人员 或 工序,单元格=设备数量。
"""生产分布透视表Y=规格型号X=人员 或 工序,单元格=设备数量。
覆盖全部任务状态(含已完成/在库),工序分布能看到「在库」(生产完成)。
since/until 按任务接手/创建时间过滤。
dimension:
- assignee: 按任务负责人聚合dimension_key 为中文姓名)
- task_name: 按工序名聚合dimension_key 为工序名,附主负责人)
"""
from app.models.task import Task, TASK_STATUS_WIP, TASK_STATUS_PENDING
from app.models.task import Task
from app.models.product import Product
dim_expr = Task.task_name if dimension == "task_name" else Task.assignee_id
@ -627,10 +632,13 @@ async def get_wip_matrix(
func.array_agg(func.distinct(Task.assignee_id)),
)
.join(Task, Task.product_id == Product.id)
.where(Task.status.in_([TASK_STATUS_WIP, TASK_STATUS_PENDING]))
.group_by(Product.spec_model, dim_expr)
.order_by(Product.spec_model, dim_expr)
)
if since:
stmt = stmt.where(func.coalesce(Task.received_at, Task.created_at) >= since)
if until:
stmt = stmt.where(func.coalesce(Task.received_at, Task.created_at) <= until)
result = await db.execute(stmt)
rows = result.all()