Files

120 lines
3.7 KiB
Python
Executable File

"""Invoice routes."""
import base64
import logging
from flask import (
Blueprint,
Response,
flash,
g,
redirect,
render_template,
request,
url_for,
)
from customer_portal.services.wordpress_api import WordPressAPI
from customer_portal.web.routes.auth import login_required
bp = Blueprint("invoices", __name__)
logger = logging.getLogger(__name__)
@bp.route("/")
@login_required
def list_invoices():
"""List customer invoices."""
try:
invoices = WordPressAPI.get_invoices(g.customer.email)
except ValueError as e:
logger.error(f"WordPress API not configured: {e}")
flash("WordPress-Verbindung nicht konfiguriert.", "error")
invoices = []
except Exception as e:
logger.error(f"Error fetching invoices: {e}")
flash("Rechnungen konnten nicht geladen werden.", "error")
invoices = []
# Extract available years for filter
years = set()
for invoice in invoices:
if invoice.get("created_at"):
try:
date_str = invoice["created_at"]
year = date_str[:4] if "T" in date_str else date_str[:4]
years.add(year)
except (ValueError, TypeError):
pass
# Sort years descending
years = sorted(years, reverse=True)
# Get filter parameters
status_filter = request.args.get("status", "")
year_filter = request.args.get("year", "")
# Apply filters
filtered_invoices = invoices
if status_filter:
filtered_invoices = [
inv for inv in filtered_invoices if inv.get("status") == status_filter
]
if year_filter:
filtered_invoices = [
inv
for inv in filtered_invoices
if inv.get("created_at", "")[:4] == year_filter
]
return render_template(
"invoices/list.html",
invoices=filtered_invoices,
all_invoices=invoices,
years=years,
status_filter=status_filter,
year_filter=year_filter,
)
@bp.route("/<int:invoice_id>/pdf")
@login_required
def download_pdf(invoice_id: int):
"""Download invoice PDF from WordPress/sevDesk."""
try:
# Get PDF via WordPress API (includes ownership verification)
pdf_data = WordPressAPI.get_invoice_pdf(invoice_id, g.customer.email)
except ValueError as e:
logger.error(f"WordPress API not configured: {e}")
flash("WordPress-Verbindung nicht konfiguriert.", "error")
return redirect(url_for("invoices.list_invoices"))
except Exception as e:
logger.error(f"Error fetching invoice PDF {invoice_id}: {e}")
flash("PDF konnte nicht geladen werden.", "error")
return redirect(url_for("invoices.list_invoices"))
if not pdf_data:
flash("Rechnung nicht gefunden oder kein Zugriff.", "error")
return redirect(url_for("invoices.list_invoices"))
# Check for error response
if "error" in pdf_data:
flash(f"Fehler: {pdf_data['error']}", "error")
return redirect(url_for("invoices.list_invoices"))
# Decode base64 PDF
try:
pdf_content = base64.b64decode(pdf_data["pdf"])
filename = pdf_data.get("filename", f"Rechnung_{invoice_id}.pdf")
except Exception as e:
logger.error(f"Error decoding PDF: {e}")
flash("PDF konnte nicht dekodiert werden.", "error")
return redirect(url_for("invoices.list_invoices"))
# Return PDF as download
return Response(
pdf_content,
mimetype="application/pdf",
headers={"Content-Disposition": f"attachment; filename={filename}"},
)