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