Beancount advancement Thread

could this be a currency conversion issue?

has anyone of the beancount activists come across an importer for neon or zak?^^

here you go

3 Likes

i should have thought about you, @tarioch! why, again, is your repo a requirement in my conda env? :smiley:
Thanks!

1 Like

here is my importer for Finpension: drnuke-bean/finpension.py at master · Dr-Nuke/drnuke-bean · GitHub

and som helping documentation in the readme.md drnuke-bean/README.md at master · Dr-Nuke/drnuke-bean · GitHub

feedback appreciated :slight_smile:

1 Like

I also revised my automated Postfinance importer narration cleanup. It is not perfect and hardcoded to the german delivery of the csv files, but might still be useful for some of you!

Best,
nugget

def automatic_fixes(d):
    """
    This function allows the user to specify multiple automatic manipulations of the 
    ingested bank statement data. Its return will be the input for the
    data.Transaction() object to be created from that line of the statement
    d: dict() with keys of a future statement, i.e. 'narration', 'payee',...
    """

    monthstring = d['date'].strftime('%b %Y')

    amount = d['amount']
    account = d['account']
    meta = d['meta']
    flag = d['flag']
    narration = d['narration']
    payee = d['payee']
    date = d['date']
    postings = d['postings']

    # preformatting
    re_auftraggeber = r"(.*) (AUFTRAGGEBER|ABSENDER):\s(.*)\sMITTEILUNGEN:\s(.*)\sREFERENZEN:\s(.*)"
    re_auftraggeber2 = r"(.*) AUFTRAGGEBER:\s(.*)\sREFERENZEN:\s(.*)"
    re_kauf = r'KAUF/(DIENSTLEISTUNG|ONLINE-SHOPPING) VOM \d\d.\d\d.\d{4} KARTEN NR. \w{8}\s'
    # re_sender_ref = r"(.*)\sSENDER REFERENZ:\s(.*)"
    
    if bool(re.search(re_kauf, narration, re.IGNORECASE)):
        narration = re.sub(re_kauf, '', narration)
        narration = re.sub(' zürich schweiz','',narration,flags=re.IGNORECASE)
        payee = ''        
        
    elif re.search(re_auftraggeber, narration, re.IGNORECASE) is not None:
        match = re.search(re_auftraggeber, narration, re.IGNORECASE)
        payee = match.groups()[2]
        narration = f"{match.groups()[3]} {match.groups()[4]}"
        
    elif re.search(re_auftraggeber2, narration, re.IGNORECASE) is not None:
        match = re.search(re_auftraggeber2, narration, re.IGNORECASE)
        payee = match.groups()[1]
        narration = f"{match.groups()[2]}"
    
#     elif re.search(re_sender_ref, narration, re.IGNORECASE) is not None:
#         match = re.search(re_sender_ref, narration, re.IGNORECASE)
#         payee = match.groups()[0]
#         narration = match.groups()[1]
        
    # remove notprovided flags
    narration = re.sub(r"\s?NOTPROVIDED\s\S{14,16}\s\S{14,16}",'',narration)
    
    # trim left side of narration
    regex_iban = r"[A-Z]{2}[0-9]{2}(?:[ ]?[0-9]{4}){4}(?!(?:[ ]?[0-9]){3})(?:[ ]?[0-9]{1,2})?\s?R?"
    trim_list=[
        r"ESR\s\d\d-\d{5}-\d ", # regex for "Postkonto"
        r"ESR DAUERAUFTRAG: ",
        r"LASTSCHRIFT DAUERAUFTRAG: ",
        r"LASTSCHRIFT " + regex_iban,
        r"LASTSCHRIFT "
    ]
 
    trim = f'({"|^".join(trim_list)})'
    narration = re.sub(trim, "",narration, re.IGNORECASE) 
    
    # trim right side from long digit "20220913000800242513572"
    narration = re.sub(r"\s?\d{23}\s?$","",narration)    
    
    # IBAN + SENDER  REFERENZ
    iban_sender = f"(.*) {regex_iban} (.*) SENDER REFERENZ:(.*)"
    match = re.search(iban_sender, narration, re.IGNORECASE)
    if match is not None:
        payee = match.groups()[1]
        narration = match.groups()[2]
    
    # only SENDER REFERENZ:
    match = re.search("(.*)\s?SENDER REFERENZ:\s?(.*)", narration, re.IGNORECASE)
    if match is not None:
        payee = match.groups()[0]
        narration = match.groups()[1]

    # if still nothing in payee, most likely the remaining narration _is_ the payee
    if narration and not payee:
        payee, narration = narration, payee

    # add your personal automated fixes here

    return dict(amount=amount,
                account=account,
                meta=meta,
                flag=flag,
                narration=narration,
                payee=payee,
                date=date,
                postings=postings,
                )
2 Likes

Hi all :smiley:
for those living in the Kanton of Zurich and normal taxation regime, i wrote a tax forecast plugin that will predict the tax load of a ongoing or past fiscal year and add monthly tax liabilities accordingly:

this plugin greatly benefits from @the_p’s shared api queries to the Steuerrechner of the Kanton Zurich.

based on your taxable income accounts, it extrapolates your current income to the full year, queries the according tax load at the Steuerrechner, and adds the resulting tax debt as a liability to your ledger

Warning: this is totally immature and needs some more work :smiley: but it basically works:

room for improvement:

  • add Vermögenssteuer
  • add deductables (accounts, lump sum,…), as it currently strongly overestimates the due taxes
  • switch to the ESTV Steuerrechner, which should work for all Kantons
  • add more choices & options support
  • reflect on any feedback here :smiley:
  • i cant get behind some things in beancount, probaby there are some really poor workarounds in the source…
  • add tax credit (Witholding etc.)
5 Likes

Hi all
as proper mustachian I got myself the halbtax plus :nerd_face:

but it has a significant drawback: my purchases do not show up with my credid card xls bill anymore. I can only find details on the sbb webpage, where i can export a pdf.

has anyone experience with importing sbb purchases via the halbtax plus? :smiley:

… this includes the monthly balance assertion :DD