mirror of
https://github.com/escalante29/WealthySmart.git
synced 2026-07-17 17:48:46 +02:00
All 29 call sites now use app.timeutil.utcnow(), which returns naive UTC via the non-deprecated API. Semantics are unchanged on purpose: every datetime column is TIMESTAMP WITHOUT TIME ZONE, so going aware here would poison naive/aware comparisons. The TIMESTAMPTZ migration (Phase 2) now has a single place to change. (BE-01) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
85 lines
2.5 KiB
Python
85 lines
2.5 KiB
Python
from datetime import datetime
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Path
|
|
from sqlmodel import Session, col, select
|
|
|
|
from app.auth import get_current_user
|
|
from app.db import get_session
|
|
from app.timeutil import utcnow
|
|
from app.models.models import (
|
|
SavingsAccrual,
|
|
SavingsAccrualCreate,
|
|
SavingsAccrualRead,
|
|
SavingsAccrualUpdate,
|
|
)
|
|
|
|
router = APIRouter(prefix="/savings-accrual", tags=["savings-accrual"])
|
|
|
|
|
|
@router.get("/", response_model=list[SavingsAccrualRead])
|
|
def list_accruals(
|
|
session: Session = Depends(get_session),
|
|
_user: str = Depends(get_current_user),
|
|
):
|
|
query = select(SavingsAccrual).order_by(
|
|
col(SavingsAccrual.year).desc(), col(SavingsAccrual.month).desc()
|
|
)
|
|
return session.exec(query).all()
|
|
|
|
|
|
@router.post("/", response_model=SavingsAccrualRead, status_code=201)
|
|
def create_accrual(
|
|
data: SavingsAccrualCreate,
|
|
session: Session = Depends(get_session),
|
|
_user: str = Depends(get_current_user),
|
|
):
|
|
existing = session.exec(
|
|
select(SavingsAccrual).where(
|
|
SavingsAccrual.year == data.year,
|
|
SavingsAccrual.month == data.month,
|
|
)
|
|
).first()
|
|
if existing:
|
|
raise HTTPException(
|
|
status_code=409,
|
|
detail=f"Accrual for {data.year}-{data.month:02d} already exists (id={existing.id})",
|
|
)
|
|
accrual = SavingsAccrual.model_validate(data)
|
|
accrual.applied_at = utcnow()
|
|
session.add(accrual)
|
|
session.commit()
|
|
session.refresh(accrual)
|
|
return accrual
|
|
|
|
|
|
@router.patch("/{accrual_id}", response_model=SavingsAccrualRead)
|
|
def update_accrual(
|
|
accrual_id: int,
|
|
data: SavingsAccrualUpdate,
|
|
session: Session = Depends(get_session),
|
|
_user: str = Depends(get_current_user),
|
|
):
|
|
accrual = session.get(SavingsAccrual, accrual_id)
|
|
if not accrual:
|
|
raise HTTPException(status_code=404, detail="Accrual not found")
|
|
update_data = data.model_dump(exclude_unset=True)
|
|
for key, value in update_data.items():
|
|
setattr(accrual, key, value)
|
|
session.add(accrual)
|
|
session.commit()
|
|
session.refresh(accrual)
|
|
return accrual
|
|
|
|
|
|
@router.delete("/{accrual_id}", status_code=204)
|
|
def delete_accrual(
|
|
accrual_id: int = Path(...),
|
|
session: Session = Depends(get_session),
|
|
_user: str = Depends(get_current_user),
|
|
):
|
|
accrual = session.get(SavingsAccrual, accrual_id)
|
|
if not accrual:
|
|
raise HTTPException(status_code=404, detail="Accrual not found")
|
|
session.delete(accrual)
|
|
session.commit()
|