| 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}" |
|
|