#!/usr/bin/env python3 from os.path import basename from beangulp import Ingest from beangulp import mimetypes from beangulp.importers import csvbase from beangulp.testing import main from beancount.core.data import Transaction, Posting from deelnemers import deelnemers participants = deelnemers() class RaboAmount(csvbase.Amount): def __init__(self, col): super().__init__(col, subs={"\\+": "", ",": "."}) class Importer(csvbase.Importer): encoding = "iso-8859-15" date = csvbase.Date("Datum", "%Y-%m-%d") payee = csvbase.Columns("Naam tegenpartij", "Tegenrekening IBAN/BBAN", sep="; ") narration = csvbase.Columns( "Omschrijving-1", "Omschrijving-2", "Omschrijving-3", sep=" " ) amount = RaboAmount("Bedrag") balance = RaboAmount("Saldo na trn") def identify(self, filepath): mimetype, encoding = mimetypes.guess_type(filepath) if mimetype != "text/csv": return False with open(filepath, "rb") as fd: head = fd.read(1024) return head.startswith( b'"IBAN/BBAN","Munt","BIC","Volgnr","Datum","Rentedatum","Bedrag","Saldo na trn","Tegenrekening IBAN/BBAN"' ) def filename(self, filepath): return "rabobank." + basename(filepath) def guess_contra(entry): posting = entry.postings[0] if entry.payee == "Kosten": return "Uitgaven:Bankkosten" if entry.payee == "Stichting Bitlair; NL09RABO3159222187": return "Activa:Spaarrekening" if ( entry.payee == "Symbiose Beheer B.V.; NL84ABNA0630587221" and posting.units.number < -3400 ): return "Uitgaven:Huur" if ( entry.payee == "Stichting EventInfra; NL59RABO0312574800" and entry.narration == "Verhuur opslagruimte " ): return "Activa:Debiteuren:EventInfra" if entry.narration.startswith("Decla") and posting.units.number < 0: return "Passiva:Declaraties" def have_keyword(*keywords): l_description = entry.narration.lower() return any(kw in l_description for kw in keywords) if have_keyword( "deposit", "revbank", " bar ", "kassa vulling", "desposit", "(RB QR)", "rev-bank", " bank", "elena transfer", "barsaldo", ): return "Passiva:RevBank" for p in participants: if ( hasattr(p, "maandbedrag") and hasattr(p, "ibans") and p.maandbedrag == posting.units.number and any(iban in entry.payee for iban in p.ibans) ): return f"Activa:Debiteuren:Deelnemers:{p.nickname.title().replace('_', '')}" return None def classify_hook(extracted_entries_list, ledger_entries): def _classify(entry): if not isinstance(entry, Transaction): return entry contra = guess_contra(entry) posting = entry.postings[0] entry.postings.append( Posting( contra or "Inkomsten:TODO", -posting.units, posting.cost, posting.price, None if contra else "!", None, ) ) return entry return [ (filename, [_classify(entry) for entry in entries], account, importer) for filename, entries, account, importer in extracted_entries_list ] if __name__ == "__main__": importers = [Importer("Activa:Betaalrekening", "EUR")] hooks = [classify_hook] main = Ingest(importers, hooks) main()