Downgrade-Ablauf wurde auf Paketentfernung umgestellt

This commit is contained in:
2026-10-05 18:52:29 +02:00
parent a07f9f6b31
commit bad0dd6b6c
3 changed files with 32 additions and 28 deletions
+23 -19
View File
@@ -2301,13 +2301,12 @@ def _get_downgrade_options(instance: dict | None) -> list[dict]:
current_modules = _package_modules(_instance_package_keys(instance))
options = []
for package_key in ("startpaket", "inventarsystem", "buecherei", "terminverwaltung"):
for package_key in ("inventarsystem", "buecherei", "terminverwaltung"):
package_modules = _package_modules([package_key])
if package_modules and package_modules < current_modules:
if package_modules and package_modules <= current_modules and current_modules - package_modules:
options.append({
"id": package_key,
"name": BOOKING_PACKAGE_MAP[package_key],
"price": BOOKING_PRICE_MAP[package_key],
})
return options
@@ -2325,8 +2324,8 @@ def _booking_restriction(instance: dict | None, package_list: list[str], booking
return "Der bestehende Paketumfang konnte nicht ermittelt werden. Bitte wenden Sie sich an unser Team."
if booking_action == "downgrade":
if not requested_modules or not requested_modules < current_modules:
return "Die gewählte Version ist keine gültige Herabstufung Ihres bestehenden Pakets."
if not requested_modules or not requested_modules <= current_modules or not current_modules - requested_modules:
return "Das ausgewählte Paket kann nicht aus Ihrer bestehenden Version entfernt werden."
return None
if not requested_modules - current_modules:
@@ -3080,7 +3079,7 @@ def booking_payment():
"flow": booking_flow,
"booking_action": booking_action,
"is_trial": is_trial,
"title": "Herabstufung Ihrer Version prüfen" if booking_action == "downgrade" else flow_config["title"],
"title": "Entfernung eines Pakets prüfen" if booking_action == "downgrade" else flow_config["title"],
"intro": flow_config["intro"],
"confirm_label": flow_config["confirm_label"],
"username": session.get("username"),
@@ -3234,9 +3233,9 @@ def booking_payment():
"booking_number": booking_number,
"package": package_raw,
"package_label": selected_package,
"amount_eur": gross_price,
"amount_net_eur": net_price,
"vat_eur": vat_amount,
"amount_eur": 0.0 if booking_action == "downgrade" else gross_price,
"amount_net_eur": 0.0 if booking_action == "downgrade" else net_price,
"vat_eur": 0.0 if booking_action == "downgrade" else vat_amount,
"booking_flow": booking_flow,
"booking_data": form_data,
"is_trial": is_trial,
@@ -3288,23 +3287,28 @@ def booking_payment():
if reuse_instance:
current_package_keys = _instance_package_keys(reuse_instance)
effective_package_keys = (
package_list
if booking_action == "downgrade"
else list(dict.fromkeys(current_package_keys + package_list))
)
if booking_action == "downgrade":
current_modules = _package_modules(current_package_keys)
modules_to_remove = _package_modules(package_list)
effective_package_keys = sorted(current_modules - modules_to_remove)
else:
effective_package_keys = list(dict.fromkeys(current_package_keys + package_list))
module_config = " ".join(
f"{module}=on" if module in _package_modules(effective_package_keys) else f"{module}=off"
for module in ALL_MODULE_KEYS
)
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"{gross_price:.2f}".replace('.', ',')
price_str = (
"Bestehende Jahresrechnung bleibt unverändert"
if booking_action == "downgrade"
else f"{gross_price:.2f}".replace('.', ',')
)
billing_update = {
"package": ",".join(effective_package_keys),
"status": "ready",
"last_message": (
"Paket wurde herabgestuft und die Module werden aktualisiert."
"Ausgewählte Module wurden entfernt. Die bestehende Jahresrechnung bleibt unverändert."
if booking_action == "downgrade"
else "Zusätzliche Module wurden zur bestehenden Instanz gebucht; Zahlungsziel beträgt 14 Tage."
),
@@ -3355,9 +3359,9 @@ def booking_payment():
"billing_city": form_data.get("billing_city"),
"billing_reference": form_data.get("billing_reference"),
"package": selected_package,
"amount_eur": gross_price,
"amount_gross_eur": gross_price,
"amount_net_eur": net_price,
"amount_eur": 0.0 if booking_action == "downgrade" else gross_price,
"amount_gross_eur": 0.0 if booking_action == "downgrade" else gross_price,
"amount_net_eur": 0.0 if booking_action == "downgrade" else net_price,
"booking_flow": booking_flow,
"invoice_id": invoice_id,
"subdomain": subdomain,
+3 -3
View File
@@ -55,14 +55,14 @@
<div class="instance-card__header">
<div>
<span class="instance-eyebrow">Paketverwaltung</span>
<h2>Version herabstufen</h2>
<h2>Pakete oder Module entfernen</h2>
</div>
</div>
<p>Wählen Sie eine kleinere Version. Ihre bestehende Instanz und Daten bleiben erhalten.</p>
<p>Wählen Sie aus, welches Paket oder Modul entfernt werden soll. Ihre Instanz, Subdomain und bestehende Jahresrechnung bleiben unverändert.</p>
<div class="downgrade-options">
{% for option in downgrade_options %}
<button class="instance-action instance-action--outline" type="button" onclick="window.location.href='{{ url_for('booking_payment', packages=option.id, flow='payment', booking_action='downgrade') }}'">
{{ option.name }} <span>{{ option.price|int }} € netto/Jahr</span>
{{ option.name }} entfernen
</button>
{% endfor %}
</div>
+6 -6
View File
@@ -298,7 +298,7 @@
<!-- STATE 1: FORMULAR (Checkout) -->
<div id="checkout-form-state">
<span class="booking-review__eyebrow">{% if booking_action == 'downgrade' %}Herabstufung prüfen{% else %}Buchung prüfen & abschließen{% endif %}</span>
<span class="booking-review__eyebrow">{% if booking_action == 'downgrade' %}Paketentfernung prüfen{% else %}Buchung prüfen & abschließen{% endif %}</span>
<h1>{{ title }}</h1>
{% if active_trial %}
@@ -311,10 +311,10 @@
<!-- Der verbindliche Buchungswert ist der Netto-Betrag. -->
<div class="booking-review__card">
<span class="booking-review__label">Gewähltes Paket</span>
<span class="booking-review__label">{% if booking_action == 'downgrade' %}Zu entfernendes Paket{% else %}Gewähltes Paket{% endif %}</span>
<div class="booking-review__value" style="font-size: 1.1rem;">{{ package }}</div>
{% if price_net %}
{% if price_net and booking_action != 'downgrade' %}
<div class="price-breakdown">
<div class="price-row">
<span>Netto:</span>
@@ -337,7 +337,7 @@
<span class="booking-review__label">Zahlungsart</span>
{% if booking_action == 'downgrade' %}
<div class="booking-review__value" style="color: #1b8a3e;">Bestehende Buchung anpassen</div>
<small style="color: #5e757d; font-weight: 600;">Keine neue Rechnung für die Herabstufung</small>
<small style="color: #5e757d; font-weight: 600;">Keine neue Rechnung; die bestehende Jahresrechnung bleibt unverändert</small>
{% else %}
<div class="booking-review__value" style="color: #1b8a3e;">Kauf auf Rechnung</div>
<small style="color: #5e757d; font-weight: 600;">14 Tage Zahlungsziel nach Bereitstellung</small>
@@ -347,7 +347,7 @@
<div class="booking-review__note">
{% if booking_action == 'downgrade' %}
Die bestehende Instanz und Ihre Daten bleiben erhalten. Nach dem Absenden wird der kleinere Paketumfang für die Instanz aktiviert.
Die bestehende Instanz, Subdomain und Rechnung bleiben erhalten. Nach dem Absenden wird das ausgewählte Paket bzw. Modul aus Ihrer Instanz entfernt.
{% else %}
Die Software-Instanz wird nach dem Absenden <strong>sofort für 14 Tage freigeschaltet</strong>. Die finale Laufzeit aktiviert sich automatisch nach Zahlungseingang durch Ihren Schulträger.
{% endif %}
@@ -432,7 +432,7 @@
<div id="form-error-alert" style="display:none; color:#b02a37; margin-top:1rem; font-weight:bold;"></div>
<div class="booking-review__actions">
<button id="booking_submit" class="btn" type="submit">{% if booking_action == 'downgrade' %}Herabstufung bestätigen{% else %}Kostenpflichtig buchen & Instanz starten{% endif %}</button>
<button id="booking_submit" class="btn" type="submit">{% if booking_action == 'downgrade' %}Entfernung bestätigen{% else %}Kostenpflichtig buchen & Instanz starten{% endif %}</button>
</div>
</form>
</div>