Add expense creation API endpoint

This commit is contained in:
2025-12-27 13:32:16 +01:00
parent 7525d2b2ed
commit 6bf56d7537
5 changed files with 71 additions and 23 deletions

View File

@@ -1,13 +1,9 @@
"""API routes aggregation."""
from fastapi import APIRouter
from mft.routes import auth, categories, health
from mft.routes import auth, categories, expense, health
api_router = APIRouter()
# Include all route modules
api_router.include_router(health.router, tags=["health"])
api_router.include_router(auth.router, prefix="/auth", tags=["auth"])
api_router.include_router(categories.router, tags=["categories"])
api_router.include_router(expense.router, tags=["expenses"])

View File

@@ -1,10 +1,6 @@
"""Authentication routes."""
from fastapi import APIRouter, Depends
from mft.auth import verify_token
router = APIRouter()
@@ -19,8 +15,4 @@ async def validate(user_id: int = Depends(verify_token)):
Returns:
A simple status response with the authenticated user ID
"""
return {
"status": "ok",
"user_id": user_id,
"message": "Successfully authenticated"
}
return {"status": "ok", "user_id": user_id, "message": "Successfully authenticated"}

View File

@@ -1,12 +1,8 @@
"""Category endpoints."""
from fastapi import APIRouter, Depends
from pydantic import BaseModel
from mft.auth import verify_token
from mft.database import get_db
router = APIRouter()

68
mft/routes/expense.py Normal file
View File

@@ -0,0 +1,68 @@
import sqlite3
from datetime import datetime, timezone
from fastapi import APIRouter, HTTPException, status, Depends
from pydantic import BaseModel, Field
from mft.auth import verify_token
from mft.database import get_db
router = APIRouter()
class ExpenseCreate(BaseModel):
cid: int = Field(..., description="Category ID")
value: int = Field(..., gt=0, description="Amount in cents")
note: str | None = Field(None, description="Optional note")
class Expense(BaseModel):
id: int
uid: int
cid: int
ts: str
value: int
note: str | None
@router.post("/expenses", response_model=Expense, status_code=status.HTTP_201_CREATED)
def create_expense(expense: ExpenseCreate, uid: int = Depends(verify_token)):
"""
Create a new expense entry.
Args:
expense: Expense data (category ID, value in cents, optional note)
uid: User ID from authentication token
Returns:
The created expense with generated ID and timestamp
Raises:
400: Invalid category ID or constraint violation
"""
timestamp = datetime.now(timezone.utc).isoformat()
with get_db() as conn:
cursor = conn.cursor()
try:
cursor.execute(
"""
INSERT INTO expense (uid, cid, ts, value, note)
VALUES (?, ?, ?, ?, ?)
""",
(uid, expense.cid, timestamp, expense.value, expense.note),
)
conn.commit()
expense_id = cursor.lastrowid
return Expense(
id=expense_id,
uid=uid,
cid=expense.cid,
ts=timestamp,
value=expense.value,
note=expense.note,
)
except sqlite3.IntegrityError as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Invalid request: constraint violation",
) from e

View File

@@ -1,12 +1,8 @@
"""Health check and status endpoints."""
from fastapi import APIRouter
router = APIRouter()
@router.get("/status")
async def status():
"""Minimal status check to verify the API is up."""
return {"status": "ok"}