FireTracker / csv_import.py
smlflg's picture
Initial public upload from Projekte/FireTracker
f91bd05 verified
Raw History Blame Contribute Delete
3.15 kB
import csv
import io
from typing import Dict, Any
def parse_bank_csv(content: bytes) -> Dict[str, Any]:
"""
Parse a bank CSV file and return categorized transactions with summary statistics.
Args:
content: Raw bytes of the CSV file
Returns:
Dict with keys:
- transactions: List of transaction dicts with date, description, amount
- total_income: Sum of positive amounts
- total_expenses: Sum of absolute negative amounts
- net: Total income minus total expenses
- count: Number of transactions
- monthly_estimate: Average monthly expenses based on unique months in data
"""
text = content.decode('utf-8', errors='replace')
lines = text.strip().split('\n')
transactions = []
total_income = 0
total_expenses = 0
# Try to detect format
try:
# Try semicolon first (German standard)
if lines:
dialect = csv.Sniffer().sniff(lines[0], delimiters=';,\t')
reader = csv.DictReader(io.StringIO(text), delimiter=dialect.delimiter)
else:
reader = csv.DictReader(io.StringIO(text), delimiter=';')
except csv.Error:
reader = csv.DictReader(io.StringIO(text), delimiter=';')
for row in reader:
amount = None
date_str = None
description = ""
for key, val in row.items():
if not key:
continue
key_lower = key.lower().strip()
# Amount detection
if key_lower in ('betrag', 'amount', 'umsatz', 'betrag (eur)', 'wert'):
try:
amount = float(val.replace('.', '').replace(',', '.').strip().strip('"'))
except (ValueError, AttributeError):
pass
# Date detection
if key_lower in ('buchungstag', 'datum', 'date', 'buchungsdatum', 'valuta'):
date_str = val.strip().strip('"')
# Description detection
if key_lower in ('verwendungszweck', 'buchungstext', 'description', 'empfaenger',
'auftraggeber / beguenstigter', 'zahlungsempfaenger', 'beschreibung'):
if val and val.strip():
description = val.strip().strip('"')[:100]
if amount is not None:
if amount > 0:
total_income += amount
else:
total_expenses += abs(amount)
transactions.append({
"date": date_str or "",
"description": description,
"amount": amount,
})
# Calculate monthly estimate based on unique months in data
unique_months = len(set(t['date'][:7] for t in transactions if t['date']))
monthly_estimate = total_expenses / max(1, unique_months) if transactions else 0
return {
"transactions": transactions,
"total_income": round(total_income, 2),
"total_expenses": round(total_expenses, 2),
"net": round(total_income - total_expenses, 2),
"count": len(transactions),
"monthly_estimate": round(monthly_estimate, 2),
}