diff --git a/backend/app/main.py b/backend/app/main.py index 7b214bb..9a89445 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -440,6 +440,9 @@ def get_machine_cycles(machine_id: int, limit: int = Query(default=100, le=500), @app.get("/api/machines/{machine_id}/downtimes") def get_machine_downtimes(machine_id: int, limit: int = Query(default=100, le=500), db: Session = Depends(get_db)) -> list[dict]: + machine = db.get(Machine, machine_id) + if machine is None: + raise HTTPException(status_code=404, detail="Machine not found") rows = db.execute( select(Downtime).where(Downtime.machine_id == machine_id).order_by(Downtime.start_time.desc()).limit(limit) ).scalars() @@ -449,6 +452,8 @@ def get_machine_downtimes(machine_id: int, limit: int = Query(default=100, le=50 "start_time": row.start_time.isoformat(), "end_time": row.end_time.isoformat() if row.end_time else None, "duration_sec": row.duration_sec, + "machine_id": row.machine_id, + "machine_code": machine.code, "reason_code": row.reason_code, "comment": row.comment, "auto_detected": row.auto_detected, @@ -549,19 +554,27 @@ def close_production_order(order_id: int, db: Session = Depends(get_db)) -> dict @app.get("/api/downtimes/open") def get_open_downtimes(db: Session = Depends(get_db)) -> list[dict]: rows = db.execute(select(Downtime).where(Downtime.end_time.is_(None)).order_by(Downtime.start_time.asc())).scalars() - return [ - { - "id": row.id, - "machine_id": row.machine_id, - "production_order_id": row.production_order_id, - "start_time": row.start_time.isoformat(), - "reason_code": row.reason_code, - "comment": row.comment, - "auto_detected": row.auto_detected, - "qualified_by": row.qualified_by, - } - for row in rows - ] + result = [] + for row in rows: + machine = db.get(Machine, row.machine_id) + order = db.get(ProductionOrder, row.production_order_id) if row.production_order_id else None + result.append( + { + "id": row.id, + "machine_id": row.machine_id, + "machine_code": machine.code if machine else None, + "production_order_id": row.production_order_id, + "order_number": order.order_number if order else None, + "start_time": row.start_time.isoformat(), + "end_time": None, + "duration_sec": row.duration_sec, + "reason_code": row.reason_code, + "comment": row.comment, + "auto_detected": row.auto_detected, + "qualified_by": row.qualified_by, + } + ) + return result @app.post("/api/downtimes/{downtime_id}/qualify") diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 0f55450..b90799c 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -192,6 +192,16 @@ export default function App() { const selectedMachine = dashboard?.machines.find((machine) => machine.id === selectedMachineId) ?? null; const machines = dashboard?.machines ?? []; + const selectedMachineOpenDowntimes = + selectedMachineId === null ? [] : openDowntimes.filter((downtime) => downtime.machine_id === selectedMachineId); + const downtimeOptions = [...openDowntimes].sort((left, right) => { + const leftSelected = selectedMachineId !== null && left.machine_id === selectedMachineId; + const rightSelected = selectedMachineId !== null && right.machine_id === selectedMachineId; + if (leftSelected !== rightSelected) { + return Number(rightSelected) - Number(leftSelected); + } + return new Date(left.start_time).getTime() - new Date(right.start_time).getTime(); + }); const summaryMetrics = { production: machines.filter((machine) => machine.status === "production").length, openDowntimes: openDowntimes.length, @@ -403,6 +413,22 @@ export default function App() { return toasts[key] ?