Commit graph

6 commits

Author SHA1 Message Date
Ubuntu
c564028ca9 feat(rental): Sprint M — refonds + annulations Stripe
All checks were successful
CI / test (pull_request) Successful in 2m37s
Politique de remboursement v1 :
- > 7 jours du début → FULL (location + caution)
- 1 à 7 jours → PARTIAL_50 (50% location + caution intégrale)
- < 24h ou passé → DEPOSIT_ONLY (caution seulement, pas de remboursement
  sur la location)

src/lib/rental-refund.ts (NEW) : computeRentalRefund({startDate,
itemsTotal, depositTotal}) → { itemsRefund, depositRefund, totalRefund,
policy, policyLabel }. Arrondi au centime, support de Decimal.

POST /api/rentals/[id]/cancel :
- Auth multi-rôle : tenant de la booking, RENTAL_PROVIDER nominal ou
  CE_MANAGER de l'org du provider, ADMIN. Détecte `cancelledBy` pour
  adapter l'email.
- Refuse si status ∉ {PENDING, CONFIRMED} (HANDED_OVER → non
  annulable, contacter Karbé).
- Calcule le refund selon la politique.
- Stripe refund best-effort si paymentStatus=SUCCEEDED + stripeSessionId
  existante + isStripeConfigured + totalRefund > 0. Retrieve session →
  payment_intent → refunds.create. Échec Stripe = audit-logged mais
  le flip status continue (l'asso pourra rembourser manuellement).
- Transaction : update RentalBooking (CANCELLED + paymentStatus
  REFUNDED si SUCCEEDED sinon FAILED) + delete RentalItemAvailability
  (libère stock).
- Audit log rental.cancel avec montants, policy, cancelledBy,
  stripeRefundId, stripeRefundError.
- Email best-effort : sendRentalCancelled à tenant + provider (sauf si
  provider est le canceller).

src/components/CancelRentalButton.tsx : composant client confirm dialog
inline avec textarea motif (max 500 chars). Branché sur :
- /mes-locations : « Annuler ma location » sur résa PENDING/CONFIRMED
- BookingDecision (utilisé par /espace-prestataire/reservations ET
  /espace-ce/materiel/reservations) : remplace l'ancienne mini-confirm
  qui flippait juste le status, désormais via la vraie API refund

sendRentalCancelled email : adapté selon cancelledBy ("Vous avez annulé"
/ "<Provider> a annulé" / "L'équipe Karbé a annulé").

tests/lib/rental-refund.test.ts : 8 cas (FULL @ 10+ et 7j, PARTIAL_50,
DEPOSIT_ONLY < 24h et passé, arrondi centime, zéro caution, policyLabel).
Total projet : 70/70 ✓.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-03 02:17:58 +00:00
Ubuntu
ea0e606735 feat(ce): Sprint K — public badge + invites CE_MEMBER + tests
All checks were successful
CI / test (pull_request) Successful in 2m45s
Public badge sur fiche carbet :
- carbet-public.ts charge les OrganizationCarbetMembership (org
  approuvée uniquement) + expose `organizations: {id,name,slug}[]`.
- /carbets/[slug] affiche « Géré par le CE <name> » sous le header
  si au moins 1 org liée.

Invites CE_MEMBER :
- Migration 20260603300000_org_invite_token : OrgInviteToken
  (tokenHash, organizationId, email?, createdByUserId, expiresAt,
  usedAt). Cascade sur Organization. Index expiresAt + organizationId.
- src/lib/ce-invites.ts : createOrgInviteToken (TTL 14j),
  listOrgInviteTokens, getOrgInviteByToken (validité + expiry),
  markOrgInviteConsumed, revokeOrgInviteToken. Token = 24 bytes
  base64url, hash sha256.
- /espace-ce/membres : liste membres (CE_MANAGER + CE_MEMBER actifs)
  + form de génération de lien (email optionnel = lock email côté
  signup) + liste des invitations avec statut actif/consommé/expiré +
  bouton révoquer.
- /espace-ce/membres/actions.ts : createInviteAction +
  revokeInviteAction. Audit log scope=ce.invite.
- API /api/signup étendue : zod accepte inviteToken, branche dédiée
  qui crée User CE_MEMBER + organizationId du token + marquage
  usedAt. Vérif email match si email fourni dans le token.
- /inscription?invite=TOKEN : récupère l'invite, pré-affiche org name,
  lock email si fourni, masque les fieldsets type de compte (forcé
  CE_MEMBER).

CTA marketing :
- /pour-comites-entreprise : section CTA « Créer mon espace CE » sous
  le rendu content-pages, conditionnée par plugin ce-management.

Tests vitest (tests/lib/ce-access.test.ts) :
- canManageCarbet : admin always, owner direct, CE_MANAGER via org
  match, refus si autre org / pas d'org / TOURIST / pas de membership.
- 9 tests, mocks next-auth + @/auth + @/lib/authorization pour éviter
  next/server (incompatible vitest sans setup).
- Total tests projet : 62/62 ✓.

Dashboard /espace-ce : lien vers /espace-ce/membres en bas.

Migration prod appliquée.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-03 00:03:03 +00:00
Ubuntu
5607a51980 feat(rental): Sprint E — emails + plugin toggle + tests
Some checks failed
CI / test (pull_request) Failing after 1m10s
3 nouveaux templates email (best-effort, dry-run sans Resend) :
- sendRentalRequestedTenant : récap de demande au locataire (par RB)
- sendRentalRequestedProvider : nouvelle demande au prestataire
- sendRentalConfirmed : confirmation paiement reçu

Branchements :
- POST /api/rentals/checkout : envoie tenant + provider après création
  des RentalBooking (PENDING), catch global pour ne pas bloquer
- Webhook Stripe rental-bundle : envoie sendRentalConfirmed à chaque
  locataire après update CONFIRMED+SUCCEEDED

Plugin gear-rental :
- Ajout au registry (catégorie business)
- layout.tsx /materiel + /espace-prestataire avec requirePluginOr404
- requirePluginOr404 dans /panier et /mes-locations
- isPluginEnabled guard dans POST /api/rentals/checkout (404 si off)
- SiteHeader masque liens Matériel / Mes locations / Espace prestataire
  + CartBadge si plugin désactivé
- CompleteYourStay renvoie null si plugin désactivé
Décision admin → activable depuis /admin/plugins comme tous les autres.

Tests vitest (tests/lib/rentals.test.ts, 16 tests) :
- diffDays (mêmes dates, 1 nuit, 7 jours, négatif)
- parseCart (null/garbage/schéma invalide/valide/format date)
- serializeCart (updatedAt, roundtrip)
- commission formula (0%, 15%, arrondi centime)
- availability arithmetic (totalQty libre, soustractions, plancher 0)

53 tests pass total. Build OK.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-02 08:49:39 +00:00
Claude Integration
e2d3b6a686 feat: variantes responsives 320/800/1600 via sharp + srcset partout (Reels, cards, galerie, favoris)
All checks were successful
CI / test (pull_request) Successful in 2m21s
2026-06-02 01:05:25 +00:00
Claude Integration
a373bd60ad feat(hardening): rate limit (signup/reset/bookings) + tâches cron + backup PostgreSQL nocturne
All checks were successful
CI / test (pull_request) Successful in 2m10s
2026-06-01 20:16:57 +00:00
Claude Integration
14fd9a5940 feat(p2): vitest + 27 tests + /api/health enrichi + /api/metrics + workflow CI
Some checks failed
CI / test (pull_request) Failing after 2m13s
2026-06-01 02:27:14 +00:00