from fastapi import APIRouter, Depends, HTTPException, Query, status from sqlalchemy import or_, select from sqlalchemy.orm import Session from app.database import get_db from app.deps import require_roles from app.models import Equipment, Personnel, Role from app.schemas import EquipmentCreate, EquipmentOut, PageResponse from app.services.attendance_points import accessible_point_names, require_attendance_point_access from app.services.common import normalize_device_no, paginate from app.services.serializers import equipment_out router = APIRouter(prefix="/api/equipment", tags=["equipment"]) EQUIPMENT_TYPES = {"冲压设备", "清洗设备"} @router.get("", response_model=PageResponse) def list_equipment( attendance_point_name: str = "", keyword: str = "", device_type: str = "", page: int = Query(1, ge=1), page_size: int = Query(10, ge=1, le=100), user: Personnel = Depends(require_roles(Role.worker, Role.admin, Role.manager)), db: Session = Depends(get_db), ) -> PageResponse: point_names = accessible_point_names(db, user) query = select(Equipment).where(Equipment.attendance_point_name.in_(point_names)).order_by(Equipment.updated_at.desc(), Equipment.device_no.asc()) if attendance_point_name: try: point_name = require_attendance_point_access(db, user, attendance_point_name) except (ValueError, PermissionError) as exc: raise HTTPException(status_code=403, detail=str(exc)) from exc query = query.where(Equipment.attendance_point_name == point_name) if device_type: query = query.where(Equipment.device_type == device_type) if keyword: like = f"%{keyword}%" query = query.where( or_( Equipment.attendance_point_name.like(like), Equipment.device_no.like(like), Equipment.device_type.like(like), Equipment.remark.like(like), ) ) result = paginate(db, query, page, page_size) return PageResponse(**{**result, "rows": [equipment_out(row) for row in result["rows"]]}) @router.post("", response_model=EquipmentOut) def save_equipment( payload: EquipmentCreate, user: Personnel = Depends(require_roles(Role.admin)), db: Session = Depends(get_db), ) -> EquipmentOut: try: point_name = require_attendance_point_access(db, user, payload.attendance_point_name) except ValueError as exc: raise HTTPException(status_code=400, detail=str(exc)) from exc except PermissionError as exc: raise HTTPException(status_code=403, detail=str(exc)) from exc device_no = normalize_device_no(payload.device_no) if not device_no: raise HTTPException(status_code=400, detail="请输入设备号") if payload.device_type not in EQUIPMENT_TYPES: raise HTTPException(status_code=400, detail="设备类型只能是冲压设备或清洗设备") original_point_name = payload.original_attendance_point_name or point_name original_device_no = normalize_device_no(payload.original_device_no) or device_no original_key = {"attendance_point_name": original_point_name, "device_no": original_device_no} next_key = {"attendance_point_name": point_name, "device_no": device_no} equipment = db.get(Equipment, original_key) if equipment is not None and original_key != next_key: existed = db.get(Equipment, next_key) if existed is not None: raise HTTPException(status_code=409, detail="该设备号已存在,不能重复保存") equipment.attendance_point_name = point_name equipment.device_no = device_no elif equipment is None: equipment = db.get(Equipment, next_key) if equipment is None: equipment = Equipment(attendance_point_name=point_name, device_no=device_no) db.add(equipment) equipment.device_type = payload.device_type equipment.remark = payload.remark db.commit() db.refresh(equipment) return equipment_out(equipment) @router.delete("/{device_no}", status_code=204) def delete_equipment( device_no: str, attendance_point_name: str, user: Personnel = Depends(require_roles(Role.admin)), db: Session = Depends(get_db), ) -> None: try: point_name = require_attendance_point_access(db, user, attendance_point_name) except (ValueError, PermissionError) as exc: raise HTTPException(status_code=403, detail=str(exc)) from exc equipment = db.get(Equipment, {"attendance_point_name": point_name, "device_no": normalize_device_no(device_no)}) if equipment is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="设备不存在") db.delete(equipment) db.commit()