Selbstbedienungs-Tarifverwaltung: Admin kann Abo im Backend waehlen und bestellen
- mandant-einstellungen.php: vollstaendige Tarif-Vergleichstabelle statt nur erzwungenem Upgrade-Hinweis. Jeder Tarif zeigt Limit, Preis und einen Aktions-Button (Buchen/Kuendigen/Anfragen); aktueller Tarif markiert, zu kleine Tarife fuer die aktuelle Teilnehmerzahl deaktiviert. - abo-upgrade.php: unterscheidet jetzt Upgrade, Downgrade zwischen bezahlten Stufen (Preis wird in-place gewechselt statt neuer Checkout-Session, Stripe prorated automatisch) und Wechsel auf 'free' (echte Kuendigung der bestehenden Subscription), statt nur eine Checkout-Session zu erzeugen. - app/stripe.php: neue Helper stripe_get_subscription(), stripe_update_subscription_price(), stripe_cancel_subscription(). - app/billing.php: billing_plan_selectable_for() prueft serverseitig, ob ein Zieltarif die aktuelle Teilnehmerzahl noch abdeckt (Downgrade-Schutz). - docs/billing.md: Phase 4 dokumentiert. Getestet: php -l fuer alle geaenderten Dateien und das gesamte Repo (keine Syntaxfehler), reine Funktionslogik-Tests ohne DB (billing_plans(), billing_required_plan_code(), stripe_flatten_params()) gruen. Kein Live-Test gegen echte Stripe-Testobjekte moeglich (keine PHP/DB-Laufzeitumgebung verfuegbar) - vor Go-Live im Stripe-Testmodus nachholen.
This commit is contained in:
+52
-14
@@ -192,34 +192,72 @@ include 'nav.php';
|
||||
Aktive Teilnehmer: <?php echo (int)$billingCheck['active_participants']; ?>
|
||||
</p>
|
||||
<?php if (isset($_GET['upgrade']) && $_GET['upgrade'] === 'success'): ?>
|
||||
<div class="hint-box success"><p>Danke! Die Zahlung wird verarbeitet, der Tarif ist gleich aktuell.</p></div>
|
||||
<div class="hint-box success"><p>Danke! Die Änderung wird verarbeitet, der Tarif ist gleich aktuell.</p></div>
|
||||
<?php elseif (isset($_GET['upgrade']) && $_GET['upgrade'] === 'cancelled'): ?>
|
||||
<div class="hint-box error"><p>Der Bezahlvorgang wurde abgebrochen, es wurde nichts geändert.</p></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($billingCheck['needs_upgrade']): ?>
|
||||
<div class="hint-box error">
|
||||
<p>Mit <?php echo (int)$billingCheck['active_participants']; ?> aktiven Teilnehmern benötigt ihr den
|
||||
Tarif „<?php echo saas_html($billingPlans[$billingCheck['required_plan']]['label'] ?? $billingCheck['required_plan']); ?>".
|
||||
Details zu den Stufen stehen unter <a href="preise.php">Preise</a>.</p>
|
||||
<?php if (($billingPlans[$billingCheck['required_plan']]['stripe_lookup_key'] ?? null) !== null): ?>
|
||||
<form method="post" action="abo-upgrade.php">
|
||||
<?php echo app_csrf_field(); ?>
|
||||
<input type="hidden" name="plan_code" value="<?php echo saas_html($billingCheck['required_plan']); ?>">
|
||||
<button type="submit">Jetzt auf „<?php echo saas_html($billingPlans[$billingCheck['required_plan']]['label']); ?>" upgraden</button>
|
||||
</form>
|
||||
<?php else: ?>
|
||||
<p>Für diese Teilnehmerzahl <a href="mailto:info@ctb-it.de">meldet euch bitte bei uns</a>.</p>
|
||||
<?php endif; ?>
|
||||
<p>Mit <?php echo (int)$billingCheck['active_participants']; ?> aktiven Teilnehmern benötigt ihr mindestens den
|
||||
Tarif „<?php echo saas_html($billingPlans[$billingCheck['required_plan']]['label'] ?? $billingCheck['required_plan']); ?>".</p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="hint-box success"><p>Euer aktueller Tarif deckt eure Teilnehmerzahl ab.</p></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Tarif</th>
|
||||
<th>Max. aktive Teilnehmer</th>
|
||||
<th>Preis/Monat</th>
|
||||
<th>Status</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<?php foreach ($billingPlans as $planCode => $plan): ?>
|
||||
<?php
|
||||
$isCurrent = $planCode === $billingCheck['current_plan'];
|
||||
$selectable = billing_plan_selectable_for($pdo, (int)$user['tenant_id'], $planCode);
|
||||
$isSelfService = $plan['stripe_lookup_key'] !== null || $planCode === 'free';
|
||||
?>
|
||||
<tr<?php echo $isCurrent ? ' class="hint-box success"' : ''; ?>>
|
||||
<td><?php echo saas_html($plan['label']); ?></td>
|
||||
<td><?php echo $plan['max_participants'] !== null ? (int)$plan['max_participants'] : 'unbegrenzt'; ?></td>
|
||||
<td><?php echo $plan['price_cents'] > 0 ? saas_html(saas_format_money_cents($plan['price_cents'])) . ' €' : 'kostenlos'; ?></td>
|
||||
<td>
|
||||
<?php if ($isCurrent): ?>
|
||||
aktuell gebucht
|
||||
<?php elseif (!$selectable): ?>
|
||||
deckt eure <?php echo (int)$billingCheck['active_participants']; ?> Teilnehmer nicht ab
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php if ($isCurrent): ?>
|
||||
—
|
||||
<?php elseif (!$isSelfService): ?>
|
||||
<a href="mailto:info@ctb-it.de" class="button small">Anfragen</a>
|
||||
<?php elseif (!$selectable): ?>
|
||||
<button type="button" class="button small" disabled>Nicht wählbar</button>
|
||||
<?php else: ?>
|
||||
<form method="post" action="abo-upgrade.php" onsubmit="return confirm('Tarif wirklich auf ' + <?php echo json_encode($plan['label']); ?> + ' ändern?');">
|
||||
<?php echo app_csrf_field(); ?>
|
||||
<input type="hidden" name="plan_code" value="<?php echo saas_html($planCode); ?>">
|
||||
<button type="submit" class="button small primary">
|
||||
<?php echo $planCode === 'free' ? 'Kündigen / auf Kostenlos wechseln' : 'Buchen'; ?>
|
||||
</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
<p><small>Ein Wechsel zwischen bezahlten Tarifen wird bei Stripe anteilig verrechnet (Proration) und
|
||||
gilt sofort. Details zu den Tarifgrenzen stehen unter <a href="preise.php">Preise</a>.</small></p>
|
||||
|
||||
<?php if (($billing['stripe_customer_id'] ?? null) !== null): ?>
|
||||
<form method="post" action="abo-portal.php">
|
||||
<?php echo app_csrf_field(); ?>
|
||||
<button type="submit">Zahlungsmethode verwalten / Abo kündigen</button>
|
||||
<button type="submit">Zahlungsmethode verwalten</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user