#!/usr/bin/env python3 from pathlib import Path from datetime import date, timedelta, datetime from urllib.request import urlopen from fints.client import FinTS3PinTanClient import csv import json import sys # -------------------------------------------------- # Konfiguration laden # -------------------------------------------------- config = {} config_file = Path.home() / ".ing.conf" if not config_file.exists(): config_file = Path(__file__).parent / ".ing.conf" with open(config_file, encoding="utf-8") as f: for line in f: line = line.strip() if not line or line.startswith("#"): continue if "=" not in line: continue key, value = line.split("=", 1) config[key] = value # -------------------------------------------------- # ING-Konfiguration # -------------------------------------------------- USER = config["ING_USER"] PIN = config["ING_PIN"] TARGET_IBAN = config["ING_IBAN"] # -------------------------------------------------- # ioBroker-Konfiguration # -------------------------------------------------- IOBROKER_HOST = config["IOBROKER_HOST"] IOBROKER_PORT = config["IOBROKER_PORT"] IOBROKER_DP_TRANSACTIONS = config["IOBROKER_DP_TRANSACTIONS"] IOBROKER_DP_WEEKSUM = config["IOBROKER_DP_WEEKSUM"] IOBROKER_DP_WEEKEXPENSES = config["IOBROKER_DP_WEEKEXPENSES"] # -------------------------------------------------- # Bank # -------------------------------------------------- BLZ = "50010517" # -------------------------------------------------- # Exportverzeichnis bestimmen # -------------------------------------------------- base_dir = Path.home() / "Transaktionen" if not base_dir.exists(): base_dir = Path(__file__).parent / "Transaktionen" # -------------------------------------------------- # Kalenderwoche bestimmen # -------------------------------------------------- if len(sys.argv) == 3: year = int(sys.argv[1]) week = int(sys.argv[2]) else: year, week, _ = datetime.now().isocalendar() # Montag der Kalenderwoche start_date = datetime.strptime( f"{year}-W{week:02d}-1", "%G-W%V-%u" ).date() # Sonntag der Kalenderwoche end_date = start_date + timedelta(days=6) today = date.today() if end_date > today: end_date = today if start_date > today: print( "Die angeforderte Kalenderwoche liegt " "vollständig in der Zukunft." ) sys.exit(1) year_dir = base_dir / str(year) csv_dir = year_dir / "csv" json_dir = year_dir / "json" csv_dir.mkdir(parents=True, exist_ok=True) json_dir.mkdir(parents=True, exist_ok=True) CSV_FILE = csv_dir / f"transactions_{year}_KW{week:02d}.csv" JSON_FILE = json_dir / f"transactions_{year}_KW{week:02d}.json" # -------------------------------------------------- # ING-Verbindung # -------------------------------------------------- client = FinTS3PinTanClient( BLZ, USER, PIN, "https://fints.ing.de/fints/", product_id="PythonFinTS" ) export_data = [] transactions = [] # -------------------------------------------------- # Transaktionen abrufen # -------------------------------------------------- with client: account_found = False for account in client.get_sepa_accounts(): if account.iban != TARGET_IBAN: continue account_found = True transactions = client.get_transactions( account, start_date=start_date, end_date=end_date ) print( f"Lade Transaktionen für KW{week:02d}/{year}" ) print( f"Zeitraum: {start_date} bis {end_date}" ) for transaction in transactions: data = transaction.data amount = data.get("amount") row = { "date": str(data.get("date", "")), "amount": round(float(amount.amount), 2) if amount else 0.0, "posting_text": data.get("posting_text", ""), "applicant_name": data.get("applicant_name", ""), "purpose": data.get("purpose", "") } export_data.append(row) break if not account_found: raise RuntimeError( f"IBAN nicht gefunden: {TARGET_IBAN}" ) # -------------------------------------------------- # CSV schreiben # -------------------------------------------------- with open(CSV_FILE, "w", newline="", encoding="utf-8") as csvfile: writer = csv.DictWriter( csvfile, fieldnames=[ "date", "amount", "posting_text", "applicant_name", "purpose" ], delimiter=";" ) writer.writeheader() writer.writerows(export_data) # -------------------------------------------------- # JSON schreiben # -------------------------------------------------- with open(JSON_FILE, "w", encoding="utf-8") as jsonfile: json.dump( export_data, jsonfile, ensure_ascii=False, indent=2 ) # -------------------------------------------------- # Statistiken berechnen # -------------------------------------------------- transaction_count = len(export_data) week_sum = 0.0 week_expenses = 0.0 for transaction in transactions: amount = float(transaction.data["amount"].amount) week_sum += amount if amount < 0: week_expenses += abs(amount) week_sum = round(week_sum, 2) week_expenses = round(week_expenses, 2) # -------------------------------------------------- # An ioBroker senden # -------------------------------------------------- base_url = f"http://{IOBROKER_HOST}:{IOBROKER_PORT}/set" urlopen( f"{base_url}/{IOBROKER_DP_TRANSACTIONS}" f"?value={transaction_count}" ).read() urlopen( f"{base_url}/{IOBROKER_DP_WEEKSUM}" f"?value={week_sum}" ).read() urlopen( f"{base_url}/{IOBROKER_DP_WEEKEXPENSES}" f"?value={week_expenses}" ).read() # -------------------------------------------------- # Erfolgsmeldung # -------------------------------------------------- print(f"CSV erstellt : {CSV_FILE}") print(f"JSON erstellt: {JSON_FILE}") print(f"Transaktionen: {transaction_count}") print(f"Wochensumme : {week_sum:.2f} EUR") print(f"Ausgaben : {week_expenses:.2f} EUR")