|
from __future__ import annotations |
|
|
|
from datetime import datetime |
|
from typing import List, Optional |
|
from pydantic import BaseModel, Field, field_validator |
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
MONTHS = [ |
|
"January","February","March","April","May","June", |
|
"July","August","September","October","November","December" |
|
] |
|
|
|
def normalize_month_name(name: str) -> str: |
|
|
|
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}" |
|
|