{% include '_molecules/page-header/page-header.html.twig' with {
title: commercial.user.fullName,
subtitle: commercial.user.email,
icon: 'wallet',
backHref: path('admin_commercial_list'),
backLabel: 'Retour aux commerciaux'
} only %}
{# Même carte que le dashboard commercial : le code est lui-même la zone cliquable. #}
Code de parrainage
{% include 'admin/commercial/_copy-script.html.twig' %}
{# ================================================================
STATISTIQUES
================================================================ #}
{# Taux de commission : éditable en place (comme les tokens des utilisateurs) #}
{% include '_molecules/stat-card/stat-card.html.twig' with {
label: 'Taux de commission',
value: (commercial.commissionRate * 100)|number_format(2, ',', ' ') ~ '%',
icon: 'chart',
variant: commercial_colors.commission,
size: 'sm',
layout: 'horizontal',
editModalId: 'modal-edit-rate'
} only %}
{% include '_molecules/stat-card/stat-card.html.twig' with {
label: 'Filleuls',
value: recruitPagination.totalItems,
icon: 'users',
variant: commercial_colors.filleuls,
size: 'sm',
layout: 'horizontal'
} only %}
{% include '_molecules/stat-card/stat-card.html.twig' with {
label: 'Statut',
value: commercial.isActive ? 'Actif' : 'Suspendu',
icon: 'power',
variant: commercial.isActive ? 'success' : 'error',
size: 'sm',
layout: 'horizontal'
} only %}
{# 4ᵉ case : activer / désactiver le commercial #}
Accès du commercial
{# ================================================================
MODALE — Édition du taux de commission (ouverte via le stat-card)
================================================================ #}
{% embed '_molecules/modal/modal.html.twig' with {
id: 'modal-edit-rate',
title: 'Taux de commission',
variant: 'primary',
size: 'md'
} %}
{% block body %}
{% endblock %}
{% block footer %}
{% include '_atoms/button/button.html.twig' with {
label: 'Annuler', variant: 'ghost', size: 'md',
attr: { onclick: "closeModal('modal-edit-rate')" }
} only %}
{% include '_atoms/button/button.html.twig' with {
label: 'Enregistrer', variant: 'primary', size: 'md',
attr: { onclick: "document.getElementById('edit-rate-form').submit()" }
} only %}
{% endblock %}
{% endembed %}
{# Modal de confirmation, déclenché par le bouton de la status-zone ci-dessus #}
{% embed '_molecules/modal/modal.html.twig' with {
id: 'modal-toggle-commercial-status',
title: commercial.isActive ? 'Suspendre ce commercial ?' : 'Réactiver ce commercial ?',
variant: commercial.isActive ? 'danger' : 'success',
size: 'md'
} %}
{% block body %}
{{ commercial.isActive
? 'Il perdra immédiatement l\'accès à son espace commercial (dashboard, filleuls, gains).'
: 'Il retrouvera immédiatement l\'accès à son espace commercial.' }}
{% set p = plansBySlug[commission.planSlug] ?? null %}
{% include '_atoms/plan-badge/plan-badge.html.twig' with {
name: p ? p.name : commission.planSlug,
gradient: p ? p.gradientCss : null,
isFree: p ? p.isFree() : (commission.planSlug is null),
isAnnual: commission.billingCycle == 'annual'
} only %}
{% include '_molecules/pagination/pagination.html.twig' with {
currentPage: commissionPagination.current,
totalPages: commissionPagination.total,
baseUrl: path('admin_commercial_show', {id: commercial.id}),
pageParam: 'lignes',
size: 'sm'
} only %}
{% endif %}
{% else %}
{% include '_molecules/empty-state/empty-state.html.twig' with {
title: 'Aucune commission',
description: 'Aucune commission n\'a encore été générée pour ce commercial.',
icon: 'wallet',
variant: 'minimal'
} only %}
{% endif %}
{# ================================================================
ENCOURS — CE QU'ON LUI DOIT, ET DE QUOI LE RÉGLER
La fiche ne listait que les relevés DÉJÀ versés et ne portait aucun bouton
« Payer » : le seul écran dédié à un commercial ne disait pas ce qu'on lui doit.
Une ligne par mois dû, chacune réglable séparément — la liste, elle, ne propose
que le mois le plus ancien.
================================================================ #}
Encours dû
{% if not due.isEmpty() %}
({{ due.count() }} mois)
{% elseif due.hasCurrent() %}
(mois en cours seulement)
{% endif %}
Total à virer{{ due.total|number_format(2, ',', ' ') }} €
{% if due.hasCurrent() %}
+ {{ due.currentTotal()|number_format(2, ',', ' ') }} € en cours
{% endif %}
{# Le tableau s'ouvre aussi quand SEUL le mois en cours porte quelque chose :
l'administrateur n'a plus à attendre le 1er du mois suivant pour voir venir
un virement. La ligne du mois ouvert n'a ni bouton ni champ de référence —
un mois n'est versable qu'une fois clos. #}
{% if not due.isEmpty() or due.hasCurrent() %}
{# Le tableau défile dans son propre conteneur : la colonne d'action porte un
champ de référence et un bouton, elle ne se comprime pas. #}
{% if not due.isEmpty() %}
{% include '_molecules/inline-alert/inline-alert.html.twig' with {
variant: 'warning',
message: 'Le versement est manuel : enregistrez-le ici après avoir émis le virement,
en reportant sa référence bancaire. Un mois versé est définitif — il n\'est jamais recalculé,
et rien ne permet aujourd\'hui de l\'annuler.'
} only %}
{% else %}
{% include '_molecules/inline-alert/inline-alert.html.twig' with {
variant: 'primary',
message: 'Aucun mois clos ne reste dû. Le montant ci-dessus est celui du mois en cours :
il continue de bouger et ne sera versable qu\'une fois le mois terminé.'
} only %}
{% endif %}
{% else %}
{% include '_molecules/empty-state/empty-state.html.twig' with {
title: 'Rien à virer',
description: 'Aucun mois clos ne reste dû à ce commercial. Un mois n\'est versable qu\'une fois terminé.',
icon: 'check-circle',
variant: 'minimal'
} only %}
{% endif %}
{# ================================================================
RELEVÉS DE COMMISSION
================================================================ #}
Relevés de commission
({{ payoutPagination.totalItems }})
{% if payouts|length > 0 %}
{# La référence bancaire OUVRE le tableau : c'est par elle qu'un
relevé se rapproche du virement réel, sur le relevé de banque
comme dans un échange avec le commercial. #}
Référence
Période
CA net HT
Frais Stripe
Commission
Statut
{% for payout in payouts %}
{% if payout.reference %}
{{ payout.reference }}
{% else %}
{# Les relevés d'avant l'obligation, et ceux restés « pending »
que l'ancienne commande de génération créait sans virement. #}
—
{% endif %}
{% include '_atoms/badge/badge.html.twig' with {
label: payout.isPaid ? 'Versé' : 'Jamais versé',
variant: payout.isPaid ? 'success' : 'warning',
size: 'sm'
} only %}
{% endfor %}
{% if payoutPagination.total > 1 %}
{% include '_molecules/pagination/pagination.html.twig' with {
currentPage: payoutPagination.current,
totalPages: payoutPagination.total,
baseUrl: path('admin_commercial_show', {id: commercial.id}),
pageParam: 'releves',
size: 'sm'
} only %}
{% endif %}
{% else %}
{% include '_molecules/empty-state/empty-state.html.twig' with {
title: 'Aucun relevé',
description: 'Aucun relevé de commission n\'a encore été généré pour ce commercial.',
icon: 'chart',
variant: 'minimal'
} only %}
{% endif %}
{# ================================================================
HISTORIQUE
================================================================ #}
{# La section s'arrête aux dernières lignes : une commission tombe à chaque
paiement d'un filleul, et l'aperçu ne couvre alors que quelques semaines. #}
{% include '_organisms/activity-log/activity-log-section.html.twig' with {
logs: logs ?? [],
moreHref: path('admin_commercial_journal', {id: commercial.id})
} only %}