diff --git a/backend/main.py b/backend/main.py index da0e0ae..f41be0b 100644 --- a/backend/main.py +++ b/backend/main.py @@ -408,7 +408,7 @@ async def serve_media(path: str, request: _Request): raise _HE(404, "Nicht gefunden.") return _media_response(filepath) -APP_VER = "983" # muss mit APP_VER in app.js übereinstimmen +APP_VER = "984" # muss mit APP_VER in app.js übereinstimmen @app.get("/.well-known/assetlinks.json") async def assetlinks(): diff --git a/backend/routes/invoices.py b/backend/routes/invoices.py index dc54a90..53562f0 100644 --- a/backend/routes/invoices.py +++ b/backend/routes/invoices.py @@ -38,6 +38,7 @@ class InvoiceCreate(BaseModel): class PayBody(BaseModel): paid_at: str paid_amount: float + notes: Optional[str] = None class CancelBody(BaseModel): @@ -373,7 +374,9 @@ def get_cashflow(admin=Depends(require_admin)): with db() as conn: monthly = conn.execute(""" SELECT substr(created_at, 1, 7) AS month, - SUM(amount_gross) AS revenue, + SUM(CASE WHEN status='paid' + THEN COALESCE(paid_amount, amount_gross) + ELSE amount_gross END) AS revenue, COUNT(*) AS count FROM invoices WHERE status IN ('sent', 'paid') @@ -383,7 +386,10 @@ def get_cashflow(admin=Depends(require_admin)): year = datetime.now().year total_year = conn.execute( - "SELECT COALESCE(SUM(amount_gross),0) FROM invoices WHERE status IN ('sent','paid') AND created_at LIKE ?", + """SELECT COALESCE(SUM(CASE WHEN status='paid' + THEN COALESCE(paid_amount, amount_gross) + ELSE amount_gross END), 0) + FROM invoices WHERE status IN ('sent','paid') AND created_at LIKE ?""", (f"{year}%",) ).fetchone()[0] @@ -705,10 +711,16 @@ def pay_invoice(invoice_id: int, data: PayBody, admin=Depends(require_admin)): raise HTTPException(404, "Rechnung nicht gefunden.") if row["status"] == "cancelled": raise HTTPException(400, "Stornierte Rechnung kann nicht als bezahlt markiert werden.") - conn.execute( - "UPDATE invoices SET status='paid', paid_at=?, paid_amount=? WHERE id=?", - (data.paid_at, data.paid_amount, invoice_id) - ) + if data.notes: + conn.execute( + "UPDATE invoices SET status='paid', paid_at=?, paid_amount=?, notes=? WHERE id=?", + (data.paid_at, data.paid_amount, data.notes, invoice_id) + ) + else: + conn.execute( + "UPDATE invoices SET status='paid', paid_at=?, paid_amount=? WHERE id=?", + (data.paid_at, data.paid_amount, invoice_id) + ) row = conn.execute("SELECT * FROM invoices WHERE id=?", (invoice_id,)).fetchone() return _row_to_dict(row) diff --git a/backend/static/js/app.js b/backend/static/js/app.js index b33aa1b..a4a7573 100644 --- a/backend/static/js/app.js +++ b/backend/static/js/app.js @@ -3,7 +3,7 @@ Router, State-Management, Navigation, Initialisierung. ============================================================ */ -const APP_VER = '983'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '984'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const APP_VERSION = '1.6.0'; // ← semantische Version, wird bei make release gesetzt const IS_STAGING = location.hostname === 'staging.banyaro.app'; // Cache-Bust-Parameter nach Update-Reload sofort entfernen diff --git a/backend/static/js/pages/admin.js b/backend/static/js/pages/admin.js index 81dc438..c3ae84f 100644 --- a/backend/static/js/pages/admin.js +++ b/backend/static/js/pages/admin.js @@ -3797,6 +3797,14 @@ window.Page_admin = (() => {