{% extends "admin/_admin_base.html" %} {% from "components/pagination.html" import render_pagination %} {% block title %}Payments · Admin · CampusCart{% endblock %} {% macro metric(label, value, icon, color, sub=None, col='col-6 col-md-4 col-xl-3') %}
{{ value }}
{{ label }}
{% if sub %}
{{ sub }}
{% endif %}
{% endmacro %} {% macro money(v) %}{{ currency }}{{ '{:,.0f}'.format(v|float) }}{% endmacro %} {% block admin_header %}

Payments

Revenue, premium purchases and payment activity across Student Bazaar.

Export CSV
{% endblock admin_header %} {% block admin_content %} {% set has_filters = q or status or provider or plan or amount_min or amount_max or date_from or date_to %} {% set has_payments = kpis.total_payments > 0 %} {# ---------------- KPI cards ---------------- Refunds are handled in the Razorpay Dashboard (external) and only synced in, so they are intentionally not surfaced as an admin metric. The remaining seven cards are laid out as a balanced 4 + 3 grid (no empty gaps). #}
{{ metric('Total Revenue', money(kpis.total_revenue), 'bi-cash-stack', 'success', col='col-6 col-xl-3') }} {{ metric('Revenue This Month', money(kpis.revenue_month), 'bi-calendar2-week', 'primary', col='col-6 col-xl-3') }} {{ metric('Active Premium Subscribers', '{:,}'.format(kpis.active_subscribers), 'bi-star-fill', 'warning', col='col-6 col-xl-3') }} {{ metric('Payment Success Rate', '%.1f%%'|format(kpis.success_rate), 'bi-graph-up-arrow', 'info', col='col-6 col-xl-3') }}
{{ metric('Successful Payments', '{:,}'.format(kpis.successful), 'bi-check-circle-fill', 'success', col='col-12 col-md-4') }} {{ metric('Failed Payments', '{:,}'.format(kpis.failed), 'bi-x-circle-fill', 'danger', col='col-12 col-md-4') }} {{ metric('Pending Payments', '{:,}'.format(kpis.pending), 'bi-hourglass-split', 'warning', col='col-12 col-md-4') }}
{# ---------------- Revenue analytics ---------------- #} {% if has_payments %}

Revenue over time · last 30 days

Total captured revenue in the last 30 days: {{ money(kpis.revenue_month) }} this month.

Payment status

Revenue by plan

Payment provider

Premium conversions · last 30 days

{% endif %} {# ---------------- Filters ---------------- #} {# ---------------- Table / empty states ---------------- #} {% if pagination.items %}
{% for p in pagination.items %} {% set u = p.user %} {% set name = (u.profile.full_name if u and u.profile else (u.email if u else '—')) %} {% set m = meta(p) %} {% endfor %}
Payments, most recent first
User Plan Amount Status Provider Order ID Created Actions
{{ name }}
{{ u.email if u else '' }}
{{ p.plan_name }} {{ currency }}{{ '{:,.2f}'.format(p.amount|float) }} {{ p.status.value|title }} {{ p.provider|title }} {{ p.provider_order_id or '—' }} {{ p.created_at.strftime('%d %b %Y') if p.created_at else '—' }}
{{ render_pagination(pagination, 'admin.payments_dashboard', filter_args) }}
{% else %} {# Polished empty states (Phase 11). #}
{% if has_filters %}

No payments match your filters

Try clearing some filters to see more results.

Clear filters {% else %}

No payments yet

Premium purchases will appear here once students upgrade online. Offline activations are handled from the Premium requests console.

{% endif %}
{% endif %} {# ---------------- Details drawer (populated from the clicked row) ---------------- #} {% endblock admin_content %} {% block scripts %} {% endblock scripts %}