changes to the pricing

This commit is contained in:
2026-10-03 12:34:08 +02:00
parent 77e388627d
commit 9ca0553421
5 changed files with 57 additions and 16 deletions
+47 -7
View File
@@ -204,6 +204,14 @@ def _utc_now_iso() -> str:
return datetime.utcnow().isoformat(timespec="seconds") + "Z"
def _booking_amounts(net_amount: float, is_trial: bool = False) -> tuple[float, float, float]:
net = round(float(net_amount or 0.0), 2)
if is_trial:
return 0.0, 0.0, 0.0
vat = round(net * 0.19, 2)
return net, vat, round(net + vat, 2)
def _is_allowed_invoice_filename(filename: str) -> bool:
return bool(filename) and filename.lower().endswith(".pdf")
@@ -2433,6 +2441,7 @@ def background_booking_provisioning(
"billing_reference": booking_data.get("billing_reference"),
"package": booking_request.get("package_label") or booking_request.get("package"),
"amount_eur": booking_request.get("amount_eur"),
"amount_gross_eur": booking_request.get("amount_eur"),
"amount_net_eur": booking_request.get("amount_net_eur") or booking_request.get("amount_eur"),
"booking_flow": booking_request.get("booking_flow"),
"invoice_id": booking_request.get("invoice_id"),
@@ -2892,6 +2901,7 @@ def booking_payment():
selected_package = ", ".join(selected_package_names)
package_raw = packages_str
net_price, vat_amount, gross_price = _booking_amounts(total_price, is_trial)
flow_config = BOOKING_FLOW_MAP.get(booking_flow, BOOKING_FLOW_MAP.get("payment"))
@@ -2950,6 +2960,8 @@ def booking_payment():
"package_price": total_price if not is_trial else 0.0,
"price": total_price if not is_trial else 0.0,
"price_net": total_price if not is_trial else 0.0,
"price_vat": vat_amount,
"price_gross": gross_price,
"flow": booking_flow,
"is_trial": is_trial,
"title": flow_config["title"],
@@ -3104,8 +3116,9 @@ def booking_payment():
"booking_number": booking_number,
"package": package_raw,
"package_label": selected_package,
"amount_eur": total_price if not is_trial else 0.0,
"amount_net_eur": total_price if not is_trial else 0.0,
"amount_eur": gross_price,
"amount_net_eur": net_price,
"vat_eur": vat_amount,
"booking_flow": booking_flow,
"booking_data": form_data,
"is_trial": is_trial,
@@ -3134,8 +3147,9 @@ def booking_payment():
"username": session.get("username"),
"invoice_number": booking_number,
"period": date.today().strftime("%m/%Y"),
"amount_eur": total_price,
"amount_net_eur": total_price,
"amount_eur": gross_price,
"amount_net_eur": net_price,
"vat_eur": vat_amount,
"status": "Offen",
"due_date": due_date,
"created_at": _utc_now_iso(),
@@ -3158,7 +3172,7 @@ def booking_payment():
module_config = build_module_config_string(package_list)
user_email = session.get("email") or form_data.get("contact_email")
address_process = f"{form_data['billing_street']}, {form_data['billing_zip']} {form_data['billing_city']}"
price_str = f"{total_price:.2f}".replace('.', ',')
price_str = f"{gross_price:.2f}".replace('.', ',')
billing_update = {
"package": package_raw,
"invoice_id": invoice_id,
@@ -3207,7 +3221,9 @@ def booking_payment():
"billing_city": form_data.get("billing_city"),
"billing_reference": form_data.get("billing_reference"),
"package": selected_package,
"amount_eur": total_price,
"amount_eur": gross_price,
"amount_gross_eur": gross_price,
"amount_net_eur": net_price,
"booking_flow": booking_flow,
"invoice_id": invoice_id,
"subdomain": subdomain,
@@ -3262,7 +3278,7 @@ def booking_payment():
username = session.get("username")
user_email = session.get("email") or form_data.get("contact_email")
address_process = f"{form_data['billing_street']}, {form_data['billing_zip']} {form_data['billing_city']}"
price_str = f"{total_price:.2f}".replace('.', ',') if not is_trial else "Kostenlose Testversion"
price_str = f"{gross_price:.2f}".replace('.', ',') if not is_trial else "Kostenlose Testversion"
thread = threading.Thread(
target=background_booking_provisioning,
@@ -3584,6 +3600,14 @@ def my_invoices():
except ValueError:
amt = 0.0
inv["amount_eur"] = amt
if "amount_net_eur" in inv:
net_amt = inv.get("amount_net_eur")
if isinstance(net_amt, str):
try:
net_amt = float(net_amt.replace('.', '').replace(',', '.'))
except ValueError:
net_amt = 0.0
inv["amount_net_eur"] = net_amt
# Flags setzen, ob Verträge/Rechnungen in MongoDB existieren (anhand des Dateinamens)
inv["has_hauptvertrag"] = bool(inv.get("hauptvertrag_filename"))
@@ -3609,6 +3633,14 @@ def my_invoices():
except ValueError:
amt = 0.0
item["amount_eur"] = amt
if "amount_net_eur" in item:
net_amt = item.get("amount_net_eur")
if isinstance(net_amt, str):
try:
net_amt = float(net_amt.replace('.', '').replace(',', '.'))
except ValueError:
net_amt = 0.0
item["amount_net_eur"] = net_amt
except Exception:
flash("Instanz-Anfragen konnten nicht geladen werden.", "error")
finally:
@@ -4038,6 +4070,14 @@ def admin_invoices():
except ValueError:
amt = 0.0
item["amount_eur"] = amt
if "amount_net_eur" in item:
net_amt = item.get("amount_net_eur")
if isinstance(net_amt, str):
try:
net_amt = float(net_amt.replace('.', '').replace(',', '.'))
except ValueError:
net_amt = 0.0
item["amount_net_eur"] = net_amt
if not isinstance(item.get("booking_data"), dict):
item["booking_data"] = {}
+2 -1
View File
@@ -255,7 +255,8 @@ def send_booking_admin_notification(booking: dict, recipient: str = "info@invari
"billing_city": "Rechnungsort",
"billing_reference": "Kassenzeichen / Aktenzeichen",
"package": "Gebuchte Produkte",
"amount_eur": "Betrag netto",
"amount_gross_eur": "Betrag brutto",
"amount_net_eur": "Betrag netto",
"booking_flow": "Buchungsfluss",
"invoice_id": "Rechnungs-ID",
"subdomain": "Subdomain",
+2 -2
View File
@@ -25,7 +25,7 @@
</select>
<input type="text" name="invoice_number" placeholder="Rechnungsnummer (optional, eigener Wert möglich)">
<input type="text" name="period" placeholder="Zeitraum (MM/YYYY)" required>
<input type="text" name="amount_eur" placeholder="Betrag netto in EUR" required>
<input type="text" name="amount_eur" placeholder="Betrag brutto in EUR" required>
<input type="text" name="due_date" placeholder="Fälligkeit (YYYY-MM-DD)">
<!-- NEU: Dropdown für Status beim Erstellen -->
@@ -46,7 +46,7 @@
<article class="entry">
<h3>{{ item.invoice_number }}</h3>
<p><strong>Nutzer:</strong> {{ item.username }} | <strong>Zeitraum:</strong> {{ item.period }}</p>
<p><strong>Betrag netto:</strong> {{ '%.2f'|format(item.amount_eur) }} EUR | <strong>Status:</strong> {{ item.status }} | <strong>Fälligkeit:</strong> {{ item.due_date }}</p>
<p><strong>Betrag brutto:</strong> {{ '%.2f'|format(item.amount_eur) }} EUR{% if item.amount_net_eur is defined %} | Netto: {{ '%.2f'|format(item.amount_net_eur) }} EUR{% endif %} | <strong>Status:</strong> {{ item.status }} | <strong>Fälligkeit:</strong> {{ item.due_date }}</p>
{% if item.source == 'booking_payment' %}
<p><strong>Buchung:</strong> {{ item.booking_package_label or item.booking_package }} | <strong>Flow:</strong> {{ item.booking_flow }}</p>
+1 -1
View File
@@ -32,7 +32,7 @@
<tr>
<td class="font-semibold">{{ invoice.invoice_number }}</td>
<td>{{ invoice.period }}</td>
<td class="amount-cell">{{ '%.2f'|format(invoice.amount_eur) }} € netto</td>
<td class="amount-cell"><strong>{{ '%.2f'|format(invoice.amount_eur) }} € brutto</strong>{% if invoice.amount_net_eur is defined %}<br><small>{{ '%.2f'|format(invoice.amount_net_eur) }} € netto</small>{% endif %}</td>
<td class="text-muted">{{ invoice.due_date }}</td>
<td>
{% set status_lower = (invoice.status or '')|lower %}
+5 -5
View File
@@ -319,16 +319,16 @@
{% if price_net %}
<div class="price-breakdown">
<div class="price-row">
<span>Verbindlicher Buchungsbetrag (Netto):</span>
<span>{{ ("%.2f"|format(price_net)) | replace('.', ',') }} €</span>
<span>Verbindlicher Buchungsbetrag (Brutto):</span>
<span>{{ ("%.2f"|format(price_gross)) | replace('.', ',') }} €</span>
</div>
<div class="price-row">
<span>zzgl. 19% USt:</span>
<span>{{ ("%.2f"|format(price_net * 0.19)) | replace('.', ',') }} €</span>
<span>{{ ("%.2f"|format(price_vat)) | replace('.', ',') }} €</span>
</div>
<div class="price-row total">
<span>Brutto (nur Information):</span>
<span>{{ ("%.2f"|format(price_net * 1.19)) | replace('.', ',') }} €</span>
<span>Brutto:</span>
<span>{{ ("%.2f"|format(price_gross)) | replace('.', ',') }} €</span>
</div>
</div>
{% endif %}