refactor: Remove unused email sending functionality and update invoice status descriptions

This commit is contained in:
2026-05-23 23:10:37 +02:00
parent 28777021ad
commit 6dbba381da
4 changed files with 29 additions and 58 deletions
+3 -55
View File
@@ -12,11 +12,9 @@ import tempfile
import threading import threading
import unicodedata import unicodedata
import zipfile import zipfile
import smtplib
from datetime import timedelta, datetime, date from datetime import timedelta, datetime, date
from functools import wraps from functools import wraps
from io import BytesIO from io import BytesIO
from email.message import EmailMessage
from urllib.parse import parse_qs, quote, urlparse from urllib.parse import parse_qs, quote, urlparse
from werkzeug.security import generate_password_hash, check_password_hash from werkzeug.security import generate_password_hash, check_password_hash
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
@@ -73,12 +71,6 @@ BOOKING_PRICE_MAP = {
"schultraeger": 0.0, "schultraeger": 0.0,
"telefonsupport": 20.0, "telefonsupport": 20.0,
} }
SMTP_HOST = os.environ.get("SMTP_HOST", "").strip()
SMTP_USERNAME = os.environ.get("SMTP_USERNAME", "").strip()
SMTP_PASSWORD = os.environ.get("SMTP_PASSWORD", "")
SMTP_USE_TLS = os.environ.get("SMTP_USE_TLS", "1").strip().lower() not in {"0", "false", "no"}
SMTP_FROM_ADDRESS = os.environ.get("SMTP_FROM_ADDRESS", SMTP_USERNAME or "noreply@localhost").strip()
BOOKING_ADMIN_EMAIL_FALLBACK = os.environ.get("BOOKING_ADMIN_EMAIL", "").strip() BOOKING_ADMIN_EMAIL_FALLBACK = os.environ.get("BOOKING_ADMIN_EMAIL", "").strip()
@@ -151,12 +143,6 @@ def _env_int(name: str, default: int) -> int:
return default return default
try:
SMTP_PORT = max(int(os.environ.get("SMTP_PORT", "587")), 1)
except ValueError:
SMTP_PORT = 587
MONGO_MAX_POOL_SIZE = max(_env_int("MONGO_MAX_POOL_SIZE", 12), 1) MONGO_MAX_POOL_SIZE = max(_env_int("MONGO_MAX_POOL_SIZE", 12), 1)
MONGO_MIN_POOL_SIZE = max(_env_int("MONGO_MIN_POOL_SIZE", 0), 0) MONGO_MIN_POOL_SIZE = max(_env_int("MONGO_MIN_POOL_SIZE", 0), 0)
MONGO_MAX_IDLE_MS = max(_env_int("MONGO_MAX_IDLE_MS", 60000), 1000) MONGO_MAX_IDLE_MS = max(_env_int("MONGO_MAX_IDLE_MS", 60000), 1000)
@@ -369,28 +355,6 @@ def _select_booking_admin() -> dict | None:
return None return None
def _send_booking_email(recipient_email: str, subject: str, body: str) -> tuple[bool, str]:
if not SMTP_HOST or not recipient_email:
return False, "SMTP nicht konfiguriert"
message = EmailMessage()
message["Subject"] = subject
message["From"] = SMTP_FROM_ADDRESS
message["To"] = recipient_email
message.set_content(body)
try:
with smtplib.SMTP(SMTP_HOST, SMTP_PORT, timeout=12) as smtp:
if SMTP_USE_TLS:
smtp.starttls()
if SMTP_USERNAME:
smtp.login(SMTP_USERNAME, SMTP_PASSWORD)
smtp.send_message(message)
return True, "E-Mail wurde versendet"
except Exception as exc:
return False, _sanitize_text(str(exc), 240)
def _sanitize_text(text: str, max_length: int = 255) -> str: def _sanitize_text(text: str, max_length: int = 255) -> str:
"""Sanitize user text input: strip, limit length, and escape HTML.""" """Sanitize user text input: strip, limit length, and escape HTML."""
text = (text or "").strip() text = (text or "").strip()
@@ -2138,22 +2102,6 @@ def booking_payment():
if invoice_client: if invoice_client:
invoice_client.close() invoice_client.close()
if assigned_admin_email:
email_subject = f"Neue Zahlungsbuchung: {selected_package}"
email_body = (
f"Es wurde eine neue direkte Buchung eingereicht.\n\n"
f"Paket: {selected_package}\n"
f"Ansprechpartner: {form_data['contact_person']}\n"
f"Schule: {form_data['school_name']}\n"
f"E-Mail: {form_data['contact_email']}\n"
f"Telefon: {form_data['contact_phone'] or '-'}\n"
f"Rechnungsadresse: {form_data['billing_street']}, {form_data['billing_zip']} {form_data['billing_city']}\n"
f"Status: Bitte die Unterlagen in der Rechnungsverwaltung prüfen.\n"
f"Buchungsnummer: {booking_number}\n"
)
mail_ok, mail_message = _send_booking_email(assigned_admin_email, email_subject, email_body)
if not mail_ok:
flash(f"Rechnung wurde angelegt, E-Mail an den Admin konnte nicht gesendet werden: {mail_message}", "info")
except PyMongoError: except PyMongoError:
flash("Buchungsanfrage konnte nicht gesendet werden.", "error") flash("Buchungsanfrage konnte nicht gesendet werden.", "error")
return redirect(url_for("booking_payment", package=package_raw, flow=booking_flow)) return redirect(url_for("booking_payment", package=package_raw, flow=booking_flow))
@@ -2164,7 +2112,7 @@ def booking_payment():
success_text = ( success_text = (
f"Gesprächstermin für {selected_package} wurde an das Team gesendet." f"Gesprächstermin für {selected_package} wurde an das Team gesendet."
if booking_flow == "consultation" if booking_flow == "consultation"
else f"Buchung für {selected_package} wurde an den Admin gesendet." else f"Buchung für {selected_package} wurde erfolgreich erfasst."
) )
flash(success_text, "success") flash(success_text, "success")
return redirect(url_for("user_chat")) return redirect(url_for("user_chat"))
@@ -3066,7 +3014,7 @@ def admin_invoices():
invoice_number = _sanitize_text(request.form.get("invoice_number") or "", 120) invoice_number = _sanitize_text(request.form.get("invoice_number") or "", 120)
period = _sanitize_text(request.form.get("period") or "", 20) period = _sanitize_text(request.form.get("period") or "", 20)
due_date = _sanitize_text(request.form.get("due_date") or "", 20) due_date = _sanitize_text(request.form.get("due_date") or "", 20)
status = _sanitize_text(request.form.get("status") or "Offen", 40) status = _sanitize_text(request.form.get("status") or "Zu prüfen", 40)
amount_text = _sanitize_text(request.form.get("amount_eur") or "0", 20) amount_text = _sanitize_text(request.form.get("amount_eur") or "0", 20)
normalized_invoice_number = invoice_number or f"INV-{datetime.utcnow().strftime('%Y%m%d%H%M%S')}" normalized_invoice_number = invoice_number or f"INV-{datetime.utcnow().strftime('%Y%m%d%H%M%S')}"
pdf_path = _save_invoice_pdf(request.files.get("invoice_pdf"), normalized_invoice_number) pdf_path = _save_invoice_pdf(request.files.get("invoice_pdf"), normalized_invoice_number)
@@ -3106,7 +3054,7 @@ def admin_invoices():
update_payload = { update_payload = {
"invoice_number": invoice_number, "invoice_number": invoice_number,
"period": _sanitize_text(request.form.get("period") or "", 20), "period": _sanitize_text(request.form.get("period") or "", 20),
"status": _sanitize_text(request.form.get("status") or "Offen", 40), "status": _sanitize_text(request.form.get("status") or "Zu prüfen", 40),
"due_date": _sanitize_text(request.form.get("due_date") or "", 20), "due_date": _sanitize_text(request.form.get("due_date") or "", 20),
"amount_eur": amount, "amount_eur": amount,
} }
+23
View File
@@ -230,6 +230,29 @@ class instace:
def __init__(): def __init__():
return list() return list()
def new_trial(name: str) -> bool:
"""
Generates a new trial instance with the subdomain [name].invario.eu
Input:
- name -> String
Output:
- bool if the creation of the instance works (True: creation worked; False: didnt work)
manage-tenant.sh trial <tenant_id> [port] [days]
"""
port_starter = 10002
port = port_starter
for i in instace.list():
port =+ 1
if execute_script(_var, _cmd, "trial", clear_special(name), port):
add_dns(name, port)
return int(port)
else:
return False
def new(name: str) -> int: def new(name: str) -> int:
""" """
Generates a new instance with the subdomain [name].invario.eu Generates a new instance with the subdomain [name].invario.eu
+2 -2
View File
@@ -5,7 +5,7 @@
{% block content %} {% block content %}
<section class="panel"> <section class="panel">
<h1>Rechnungsverwaltung</h1> <h1>Rechnungsverwaltung</h1>
<p>Rechnungen für Nutzer erstellen, aktualisieren und löschen. Direktbuchungen werden hier automatisch mit zugewiesenem Admin und Buchungsunterlagen angezeigt.</p> <p>Rechnungen für Nutzer erstellen, aktualisieren und löschen. Neue Rechnungen starten mit dem Status „Zu prüfen“, damit der Admin sie zuerst kontrolliert. Direktbuchungen werden hier automatisch mit zugewiesenem Admin und Buchungsunterlagen angezeigt.</p>
</section> </section>
<section class="layout"> <section class="layout">
@@ -22,7 +22,7 @@
<input type="text" name="period" placeholder="Zeitraum (MM/YYYY)" required> <input type="text" name="period" placeholder="Zeitraum (MM/YYYY)" required>
<input type="text" name="amount_eur" placeholder="Betrag in EUR" required> <input type="text" name="amount_eur" placeholder="Betrag in EUR" required>
<input type="text" name="due_date" placeholder="Fälligkeit (YYYY-MM-DD)"> <input type="text" name="due_date" placeholder="Fälligkeit (YYYY-MM-DD)">
<input type="text" name="status" placeholder="Status (Offen, Bezahlt)"> <input type="text" name="status" placeholder="Status (Zu prüfen, Geprüft, Bezahlt)">
<input type="file" name="invoice_pdf" accept="application/pdf"> <input type="file" name="invoice_pdf" accept="application/pdf">
<button type="submit">Rechnung anlegen</button> <button type="submit">Rechnung anlegen</button>
</form> </form>
+1 -1
View File
@@ -5,7 +5,7 @@
{% block content %} {% block content %}
<section class="panel"> <section class="panel">
<h1>Rechnungseinsicht</h1> <h1>Rechnungseinsicht</h1>
<p>Alle Rechnungen im Überblick.</p> <p>Alle Rechnungen im Überblick. Der Admin prüft neue Rechnungen zuerst; der Status zeigt dir, ob die Rechnung noch geprüft wird oder bereits bearbeitet wurde.</p>
</section> </section>
<section class="table-wrap"> <section class="table-wrap">