{% extends 'base.html.twig' %} {% block title %}Mes transactions — Bubul{% endblock %} {# Le sous-tableau des lignes d'un mois. Six colonnes, pas huit. Le CA brut et les frais Stripe sortent : c'est la BASE COMMISSIONNÉE — le net après frais Stripe — qui est réellement multipliée par le taux, et elle suffit à rendre le calcul vérifiable. Le détail complet reste dans l'export CSV. Le même tableau sert aux lignes réglées et aux lignes tardives : c'est la même information, seul son sort diffère. #} {% macro lignes(lines, plansBySlug, tardives = false) %}
| Date | Filleul | Offre | {# Les opérateurs vivent dans l'en-tête, pas dans les cellules : une contre-passation porte des montants négatifs, et « × -1,03 € » ne se lit pas. Lue en travers, la ligne d'en-tête EST le calcul. #}Base commissionnée | × Taux | = Commission |
|---|---|---|---|---|---|
| {{ line.paidAt|date('d/m/Y') }} | {{ line.user ? line.user.fullName : '—' }} {{ line.user ? line.user.email : '' }} | {% set p = plansBySlug[line.planSlug] ?? null %} {% include '_atoms/plan-badge/plan-badge.html.twig' with { name: p ? p.name : line.planSlug, gradient: p ? p.gradientCss : null, isFree: p ? p.isFree() : (line.planSlug is null), isAnnual: line.billingCycle == 'annual' } only %} | {{ line.amountNetAfterStripe|number_format(2, ',', ' ') }} € | {{ (line.appliedRate * 100)|number_format(2, ',', ' ') }} % | {{ line.commissionAmount|number_format(2, ',', ' ') }} € {% if line.isReversal %} {% include '_atoms/badge/badge.html.twig' with { label: 'Contre-passation', variant: 'error', size: 'xs' } only %} {% endif %} |
| Mois | Paiements | Commission acquise | Montant viré | Statut | {# La colonne du chevron : sans libellé, elle n'annonce rien d'autre que le fait que la ligne se déplie. #}Détail |
|---|---|---|---|---|---|
| {{ period.label() }} | {{ period.lines|length }} | {{ period.commissionAmount|number_format(2, ',', ' ') }} € {% if period.hasLateLines() %} + {{ period.lateCommissionAmount|number_format(2, ',', ' ') }} € hors relevé {% endif %} | {{ period.status == 'paye' ? (period.amountPayable|number_format(2, ',', ' ')) ~ ' €' : '—' }} | {% include '_atoms/badge/badge.html.twig' with { label: period.status == 'paye' ? 'Versé' : (period.status == 'en_cours' ? 'Mois en cours' : 'À verser'), variant: period.status == 'paye' ? 'success' : (period.status == 'en_cours' ? 'info' : 'warning'), size: 'sm' } only %} | {% include '_atoms/icon/icon.html.twig' with { name: 'chevron-down', size: 'xs' } only %} |
|
{# La cible est ce , jamais le
{% if period.isPaid or period.carryOverIn < 0 or period.carryOverOut < 0 %}
{% if period.isPaid %}
{% include '_atoms/icon/icon.html.twig' with { name: 'check-circle', size: 'xs', color: 'success' } only %}
Viré le {{ period.paidAt ? period.paidAt|date('d/m/Y') : '—' }}{% if period.reference %} · référence {{ period.reference }}{% endif %}
{% endif %}
{% if period.carryOverIn < 0 %}
Report du mois précédent : {{ period.carryOverIn|number_format(2, ',', ' ') }} €
{% endif %}
{% if period.carryOverOut < 0 %}
Reste {{ period.carryOverOut|number_format(2, ',', ' ') }} € reporté au mois suivant
{% endif %}
{% endif %}
{{ _self.lignes(period.lines, plansBySlug) }}
{# ── Ce qui est arrivé APRÈS le virement de ce mois ──
Un virement figé n'est JAMAIS recalculé : ces lignes ne sont
ni comprises dans le versement, ni payables, ni reportées au
mois suivant. Les taire est l'anomalie la plus coûteuse de
cet écran — l'encart reste en clair. #}
{% if period.hasLateLines() %}
{% include '_molecules/inline-alert/inline-alert.html.twig' with {
variant: 'warning',
icon: 'warning',
message: ''
~ period.lateLines|length ~ ' transaction' ~ (period.lateLines|length > 1 ? 's' : '')
~ ' arrivée' ~ (period.lateLines|length > 1 ? 's' : '') ~ ' après le virement — '
~ (period.lateCommissionAmount|number_format(2, ',', ' ')) ~ ' €'
~ 'Le virement de ce mois est définitif : il n\'est jamais recalculé. Ces commissions
ne sont donc ni comprises dans ce versement, ni reportées au mois suivant.
Si ce montant vous semble vous revenir, signalez-le à l\'administration.'
} only %}
{{ _self.lignes(period.lateLines, plansBySlug, true) }}
{% endif %}
| |||||