Files
pickling-mes/backend/app/api/inspection.py
wangyu b461f0d2f8 feat: 重构质量管理和设备巡检模块
质量管理: 由平铺记录改为任务制工作流(qc_task/qc_task_item/qc_defect三表)
设备巡检: 由点位+记录改为巡检模板制(eqp_checklist/item/record/detail四表)
前端: Quality.vue 支持任务列表+检验项详情+缺陷记录双Tab
前端: Inspection.vue 支持模板管理+项目维护+巡检记录+明细查看

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 16:29:02 +08:00

135 lines
6.1 KiB
Python

from fastapi import APIRouter, Depends, HTTPException
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.inspection import EqpChecklist, EqpChecklistItem, EqpInspectionRecord, EqpInspectionDetail
from app.schemas.inspection import (
EqpChecklistCreate, EqpChecklistUpdate, EqpChecklistOut,
EqpChecklistItemCreate, EqpChecklistItemOut,
EqpInspectionRecordCreate, EqpInspectionRecordOut,
EqpInspectionDetailOut,
)
from app.schemas.common import Response, PageResponse
from app.services.auth_service import get_current_user
router = APIRouter()
# ─── 巡检模板 ────────────────────────────────────────────────────────────────
@router.get("/checklists", response_model=Response[list[EqpChecklistOut]])
async def list_checklists(
equipment_code: Optional[str] = None,
db: AsyncSession = Depends(get_db),
_=Depends(get_current_user),
):
query = select(EqpChecklist).order_by(EqpChecklist.id)
if equipment_code:
query = query.where(EqpChecklist.equipment_code == equipment_code)
r = await db.execute(query)
return Response.ok([EqpChecklistOut.model_validate(c) for c in r.scalars()])
@router.post("/checklists", response_model=Response[EqpChecklistOut])
async def create_checklist(body: EqpChecklistCreate, db: AsyncSession = Depends(get_db), _=Depends(get_current_user)):
items_data = body.items or []
data = body.model_dump(exclude={"items"})
checklist = EqpChecklist(**data)
db.add(checklist)
await db.flush()
for item in items_data:
ci = EqpChecklistItem(checklist_id=checklist.id, **item.model_dump())
db.add(ci)
await db.flush()
return Response.ok(EqpChecklistOut.model_validate(checklist))
@router.put("/checklists/{checklist_id}", response_model=Response[EqpChecklistOut])
async def update_checklist(checklist_id: int, body: EqpChecklistUpdate, db: AsyncSession = Depends(get_db), _=Depends(get_current_user)):
r = await db.execute(select(EqpChecklist).where(EqpChecklist.id == checklist_id))
checklist = r.scalar_one_or_none()
if not checklist:
raise HTTPException(status_code=404, detail="模板不存在")
for k, v in body.model_dump(exclude_none=True).items():
setattr(checklist, k, v)
await db.flush()
return Response.ok(EqpChecklistOut.model_validate(checklist))
@router.get("/checklists/{checklist_id}/items", response_model=Response[list[EqpChecklistItemOut]])
async def list_checklist_items(checklist_id: int, db: AsyncSession = Depends(get_db), _=Depends(get_current_user)):
r = await db.execute(
select(EqpChecklistItem).where(EqpChecklistItem.checklist_id == checklist_id)
.order_by(EqpChecklistItem.sort_order, EqpChecklistItem.id)
)
return Response.ok([EqpChecklistItemOut.model_validate(i) for i in r.scalars()])
@router.post("/checklist-items", response_model=Response[EqpChecklistItemOut])
async def create_checklist_item(
body: EqpChecklistItemCreate,
checklist_id: int,
db: AsyncSession = Depends(get_db),
_=Depends(get_current_user),
):
item = EqpChecklistItem(checklist_id=checklist_id, **body.model_dump())
db.add(item)
await db.flush()
return Response.ok(EqpChecklistItemOut.model_validate(item))
# ─── 巡检记录 ────────────────────────────────────────────────────────────────
@router.get("/records", response_model=Response[PageResponse[EqpInspectionRecordOut]])
async def list_records(
page: int = 1,
page_size: int = 20,
checklist_id: Optional[int] = None,
status: Optional[str] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
db: AsyncSession = Depends(get_db),
_=Depends(get_current_user),
):
query = select(EqpInspectionRecord).order_by(desc(EqpInspectionRecord.created_at))
if checklist_id:
query = query.where(EqpInspectionRecord.checklist_id == checklist_id)
if status:
query = query.where(EqpInspectionRecord.status == status)
if start_date:
query = query.where(EqpInspectionRecord.inspect_time >= datetime.fromisoformat(start_date))
if end_date:
query = query.where(EqpInspectionRecord.inspect_time <= datetime.fromisoformat(end_date + "T23:59:59"))
total = (await db.execute(select(func.count()).select_from(query.subquery()))).scalar()
rows = await db.execute(query.offset((page - 1) * page_size).limit(page_size))
items = [EqpInspectionRecordOut.model_validate(r) for r in rows.scalars()]
return Response.ok(PageResponse(total=total, page=page, page_size=page_size, items=items))
@router.post("/records", response_model=Response[EqpInspectionRecordOut])
async def create_record(body: EqpInspectionRecordCreate, db: AsyncSession = Depends(get_db), _=Depends(get_current_user)):
details_data = body.details or []
# get checklist name
cl_r = await db.execute(select(EqpChecklist).where(EqpChecklist.id == body.checklist_id))
cl = cl_r.scalar_one_or_none()
data = body.model_dump(exclude={"details"})
record = EqpInspectionRecord(**data, checklist_name=cl.name if cl else None)
db.add(record)
await db.flush()
for d in details_data:
detail = EqpInspectionDetail(record_id=record.id, **d.model_dump())
db.add(detail)
await db.flush()
return Response.ok(EqpInspectionRecordOut.model_validate(record))
@router.get("/records/{record_id}/details", response_model=Response[list[EqpInspectionDetailOut]])
async def get_record_details(record_id: int, db: AsyncSession = Depends(get_db), _=Depends(get_current_user)):
r = await db.execute(
select(EqpInspectionDetail).where(EqpInspectionDetail.record_id == record_id).order_by(EqpInspectionDetail.id)
)
return Response.ok([EqpInspectionDetailOut.model_validate(d) for d in r.scalars()])