Jun 28 - Implement payment functions (Stripe)

This commit is contained in:
2026-06-28 12:01:25 -04:00
parent 61ede27093
commit f292c8fb7b
21 changed files with 1112 additions and 18 deletions
@@ -268,7 +268,7 @@
</div>
{# ── Quick info ── #}
<div class="card border-0 shadow-sm">
<div class="card border-0 shadow-sm mb-3">
<div class="card-header bg-white py-2">
<span class="fw-semibold" style="font-size:.9rem;"><i class="bi bi-link-45deg me-1"></i>Primary URL</span>
</div>
@@ -286,6 +286,70 @@
</div>
</div>
{# ── Billing (MT-8, read-only) ── #}
<div class="card border-0 shadow-sm">
<div class="card-header bg-white py-2">
<span class="fw-semibold" style="font-size:.9rem;"><i class="bi bi-credit-card me-1"></i>Billing</span>
</div>
<div class="card-body py-2" style="font-size:.83rem;">
<div class="mb-1">
<span class="text-muted">Subscription</span>
<div>
{% if tenant.subscription_status == 'active' %}
<span class="badge bg-success">active</span>
{% elif tenant.subscription_status == 'trial' %}
<span class="badge bg-info text-dark">trial</span>
{% elif tenant.subscription_status == 'past_due' %}
<span class="badge bg-warning text-dark">past_due</span>
{% elif tenant.subscription_status == 'cancelled' %}
<span class="badge bg-danger">cancelled</span>
{% else %}
<span class="text-muted"></span>
{% endif %}
</div>
</div>
{% if tenant.trial_ends_at %}
<div class="mb-1">
<span class="text-muted">Trial ends</span>
<div>{{ tenant.trial_ends_at.strftime('%Y-%m-%d') }}</div>
</div>
{% endif %}
{% if tenant.current_period_end %}
<div class="mb-1">
<span class="text-muted">Period ends</span>
<div>{{ tenant.current_period_end.strftime('%Y-%m-%d') }}</div>
</div>
{% endif %}
{% if tenant.billing_email %}
<div class="mb-1">
<span class="text-muted">Billing email</span>
<div>{{ tenant.billing_email }}</div>
</div>
{% endif %}
{% if tenant.stripe_customer_id %}
<div class="mb-1">
<span class="text-muted">Stripe customer</span>
<div class="font-monospace" style="font-size:.75rem;"
title="{{ tenant.stripe_customer_id }}">
{{ tenant.stripe_customer_id[:20] }}…
</div>
</div>
{% endif %}
{% if tenant.stripe_subscription_id %}
<div class="mb-1">
<span class="text-muted">Stripe subscription</span>
<div class="font-monospace" style="font-size:.75rem;"
title="{{ tenant.stripe_subscription_id }}">
{{ tenant.stripe_subscription_id[:20] }}…
</div>
</div>
{% endif %}
{% if not tenant.subscription_status %}
<span class="text-muted">No billing configured.</span>
{% endif %}
</div>
</div>
</div>{# /col-lg-4 #}
</div>{# /row #}
+7
View File
@@ -119,6 +119,13 @@ def tenant_detail(tenant_id):
'db_host': t.db_host, 'db_port': t.db_port,
'alembic_head': t.alembic_head, 'created_at': t.created_at,
'suspended_at': t.suspended_at, 'notes': t.notes,
# MT-8: billing fields (read-only in panel)
'subscription_status': t.subscription_status,
'trial_ends_at': t.trial_ends_at,
'current_period_end': t.current_period_end,
'stripe_customer_id': t.stripe_customer_id,
'stripe_subscription_id': t.stripe_subscription_id,
'billing_email': t.billing_email,
}
plan_rows = [{'id': p.id, 'code': p.code, 'name': p.name} for p in plans]
domain_rows = [