utility functions for category
This commit is contained in:
+47
-3
@@ -1,9 +1,12 @@
|
||||
from pydantic import Field, computed_field
|
||||
from sqlalchemy import ForeignKey, String, UniqueConstraint
|
||||
from datetime import date
|
||||
from decimal import Decimal
|
||||
from typing import Self
|
||||
|
||||
from pydantic import BaseModel, Field, computed_field, model_validator
|
||||
from sqlalchemy import Date, ForeignKey, Numeric, String, UniqueConstraint
|
||||
from sqlalchemy.orm import Mapped, Session, mapped_column, relationship
|
||||
|
||||
from src.db_utils import upsert
|
||||
from src.models.category_budget import CategoryBudgetDb
|
||||
from src.models.common import BaseModelDb, ExportBaseModel, hashify
|
||||
|
||||
|
||||
@@ -74,3 +77,44 @@ def upsert_category(
|
||||
do_update=False,
|
||||
do_commit=do_commit,
|
||||
)
|
||||
|
||||
|
||||
class CategoryBudget(BaseModel):
|
||||
category: Category
|
||||
amount_eur: Decimal = Field(gt=0, decimal_places=2)
|
||||
valid_from: date | None = Field(
|
||||
description="Start of validity. None means unbounded"
|
||||
)
|
||||
valid_to: date | None = Field(description="End of validity. None means unbounded")
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_date_range(self) -> Self:
|
||||
if (
|
||||
self.valid_from is not None
|
||||
and self.valid_to is not None
|
||||
and self.valid_from > self.valid_to
|
||||
):
|
||||
raise ValueError(
|
||||
f"`valid_from` ({self.valid_from}) and valid_to ({self.valid_to}) are nor in order"
|
||||
)
|
||||
return self
|
||||
|
||||
|
||||
class CategoryBudgetDb(BaseModelDb):
|
||||
"""Budget amount for a category, optionally bounded to a time window.
|
||||
|
||||
Satellite table to ``category``: one category may have several budgets
|
||||
(e.g. one per month). ``valid_from``/``valid_to`` are nullable; ``None``
|
||||
means unbounded on that side.
|
||||
"""
|
||||
|
||||
__tablename__ = "category_budget"
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
||||
category_id: Mapped[int] = mapped_column(ForeignKey("category.id"), nullable=False)
|
||||
amount_eur: Mapped[Decimal] = mapped_column(Numeric(12, 2), nullable=False)
|
||||
valid_from: Mapped[date | None] = mapped_column(Date, nullable=True, default=None)
|
||||
valid_to: Mapped[date | None] = mapped_column(Date, nullable=True, default=None)
|
||||
|
||||
# relationship
|
||||
category = relationship("CategoryDb", back_populates="budgets")
|
||||
|
||||
Reference in New Issue
Block a user