feat(api): ressource conflicts (matérialisation + résolution) - #4
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Objectif
Matérialiser les chevauchements horaires détectés en entités
Conflict/ConflictSessionet 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
/api/conflicts/detect/api/conflicts/api/conflicts/{id}/api/conflicts/{id}resolve_conflict)Logique de détection
proposal/confirmed) qui se chevauchent. Auto-jointuretstzrange(bornes semi-ouvertes → contigus ignorés), nouveau helperfindOverlappingPairsdanslib/conflicts.openouignored.opendont le chevauchement a disparu (session reprogrammée/annulée) passe àresolvedautomatiquement. Lesignoredne sont jamais touchés ni rouverts.openest réservé à la détection : le PATCH n'accepte queresolved/ignored(sinon 422).Conformité CLAUDE.md
requireAuth(ADR-09).resolve_conflictsur toute résolution (manuelle et auto),createà l'ouverture, en transaction.Vérifications
tsc --noEmitclean, ESLint 0 warning.ignored, filtre liste).detect(created/autoResolved/openTotal), résolution du segment statique/conflicts/detectau-dessus de/conflicts/{id}, GET imbriqué, PATCH resolve, rejet 422 destatus:open. Données de smoke nettoyées.🤖 Generated with Claude Code