| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- from typing import Optional
- from datetime import date
- from uuid import UUID
- from fastapi import APIRouter, Depends, HTTPException, Query
- from sqlalchemy import func, select
- from sqlalchemy.ext.asyncio import AsyncSession
- from backend.app.core.dependencies import require_permissions, get_current_user
- from backend.app.db.session import get_db
- from backend.app.models import DutyItem, User
- from backend.app.schemas.pagination import PaginatedResponse
- from backend.app.schemas.duty import DutyCreate, DutyResponse, DutyUpdate
- router = APIRouter(prefix="/duty", tags=["duty"])
- def is_limited_scope(user: User) -> bool:
- return user.role and user.role.name not in {"管理员", "排班员"}
- @router.get(
- "",
- response_model=list[DutyResponse] | PaginatedResponse[DutyResponse],
- dependencies=[Depends(require_permissions(["duty.view"]))],
- )
- async def list_duty(
- db: AsyncSession = Depends(get_db),
- current_user: User = Depends(get_current_user),
- start: Optional[str] = Query(default=None),
- end: Optional[str] = Query(default=None),
- page: Optional[int] = Query(default=None, ge=1),
- page_size: Optional[int] = Query(default=None, ge=1, le=200, alias="pageSize"),
- size: Optional[int] = Query(default=None, ge=1, le=200),
- ):
- query = select(DutyItem)
- if is_limited_scope(current_user) and current_user.dept_id:
- query = query.where(DutyItem.staff_id == current_user.id)
- if start:
- query = query.where(DutyItem.date >= date.fromisoformat(start))
- if end:
- query = query.where(DutyItem.date <= date.fromisoformat(end))
- if page is None and page_size is None and size is None:
- result = await db.execute(query.order_by(DutyItem.date))
- return result.scalars().all()
- page_value = page or 1
- size_value = page_size or size or 10
- total = await db.scalar(select(func.count()).select_from(query.subquery()))
- result = await db.execute(
- query.order_by(DutyItem.date)
- .offset((page_value - 1) * size_value)
- .limit(size_value)
- )
- return {
- "items": result.scalars().all(),
- "total": total or 0,
- "page": page_value,
- "pageSize": size_value,
- }
- @router.post("", response_model=DutyResponse, dependencies=[Depends(require_permissions(["duty.create"]))])
- async def create_duty(
- payload: DutyCreate,
- db: AsyncSession = Depends(get_db),
- ):
- item = DutyItem(
- date=date.fromisoformat(payload.date),
- staff_id=payload.staff_id,
- duty_type=payload.duty_type,
- contact=payload.contact,
- note=payload.note
- )
- db.add(item)
- await db.commit()
- await db.refresh(item)
- return item
- @router.put("/{item_id}", response_model=DutyResponse, dependencies=[Depends(require_permissions(["duty.edit"]))])
- async def update_duty(item_id: UUID, payload: DutyUpdate, db: AsyncSession = Depends(get_db)):
- result = await db.execute(select(DutyItem).where(DutyItem.id == item_id))
- item = result.scalar_one_or_none()
- if not item:
- raise HTTPException(status_code=404, detail="值班不存在")
- update_data = payload.model_dump(exclude_unset=True)
- if "date" in update_data and update_data["date"]:
- update_data["date"] = date.fromisoformat(update_data["date"])
- for key, value in update_data.items():
- setattr(item, key, value)
- await db.commit()
- await db.refresh(item)
- return item
- @router.delete("/{item_id}", dependencies=[Depends(require_permissions(["duty.delete"]))])
- async def delete_duty(item_id: UUID, db: AsyncSession = Depends(get_db)):
- result = await db.execute(select(DutyItem).where(DutyItem.id == item_id))
- item = result.scalar_one_or_none()
- if not item:
- raise HTTPException(status_code=404, detail="值班不存在")
- await db.delete(item)
- await db.commit()
- return {"success": True}
|