xpeditis2.0/docs/features/csv-bookings.md
2026-09-07 21:40:49 +02:00

134 lines
5.1 KiB
Markdown

# Réservations CSV & Portail Carrier
---
## Vue d'ensemble
Le système de réservation CSV permet aux admins de créer des réservations en important des fichiers CSV et d'envoyer automatiquement un **lien magique** aux transporteurs pour qu'ils acceptent ou rejettent via un portail dédié.
---
## Workflow complet
```
1. Admin upload CSV → création csv_bookings
2. Admin assigne un carrier à la réservation
3. Système envoie email avec magic link (expiry 1h)
4. Carrier clique → authentification automatique (token URL)
5. Carrier voit les détails → Accept ou Reject
6. Activité logguée dans carrier_activities
7. Admin voit le statut mis à jour en dashboard
```
---
## API — Réservations CSV (Admin)
| Méthode | Route | Description |
|---------|-------|-------------|
| GET | /api/v1/csv-bookings | Liste des réservations CSV |
| POST | /api/v1/csv-bookings | Créer une réservation CSV |
| GET | /api/v1/csv-bookings/:id | Détail d'une réservation |
| PATCH | /api/v1/csv-bookings/:id | Mettre à jour |
| DELETE | /api/v1/csv-bookings/:id | Supprimer |
| POST | /api/v1/csv-bookings/:id/assign-carrier | Assigner un carrier |
| POST | /api/v1/csv-bookings/:id/send-magic-link | Envoyer le lien magique |
---
## API — Portail Carrier
| Méthode | Route | Description |
|---------|-------|-------------|
| GET | /api/v1/carrier/auth | Auth via magic link token |
| GET | /api/v1/carrier/booking | Voir la réservation assignée |
| POST | /api/v1/carrier/booking/accept | Accepter |
| POST | /api/v1/carrier/booking/reject | Rejeter |
| POST | /api/v1/carrier/booking/documents | Uploader des documents |
### Authentification portail carrier
Le lien magique contient un token unique :
```
https://app.xpeditis.com/carrier/auth?token=xxxxxxxx
```
Le token est stocké dans `csv_bookings.carrier_magic_link_token` (hashé).
Expiry : 1 heure. Si expiré, l'admin doit renvoyer un nouveau lien.
---
## Statuts des réservations CSV
Valeurs réelles de l'énumération `CsvBookingStatus` (`domain/entities/csv-booking.entity.ts`) :
| Statut | Description |
|--------|-------------|
| PENDING_PAYMENT | Réservation créée, commission non payée |
| PENDING_BANK_TRANSFER | Virement déclaré, en attente de validation par l'administration |
| PENDING | Commission payée, en attente de réponse du transporteur |
| ACCEPTED | Le transporteur a accepté |
| REJECTED | Le transporteur a refusé |
| CANCELLED | Annulée par l'utilisateur |
---
## Suppression d'une réservation impayée
`DELETE /api/v1/csv-bookings/:id` supprime définitivement une réservation **dont la commission n'a pas été payée**, c'est-à-dire au seul statut `PENDING_PAYMENT`. Seul le propriétaire peut le faire ; une réservation appartenant à quelqu'un d'autre répond `404`, sans se distinguer d'une réservation inexistante.
Une fois la commission payée, la réservation est partie chez le transporteur et porte une trace comptable : elle ne peut plus qu'être **annulée** (`PATCH :id/cancel`), jamais effacée. L'API répond alors `400`.
`PENDING_BANK_TRANSFER` est volontairement exclu : le virement déclaré peut être en cours d'acheminement, et supprimer la réservation priverait l'administration de ce qu'elle doit rapprocher à sa réception. Étendre la règle à ce statut est une décision comptable, pas technique — il suffit d'ajouter le statut à `DELETABLE_STATUSES` dans l'entité.
Les documents déjà téléversés restent dans le stockage objet, conformément à la politique appliquée à la suppression d'un document isolé (conservation pour l'audit). Le quota de réservations n'est pas affecté : il ne compte que les expéditions payées.
Côté interface, l'action « Supprimer » n'apparaît dans le menu d'une ligne que pour les réservations impayées, à côté de « Modifier » et « Payer ». Elle demande une confirmation qui nomme la réservation concernée.
---
## Pages frontend
| Route | Description |
|-------|-------------|
| /dashboard/bookings | Liste des réservations (voir, modifier, payer, supprimer) |
| /dashboard/csv-bookings | Liste admin des réservations CSV |
| /carrier/auth | Page d'auth carrier (via magic link) |
| /carrier/booking | Dashboard carrier (accept/reject) |
| /carrier/documents | Upload documents carrier |
---
## Import CSV (upload admin)
Le fichier CSV peut être uploadé via `POST /api/v1/admin/csv-rates/upload`.
Format des colonnes requis : voir [../csv-system/CSV_RATE_SYSTEM.md](../csv-system/CSV_RATE_SYSTEM.md).
---
## Profils carrier
Les carriers qui utilisent le portail ont un `CarrierProfile` lié à leur `Organization`.
Chaque action (accept, reject, document upload) est tracée dans `carrier_activities`.
```sql
SELECT ca.action, ca.created_at, cb.booking_number
FROM carrier_activities ca
JOIN csv_bookings cb ON cb.id = ca.csv_booking_id
WHERE ca.carrier_profile_id = 'xxx'
ORDER BY ca.created_at DESC;
```
---
## Email magic link
Template MJML dans `apps/backend/src/infrastructure/email/templates/`.
Variables disponibles :
- `bookingNumber` — numéro de réservation
- `magicLink` — URL avec token
- `expiresIn` — durée de validité ("1 heure")
- `carrierName` — nom du carrier