feat(rental): Sprint O — reversements prestataires #89
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/rental-sprint-o"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Sprint O — Reversements prestataires (payouts)
Comble le gap ops du marketplace rental : System D encaisse centralisé via Stripe, mais l'admin n'a aucune visibilité sur ce qu'il doit reverser à chaque prestataire chaque mois.
Schema (migration appliquée prod)
RentalPayoutMark { id, providerId, periodMonth, amount, reference, paidAt, paidByEmail }(providerId, periodMonth)→ 1 mark = 1 mois = 1 virement par providersrc/lib/payouts.tsmonthKey(d)→ 1er du mois minuit UTC (clé de période normalisée)listProviderPayouts({monthsBack=6})→ grid provider × mois avec bookingsCount + grossAmount (itemsTotal) + commission + netAmount (gross-commission) + statut paid via markcreatePayoutMark(idempotent via findUnique avant insert) +deletePayoutMarkPolitique : net dû =
itemsTotal - commissionAmount(ladepositTotaln'entre pas dans le flux — elle est collectée par le provider auprès du client). Politique documentée dans le commentaire en tête depayouts.ts./admin/payouts/page.tsxMarkPaidForm: bouton « Marquer payé » → form inline (amount pré-rempli avec net dû, reference optionnelle) → actionmarkPayoutPaidAction. Statut payé affiche amount + ref + bouton « Annuler marquage »Server actions
markPayoutPaidAction(admin only, idempotent, auditadmin.payouts/payout.markoupayout.already_marked) → envoiesendPayoutSentau contactEmail du provider (best-effort)unmarkPayoutPaidAction→ delete + auditpayout.unmarkEmail
sendPayoutSentNotification au provider quand un virement est marqué payé. Inclut amount + reference + lien dashboard.
UX
Sidebar admin gagne entrée « Reversements » sous « Activité ».
Tests
tests/lib/payouts.test.ts(4 cas) :monthKeynormalisation UTC (n'importe quel jour du mois → 1er minuit UTC)formatMonthlibellé fr-FRTotal : 74/74 ✓ (70 précédents + 4 nouveaux). Lint + typecheck + build ✓.
Test plan
/admin/payouts→ liste 6 mois, System D absent, providers tiers présents🤖 Generated with Claude Code
Marketplace encaisse centralisé sur System D → besoin de tracer les virements mensuels aux prestataires tiers. Migration appliquée prod. Schema : - Modèle RentalPayoutMark { id, providerId, periodMonth, amount, reference, paidAt, paidByEmail }. Unique (providerId, periodMonth) → 1 mark = 1 mois = 1 virement par provider. Lib src/lib/payouts.ts : - monthKey(d) → 1er du mois minuit UTC (clé de période). - listProviderPayouts({monthsBack=6}) → grid provider × mois avec bookingsCount + grossAmount (itemsTotal) + commission + netAmount (gross-commission) + statut paid via RentalPayoutMark. Exclut System D (commission 0%, géré par l'asso). Statut « payé » lu depuis les marks. Tri : mois desc puis providerName. - createPayoutMark (idempotent via findUnique avant insert) + deletePayoutMark. Politique : net dû = itemsTotal - commissionAmount (depositTotal hors flux, collecté par le provider auprès du client). Politique documentée dans le commentaire en tête de payouts.ts. /admin/payouts/page.tsx : - 3 KPIs (À payer / Déjà payé / Mois affichés). - Une section par mois (6 derniers), tableau provider × CA brut + commission + net dû + statut. - MarkPaidForm : bouton « Marquer payé » → form inline (amount pré-rempli avec net dû, reference optionnelle) → action markPayoutPaidAction. Statut payé montre amount + ref + bouton « Annuler marquage ». Server actions : - markPayoutPaidAction (admin only, idempotent, audit admin.payouts/payout.mark + payout.already_marked) → envoie sendPayoutSent au contactEmail du provider (best-effort). - unmarkPayoutPaidAction → delete + audit payout.unmark. Email sendPayoutSent : notification au provider quand un virement est marqué payé. Inclut amount + reference + lien dashboard. Sidebar admin gagne entrée « Reversements » sous Activité. Tests vitest tests/lib/payouts.test.ts (4 cas) : monthKey normalisation UTC + idempotence + janvier sans bug, formatMonth fr-FR. Total : 74/74 ✓. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>