Files
pickling-mes/backend/app/api/downtime.py

109 lines
3.8 KiB
Python
Raw Normal View History

from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func, desc
from typing import Optional
from datetime import datetime
from app.database import get_db
from app.models.downtime import DowntimeRecord, DowntimeCategory
from app.schemas.downtime import (
DowntimeCreate, DowntimeUpdate, DowntimeOut,
CategoryCreate, CategoryOut
)
from app.schemas.common import Response, PageResponse
from app.services.auth_service import get_current_user
router = APIRouter()
def _parse_dt(s):
if not s:
return None
try:
return datetime.fromisoformat(s.replace('Z', ''))
except Exception:
return None
@router.get("/categories", response_model=Response[list[CategoryOut]])
async def list_categories(db: AsyncSession = Depends(get_db), _ = Depends(get_current_user)):
result = await db.execute(select(DowntimeCategory).where(DowntimeCategory.is_active == 1))
return Response.ok([CategoryOut.model_validate(c) for c in result.scalars()])
@router.post("/categories", response_model=Response[CategoryOut])
async def create_category(
body: CategoryCreate,
db: AsyncSession = Depends(get_db),
_ = Depends(get_current_user),
):
cat = DowntimeCategory(**body.model_dump())
db.add(cat)
await db.flush()
return Response.ok(CategoryOut.model_validate(cat))
@router.get("/", response_model=Response[PageResponse[DowntimeOut]])
async def list_downtime(
page: int = 1,
page_size: int = 20,
category_code: Optional[str] = None,
shift: Optional[str] = None,
start_date: Optional[str] = Query(None),
end_date: Optional[str] = Query(None),
is_planned: Optional[int] = None,
db: AsyncSession = Depends(get_db),
_ = Depends(get_current_user),
):
query = select(DowntimeRecord).order_by(desc(DowntimeRecord.start_time))
if category_code:
query = query.where(DowntimeRecord.category_code == category_code)
if shift:
query = query.where(DowntimeRecord.shift == shift)
_sd = _parse_dt(start_date)
if _sd:
query = query.where(DowntimeRecord.start_time >= _sd)
_ed = _parse_dt(end_date)
if _ed:
query = query.where(DowntimeRecord.start_time <= _ed)
if is_planned is not None:
query = query.where(DowntimeRecord.is_planned == is_planned)
total = (await db.execute(select(func.count()).select_from(query.subquery()))).scalar()
result = await db.execute(query.offset((page - 1) * page_size).limit(page_size))
items = [DowntimeOut.model_validate(r) for r in result.scalars()]
return Response.ok(PageResponse(total=total, page=page, page_size=page_size, items=items))
@router.post("/", response_model=Response[DowntimeOut])
async def create_downtime(
body: DowntimeCreate,
db: AsyncSession = Depends(get_db),
_ = Depends(get_current_user),
):
record = DowntimeRecord(**body.model_dump())
db.add(record)
await db.flush()
return Response.ok(DowntimeOut.model_validate(record))
@router.put("/{record_id}", response_model=Response[DowntimeOut])
async def update_downtime(
record_id: int,
body: DowntimeUpdate,
db: AsyncSession = Depends(get_db),
_ = Depends(get_current_user),
):
result = await db.execute(select(DowntimeRecord).where(DowntimeRecord.id == record_id))
record = result.scalar_one_or_none()
if not record:
raise HTTPException(status_code=404, detail="停机记录不存在")
update_data = body.model_dump(exclude_none=True)
for k, v in update_data.items():
setattr(record, k, v)
if record.end_time and record.start_time:
delta = (record.end_time - record.start_time).total_seconds() / 60
record.duration = round(delta, 2)
await db.flush()
return Response.ok(DowntimeOut.model_validate(record))