- 일일 공수 입력 기능 - 부적합 사항 등록 (이미지 선택사항) - 날짜별 부적합 조회 (시간순 나열) - 목록 관리 (인라인 편집, 작업시간 확인 버튼) - 보고서 생성 (총 공수/부적합 시간 분리) - JWT 인증 및 권한 관리 - Docker 기반 배포 환경 구성
164 lines
5.2 KiB
Python
164 lines
5.2 KiB
Python
from fastapi import APIRouter, Depends, HTTPException
|
|
from sqlalchemy.orm import Session
|
|
from typing import List, Optional
|
|
from datetime import datetime, date
|
|
|
|
from database.database import get_db
|
|
from database.models import DailyWork, User, UserRole
|
|
from database import schemas
|
|
from routers.auth import get_current_user
|
|
|
|
router = APIRouter(prefix="/api/daily-work", tags=["daily-work"])
|
|
|
|
@router.post("/", response_model=schemas.DailyWork)
|
|
async def create_daily_work(
|
|
work: schemas.DailyWorkCreate,
|
|
current_user: User = Depends(get_current_user),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
# 중복 확인 (같은 날짜)
|
|
existing = db.query(DailyWork).filter(
|
|
DailyWork.date == work.date.date()
|
|
).first()
|
|
if existing:
|
|
raise HTTPException(status_code=400, detail="Daily work for this date already exists")
|
|
|
|
# 계산
|
|
regular_hours = work.worker_count * 8 # 정규 근무 8시간
|
|
overtime_total = work.overtime_workers * work.overtime_hours
|
|
total_hours = regular_hours + overtime_total
|
|
|
|
# 생성
|
|
db_work = DailyWork(
|
|
date=work.date,
|
|
worker_count=work.worker_count,
|
|
regular_hours=regular_hours,
|
|
overtime_workers=work.overtime_workers,
|
|
overtime_hours=work.overtime_hours,
|
|
overtime_total=overtime_total,
|
|
total_hours=total_hours,
|
|
created_by_id=current_user.id
|
|
)
|
|
db.add(db_work)
|
|
db.commit()
|
|
db.refresh(db_work)
|
|
return db_work
|
|
|
|
@router.get("/", response_model=List[schemas.DailyWork])
|
|
async def read_daily_works(
|
|
skip: int = 0,
|
|
limit: int = 100,
|
|
start_date: Optional[date] = None,
|
|
end_date: Optional[date] = None,
|
|
current_user: User = Depends(get_current_user),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
query = db.query(DailyWork)
|
|
|
|
if start_date:
|
|
query = query.filter(DailyWork.date >= start_date)
|
|
if end_date:
|
|
query = query.filter(DailyWork.date <= end_date)
|
|
|
|
works = query.order_by(DailyWork.date.desc()).offset(skip).limit(limit).all()
|
|
return works
|
|
|
|
@router.get("/{work_id}", response_model=schemas.DailyWork)
|
|
async def read_daily_work(
|
|
work_id: int,
|
|
current_user: User = Depends(get_current_user),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
work = db.query(DailyWork).filter(DailyWork.id == work_id).first()
|
|
if not work:
|
|
raise HTTPException(status_code=404, detail="Daily work not found")
|
|
return work
|
|
|
|
@router.put("/{work_id}", response_model=schemas.DailyWork)
|
|
async def update_daily_work(
|
|
work_id: int,
|
|
work_update: schemas.DailyWorkUpdate,
|
|
current_user: User = Depends(get_current_user),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
work = db.query(DailyWork).filter(DailyWork.id == work_id).first()
|
|
if not work:
|
|
raise HTTPException(status_code=404, detail="Daily work not found")
|
|
|
|
# 업데이트
|
|
update_data = work_update.dict(exclude_unset=True)
|
|
|
|
# 재계산 필요한 경우
|
|
if any(key in update_data for key in ["worker_count", "overtime_workers", "overtime_hours"]):
|
|
worker_count = update_data.get("worker_count", work.worker_count)
|
|
overtime_workers = update_data.get("overtime_workers", work.overtime_workers)
|
|
overtime_hours = update_data.get("overtime_hours", work.overtime_hours)
|
|
|
|
regular_hours = worker_count * 8
|
|
overtime_total = overtime_workers * overtime_hours
|
|
total_hours = regular_hours + overtime_total
|
|
|
|
update_data["regular_hours"] = regular_hours
|
|
update_data["overtime_total"] = overtime_total
|
|
update_data["total_hours"] = total_hours
|
|
|
|
for field, value in update_data.items():
|
|
setattr(work, field, value)
|
|
|
|
db.commit()
|
|
db.refresh(work)
|
|
return work
|
|
|
|
@router.delete("/{work_id}")
|
|
async def delete_daily_work(
|
|
work_id: int,
|
|
current_user: User = Depends(get_current_user),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
work = db.query(DailyWork).filter(DailyWork.id == work_id).first()
|
|
if not work:
|
|
raise HTTPException(status_code=404, detail="Daily work not found")
|
|
|
|
# 권한 확인 (관리자만 삭제 가능)
|
|
if current_user.role != UserRole.ADMIN:
|
|
raise HTTPException(status_code=403, detail="Only admin can delete daily work")
|
|
|
|
db.delete(work)
|
|
db.commit()
|
|
return {"detail": "Daily work deleted successfully"}
|
|
|
|
@router.get("/stats/summary")
|
|
async def get_daily_work_stats(
|
|
start_date: Optional[date] = None,
|
|
end_date: Optional[date] = None,
|
|
current_user: User = Depends(get_current_user),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""일일 공수 통계"""
|
|
query = db.query(DailyWork)
|
|
|
|
if start_date:
|
|
query = query.filter(DailyWork.date >= start_date)
|
|
if end_date:
|
|
query = query.filter(DailyWork.date <= end_date)
|
|
|
|
works = query.all()
|
|
|
|
if not works:
|
|
return {
|
|
"total_days": 0,
|
|
"total_hours": 0,
|
|
"total_overtime": 0,
|
|
"average_daily_hours": 0
|
|
}
|
|
|
|
total_hours = sum(w.total_hours for w in works)
|
|
total_overtime = sum(w.overtime_total for w in works)
|
|
|
|
return {
|
|
"total_days": len(works),
|
|
"total_hours": total_hours,
|
|
"total_overtime": total_overtime,
|
|
"average_daily_hours": total_hours / len(works)
|
|
}
|