Fix: Storno sendet PDF+Mail+Scaninput; /scaninput Volume in staging ergänzt
This commit is contained in:
parent
8e36eb0611
commit
41a4808ad5
2 changed files with 65 additions and 2 deletions
|
|
@ -599,7 +599,7 @@ def pay_invoice(invoice_id: int, data: PayBody, admin=Depends(require_admin)):
|
||||||
|
|
||||||
|
|
||||||
@router.post("/{invoice_id}/cancel")
|
@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:
|
with db() as conn:
|
||||||
row = conn.execute("SELECT * FROM invoices WHERE id=?", (invoice_id,)).fetchone()
|
row = conn.execute("SELECT * FROM invoices WHERE id=?", (invoice_id,)).fetchone()
|
||||||
if not row:
|
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)
|
(now, data.reason, cancellation_number, invoice_id)
|
||||||
)
|
)
|
||||||
row = conn.execute("SELECT * FROM invoices WHERE id=?", (invoice_id,)).fetchone()
|
row = conn.execute("SELECT * FROM invoices WHERE id=?", (invoice_id,)).fetchone()
|
||||||
|
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)
|
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
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- ./data:/data
|
- ./data:/data
|
||||||
- /volume1/docker/banyaro/data/media:/prod-media:ro
|
- /volume1/docker/banyaro/data/media:/prod-media:ro
|
||||||
|
- /volume1/scaninput:/scaninput
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
environment:
|
environment:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue