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