diff --git a/pfbudget/__main__.py b/pfbudget/__main__.py index 89c2780..0ceb1cc 100644 --- a/pfbudget/__main__.py +++ b/pfbudget/__main__.py @@ -232,7 +232,16 @@ if __name__ == "__main__": pfbudget.t.Link(args["original"][0], link) for link in args["links"] ] - case pfbudget.Operation.Export | pfbudget.Operation.Import | pfbudget.Operation.ExportCategoryRules | pfbudget.Operation.ImportCategoryRules | pfbudget.Operation.ExportTagRules | pfbudget.Operation.ImportTagRules: + case ( + pfbudget.Operation.Export + | pfbudget.Operation.Import + | pfbudget.Operation.ExportBanks + | pfbudget.Operation.ImportBanks + | pfbudget.Operation.ExportCategoryRules + | pfbudget.Operation.ImportCategoryRules + | pfbudget.Operation.ExportTagRules + | pfbudget.Operation.ImportTagRules + ): keys = {"file"} assert args.keys() >= keys, f"missing {args.keys() - keys}" diff --git a/pfbudget/cli/runnable.py b/pfbudget/cli/runnable.py index d368f7e..207848f 100644 --- a/pfbudget/cli/runnable.py +++ b/pfbudget/cli/runnable.py @@ -225,6 +225,14 @@ def bank(parser: argparse.ArgumentParser): nordigen(commands.add_parser("nordigen")) + export = commands.add_parser("export") + export.set_defaults(op=Operation.ExportBanks) + export_args(export) + + pimport = commands.add_parser("import") + pimport.set_defaults(op=Operation.ImportBanks) + export_args(pimport) + def nordigen(parser: argparse.ArgumentParser): commands = parser.add_subparsers(required=True) diff --git a/pfbudget/common/types.py b/pfbudget/common/types.py index a77cc52..ae533c2 100644 --- a/pfbudget/common/types.py +++ b/pfbudget/common/types.py @@ -37,6 +37,8 @@ class Operation(Enum): NordigenCountryBanks = auto() Export = auto() Import = auto() + ExportBanks = auto() + ImportBanks = auto() ExportCategoryRules = auto() ImportCategoryRules = auto() ExportTagRules = auto() diff --git a/pfbudget/core/manager.py b/pfbudget/core/manager.py index 130e43e..f50eec9 100644 --- a/pfbudget/core/manager.py +++ b/pfbudget/core/manager.py @@ -213,16 +213,26 @@ class Manager: transactions.append(transaction) - if ( - len(transactions) > 0 - and input( - f"{transactions[:5]}\nDoes the import seem correct? (y/n)" - ) - == "y" - ): + if self.certify(transactions): with self.db.session() as session: session.add(transactions) + case Operation.ExportBanks: + with self.db.session() as session: + self.dump(params[0], session.get(Bank)) + + case Operation.ImportBanks: + banks = [] + for row in self.load(params[0]): + bank = Bank(row["name"], row["BIC"], row["type"]) + if row["nordigen"]: + bank.nordigen = Nordigen(**row["nordigen"]) + banks.append(bank) + + if self.certify(banks): + with self.db.session() as session: + session.add(banks) + case Operation.ExportCategoryRules: with self.db.session() as session: self.dump(params[0], session.get(CategoryRule)) @@ -230,11 +240,7 @@ class Manager: case Operation.ImportCategoryRules: 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" - ): + if self.certify(rules): with self.db.session() as session: session.add(rules) @@ -245,25 +251,29 @@ class Manager: case Operation.ImportTagRules: 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" - ): + if self.certify(rules): with self.db.session() as session: session.add(rules) def parse(self, filename: Path, args: dict): return parse_data(filename, args) - def dump(self, fn, sequence): + @staticmethod + def dump(fn, sequence): with open(fn, "wb") as f: pickle.dump([e.format for e in sequence], f) - def load(self, fn): + @staticmethod + def load(fn): with open(fn, "rb") as f: return pickle.load(f) + @staticmethod + def certify(imports: list) -> bool: + if input(f"{imports[:10]}\nDoes the import seem correct? (y/n)") == "y": + return True + return False + @property def db(self) -> DbClient: return DbClient(self._db, self._verbosity > 2) diff --git a/pfbudget/db/model.py b/pfbudget/db/model.py index bd44706..a1e888c 100644 --- a/pfbudget/db/model.py +++ b/pfbudget/db/model.py @@ -57,7 +57,7 @@ class Export: raise NotImplementedError -class Bank(Base): +class Bank(Base, Export): __tablename__ = "banks" name: Mapped[str] = mapped_column(unique=True) @@ -66,6 +66,15 @@ class Bank(Base): nordigen: Mapped[Optional[Nordigen]] = relationship(lazy="joined", init=False) + @property + def format(self) -> dict[str, Any]: + return dict( + name=self.name, + BIC=self.BIC, + type=self.type, + nordigen=self.nordigen.format if self.nordigen else None, + ) + bankfk = Annotated[str, mapped_column(Text, ForeignKey(Bank.name))] @@ -190,7 +199,7 @@ class Note(Base): note: Mapped[str] -class Nordigen(Base): +class Nordigen(Base, Export): __tablename__ = "nordigen" name: Mapped[bankfk] = mapped_column(primary_key=True) @@ -198,6 +207,15 @@ class Nordigen(Base): requisition_id: Mapped[Optional[str]] invert: Mapped[Optional[bool]] + @property + def format(self) -> dict[str, Any]: + return dict( + name=self.name, + bank_id=self.bank_id, + requisition_id=self.requisition_id, + invert=self.invert, + ) + class Tag(Base): __tablename__ = "tags_available"