---
suivi: 1167
date: 2026-08-03
sujet: Commercial — pivot reservation_lots brique 1/3 (socle, back seul)
chantier: commercialisation
type: feature
statut: poussé
hash: 2a991661
fichiers:
  - database/migrations/2026_08_03_170000_create_reservation_lots_table.php
  - app/Models/ReservationLot.php
  - app/Models/Reservation.php
  - app/Models/LotCommercial.php
  - app/Support/Commercial/ReservationLotsSync.php
  - app/Support/Commercial/ReservationLotsCoherence.php
  - app/Observers/ReservationObserver.php
  - app/Console/Commands/DiagReservationLotsCoherenceCommand.php
  - tools/diag/diag_reservation_lots_1167.php
  - docs/suivi/SUIVI_1167_commercial_pivot_reservation_lots.md
---

## PROMPT ENVOYÉ

SUIVI #1167 brique 1/3 — socle multi-lots : pivot `reservation_lots`,
backfill, double écriture FK, garde-fou. BACK SEUL, zéro .vue / bundle.
Réf. SUIVI_1154 / SUIVI_1161. Décisions D1–D5 arrêtées (impl. 2/3 et 3/3).

## SYNTHÈSE

### Fiches lues
- `SUIVI_1154` — cardinalité 1:1 actuelle ; #85 = nouveau modèle.
- `SUIVI_1161` — 20 lecteurs Q5 ; reco pivot + conservation FK (Q7).
- `#1160` — pattern migration idempotente + rapport `storage/app/`.

### Livré
- Table `reservation_lots` (FK courtes `resa_lots_*`, unique resa+lot).
- Backfill : 1 ligne principal/position=1 depuis `lot_commercial_id`.
- Rapport : `storage/app/migration_1167_reservation_lots_report.json`.
- `Reservation::lotCommercial()` inchangé ; `lotsCommerciaux()` +
  `reservationLots()` ajoutés ; `LotCommercial::reservations()` inchangé +
  `reservationsPivot()`.
- Double écriture via `ReservationLotsSync` dans `ReservationObserver`
  (created + updated si FK dirty). Soft-delete résa : pivot conserve
  (cascade hard delete uniquement).
- Garde-fou : `php artisan commercial:coherence-reservation-lots` et
  `php tools/diag/diag_reservation_lots_1167.php`.

### Hors périmètre (2/3 et 3/3)
Prix par lot, KPI, AdF, annulation groupée, UI, SharePoint.

### Lecteurs (#1161 Q5+) — INTOUCHÉS par ce lot
Tous les lecteurs listés en synthèse livrable (aucun fichier service /
contrôleur métier / Vue modifié hors observer + modèles).

## DÉPLOIEMENT-TEST

OVH :
1. `git pull origin main`
2. `php artisan migrate --force`
3. Lire `storage/app/migration_1167_reservation_lots_report.json`
4. `php artisan commercial:coherence-reservation-lots` → 0 anomalie
5. Rejouer migrate → `lignes_creees=0`
6. Smoke : grille, fiche acquéreur, KPI remises (= 107 304,48), AdF

Pas de `journal:sync` (invisible utilisateur). Pas de `npm` / build.

## LEÇON

Dual-write FK + pivot avant de toucher les 20 lecteurs (#1099). Observer
sur create/update FK évite d’oublier un chemin `Reservation::create`.
Rapport backfill + commande cohérence = filet anti-silence (#1043).
