budget/pfbudget/db/model.py

123 lines
3.0 KiB
Python

from __future__ import annotations
from sqlalchemy import (
BigInteger,
Enum,
ForeignKey,
MetaData,
Numeric,
String,
Text,
)
from sqlalchemy.orm import (
DeclarativeBase,
Mapped,
mapped_column,
MappedAsDataclass,
relationship,
)
from decimal import Decimal
from typing import Annotated, Optional
import datetime as dt
import enum
class Base(MappedAsDataclass, DeclarativeBase):
__table_args__ = {"schema": "transactions"}
metadata = MetaData(
naming_convention={
"ix": "ix_%(column_0_label)s",
"uq": "uq_%(table_name)s_%(column_0_name)s",
"ck": "ck_%(table_name)s_`%(constraint_name)s`",
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
"pk": "pk_%(table_name)s",
}
)
class AccountType(enum.Enum):
checking = enum.auto()
savings = enum.auto()
investment = enum.auto()
mealcard = enum.auto()
VISA = enum.auto()
MASTERCARD = enum.auto()
accounttype = Annotated[
AccountType,
mapped_column(Enum(AccountType, inherit_schema=True)),
]
class Bank(Base):
__tablename__ = "banks"
name: Mapped[str] = mapped_column(unique=True)
BIC: Mapped[str] = mapped_column(String(8), primary_key=True)
type: Mapped[accounttype] = mapped_column(primary_key=True)
bankfk = Annotated[str, mapped_column(Text, ForeignKey(Bank.name))]
idpk = Annotated[int, mapped_column(BigInteger, primary_key=True)]
money = Annotated[Decimal, mapped_column(Numeric(16, 2), nullable=False)]
class Original(Base):
__tablename__ = "originals"
id: Mapped[idpk] = mapped_column(autoincrement=True)
date: Mapped[dt.date]
description: Mapped[Optional[str]]
bank: Mapped[bankfk]
amount: Mapped[money]
category: Mapped[Category] = relationship(back_populates="original")
note: Mapped[Note] = relationship(back_populates="original")
tags: Mapped[set[Tag]] = relationship(
back_populates="original", cascade="all, delete-orphan", passive_deletes=True
)
idfk = Annotated[
int, mapped_column(BigInteger, ForeignKey(Original.id, ondelete="CASCADE"))
]
class Category(Base):
__tablename__ = "categorized"
id: Mapped[idfk] = mapped_column(primary_key=True)
category: Mapped[str]
original: Mapped[Original] = relationship(back_populates="category")
class Note(Base):
__tablename__ = "notes"
id: Mapped[idfk] = mapped_column(primary_key=True)
note: Mapped[str]
original: Mapped[Original] = relationship(back_populates="note")
class Nordigen(Base):
__tablename__ = "nordigen"
name: Mapped[bankfk] = mapped_column(primary_key=True)
bank_id: Mapped[Optional[str]]
requisition_id: Mapped[Optional[str]]
invert: Mapped[Optional[bool]]
class Tag(Base):
__tablename__ = "tags"
id: Mapped[idfk] = mapped_column(primary_key=True)
tag: Mapped[str] = mapped_column(primary_key=True)
original: Mapped[Original] = relationship(back_populates="tags")