from __future__ import annotations from datetime import datetime from typing import List, Optional from pydantic import BaseModel, Field, field_validator # ----- Pydantic Models ----- class ExpenseCategory(BaseModel): category_id: str name: str amount: float = 0.0 color: str = "#cccccc" class MonthlyRecord(BaseModel): id: Optional[str] = Field(None, alias="_id") month: str year: int month_key: str salary: float expenses: List[ExpenseCategory] = [] total_expenses: float = 0.0 remaining: float = 0.0 created_at: datetime updated_at: datetime model_config = { "populate_by_name": True, "json_encoders": {}, } class MonthlyRecordCreate(BaseModel): month: str year: int salary: float expenses: List[ExpenseCategory] = [] class MonthlyRecordUpdate(BaseModel): salary: Optional[float] = None expenses: Optional[List[ExpenseCategory]] = None # ----- Helpers ----- MONTHS = [ "January","February","March","April","May","June", "July","August","September","October","November","December" ] def normalize_month_name(name: str) -> str: # Capitalize properly if user sends 'august' return name.strip().capitalize() def month_key_from(month: str, year: int) -> str: month_norm = normalize_month_name(month) idx = MONTHS.index(month_norm) + 1 return f"{year:04d}-{idx:02d}"