Add SQLite passive income dashboard with Excel import and deployment tools
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
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"'})
|
||||
Reference in New Issue
Block a user