Tests (16 total):
- Valid/invalid signature
- v2.core.account.created/updated/closed status updates
- Account status with unknown user and missing related_object
- Merchant capability card_payments active
- Recipient capability payouts active
- Both capabilities active sets status to 'active'
- Capability update with unknown user
- Payout created with email notification
- Payout paid with PDF attachment
- Payout updated on existing payout
- Payout with missing payout ID
- Payout with unknown user (no organizer found)
Fix: skip payout creation when organizer not found instead of persisting
with null organizer_id (NOT NULL constraint)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Payout system:
- Create Payout entity (stripePayoutId, status, amount, currency, destination, arrivalDate)
- Webhook handles payout.created/updated/paid/failed/canceled with email notification
- Payout list in /mon-compte virements tab with status badges
- PDF attestation on paid payouts with email attachment
PDF attestation:
- dompdf with DejaVu Sans font, yellow-orange gradient background
- Orange centered title bar, E-Cosplay logo, emitter/beneficiary info blocks
- QR code linking to /attestation/check/{payoutId} for authenticity verification
- Public verification page: shows payout details if valid, error if altered
- Legal disclaimer and CGV reference
- Button visible only when status is paid, opens in new tab
Sub-accounts:
- Add parentOrganizer (self-referencing ManyToOne) and subAccountPermissions (JSON) to User
- Permissions: scanner (validate tickets), events (CRUD), tickets (free invitations)
- Create sub-account with random password, send email with credentials
- Edit page with name/email/permissions checkboxes
- Delete with confirmation
- hasPermission() helper method
Account improvements:
- Block entire page for unapproved organizers with validation pending message
- Display stripeStatus in Stripe Connect banners
- Remove test payout button
Webhook v2 Connect events:
- v2.core.account.created/updated/closed → update stripeStatus
- capability_status_updated → sync charges/payouts enabled from capabilities
- PayoutPdfService for reusable PDF generation
Migrations: stripeStatus, Payout table, sub-account fields, drop pdfPath
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add thead headers to all tables in siret_check.html.twig
- Add @codeCoverageIgnore to Stripe API methods (syncWebhook, createAccountConnect, createAccountLink, getClient)
- Remove redundant false check in saveWebhookSecret, use string cast
- Remove redundant false check in getNafLabel, use string cast
- Add meaningful comments to catch blocks in SiretService
- Fix StripeWebhookControllerTest: use Event::constructFrom and fresh EntityManager
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add stripeChargesEnabled and stripePayoutsEnabled fields to User entity + migration
- Handle account.updated webhook: sync charges_enabled and payouts_enabled from Stripe
- Add createAccountConnect() and createAccountLink() to StripeService
- Update organizer approved email with Stripe verification notice
- Tests: webhook account.updated with flags, unknown account, User stripe fields
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Create StripeService: webhook sync, signature verification, save secret to .env.local
- Create StripeWebhookController with signature verification (400 on invalid)
- Create stripe:sync command to auto-create webhook endpoint via Stripe API
- Webhook listens to all events (configurable later)
- Save webhook secret automatically to .env.local on creation
- Add stripeAccountId field to User entity for Stripe Connect + migration
- Tests: StripeServiceTest (5), StripeWebhookControllerTest (2), StripeSyncCommandTest (1), UserTest updated
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>