Files

36 lines
1.4 KiB
Python

import csv
import io
from decimal import Decimal
from fastapi import APIRouter
from fastapi.responses import StreamingResponse
from database import connect
from models import CATEGORIES
router = APIRouter()
def safe_cell(value):
text = str(value or '')
return "'" + text if text.lstrip().startswith(('=', '+', '-', '@')) or text.startswith(('\t', '\r', '\n')) else text
def csv_rows():
stream = io.StringIO(newline='')
writer = csv.writer(stream, delimiter=';', lineterminator='\r\n')
yield '\ufeff'
writer.writerow(['Datum', 'Position', 'Kategorie', 'Betrag', 'Notiz', 'Erwartet', 'Erhalten'])
yield stream.getvalue()
stream.seek(0); stream.truncate(0)
with connect() as db:
for row in db.execute('SELECT i.*, a.name FROM income_entries i JOIN assets a ON a.id=i.asset_id ORDER BY date DESC, i.id DESC'):
writer.writerow([row['date'], safe_cell(row['name']), CATEGORIES[row['category']],
f"{Decimal(row['amount'])/100:.2f}".replace('.', ','), safe_cell(row['note']),
'Ja' if row['expected'] else 'Nein', 'Ja' if row['received'] else 'Nein'])
yield stream.getvalue()
stream.seek(0); stream.truncate(0)
@router.get('/export/income.csv')
def export():
return StreamingResponse(csv_rows(), media_type='text/csv; charset=utf-8', headers={'Content-Disposition': 'attachment; filename="income.csv"'})