diff --git a/alembic/versions/d18cbd50f7c6_category_schedule.py b/alembic/versions/d18cbd50f7c6_category_schedule.py new file mode 100644 index 0000000..c6da5ab --- /dev/null +++ b/alembic/versions/d18cbd50f7c6_category_schedule.py @@ -0,0 +1,53 @@ +"""Category schedule + +Revision ID: d18cbd50f7c6 +Revises: 6863dda76ea2 +Create Date: 2022-12-08 13:30:29.048811+00:00 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = "d18cbd50f7c6" +down_revision = "6863dda76ea2" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.create_table( + "categories_schedules", + sa.Column("name", sa.String(), nullable=False), + sa.Column("recurring", sa.Boolean(), nullable=False), + sa.Column( + "period", + sa.Enum( + "daily", + "monthly", + "yearly", + name="period", + schema="transactions", + inherit_schema=True, + ), + nullable=True, + ), + sa.Column("period_multiplier", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["name"], + ["transactions.categories_available.name"], + name=op.f("fk_categories_schedules_name_categories_available"), + ondelete="CASCADE", + ), + sa.PrimaryKeyConstraint("name", name=op.f("pk_categories_schedules")), + schema="transactions", + ) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table("categories_schedules", schema="transactions") + # ### end Alembic commands ### diff --git a/pfbudget/db/model.py b/pfbudget/db/model.py index 6bc0ef9..a852768 100644 --- a/pfbudget/db/model.py +++ b/pfbudget/db/model.py @@ -107,6 +107,7 @@ class Category(Base): rules: Mapped[Optional[set[CategoryRule]]] = relationship( cascade="all, delete-orphan", passive_deletes=True ) + schedule: Mapped[CategorySchedule] = relationship() def __repr__(self) -> str: return ( @@ -114,6 +115,12 @@ class Category(Base): ) +catfk = Annotated[ + str, + mapped_column(ForeignKey(Category.name, ondelete="CASCADE")), +] + + class TransactionCategory(Base): __tablename__ = "categorized" @@ -127,12 +134,6 @@ class TransactionCategory(Base): return f"Category({self.name})" -catfk = Annotated[ - int, - mapped_column(BigInteger, ForeignKey(TransactionCategory.id, ondelete="CASCADE")), -] - - class Note(Base): __tablename__ = "notes" @@ -192,7 +193,29 @@ categoryselector = Annotated[ class CategorySelector(Base): __tablename__ = "categories_selector" - id: Mapped[catfk] = mapped_column(primary_key=True) + id: Mapped[int] = mapped_column( + BigInteger, + ForeignKey(TransactionCategory.id, ondelete="CASCADE"), + primary_key=True, + ) selector: Mapped[categoryselector] category: Mapped[TransactionCategory] = relationship(back_populates="selector") + + +class Period(enum.Enum): + daily = enum.auto() + monthly = enum.auto() + yearly = enum.auto() + + +scheduleperiod = Annotated[Selector, mapped_column(Enum(Period, inherit_schema=True))] + + +class CategorySchedule(Base): + __tablename__ = "categories_schedules" + + name: Mapped[catfk] = mapped_column(primary_key=True) + recurring: Mapped[bool] + period: Mapped[Optional[scheduleperiod]] + period_multiplier: Mapped[Optional[int]]