Fix: Storno sendet PDF+Mail+Scaninput; /scaninput Volume in staging ergänzt

This commit is contained in:
rene 2026-05-15 11:18:48 +02:00
parent 8e36eb0611
commit 41a4808ad5
2 changed files with 65 additions and 2 deletions

View file

@ -599,7 +599,7 @@ def pay_invoice(invoice_id: int, data: PayBody, admin=Depends(require_admin)):
@router.post("/{invoice_id}/cancel")
def cancel_invoice(invoice_id: int, data: CancelBody, admin=Depends(require_admin)):
async def cancel_invoice(invoice_id: int, data: CancelBody, admin=Depends(require_admin)):
with db() as conn:
row = conn.execute("SELECT * FROM invoices WHERE id=?", (invoice_id,)).fetchone()
if not row:
@ -613,4 +613,66 @@ def cancel_invoice(invoice_id: int, data: CancelBody, admin=Depends(require_admi
(now, data.reason, cancellation_number, invoice_id)
)
row = conn.execute("SELECT * FROM invoices WHERE id=?", (invoice_id,)).fetchone()
return _row_to_dict(row)
items = _fetch_items(conn, invoice_id)
invoice = _row_to_dict(row)
# Storno-PDF: invoice-Dict als Stornobeleg aufbereiten
storno_invoice = dict(invoice)
storno_invoice["invoice_number"] = cancellation_number
storno_invoice["notes"] = (
f"Stornierung zu Rechnung {invoice['invoice_number']}\n"
f"Grund: {data.reason}"
)
storno_invoice["amount_net"] = -invoice["amount_net"]
storno_invoice["discount_amount"] = -invoice.get("discount_amount", 0)
storno_invoice["amount_after_discount"] = -invoice["amount_after_discount"]
storno_invoice["tax_amount"] = -invoice.get("tax_amount", 0)
storno_invoice["amount_gross"] = -invoice["amount_gross"]
for item in items:
item["unit_price"] = -item["unit_price"]
item["total"] = -item["total"]
try:
pdf_bytes = _generate_pdf(storno_invoice, items)
except Exception as e:
logger.error(f"Storno-PDF fehlgeschlagen: {e}")
return _row_to_dict(row)
filename = f"{cancellation_number}_banyaro.pdf"
try:
await _save_to_paperless(pdf_bytes, cancellation_number, filename)
except Exception as e:
logger.warning(f"Storno Paperless fehlgeschlagen: {e}")
# Mail an Kunden
try:
body_html = mailer.email_html(f"""
<p style="margin:0 0 16px">Hallo <b>{invoice['recipient_name']}</b>,</p>
<p style="margin:0 0 16px">
Ihre Rechnung <b>{invoice['invoice_number']}</b> wurde storniert
(Stornonummer: <b>{cancellation_number}</b>).
</p>
<p style="margin:0 0 8px;color:#666;font-size:13px">Grund: {data.reason}</p>
<p style="margin:0;color:#666;font-size:13px">
Das Stornodokument liegt diesem Schreiben bei.
</p>
""")
plain = (
f"Hallo {invoice['recipient_name']},\n\n"
f"Ihre Rechnung {invoice['invoice_number']} wurde storniert "
f"(Stornonummer: {cancellation_number}).\n"
f"Grund: {data.reason}\n"
)
await mailer.send_email(
to=invoice["recipient_email"],
subject=f"Stornierung Rechnung {invoice['invoice_number']} — Ban Yaro",
html=body_html,
plain=plain,
attachments=[{"filename": filename, "content": pdf_bytes, "content_type": "application/pdf"}],
)
except Exception as e:
logger.error(f"Storno-Mail fehlgeschlagen: {e}")
return invoice

View file

@ -8,6 +8,7 @@ services:
volumes:
- ./data:/data
- /volume1/docker/banyaro/data/media:/prod-media:ro
- /volume1/scaninput:/scaninput
env_file:
- .env
environment: