Files
pickling-mes/backend/app/api/plan.py
wangyu 193da0018f feat: 移除PDI和订单号字段,新增设备巡检模块
- 从物料跟踪页面移除订单号列和表单字段
- 从导航菜单移除PDI管理,添加设备巡检
- 新增InspectionLocation和InspectionRecord后端模型和API
- 新增设备巡检前端页面(左侧点位列表,右侧设备和历史记录)
2026-05-27 16:38:40 +08:00

104 lines
3.8 KiB
Python

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.plan import ProductionPlan, PlanStatus
from app.schemas.plan import PlanCreate, PlanUpdate, PlanOut
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("/", response_model=Response[PageResponse[PlanOut]])
async def list_plans(
page: int = 1,
page_size: int = 20,
status: Optional[str] = None,
start_date: Optional[str] = Query(None),
end_date: Optional[str] = Query(None),
db: AsyncSession = Depends(get_db),
_ = Depends(get_current_user),
):
query = select(ProductionPlan).order_by(desc(ProductionPlan.plan_date))
if status:
try:
query = query.where(ProductionPlan.status == PlanStatus(status))
except ValueError:
pass
_sd = _parse_dt(start_date)
if _sd:
query = query.where(ProductionPlan.plan_date >= _sd)
_ed = _parse_dt(end_date)
if _ed:
query = query.where(ProductionPlan.plan_date <= _ed)
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 = [PlanOut.model_validate(p) for p in result.scalars()]
return Response.ok(PageResponse(total=total, page=page, page_size=page_size, items=items))
@router.post("/", response_model=Response[PlanOut])
async def create_plan(
body: PlanCreate,
db: AsyncSession = Depends(get_db),
current_user = Depends(get_current_user),
):
existing = await db.execute(select(ProductionPlan).where(ProductionPlan.plan_no == body.plan_no))
if existing.scalar_one_or_none():
raise HTTPException(status_code=400, detail="计划号已存在")
plan = ProductionPlan(**body.model_dump(), created_by=current_user.username)
db.add(plan)
await db.flush()
return Response.ok(PlanOut.model_validate(plan))
@router.get("/{plan_id}", response_model=Response[PlanOut])
async def get_plan(plan_id: int, db: AsyncSession = Depends(get_db), _ = Depends(get_current_user)):
result = await db.execute(select(ProductionPlan).where(ProductionPlan.id == plan_id))
plan = result.scalar_one_or_none()
if not plan:
raise HTTPException(status_code=404, detail="计划不存在")
return Response.ok(PlanOut.model_validate(plan))
@router.put("/{plan_id}", response_model=Response[PlanOut])
async def update_plan(
plan_id: int,
body: PlanUpdate,
db: AsyncSession = Depends(get_db),
_ = Depends(get_current_user),
):
result = await db.execute(select(ProductionPlan).where(ProductionPlan.id == plan_id))
plan = result.scalar_one_or_none()
if not plan:
raise HTTPException(status_code=404, detail="计划不存在")
for k, v in body.model_dump(exclude_none=True).items():
setattr(plan, k, v)
await db.flush()
return Response.ok(PlanOut.model_validate(plan))
@router.patch("/{plan_id}/confirm", response_model=Response[PlanOut])
async def confirm_plan(plan_id: int, db: AsyncSession = Depends(get_db), _ = Depends(get_current_user)):
result = await db.execute(select(ProductionPlan).where(ProductionPlan.id == plan_id))
plan = result.scalar_one_or_none()
if not plan:
raise HTTPException(status_code=404, detail="计划不存在")
plan.status = PlanStatus.CONFIRMED
await db.flush()
return Response.ok(PlanOut.model_validate(plan))