Export/Import categories and groups
This commit is contained in:
parent
dd0aaa01b8
commit
8760f5a0a4
@ -241,6 +241,10 @@ if __name__ == "__main__":
|
|||||||
| pfbudget.Operation.ImportCategoryRules
|
| pfbudget.Operation.ImportCategoryRules
|
||||||
| pfbudget.Operation.ExportTagRules
|
| pfbudget.Operation.ExportTagRules
|
||||||
| pfbudget.Operation.ImportTagRules
|
| pfbudget.Operation.ImportTagRules
|
||||||
|
| pfbudget.Operation.ExportCategories
|
||||||
|
| pfbudget.Operation.ImportCategories
|
||||||
|
| pfbudget.Operation.ExportCategoryGroups
|
||||||
|
| pfbudget.Operation.ImportCategoryGroups
|
||||||
):
|
):
|
||||||
keys = {"file"}
|
keys = {"file"}
|
||||||
assert args.keys() >= keys, f"missing {args.keys() - keys}"
|
assert args.keys() >= keys, f"missing {args.keys() - keys}"
|
||||||
|
|||||||
@ -286,6 +286,14 @@ def category(parser: argparse.ArgumentParser):
|
|||||||
group = commands.add_parser("group")
|
group = commands.add_parser("group")
|
||||||
category_group(group)
|
category_group(group)
|
||||||
|
|
||||||
|
export = commands.add_parser("export")
|
||||||
|
export.set_defaults(op=Operation.ExportCategories)
|
||||||
|
export_args(export)
|
||||||
|
|
||||||
|
pimport = commands.add_parser("import")
|
||||||
|
pimport.set_defaults(op=Operation.ImportCategories)
|
||||||
|
export_args(pimport)
|
||||||
|
|
||||||
|
|
||||||
def category_group(parser: argparse.ArgumentParser):
|
def category_group(parser: argparse.ArgumentParser):
|
||||||
commands = parser.add_subparsers(required=True)
|
commands = parser.add_subparsers(required=True)
|
||||||
@ -298,6 +306,14 @@ def category_group(parser: argparse.ArgumentParser):
|
|||||||
remove.set_defaults(op=Operation.GroupRemove)
|
remove.set_defaults(op=Operation.GroupRemove)
|
||||||
remove.add_argument("group", nargs="+", type=str)
|
remove.add_argument("group", nargs="+", type=str)
|
||||||
|
|
||||||
|
export = commands.add_parser("export")
|
||||||
|
export.set_defaults(op=Operation.ExportCategoryGroups)
|
||||||
|
export_args(export)
|
||||||
|
|
||||||
|
pimport = commands.add_parser("import")
|
||||||
|
pimport.set_defaults(op=Operation.ImportCategoryGroups)
|
||||||
|
export_args(pimport)
|
||||||
|
|
||||||
|
|
||||||
def category_rule(parser: argparse.ArgumentParser):
|
def category_rule(parser: argparse.ArgumentParser):
|
||||||
commands = parser.add_subparsers(required=True)
|
commands = parser.add_subparsers(required=True)
|
||||||
|
|||||||
@ -43,6 +43,10 @@ class Operation(Enum):
|
|||||||
ImportCategoryRules = auto()
|
ImportCategoryRules = auto()
|
||||||
ExportTagRules = auto()
|
ExportTagRules = auto()
|
||||||
ImportTagRules = auto()
|
ImportTagRules = auto()
|
||||||
|
ExportCategories = auto()
|
||||||
|
ImportCategories = auto()
|
||||||
|
ExportCategoryGroups = auto()
|
||||||
|
ImportCategoryGroups = auto()
|
||||||
|
|
||||||
|
|
||||||
class TransactionError(Exception):
|
class TransactionError(Exception):
|
||||||
|
|||||||
@ -11,6 +11,7 @@ from pfbudget.db.model import (
|
|||||||
Category,
|
Category,
|
||||||
CategoryGroup,
|
CategoryGroup,
|
||||||
CategoryRule,
|
CategoryRule,
|
||||||
|
CategorySchedule,
|
||||||
CategorySelector,
|
CategorySelector,
|
||||||
Link,
|
Link,
|
||||||
MoneyTransaction,
|
MoneyTransaction,
|
||||||
@ -255,6 +256,41 @@ class Manager:
|
|||||||
with self.db.session() as session:
|
with self.db.session() as session:
|
||||||
session.add(rules)
|
session.add(rules)
|
||||||
|
|
||||||
|
case Operation.ExportCategories:
|
||||||
|
with self.db.session() as session:
|
||||||
|
self.dump(params[0], session.get(Category))
|
||||||
|
|
||||||
|
case Operation.ImportCategories:
|
||||||
|
# rules = [Category(**row) for row in self.load(params[0])]
|
||||||
|
categories = []
|
||||||
|
for row in self.load(params[0]):
|
||||||
|
category = Category(row["name"], row["group"])
|
||||||
|
if len(row["rules"]) > 0:
|
||||||
|
# Only category rules could have been created with a rule
|
||||||
|
rules = row["rules"]
|
||||||
|
for rule in rules:
|
||||||
|
del rule["type"]
|
||||||
|
|
||||||
|
category.rules = set(CategoryRule(**rule) for rule in rules)
|
||||||
|
if row["schedule"]:
|
||||||
|
category.schedule = CategorySchedule(**row["schedule"])
|
||||||
|
categories.append(category)
|
||||||
|
|
||||||
|
if self.certify(categories):
|
||||||
|
with self.db.session() as session:
|
||||||
|
session.add(categories)
|
||||||
|
|
||||||
|
case Operation.ExportCategoryGroups:
|
||||||
|
with self.db.session() as session:
|
||||||
|
self.dump(params[0], session.get(CategoryGroup))
|
||||||
|
|
||||||
|
case Operation.ImportCategoryGroups:
|
||||||
|
groups = [CategoryGroup(**row) for row in self.load(params[0])]
|
||||||
|
|
||||||
|
if self.certify(groups):
|
||||||
|
with self.db.session() as session:
|
||||||
|
session.add(groups)
|
||||||
|
|
||||||
def parse(self, filename: Path, args: dict):
|
def parse(self, filename: Path, args: dict):
|
||||||
return parse_data(filename, args)
|
return parse_data(filename, args)
|
||||||
|
|
||||||
|
|||||||
@ -146,13 +146,17 @@ class SplitTransaction(Transaction):
|
|||||||
return super().format | dict(original=self.original)
|
return super().format | dict(original=self.original)
|
||||||
|
|
||||||
|
|
||||||
class CategoryGroup(Base):
|
class CategoryGroup(Base, Export):
|
||||||
__tablename__ = "categories_groups"
|
__tablename__ = "categories_groups"
|
||||||
|
|
||||||
name: Mapped[str] = mapped_column(primary_key=True)
|
name: Mapped[str] = mapped_column(primary_key=True)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def format(self) -> dict[str, Any]:
|
||||||
|
return dict(name=self.name)
|
||||||
|
|
||||||
class Category(Base):
|
|
||||||
|
class Category(Base, Export):
|
||||||
__tablename__ = "categories_available"
|
__tablename__ = "categories_available"
|
||||||
|
|
||||||
name: Mapped[str] = mapped_column(primary_key=True)
|
name: Mapped[str] = mapped_column(primary_key=True)
|
||||||
@ -170,6 +174,15 @@ class Category(Base):
|
|||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return f"Category(name={self.name}, group={self.group}, #rules={len(self.rules)}, schedule={self.schedule})"
|
return f"Category(name={self.name}, group={self.group}, #rules={len(self.rules)}, schedule={self.schedule})"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def format(self) -> dict[str, Any]:
|
||||||
|
return dict(
|
||||||
|
name=self.name,
|
||||||
|
group=self.group.format if self.group else None,
|
||||||
|
rules=[rule.format for rule in self.rules],
|
||||||
|
schedule=self.schedule.format if self.schedule else None,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
catfk = Annotated[
|
catfk = Annotated[
|
||||||
str,
|
str,
|
||||||
@ -282,7 +295,7 @@ class Period(enum.Enum):
|
|||||||
scheduleperiod = Annotated[Selector, mapped_column(Enum(Period, inherit_schema=True))]
|
scheduleperiod = Annotated[Selector, mapped_column(Enum(Period, inherit_schema=True))]
|
||||||
|
|
||||||
|
|
||||||
class CategorySchedule(Base):
|
class CategorySchedule(Base, Export):
|
||||||
__tablename__ = "categories_schedules"
|
__tablename__ = "categories_schedules"
|
||||||
|
|
||||||
name: Mapped[catfk] = mapped_column(primary_key=True)
|
name: Mapped[catfk] = mapped_column(primary_key=True)
|
||||||
@ -290,6 +303,15 @@ class CategorySchedule(Base):
|
|||||||
period_multiplier: Mapped[Optional[int]]
|
period_multiplier: Mapped[Optional[int]]
|
||||||
amount: Mapped[Optional[int]]
|
amount: Mapped[Optional[int]]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def format(self) -> dict[str, Any]:
|
||||||
|
return dict(
|
||||||
|
name=self.name,
|
||||||
|
period=self.period,
|
||||||
|
period_multiplier=self.period_multiplier,
|
||||||
|
amount=self.amount,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Link(Base):
|
class Link(Base):
|
||||||
__tablename__ = "links"
|
__tablename__ = "links"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user