Bankbot / backend /app /goals /router.py
mohsin-devs's picture
feat: implement Goals, Loans, and Settings pages with real APIs
6a71f57
Raw
History Blame Contribute Delete
3.05 kB
from datetime import datetime
from typing import Optional
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel, Field
from sqlalchemy.orm import Session
from app.database.database import get_db
from app.database.models import Goal, User
router = APIRouter(prefix="/api/goals", tags=["Goals"])
def _resolve_user(db: Session, user_id: Optional[str]) -> str:
if user_id:
return user_id
user = db.query(User).first()
if not user:
raise HTTPException(status_code=404, detail="No users found. Seed the database first.")
return user.id
class ContributeRequest(BaseModel):
amount: float = Field(gt=0)
@router.get("")
def list_goals(user_id: Optional[str] = None, db: Session = Depends(get_db)):
uid = _resolve_user(db, user_id)
goals = db.query(Goal).filter(Goal.user_id == uid).order_by(Goal.target_date.asc()).all()
items = []
total_target = 0.0
total_saved = 0.0
for g in goals:
progress = min(100.0, (g.current_amount / g.target_amount * 100) if g.target_amount > 0 else 0)
total_target += g.target_amount
total_saved += g.current_amount
days_left = None
if g.target_date:
days_left = max(0, (g.target_date.replace(tzinfo=None) - datetime.utcnow()).days)
plan = g.ai_generated_plan or {}
items.append({
"id": g.id,
"title": g.title,
"target_amount": g.target_amount,
"current_amount": g.current_amount,
"progress_percent": round(progress, 1),
"target_date": g.target_date.isoformat() if g.target_date else None,
"days_left": days_left,
"monthly_contribution": plan.get("monthly_contribution"),
"months_remaining": plan.get("months_remaining"),
"on_track": progress >= 50 or (days_left is not None and days_left > 180),
})
return {
"goals": items,
"summary": {
"count": len(items),
"total_target": round(total_target, 2),
"total_saved": round(total_saved, 2),
"overall_progress": round(total_saved / total_target * 100, 1) if total_target > 0 else 0,
},
}
@router.post("/{goal_id}/contribute")
def contribute_to_goal(
goal_id: str,
body: ContributeRequest,
user_id: Optional[str] = None,
db: Session = Depends(get_db),
):
uid = _resolve_user(db, user_id)
goal = db.query(Goal).filter(Goal.id == goal_id, Goal.user_id == uid).first()
if not goal:
raise HTTPException(status_code=404, detail="Goal not found")
goal.current_amount = min(goal.target_amount, goal.current_amount + body.amount)
db.commit()
db.refresh(goal)
progress = min(100.0, goal.current_amount / goal.target_amount * 100) if goal.target_amount > 0 else 0
return {
"id": goal.id,
"current_amount": goal.current_amount,
"progress_percent": round(progress, 1),
"completed": goal.current_amount >= goal.target_amount,
}