Extract Category model into src/models/category.py
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
from pydantic import Field, computed_field
|
||||
from sqlalchemy import ForeignKey, String, UniqueConstraint
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from src.models._common import BaseModelDb, ExportBaseModel, _hash
|
||||
|
||||
|
||||
class Category(ExportBaseModel):
|
||||
name: str = Field(pattern=r"[^:\r\n]+")
|
||||
parent: Category | None = None
|
||||
|
||||
@computed_field # type: ignore[prop-decorator]
|
||||
@property
|
||||
def hash_id(self) -> str:
|
||||
return _hash(self.name, self.parent)
|
||||
|
||||
@classmethod
|
||||
def from_str(cls, s: str) -> Category | None:
|
||||
if not s:
|
||||
return None
|
||||
components = s.split(":")
|
||||
name = components[-1]
|
||||
rest = ":".join(components[:-1])
|
||||
return cls(name=name, parent=cls.from_str(rest))
|
||||
|
||||
def to_str(self) -> str | None:
|
||||
if not self.parent:
|
||||
return self.name
|
||||
else:
|
||||
return f"{self.parent.to_str()}:{self.name}"
|
||||
|
||||
def __str__(self):
|
||||
return self.to_str()
|
||||
|
||||
def __repr__(self):
|
||||
return f'Category.from_str("{self.__str__()}")'
|
||||
|
||||
|
||||
class CategoryDb(BaseModelDb):
|
||||
__tablename__ = "category"
|
||||
__table_args__ = (
|
||||
UniqueConstraint("name", "parent_id", name="uq_category_name_parent"),
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
||||
name: Mapped[str] = mapped_column(String, nullable=False)
|
||||
parent_id: Mapped[int | None] = mapped_column(
|
||||
ForeignKey("category.id"), nullable=True
|
||||
)
|
||||
|
||||
# Relationships
|
||||
parent = relationship(
|
||||
"CategoryDb", remote_side="CategoryDb.id", back_populates="children"
|
||||
)
|
||||
children = relationship("CategoryDb", back_populates="parent")
|
||||
budgets = relationship("CategoryBudgetDb", back_populates="category")
|
||||
Reference in New Issue
Block a user