Export/import for banks

This commit is contained in:
Luís Murta 2023-01-22 23:35:29 +00:00
parent fd6793b4f4
commit dd0aaa01b8
Signed by: satprog
GPG Key ID: 169EF1BBD7049F94
5 changed files with 69 additions and 22 deletions

View File

@ -232,7 +232,16 @@ if __name__ == "__main__":
pfbudget.t.Link(args["original"][0], link) for link in args["links"] 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"} keys = {"file"}
assert args.keys() >= keys, f"missing {args.keys() - keys}" assert args.keys() >= keys, f"missing {args.keys() - keys}"

View File

@ -225,6 +225,14 @@ def bank(parser: argparse.ArgumentParser):
nordigen(commands.add_parser("nordigen")) 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): def nordigen(parser: argparse.ArgumentParser):
commands = parser.add_subparsers(required=True) commands = parser.add_subparsers(required=True)

View File

@ -37,6 +37,8 @@ class Operation(Enum):
NordigenCountryBanks = auto() NordigenCountryBanks = auto()
Export = auto() Export = auto()
Import = auto() Import = auto()
ExportBanks = auto()
ImportBanks = auto()
ExportCategoryRules = auto() ExportCategoryRules = auto()
ImportCategoryRules = auto() ImportCategoryRules = auto()
ExportTagRules = auto() ExportTagRules = auto()

View File

@ -213,16 +213,26 @@ class Manager:
transactions.append(transaction) transactions.append(transaction)
if ( if self.certify(transactions):
len(transactions) > 0
and input(
f"{transactions[:5]}\nDoes the import seem correct? (y/n)"
)
== "y"
):
with self.db.session() as session: with self.db.session() as session:
session.add(transactions) 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: case Operation.ExportCategoryRules:
with self.db.session() as session: with self.db.session() as session:
self.dump(params[0], session.get(CategoryRule)) self.dump(params[0], session.get(CategoryRule))
@ -230,11 +240,7 @@ 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 ( if self.certify(rules):
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)
@ -245,25 +251,29 @@ 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 ( if self.certify(rules):
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)
def parse(self, filename: Path, args: dict): def parse(self, filename: Path, args: dict):
return parse_data(filename, args) return parse_data(filename, args)
def dump(self, fn, sequence): @staticmethod
def dump(fn, sequence):
with open(fn, "wb") as f: with open(fn, "wb") as f:
pickle.dump([e.format for e in sequence], f) pickle.dump([e.format for e in sequence], f)
def load(self, fn): @staticmethod
def load(fn):
with open(fn, "rb") as f: with open(fn, "rb") as f:
return pickle.load(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 @property
def db(self) -> DbClient: def db(self) -> DbClient:
return DbClient(self._db, self._verbosity > 2) return DbClient(self._db, self._verbosity > 2)

View File

@ -57,7 +57,7 @@ class Export:
raise NotImplementedError raise NotImplementedError
class Bank(Base): class Bank(Base, Export):
__tablename__ = "banks" __tablename__ = "banks"
name: Mapped[str] = mapped_column(unique=True) name: Mapped[str] = mapped_column(unique=True)
@ -66,6 +66,15 @@ class Bank(Base):
nordigen: Mapped[Optional[Nordigen]] = relationship(lazy="joined", init=False) 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))] bankfk = Annotated[str, mapped_column(Text, ForeignKey(Bank.name))]
@ -190,7 +199,7 @@ class Note(Base):
note: Mapped[str] note: Mapped[str]
class Nordigen(Base): class Nordigen(Base, Export):
__tablename__ = "nordigen" __tablename__ = "nordigen"
name: Mapped[bankfk] = mapped_column(primary_key=True) name: Mapped[bankfk] = mapped_column(primary_key=True)
@ -198,6 +207,15 @@ class Nordigen(Base):
requisition_id: Mapped[Optional[str]] requisition_id: Mapped[Optional[str]]
invert: Mapped[Optional[bool]] 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): class Tag(Base):
__tablename__ = "tags_available" __tablename__ = "tags_available"