Skip to content

feat(api): ressource conflicts (matérialisation + résolution) - #4

Merged
IliesMahd merged 2 commits into
mainfrom
feat/api-conflicts
May 21, 2026
Merged

feat(api): ressource conflicts (matérialisation + résolution)#4
IliesMahd merged 2 commits into
mainfrom
feat/api-conflicts

Conversation

@IliesMahd

Copy link
Copy Markdown
Contributor

Objectif

Matérialiser les chevauchements horaires détectés en entités Conflict/ConflictSession et exposer le workflow de résolution du formateur. Suite logique de la ressource sessions (#3) : la détection ponctuelle existait, il manquait la persistance et l'arbitrage.

Endpoints

Méthode Route Rôle
POST /api/conflicts/detect Passe de détection globale (déclenchable par n8n ou le front)
GET /api/conflicts Liste paginée, filtre par statut, sessions imbriquées
GET /api/conflicts/{id} Détail + sessions
PATCH /api/conflicts/{id} Résoudre / ignorer (audit resolve_conflict)

Logique de détection

  • Pairwise : un conflit lie exactement deux sessions actives (proposal/confirmed) qui se chevauchent. Auto-jointure tstzrange (bornes semi-ouvertes → contigus ignorés), nouveau helper findOverlappingPairs dans lib/conflicts.
  • Idempotente : déduplication par paire ; ne recrée pas un conflit déjà open ou ignored.
  • Auto-clôture : un conflit open dont le chevauchement a disparu (session reprogrammée/annulée) passe à resolved automatiquement. Les ignored ne sont jamais touchés ni rouverts.
  • open est réservé à la détection : le PATCH n'accepte que resolved/ignored (sinon 422).

Conformité CLAUDE.md

  • Thin-route / fat-lib (ADR-07) ; contrat OpenAPI dérivé des mêmes schémas Zod (ADR-08) ; auth via la couture requireAuth (ADR-09).
  • Audit resolve_conflict sur toute résolution (manuelle et auto), create à l'ouverture, en transaction.
  • Réutilise le mapper de session → forme JSON identique partout (source unique).

Vérifications

  • tsc --noEmit clean, ESLint 0 warning.
  • 75 tests verts (+17 : validateurs + intégration — matérialisation, idempotence, contiguïté, auto-clôture sur annulation, résolution + audit, non-réouverture d'un ignored, filtre liste).
  • Smoke HTTP bout-à-bout sur Next 16.2.6 : detect (created/autoResolved/openTotal), résolution du segment statique /conflicts/detect au-dessus de /conflicts/{id}, GET imbriqué, PATCH resolve, rejet 422 de status:open. Données de smoke nettoyées.

🤖 Generated with Claude Code

IliesMahd and others added 2 commits May 21, 2026 12:21
Matérialise les chevauchements horaires en entités Conflict/ConflictSession
et expose le workflow de résolution attendu par le formateur.

- POST /api/conflicts/detect : passe de détection globale. Ouvre un conflit
  par paire de sessions actives qui se chevauchent (déduplication par paire),
  referme automatiquement les conflits open dont le chevauchement a disparu
  (session reprogrammée/annulée), ne rouvre jamais un conflit ignoré.
  Idempotente.
- GET /api/conflicts : liste paginée, filtre par statut, sessions imbriquées.
- GET /api/conflicts/{id} : détail + sessions.
- PATCH /api/conflicts/{id} : résout ou ignore (statut open exclu, réservé à
  la détection), audit resolve_conflict.

Détection des paires via auto-jointure tstzrange (lib/conflicts), réutilise le
mapper de session pour exposer la même forme. Contrat OpenAPI dérivé des mêmes
schémas Zod. 17 tests ajoutés (validateurs + intégration : matérialisation,
idempotence, contiguïté, auto-clôture, résolution, ignore, filtre liste).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- resolveConflict refuse un conflit déjà clos (409) : évite les écritures et
  l'audit redondants sur un conflit resolved/ignored.
- runDetection : lectures et écritures dans une même transaction, précédée d'un
  verrou consultatif Postgres (pg_advisory_xact_lock), pour sérialiser les
  passes concurrentes (cron n8n + déclenchement manuel) et éviter un conflit
  créé en double faute de contrainte d'unicité sur la paire.
- Documente que `ignored` est volontairement définitif pour une paire de
  sessions (choix produit, pas un oubli).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@IliesMahd
IliesMahd merged commit de9e375 into main May 21, 2026
1 check passed
@IliesMahd
IliesMahd deleted the feat/api-conflicts branch May 21, 2026 11:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant