Rule inheritance
Both rules, categorries and tags, now derive from the rule base type. This clears up some type definitions.
This commit is contained in:
parent
6110858d48
commit
d4b5f1f11a
152
alembic/versions/6b293f78cc97_rule_inheritance.py
Normal file
152
alembic/versions/6b293f78cc97_rule_inheritance.py
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
"""Rule inheritance
|
||||||
|
|
||||||
|
Revision ID: 6b293f78cc97
|
||||||
|
Revises: 37d80de801a7
|
||||||
|
Create Date: 2023-01-22 20:05:32.887092+00:00
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = "6b293f78cc97"
|
||||||
|
down_revision = "37d80de801a7"
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table(
|
||||||
|
"rules",
|
||||||
|
sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
|
||||||
|
sa.Column("date", sa.Date(), nullable=True),
|
||||||
|
sa.Column("description", sa.String(), nullable=True),
|
||||||
|
sa.Column("regex", sa.String(), nullable=True),
|
||||||
|
sa.Column("bank", sa.String(), nullable=True),
|
||||||
|
sa.Column("min", sa.Numeric(precision=16, scale=2), nullable=True),
|
||||||
|
sa.Column("max", sa.Numeric(precision=16, scale=2), nullable=True),
|
||||||
|
sa.Column("type", sa.String(), nullable=False),
|
||||||
|
sa.PrimaryKeyConstraint("id", name=op.f("pk_rules")),
|
||||||
|
schema="transactions",
|
||||||
|
)
|
||||||
|
op.create_foreign_key(
|
||||||
|
op.f("fk_categories_rules_id_rules"),
|
||||||
|
"categories_rules",
|
||||||
|
"rules",
|
||||||
|
["id"],
|
||||||
|
["id"],
|
||||||
|
source_schema="transactions",
|
||||||
|
referent_schema="transactions",
|
||||||
|
ondelete="CASCADE",
|
||||||
|
)
|
||||||
|
op.drop_column("categories_rules", "bank", schema="transactions")
|
||||||
|
op.drop_column("categories_rules", "min", schema="transactions")
|
||||||
|
op.drop_column("categories_rules", "date", schema="transactions")
|
||||||
|
op.drop_column("categories_rules", "regex", schema="transactions")
|
||||||
|
op.drop_column("categories_rules", "description", schema="transactions")
|
||||||
|
op.drop_column("categories_rules", "max", schema="transactions")
|
||||||
|
op.create_foreign_key(
|
||||||
|
op.f("fk_tag_rules_id_rules"),
|
||||||
|
"tag_rules",
|
||||||
|
"rules",
|
||||||
|
["id"],
|
||||||
|
["id"],
|
||||||
|
source_schema="transactions",
|
||||||
|
referent_schema="transactions",
|
||||||
|
ondelete="CASCADE",
|
||||||
|
)
|
||||||
|
op.drop_column("tag_rules", "bank", schema="transactions")
|
||||||
|
op.drop_column("tag_rules", "min", schema="transactions")
|
||||||
|
op.drop_column("tag_rules", "date", schema="transactions")
|
||||||
|
op.drop_column("tag_rules", "regex", schema="transactions")
|
||||||
|
op.drop_column("tag_rules", "description", schema="transactions")
|
||||||
|
op.drop_column("tag_rules", "max", schema="transactions")
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column(
|
||||||
|
"tag_rules",
|
||||||
|
sa.Column(
|
||||||
|
"max", sa.NUMERIC(precision=16, scale=2), autoincrement=False, nullable=True
|
||||||
|
),
|
||||||
|
schema="transactions",
|
||||||
|
)
|
||||||
|
op.add_column(
|
||||||
|
"tag_rules",
|
||||||
|
sa.Column("description", sa.VARCHAR(), autoincrement=False, nullable=True),
|
||||||
|
schema="transactions",
|
||||||
|
)
|
||||||
|
op.add_column(
|
||||||
|
"tag_rules",
|
||||||
|
sa.Column("regex", sa.VARCHAR(), autoincrement=False, nullable=True),
|
||||||
|
schema="transactions",
|
||||||
|
)
|
||||||
|
op.add_column(
|
||||||
|
"tag_rules",
|
||||||
|
sa.Column("date", sa.DATE(), autoincrement=False, nullable=True),
|
||||||
|
schema="transactions",
|
||||||
|
)
|
||||||
|
op.add_column(
|
||||||
|
"tag_rules",
|
||||||
|
sa.Column(
|
||||||
|
"min", sa.NUMERIC(precision=16, scale=2), autoincrement=False, nullable=True
|
||||||
|
),
|
||||||
|
schema="transactions",
|
||||||
|
)
|
||||||
|
op.add_column(
|
||||||
|
"tag_rules",
|
||||||
|
sa.Column("bank", sa.VARCHAR(), autoincrement=False, nullable=True),
|
||||||
|
schema="transactions",
|
||||||
|
)
|
||||||
|
op.drop_constraint(
|
||||||
|
op.f("fk_tag_rules_id_rules"),
|
||||||
|
"tag_rules",
|
||||||
|
schema="transactions",
|
||||||
|
type_="foreignkey",
|
||||||
|
)
|
||||||
|
op.add_column(
|
||||||
|
"categories_rules",
|
||||||
|
sa.Column(
|
||||||
|
"max", sa.NUMERIC(precision=16, scale=2), autoincrement=False, nullable=True
|
||||||
|
),
|
||||||
|
schema="transactions",
|
||||||
|
)
|
||||||
|
op.add_column(
|
||||||
|
"categories_rules",
|
||||||
|
sa.Column("description", sa.VARCHAR(), autoincrement=False, nullable=True),
|
||||||
|
schema="transactions",
|
||||||
|
)
|
||||||
|
op.add_column(
|
||||||
|
"categories_rules",
|
||||||
|
sa.Column("regex", sa.VARCHAR(), autoincrement=False, nullable=True),
|
||||||
|
schema="transactions",
|
||||||
|
)
|
||||||
|
op.add_column(
|
||||||
|
"categories_rules",
|
||||||
|
sa.Column("date", sa.DATE(), autoincrement=False, nullable=True),
|
||||||
|
schema="transactions",
|
||||||
|
)
|
||||||
|
op.add_column(
|
||||||
|
"categories_rules",
|
||||||
|
sa.Column(
|
||||||
|
"min", sa.NUMERIC(precision=16, scale=2), autoincrement=False, nullable=True
|
||||||
|
),
|
||||||
|
schema="transactions",
|
||||||
|
)
|
||||||
|
op.add_column(
|
||||||
|
"categories_rules",
|
||||||
|
sa.Column("bank", sa.VARCHAR(), autoincrement=False, nullable=True),
|
||||||
|
schema="transactions",
|
||||||
|
)
|
||||||
|
op.drop_constraint(
|
||||||
|
op.f("fk_categories_rules_id_rules"),
|
||||||
|
"categories_rules",
|
||||||
|
schema="transactions",
|
||||||
|
type_="foreignkey",
|
||||||
|
)
|
||||||
|
op.drop_table("rules", schema="transactions")
|
||||||
|
# ### end Alembic commands ###
|
||||||
@ -223,6 +223,11 @@ class Manager:
|
|||||||
case Operation.ImportCategoryRules:
|
case Operation.ImportCategoryRules:
|
||||||
rules = [CategoryRule(**row) for row in self.load(params[0])]
|
rules = [CategoryRule(**row) for row in self.load(params[0])]
|
||||||
|
|
||||||
|
if (
|
||||||
|
len(rules) > 0
|
||||||
|
and input(f"{rules[:5]}\nDoes the import seem correct? (y/n)")
|
||||||
|
== "y"
|
||||||
|
):
|
||||||
with self.db.session() as session:
|
with self.db.session() as session:
|
||||||
session.add(rules)
|
session.add(rules)
|
||||||
|
|
||||||
@ -233,6 +238,11 @@ class Manager:
|
|||||||
case Operation.ImportTagRules:
|
case Operation.ImportTagRules:
|
||||||
rules = [TagRule(**row) for row in self.load(params[0])]
|
rules = [TagRule(**row) for row in self.load(params[0])]
|
||||||
|
|
||||||
|
if (
|
||||||
|
len(rules) > 0
|
||||||
|
and input(f"{rules[:5]}\nDoes the import seem correct? (y/n)")
|
||||||
|
== "y"
|
||||||
|
):
|
||||||
with self.db.session() as session:
|
with self.db.session() as session:
|
||||||
session.add(rules)
|
session.add(rules)
|
||||||
|
|
||||||
|
|||||||
@ -283,7 +283,10 @@ class Link(Base):
|
|||||||
link: Mapped[idfk] = mapped_column(primary_key=True)
|
link: Mapped[idfk] = mapped_column(primary_key=True)
|
||||||
|
|
||||||
|
|
||||||
class Rule(Export):
|
class Rule(Base, Export):
|
||||||
|
__tablename__ = "rules"
|
||||||
|
|
||||||
|
id: Mapped[idpk] = mapped_column(init=False)
|
||||||
date: Mapped[Optional[dt.date]]
|
date: Mapped[Optional[dt.date]]
|
||||||
description: Mapped[Optional[str]]
|
description: Mapped[Optional[str]]
|
||||||
regex: Mapped[Optional[str]]
|
regex: Mapped[Optional[str]]
|
||||||
@ -291,6 +294,13 @@ class Rule(Export):
|
|||||||
min: Mapped[Optional[money]]
|
min: Mapped[Optional[money]]
|
||||||
max: Mapped[Optional[money]]
|
max: Mapped[Optional[money]]
|
||||||
|
|
||||||
|
type: Mapped[str] = mapped_column(init=False)
|
||||||
|
|
||||||
|
__mapper_args__ = {
|
||||||
|
"polymorphic_identity": "rule",
|
||||||
|
"polymorphic_on": "type",
|
||||||
|
}
|
||||||
|
|
||||||
def matches(self, transaction: BankTransaction) -> bool:
|
def matches(self, transaction: BankTransaction) -> bool:
|
||||||
if (
|
if (
|
||||||
(self.date and self.date < transaction.date)
|
(self.date and self.date < transaction.date)
|
||||||
@ -322,15 +332,25 @@ class Rule(Export):
|
|||||||
bank=self.bank,
|
bank=self.bank,
|
||||||
min=self.min,
|
min=self.min,
|
||||||
max=self.max,
|
max=self.max,
|
||||||
|
type=self.type,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class CategoryRule(Base, Rule):
|
class CategoryRule(Rule):
|
||||||
__tablename__ = "categories_rules"
|
__tablename__ = "categories_rules"
|
||||||
|
|
||||||
id: Mapped[idpk] = mapped_column(init=False)
|
id: Mapped[int] = mapped_column(
|
||||||
|
BigInteger,
|
||||||
|
ForeignKey(Rule.id, ondelete="CASCADE"),
|
||||||
|
primary_key=True,
|
||||||
|
init=False,
|
||||||
|
)
|
||||||
name: Mapped[catfk]
|
name: Mapped[catfk]
|
||||||
|
|
||||||
|
__mapper_args__ = {
|
||||||
|
"polymorphic_identity": "category_rule",
|
||||||
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def format(self) -> dict[str, Any]:
|
def format(self) -> dict[str, Any]:
|
||||||
return super().format | dict(name=self.name)
|
return super().format | dict(name=self.name)
|
||||||
@ -339,12 +359,21 @@ class CategoryRule(Base, Rule):
|
|||||||
return hash(self.id)
|
return hash(self.id)
|
||||||
|
|
||||||
|
|
||||||
class TagRule(Base, Rule):
|
class TagRule(Rule):
|
||||||
__tablename__ = "tag_rules"
|
__tablename__ = "tag_rules"
|
||||||
|
|
||||||
id: Mapped[idpk] = mapped_column(init=False)
|
id: Mapped[int] = mapped_column(
|
||||||
|
BigInteger,
|
||||||
|
ForeignKey(Rule.id, ondelete="CASCADE"),
|
||||||
|
primary_key=True,
|
||||||
|
init=False,
|
||||||
|
)
|
||||||
tag: Mapped[str] = mapped_column(ForeignKey(Tag.name, ondelete="CASCADE"))
|
tag: Mapped[str] = mapped_column(ForeignKey(Tag.name, ondelete="CASCADE"))
|
||||||
|
|
||||||
|
__mapper_args__ = {
|
||||||
|
"polymorphic_identity": "tag_rule",
|
||||||
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def format(self) -> dict[str, Any]:
|
def format(self) -> dict[str, Any]:
|
||||||
return super().format | dict(tag=self.tag)
|
return super().format | dict(tag=self.tag)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user