File size: 1,407 Bytes
fade1d6 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
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}"
|