Finishes category schedule implementation

This commit is contained in:
Luís Murta 2022-12-08 20:15:30 +00:00
parent f09b328c66
commit 63d6a2aab7
Signed by: satprog
GPG Key ID: 169EF1BBD7049F94
5 changed files with 69 additions and 6 deletions

View File

@ -4,6 +4,7 @@ import re
from pfbudget.common.types import Operation from pfbudget.common.types import Operation
from pfbudget.core.categories import categorize_data from pfbudget.core.categories import categorize_data
from pfbudget.db.model import Period
from pfbudget.input.json import JsonParser from pfbudget.input.json import JsonParser
from pfbudget.input.nordigen import NordigenInput from pfbudget.input.nordigen import NordigenInput
from pfbudget.db.sqlite import DatabaseClient from pfbudget.db.sqlite import DatabaseClient
@ -333,6 +334,12 @@ def category(parser: argparse.ArgumentParser, universal: argparse.ArgumentParser
update.add_argument("category", nargs="+", type=str) update.add_argument("category", nargs="+", type=str)
update.add_argument("--group", nargs="?", type=str) update.add_argument("--group", nargs="?", type=str)
schedule = commands.add_parser("schedule", parents=[universal])
schedule.set_defaults(op=Operation.CategorySchedule)
schedule.add_argument("category", nargs="+", type=str)
schedule.add_argument("period", nargs=1, choices=[e.value for e in Period])
schedule.add_argument("--frequency", nargs=1, default=[1], type=int)
group = commands.add_parser("group", parents=[universal]) group = commands.add_parser("group", parents=[universal])
category_group(group, universal) category_group(group, universal)

View File

@ -16,6 +16,7 @@ class Operation(Enum):
CategoryAdd = auto() CategoryAdd = auto()
CategoryUpdate = auto() CategoryUpdate = auto()
CategoryRemove = auto() CategoryRemove = auto()
CategorySchedule = auto()
GroupAdd = auto() GroupAdd = auto()
GroupRemove = auto() GroupRemove = auto()

View File

@ -2,7 +2,7 @@ from pfbudget.input.input import Input
from pfbudget.input.nordigen import NordigenClient from pfbudget.input.nordigen import NordigenClient
from pfbudget.input.parsers import parse_data from pfbudget.input.parsers import parse_data
from pfbudget.db.client import DbClient from pfbudget.db.client import DbClient
from pfbudget.db.model import Category, CategoryGroup from pfbudget.db.model import Category, CategoryGroup, CategorySchedule
from pfbudget.common.types import Operation from pfbudget.common.types import Operation
from pfbudget.core.categorizer import Categorizer from pfbudget.core.categorizer import Categorizer
from pfbudget.utils import convert from pfbudget.utils import convert
@ -67,6 +67,21 @@ class Manager:
[Category(name=category) for category in self.args["category"]] [Category(name=category) for category in self.args["category"]]
) )
case Operation.CategorySchedule:
assert (
"period" in self.args and "frequency" in self.args
), "Schedule not well defined"
with self.db.session() as session:
session.updateschedules(
[Category(name=category) for category in self.args["category"]],
CategorySchedule(
recurring=True,
period=self.args["period"][0],
period_multiplier=self.args["frequency"][0],
),
)
case Operation.GroupAdd: case Operation.GroupAdd:
with self.db.session() as session: with self.db.session() as session:
for group in self.args["group"]: for group in self.args["group"]:

View File

@ -1,7 +1,16 @@
from copy import deepcopy
from dataclasses import asdict
from sqlalchemy import create_engine, delete, select, update from sqlalchemy import create_engine, delete, select, update
from sqlalchemy.dialects.postgresql import insert
from sqlalchemy.orm import Session, joinedload, selectinload from sqlalchemy.orm import Session, joinedload, selectinload
from pfbudget.db.model import Bank, Category, CategoryGroup, Transaction from pfbudget.db.model import (
Bank,
Category,
CategoryGroup,
CategorySchedule,
Transaction,
)
# import logging # import logging
@ -91,6 +100,30 @@ class DbClient:
) )
self.__session.execute(stmt) self.__session.execute(stmt)
def updateschedules(
self, categories: list[Category], schedule: CategorySchedule
):
stmt = insert(CategorySchedule).values(
[
dict(
name=cat.name,
recurring=schedule.recurring,
period=schedule.period,
period_multiplier=schedule.period_multiplier,
)
for cat in categories
]
)
stmt = stmt.on_conflict_do_update(
index_elements=[CategorySchedule.name],
set_=dict(
recurring=stmt.excluded.recurring,
period=stmt.excluded.period,
period_multiplier=stmt.excluded.period_multiplier,
),
)
self.__session.execute(stmt)
def addcategorygroup(self, group: CategoryGroup): def addcategorygroup(self, group: CategoryGroup):
self.__session.add(group) self.__session.add(group)

View File

@ -107,12 +107,10 @@ class Category(Base):
rules: Mapped[Optional[set[CategoryRule]]] = relationship( rules: Mapped[Optional[set[CategoryRule]]] = relationship(
cascade="all, delete-orphan", passive_deletes=True cascade="all, delete-orphan", passive_deletes=True
) )
schedule: Mapped[CategorySchedule] = relationship() schedule: Mapped[CategorySchedule] = relationship(back_populates="category")
def __repr__(self) -> str: def __repr__(self) -> str:
return ( return f"Category(name={self.name}, group={self.group}, #rules={len(self.rules)}, schedule={self.schedule})"
f"Category(name={self.name}, group={self.group}, #rules={len(self.rules)})"
)
catfk = Annotated[ catfk = Annotated[
@ -220,3 +218,12 @@ class CategorySchedule(Base):
recurring: Mapped[bool] recurring: Mapped[bool]
period: Mapped[Optional[scheduleperiod]] period: Mapped[Optional[scheduleperiod]]
period_multiplier: Mapped[Optional[int]] period_multiplier: Mapped[Optional[int]]
category: Mapped[Category] = relationship(back_populates="schedule")
def __repr__(self) -> str:
return (
f"{self.name} schedule=Schedule(period={self.period}, multiplier={self.period_multiplier})"
if self.recurring
else f"{self.name} has no Schedule"
)