133 lines
5.5 KiB
Python
133 lines
5.5 KiB
Python
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlalchemy.orm import Session
|
|
from typing import List, Optional
|
|
from datetime import datetime, timezone
|
|
from backend.database import get_db
|
|
from backend.models import User, ChoreType, ChoreCompletion, UserRole, RecurrenceType
|
|
from backend.schemas import ChoreTypeOut, ChoreTypeCreate, ChoreTypeUpdate, ChoreCompletionCreate, ChoreCompletionOut
|
|
from backend.routers.auth import get_current_user, get_admin_user
|
|
from backend.config import get_current_week_identifier
|
|
|
|
router = APIRouter(prefix="/api/chores", tags=["chores"])
|
|
|
|
@router.get("/types", response_model=List[ChoreTypeOut])
|
|
def list_chore_types(db: Session = Depends(get_db), current_user: User = Depends(get_current_user)):
|
|
return db.query(ChoreType).order_by(ChoreType.id.asc()).all()
|
|
|
|
@router.post("/types", response_model=ChoreTypeOut)
|
|
def create_chore_type(chore_in: ChoreTypeCreate, db: Session = Depends(get_db), admin: User = Depends(get_admin_user)):
|
|
if chore_in.star_reward < 1 or chore_in.star_reward > 5:
|
|
raise HTTPException(status_code=400, detail="Star reward must be between 1 and 5")
|
|
|
|
if chore_in.recurrence not in [r.value for r in RecurrenceType]:
|
|
raise HTTPException(status_code=400, detail=f"Invalid recurrence type. Must be daily, weekly, or spontaneous")
|
|
|
|
new_chore = ChoreType(
|
|
title=chore_in.title,
|
|
description=chore_in.description,
|
|
star_reward=chore_in.star_reward,
|
|
recurrence=chore_in.recurrence,
|
|
icon=chore_in.icon
|
|
)
|
|
db.add(new_chore)
|
|
db.commit()
|
|
db.refresh(new_chore)
|
|
return new_chore
|
|
|
|
@router.patch("/types/{chore_id}", response_model=ChoreTypeOut)
|
|
def update_chore_type(chore_id: int, chore_in: ChoreTypeUpdate, db: Session = Depends(get_db), admin: User = Depends(get_admin_user)):
|
|
chore = db.query(ChoreType).filter(ChoreType.id == chore_id).first()
|
|
if not chore:
|
|
raise HTTPException(status_code=404, detail="Chore type not found")
|
|
|
|
if chore_in.title is not None:
|
|
chore.title = chore_in.title
|
|
if chore_in.description is not None:
|
|
chore.description = chore_in.description
|
|
if chore_in.star_reward is not None:
|
|
if chore_in.star_reward < 1 or chore_in.star_reward > 5:
|
|
raise HTTPException(status_code=400, detail="Star reward must be between 1 and 5")
|
|
chore.star_reward = chore_in.star_reward
|
|
if chore_in.recurrence is not None:
|
|
if chore_in.recurrence not in [r.value for r in RecurrenceType]:
|
|
raise HTTPException(status_code=400, detail="Invalid recurrence type")
|
|
chore.recurrence = chore_in.recurrence
|
|
if chore_in.icon is not None:
|
|
chore.icon = chore_in.icon
|
|
|
|
db.commit()
|
|
db.refresh(chore)
|
|
return chore
|
|
|
|
@router.delete("/types/{chore_id}")
|
|
def delete_chore_type(chore_id: int, db: Session = Depends(get_db), admin: User = Depends(get_admin_user)):
|
|
chore = db.query(ChoreType).filter(ChoreType.id == chore_id).first()
|
|
if not chore:
|
|
raise HTTPException(status_code=404, detail="Chore type not found")
|
|
|
|
db.delete(chore)
|
|
db.commit()
|
|
return {"message": "Chore type deleted successfully", "id": chore_id}
|
|
|
|
@router.post("/complete", response_model=ChoreCompletionOut)
|
|
def complete_chore(payload: ChoreCompletionCreate, db: Session = Depends(get_db), current_user: User = Depends(get_current_user)):
|
|
chore_type = db.query(ChoreType).filter(ChoreType.id == payload.chore_type_id).first()
|
|
if not chore_type:
|
|
raise HTTPException(status_code=404, detail="Chore type not found")
|
|
|
|
week_id = get_current_week_identifier()
|
|
now_utc = datetime.now(timezone.utc)
|
|
|
|
completion = ChoreCompletion(
|
|
chore_type_id=chore_type.id,
|
|
user_id=current_user.id,
|
|
completed_at=now_utc,
|
|
stars_earned=chore_type.star_reward,
|
|
week_identifier=week_id,
|
|
notes=payload.notes
|
|
)
|
|
db.add(completion)
|
|
db.commit()
|
|
db.refresh(completion)
|
|
|
|
return ChoreCompletionOut(
|
|
id=completion.id,
|
|
chore_type_id=completion.chore_type_id,
|
|
user_id=completion.user_id,
|
|
completed_at=completion.completed_at,
|
|
stars_earned=completion.stars_earned,
|
|
week_identifier=completion.week_identifier,
|
|
notes=completion.notes,
|
|
user_name=current_user.name,
|
|
user_avatar=current_user.avatar_url,
|
|
chore_title=chore_type.title,
|
|
chore_icon=chore_type.icon
|
|
)
|
|
|
|
@router.get("/completions", response_model=List[ChoreCompletionOut])
|
|
def get_recent_completions(week: Optional[str] = None, user_id: Optional[int] = None, limit: int = 50, db: Session = Depends(get_db), current_user: User = Depends(get_current_user)):
|
|
query = db.query(ChoreCompletion)
|
|
if week:
|
|
query = query.filter(ChoreCompletion.week_identifier == week)
|
|
if user_id:
|
|
query = query.filter(ChoreCompletion.user_id == user_id)
|
|
|
|
completions = query.order_by(ChoreCompletion.completed_at.desc()).limit(limit).all()
|
|
|
|
result = []
|
|
for c in completions:
|
|
result.append(ChoreCompletionOut(
|
|
id=c.id,
|
|
chore_type_id=c.chore_type_id,
|
|
user_id=c.user_id,
|
|
completed_at=c.completed_at,
|
|
stars_earned=c.stars_earned,
|
|
week_identifier=c.week_identifier,
|
|
notes=c.notes,
|
|
user_name=c.user.name if c.user else "Unknown",
|
|
user_avatar=c.user.avatar_url if c.user else None,
|
|
chore_title=c.chore_type.title if c.chore_type else "Chore",
|
|
chore_icon=c.chore_type.icon if c.chore_type else "CheckSquare"
|
|
))
|
|
return result
|