Add financial dashboard for organizer in payouts tab

- 6 KPIs: encaissé, en attente, remboursé, com E-Ticket, com Stripe, net perçu
- Calculated from all orders linked to organizer's events
- Displayed above export buttons and payouts table

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Serreau Jovann
2026-03-22 22:23:59 +01:00
parent 141871af1f
commit 80b48b9dbf
3 changed files with 58 additions and 1 deletions

View File

@@ -19,7 +19,7 @@
- [ ] Ajouter une notification admin quand un orga accepte/refuse une invitation
### Paiements & Finances
- [ ] Ajouter le dashboard financier pour l'orga (total encaissé, en attente, remboursé)
- [x] Ajouter le dashboard financier pour l'orga (encaissé, en attente, remboursé, com E-Ticket, com Stripe, net perçu)
- [x] Ajouter les virements Stripe (payouts) dans l'onglet de l'orga (déjà en place)
- [x] Générer un récapitulatif mensuel des ventes (export CSV + PDF, admin et orga)

View File

@@ -73,6 +73,35 @@ class AccountController extends AbstractController
$events = $paginator->paginate($eventsQuery, $request->query->getInt('page', 1), 10);
}
$financeStats = ['paid' => 0, 'pending' => 0, 'refunded' => 0, 'cancelled' => 0, 'commissionEticket' => 0, 'commissionStripe' => 0, 'net' => 0];
if ($isOrganizer) {
$orgaOrders = $em->createQueryBuilder()
->select('o')
->from(BilletBuyer::class, 'o')
->join('o.event', 'e')
->where('e.account = :user')
->setParameter('user', $user)
->getQuery()
->getResult();
$rate = $user->getCommissionRate() ?? 3;
foreach ($orgaOrders as $o) {
$ht = $o->getTotalHT() / 100;
if (BilletBuyer::STATUS_PAID === $o->getStatus()) {
$financeStats['paid'] += $ht;
$financeStats['commissionEticket'] += $ht * ($rate / 100);
$financeStats['commissionStripe'] += $ht * 0.015 + 0.25;
} elseif (BilletBuyer::STATUS_PENDING === $o->getStatus()) {
$financeStats['pending'] += $ht;
} elseif (BilletBuyer::STATUS_REFUNDED === $o->getStatus()) {
$financeStats['refunded'] += $ht;
} elseif (BilletBuyer::STATUS_CANCELLED === $o->getStatus()) {
$financeStats['cancelled'] += $ht;
}
}
$financeStats['net'] = $financeStats['paid'] - $financeStats['commissionEticket'] - $financeStats['commissionStripe'];
}
$orders = $em->getRepository(BilletBuyer::class)->findBy(
['user' => $user],
['createdAt' => 'DESC'],
@@ -94,6 +123,7 @@ class AccountController extends AbstractController
'events' => $events,
'orders' => $orders,
'userTickets' => $userTickets,
'financeStats' => $financeStats,
'breadcrumbs' => [
self::BREADCRUMB_HOME,
self::BREADCRUMB_ACCOUNT,

View File

@@ -415,6 +415,33 @@
</div>
{% elseif tab == 'payouts' %}
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4 mb-6">
<div class="card-brutal p-4 text-center">
<div class="text-[10px] font-black uppercase tracking-widest text-gray-500 mb-1">Encaisse</div>
<div class="text-xl font-black text-green-600">{{ financeStats.paid|number_format(2, ',', ' ') }} &euro;</div>
</div>
<div class="card-brutal p-4 text-center">
<div class="text-[10px] font-black uppercase tracking-widest text-gray-500 mb-1">En attente</div>
<div class="text-xl font-black text-yellow-600">{{ financeStats.pending|number_format(2, ',', ' ') }} &euro;</div>
</div>
<div class="card-brutal p-4 text-center">
<div class="text-[10px] font-black uppercase tracking-widest text-gray-500 mb-1">Rembourse</div>
<div class="text-xl font-black text-red-600">{{ financeStats.refunded|number_format(2, ',', ' ') }} &euro;</div>
</div>
<div class="card-brutal p-4 text-center">
<div class="text-[10px] font-black uppercase tracking-widest text-gray-500 mb-1">Com E-Ticket</div>
<div class="text-xl font-black text-red-500">{{ financeStats.commissionEticket|number_format(2, ',', ' ') }} &euro;</div>
</div>
<div class="card-brutal p-4 text-center">
<div class="text-[10px] font-black uppercase tracking-widest text-gray-500 mb-1">Com Stripe</div>
<div class="text-xl font-black text-red-500">{{ financeStats.commissionStripe|number_format(2, ',', ' ') }} &euro;</div>
</div>
<div class="card-brutal p-4 text-center bg-green-50">
<div class="text-[10px] font-black uppercase tracking-widest text-gray-500 mb-1">Net percu</div>
<div class="text-xl font-black text-green-600">{{ financeStats.net|number_format(2, ',', ' ') }} &euro;</div>
</div>
</div>
<div class="card-brutal overflow-hidden mb-6">
<div class="section-header">
<h2 class="text-[10px] font-black uppercase tracking-widest text-white">Export mensuel</h2>