Files
e-ticket/templates/email/order_cancelled_orga.html.twig
Serreau Jovann 61200adc74 Add stock management, order notifications, webhooks, expiration cron, and billet type validation
- Decrement billet quantity after purchase in BilletOrderService::generateOrderTickets
- Block purchase when stock is exhausted (quantity <= 0) in OrderController::buildOrderItems
- Add organizer email notification on new order (order_notification_orga template)
- Add organizer email notification on cancel/refund (order_cancelled_orga template)
- Add ExpirePendingOrdersCommand (app:orders:expire-pending) cron every 5min via Ansible
  - Cancels pending orders older than 30 minutes, restores stock, invalidates tickets
  - Includes BilletBuyerRepository::findExpiredPending query method
  - 3 unit tests covering: no expired orders, stock restoration, unlimited billets
- Add payment_intent.payment_failed webhook: cancels order, logs audit, emails buyer
- Add charge.refunded webhook: sets order to refunded, invalidates tickets, notifies orga and buyer
- Validate billet type (billet/reservation_brocante/vote) against organizer offer
  - getAllowedBilletTypes: gratuit=billet only, basic/sur-mesure=all types
  - Server-side validation in hydrateBilletFromRequest, UI filtering in templates
- Update TASK_CHECKUP.md: all Billetterie & Commandes items now complete

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 00:12:30 +01:00

54 lines
3.4 KiB
Twig

{% extends 'email/base.html.twig' %}
{% block title %}Commande {{ action }} - {{ order.event.title }}{% endblock %}
{% block content %}
<h2>Commande {{ action }}</h2>
<p>Bonjour,</p>
<p>La commande <strong>{{ order.orderNumber }}</strong> pour l'evenement <strong>{{ order.event.title }}</strong> a ete <strong>{{ action }}</strong>.</p>
<table style="width: 100%; border-collapse: collapse; margin: 20px 0; border: 2px solid #111827;">
<tr style="border-bottom: 1px solid #e5e7eb;">
<td style="padding: 10px 12px; font-weight: 900; text-transform: uppercase; font-size: 11px; color: #6b7280; width: 140px;">Commande</td>
<td style="padding: 10px 12px; font-weight: 700; font-size: 14px;">{{ order.orderNumber }}</td>
</tr>
<tr style="border-bottom: 1px solid #e5e7eb;">
<td style="padding: 10px 12px; font-weight: 900; text-transform: uppercase; font-size: 11px; color: #6b7280;">Statut</td>
<td style="padding: 10px 12px; font-weight: 700; color: #dc2626;">{{ action|upper }}</td>
</tr>
<tr style="border-bottom: 1px solid #e5e7eb;">
<td style="padding: 10px 12px; font-weight: 900; text-transform: uppercase; font-size: 11px; color: #6b7280;">Acheteur</td>
<td style="padding: 10px 12px; font-weight: 700;">{{ order.firstName }} {{ order.lastName }}</td>
</tr>
<tr style="border-bottom: 1px solid #e5e7eb;">
<td style="padding: 10px 12px; font-weight: 900; text-transform: uppercase; font-size: 11px; color: #6b7280;">Email</td>
<td style="padding: 10px 12px;">{{ order.email }}</td>
</tr>
<tr>
<td style="padding: 10px 12px; font-weight: 900; text-transform: uppercase; font-size: 11px; color: #6b7280;">Montant HT</td>
<td style="padding: 10px 12px; font-weight: 900; color: #4f46e5;">{{ order.totalHTDecimal|number_format(2, ',', ' ') }} &euro;</td>
</tr>
</table>
<table style="width: 100%; border-collapse: collapse; margin: 20px 0;">
<thead>
<tr style="background: #111827; color: #fff;">
<th style="padding: 10px 12px; text-align: left; font-size: 11px; font-weight: 900; text-transform: uppercase; letter-spacing: 1px;">Billet</th>
<th style="padding: 10px 12px; text-align: center; font-size: 11px; font-weight: 900; text-transform: uppercase; letter-spacing: 1px;">Qt</th>
<th style="padding: 10px 12px; text-align: right; font-size: 11px; font-weight: 900; text-transform: uppercase; letter-spacing: 1px;">Total HT</th>
</tr>
</thead>
<tbody>
{% for item in order.items %}
<tr style="border-bottom: 1px solid #e5e7eb;">
<td style="padding: 10px 12px; font-weight: 700; font-size: 14px;">{{ item.billetName }}</td>
<td style="padding: 10px 12px; text-align: center; font-weight: 700;">{{ item.quantity }}</td>
<td style="padding: 10px 12px; text-align: right; font-weight: 900; color: #4f46e5;">{{ item.lineTotalHTDecimal|number_format(2, ',', ' ') }} &euro;</td>
</tr>
{% endfor %}
</tbody>
</table>
<p style="font-size: 12px; color: #9ca3af;">Les billets associes a cette commande ont ete invalides. Vous pouvez consulter le detail depuis votre espace organisateur.</p>
{% endblock %}