feat: Implement promoter payout system for event revenue processing

- Add Payout model with associations to User and Event
- Create payout requests for completed events with proper earnings calculation
- Exclude refunded tickets from payout calculations
- Add promoter dashboard views for managing payouts
- Implement admin interface for processing payouts
- Integrate with Stripe for actual payment processing
- Add comprehensive tests for payout functionality

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
kbe
2025-09-17 00:29:20 +02:00
parent 58141dca94
commit 59e1854803
20 changed files with 587 additions and 254 deletions

View File

@@ -84,6 +84,36 @@
À la une
</span>
<% end %>
<% if event.event_ended? && event.can_request_payout? %>
<% case event.payout_status %>
<% when "not_requested" %>
<span class="inline-flex px-2 py-1 text-xs font-semibold rounded-full bg-orange-100 text-orange-800 ml-1">
<i data-lucide="dollar-sign" class="w-3 h-3 mr-1"></i>
Paiement disponible
</span>
<% when "requested" %>
<span class="inline-flex px-2 py-1 text-xs font-semibold rounded-full bg-yellow-100 text-yellow-800 ml-1">
<i data-lucide="clock" class="w-3 h-3 mr-1"></i>
Paiement demandé
</span>
<% when "processing" %>
<span class="inline-flex px-2 py-1 text-xs font-semibold rounded-full bg-blue-100 text-blue-800 ml-1">
<i data-lucide="refresh-cw" class="w-3 h-3 mr-1"></i>
Paiement en cours
</span>
<% when "completed" %>
<span class="inline-flex px-2 py-1 text-xs font-semibold rounded-full bg-green-100 text-green-800 ml-1">
<i data-lucide="check-circle" class="w-3 h-3 mr-1"></i>
Paiement effectué
</span>
<% when "failed" %>
<span class="inline-flex px-2 py-1 text-xs font-semibold rounded-full bg-red-100 text-red-800 ml-1">
<i data-lucide="x-circle" class="w-3 h-3 mr-1"></i>
Paiement échoué
</span>
<% end %>
<% end %>
</td>
<td class="px-6 py-4 text-sm text-gray-500">
<% if event.start_time %>

View File

@@ -290,6 +290,53 @@
<% end %>
<% end %>
<!-- Payout section -->
<% if @event.event_ended? && @event.can_request_payout? %>
<hr class="border-gray-200">
<div class="space-y-3">
<h4 class="text-md font-medium text-gray-900">Paiement des revenus</h4>
<div class="text-sm text-gray-500">
<p>Revenus disponibles : <span class="font-medium">€<%= @event.net_earnings_cents / 100.0 %></span></p>
<p>Frais de plateforme : <span class="font-medium">€<%= @event.total_fees_cents / 100.0 %></span></p>
</div>
<% if @event.payout_status == "not_requested" %>
<%= button_to promoter_payouts_path(event_id: @event.id), method: :post,
data: { confirm: "Êtes-vous sûr de vouloir demander le paiement des revenus ?" },
class: "w-full inline-flex items-center justify-center px-4 py-3 bg-green-600 text-white font-medium text-sm rounded-lg hover:bg-green-700 transition-colors duration-200" do %>
<i data-lucide="dollar-sign" class="w-4 h-4 mr-2"></i>
Demander le paiement
<% end %>
<% elsif @event.payout_status == "requested" %>
<div class="w-full inline-flex items-center justify-center px-4 py-3 bg-yellow-100 text-yellow-800 font-medium text-sm rounded-lg">
<i data-lucide="clock" class="w-4 h-4 mr-2"></i>
Paiement demandé
</div>
<% elsif @event.payout_status == "processing" %>
<div class="w-full inline-flex items-center justify-center px-4 py-3 bg-blue-100 text-blue-800 font-medium text-sm rounded-lg">
<i data-lucide="refresh-cw" class="w-4 h-4 mr-2"></i>
Paiement en cours
</div>
<% elsif @event.payout_status == "completed" %>
<div class="w-full inline-flex items-center justify-center px-4 py-3 bg-green-100 text-green-800 font-medium text-sm rounded-lg">
<i data-lucide="check-circle" class="w-4 h-4 mr-2"></i>
Paiement effectué
</div>
<% elsif @event.payout_status == "failed" %>
<div class="w-full inline-flex items-center justify-center px-4 py-3 bg-red-100 text-red-800 font-medium text-sm rounded-lg">
<i data-lucide="x-circle" class="w-4 h-4 mr-2"></i>
Paiement échoué
</div>
<%= button_to promoter_payouts_path(event_id: @event.id), method: :post,
data: { confirm: "Êtes-vous sûr de vouloir redemander le paiement des revenus ?" },
class: "w-full inline-flex items-center justify-center px-4 py-3 bg-green-600 text-white font-medium text-sm rounded-lg hover:bg-green-700 transition-colors duration-200" do %>
<i data-lucide="dollar-sign" class="w-4 h-4 mr-2"></i>
Redemander le paiement
<% end %>
<% end %>
</div>
<% end %>
<hr class="border-gray-200">
<%= button_to promoter_event_path(@event), method: :delete,
data: { confirm: "Êtes-vous sûr de vouloir supprimer cet événement ? Cette action est irréversible." },