feat(ce): Sprint J — matériel rental côté CE
All checks were successful
CI / test (pull_request) Successful in 2m41s

src/lib/rental-access.ts CE-aware :
- requireRentalProviderSession accepte CE_MANAGER (en plus de
  RENTAL_PROVIDER et ADMIN).
- getCurrentRentalProvider : CE_MANAGER → findFirst par
  organizationId ; RENTAL_PROVIDER → par managedByUserId.
- getCurrentRentalProviderForCe(organizationId) helper explicite.
- canManageRentalProvider gagne un userOrgId? optionnel : vrai si
  manager nominal OU CE_MANAGER + provider.organizationId === userOrgId.
- Callers existants (5 sites : actions.ts + 4 routes API rental)
  passent désormais session.user.organizationId.

Actions /espace-prestataire/actions.ts role-aware :
- requireOwnedProvider() dérive basePath selon le rôle :
  CE_MANAGER → /espace-ce/materiel ; sinon → /espace-prestataire.
- Tous les redirect/revalidatePath utilisent basePath, donc
  createHostItemAction, updateHostItemAction, deleteHostItemAction,
  addItemBlockAction, removeItemBlockAction, updateBookingStatusAction
  emmènent le user vers son espace contextuel après chaque opération.

/espace-ce/materiel/page.tsx — onboarding :
- Plugin gear-rental disabled → message d'info.
- Pas de provider activé → CTA « Activer la location matériel pour
  <org> » (bouton bloqué si org pending, message bannière).
- Provider existant → dashboard avec KPIs (items actifs, résa pending,
  confirmées à venir, revenu 30j) + 2 ActionCards Items + Réservations.

actions.ts (CE) :
- activateRentalProviderForCeAction → crée RentalProvider(organizationId,
  name="Matériel <org>", managedByUserId=session.user.id, approved=true)
  + audit + redirect /espace-ce/materiel.

Pages CE clonées (réutilisent les composants, actions, helpers
existants — zéro duplication de logique métier) :
- /espace-ce/materiel/items/page.tsx (liste)
- /espace-ce/materiel/items/new/page.tsx (HostItemForm)
- /espace-ce/materiel/items/[itemId]/page.tsx (MediaUploader +
  HostItemForm + ItemBlocksManager + ItemInlineDelete)
- /espace-ce/materiel/reservations/page.tsx (BookingDecision)

Tous importent depuis /espace-prestataire/{actions, items, reservations}
pour rester DRY. Les breadcrumbs et links sont adaptés au contexte CE.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ubuntu 2026-06-02 23:47:57 +00:00
parent 03b740dfff
commit caa3d5214f
12 changed files with 714 additions and 25 deletions

View file

@ -23,6 +23,7 @@ export async function DELETE(_req: Request, ctx: { params: Promise<{ id: string
session.user.id,
session.user.role,
media.item.providerId,
session.user.organizationId,
);
if (!allowed) return NextResponse.json({ error: "Accès refusé" }, { status: 403 });

View file

@ -34,6 +34,7 @@ export async function POST(req: Request) {
session.user.id,
session.user.role,
item.providerId,
session.user.organizationId,
);
if (!allowed) return NextResponse.json({ error: "Accès refusé" }, { status: 403 });

View file

@ -43,6 +43,7 @@ export async function POST(req: Request) {
session.user.id,
session.user.role,
item.providerId,
session.user.organizationId,
);
if (!allowed) {
return NextResponse.json({ error: "Accès refusé" }, { status: 403 });

View file

@ -45,6 +45,7 @@ export async function POST(req: Request) {
session.user.id,
session.user.role,
item.providerId,
session.user.organizationId,
);
if (!allowed) {
return NextResponse.json({ error: "Accès refusé" }, { status: 403 });