Files
finance/backend/app/categorization/models.py
T
k1nq 63d065011b Update manifest.json and infra README
- Updated timestamps and AST hashes in manifest.json for various backend and frontend files to reflect recent changes.
- Added new files related to MCC categories and optional hold reasons in the manifest.
- Modified the README in the infra directory to correct the linting tool from 'mypy' to 'ty' for type checking in the backend project.
2026-09-23 10:57:27 +05:00

142 lines
5.0 KiB
Python

import uuid
from sqlalchemy import (
Boolean,
ForeignKey,
ForeignKeyConstraint,
Integer,
String,
UniqueConstraint,
Uuid,
)
from sqlalchemy.orm import Mapped, mapped_column
from app.db.base import Base, PkMixin, TimestampMixin
class IncomeSource(Base, PkMixin, TimestampMixin):
__tablename__ = "income_sources"
__table_args__ = (
UniqueConstraint("space_id", "name", name="uq_income_sources_space_name"),
UniqueConstraint("space_id", "id", name="uq_income_sources_space_id"),
)
space_id: Mapped[uuid.UUID] = mapped_column(
Uuid, ForeignKey("financial_spaces.id", ondelete="CASCADE"), nullable=False, index=True
)
name: Mapped[str] = mapped_column(String(200), nullable=False)
archived: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
class Payee(Base, PkMixin, TimestampMixin):
__tablename__ = "payees"
__table_args__ = (
UniqueConstraint("space_id", "name", name="uq_payees_space_name"),
UniqueConstraint("space_id", "id", name="uq_payees_space_id"),
)
space_id: Mapped[uuid.UUID] = mapped_column(
Uuid, ForeignKey("financial_spaces.id", ondelete="CASCADE"), nullable=False, index=True
)
name: Mapped[str] = mapped_column(String(200), nullable=False)
archived: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
class PayeeAlias(Base, PkMixin, TimestampMixin):
__tablename__ = "payee_aliases"
__table_args__ = (
UniqueConstraint("space_id", "alias", name="uq_payee_aliases_space_alias"),
ForeignKeyConstraint(
["space_id", "payee_id"],
["payees.space_id", "payees.id"],
ondelete="CASCADE",
name="fk_payee_aliases_payee_tenant",
),
)
space_id: Mapped[uuid.UUID] = mapped_column(
Uuid, ForeignKey("financial_spaces.id", ondelete="CASCADE"), nullable=False, index=True
)
payee_id: Mapped[uuid.UUID] = mapped_column(Uuid, nullable=False, index=True)
alias: Mapped[str] = mapped_column(String(300), nullable=False)
class CategorizationRule(Base, PkMixin, TimestampMixin):
"""Confirmed payee rule: auto-applies category to matching future operations."""
__tablename__ = "categorization_rules"
__table_args__ = (
UniqueConstraint("space_id", "payee_id", name="uq_rules_space_payee"),
ForeignKeyConstraint(
["space_id", "payee_id"],
["payees.space_id", "payees.id"],
ondelete="CASCADE",
name="fk_rules_payee_tenant",
),
ForeignKeyConstraint(
["space_id", "category_id"],
["categories.space_id", "categories.id"],
name="fk_rules_category_tenant",
),
)
space_id: Mapped[uuid.UUID] = mapped_column(
Uuid, ForeignKey("financial_spaces.id", ondelete="CASCADE"), nullable=False, index=True
)
payee_id: Mapped[uuid.UUID] = mapped_column(Uuid, nullable=False)
category_id: Mapped[uuid.UUID] = mapped_column(Uuid, nullable=False)
created_by_user_id: Mapped[uuid.UUID | None] = mapped_column(
Uuid, ForeignKey("users.id", ondelete="SET NULL"), nullable=True
)
class MccCode(Base):
"""Global versioned MCC dictionary (not space-scoped, outside RLS)."""
__tablename__ = "mcc_codes"
code: Mapped[int] = mapped_column(Integer, primary_key=True)
title: Mapped[str] = mapped_column(String(300), nullable=False)
dictionary_version: Mapped[int] = mapped_column(nullable=False, default=1)
class CategoryMcc(Base, PkMixin):
"""Space-scoped MCC codes of a category: many codes per category, but every
code maps to at most one category inside the space."""
__tablename__ = "category_mcc_codes"
__table_args__ = (
UniqueConstraint("space_id", "mcc_code", name="uq_category_mcc_space_code"),
ForeignKeyConstraint(
["space_id", "category_id"],
["categories.space_id", "categories.id"],
ondelete="CASCADE",
name="fk_category_mcc_category_tenant",
),
ForeignKeyConstraint(
["mcc_code"],
["mcc_codes.code"],
ondelete="RESTRICT",
name="fk_category_mcc_dictionary",
),
)
space_id: Mapped[uuid.UUID] = mapped_column(
Uuid, ForeignKey("financial_spaces.id", ondelete="CASCADE"), nullable=False, index=True
)
category_id: Mapped[uuid.UUID] = mapped_column(Uuid, nullable=False, index=True)
mcc_code: Mapped[int] = mapped_column(Integer, nullable=False)
class BankCategoryMapping(Base, PkMixin):
"""Maps a bank's raw category string to an MCC for suggestion purposes."""
__tablename__ = "bank_category_mappings"
__table_args__ = (
UniqueConstraint("bank_code", "bank_category", name="uq_bank_mappings_bank_category"),
)
bank_code: Mapped[str] = mapped_column(String(32), nullable=False, index=True)
bank_category: Mapped[str] = mapped_column(String(200), nullable=False)
mcc_code: Mapped[int | None] = mapped_column(Integer, nullable=True)