Sprint 4 : decisions et mandats -- workflow complet + vote integration

Backend: 7 nouveaux endpoints (advance, assign, revoke, create-vote-session),
services enrichis avec creation de sessions de vote, assignation de mandataire
et revocation. 35 nouveaux tests (104 total). Frontend: store mandates, page
cadrage decisions, detail mandats, composants DecisionWorkflow, DecisionCadrage,
DecisionCard, MandateTimeline, MandateCard. Documentation mise a jour.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Yvv
2026-02-28 14:28:34 +01:00
parent cede2a585f
commit 3cb1754592
24 changed files with 3988 additions and 354 deletions

View File

@@ -44,7 +44,10 @@ Tous les endpoints sont prefixes par `/api/v1`. L'API est auto-documentee via Op
| POST | `/` | Creer une nouvelle decision | Oui |
| GET | `/{id}` | Obtenir une decision avec ses etapes | Non |
| PUT | `/{id}` | Mettre a jour une decision | Oui |
| DELETE | `/{id}` | Supprimer une decision (brouillon uniquement) | Oui |
| POST | `/{id}/steps` | Ajouter une etape a une decision | Oui |
| POST | `/{id}/advance` | Avancer la decision a l'etape suivante | Oui |
| POST | `/{id}/steps/{step_id}/create-vote-session` | Creer une session de vote pour une etape | Oui |
## Votes (`/api/v1/votes`)
@@ -71,6 +74,10 @@ Tous les endpoints sont prefixes par `/api/v1`. L'API est auto-documentee via Op
| DELETE | `/{id}` | Supprimer un mandat (brouillon uniquement) | Oui |
| POST | `/{id}/steps` | Ajouter une etape a un mandat | Oui |
| GET | `/{id}/steps` | Lister les etapes d'un mandat | Non |
| POST | `/{id}/advance` | Avancer le mandat a l'etape suivante | Oui |
| POST | `/{id}/assign` | Assigner un mandataire au mandat | Oui |
| POST | `/{id}/revoke` | Revoquer un mandat actif | Oui |
| POST | `/{id}/steps/{step_id}/create-vote-session` | Creer une session de vote pour une etape | Oui |
## Protocoles (`/api/v1/protocols`)
@@ -448,6 +455,184 @@ Simule le calcul de seuil d'une formule avec des parametres arbitraires, sans cr
}
```
## Details des endpoints Sprint 4
### `POST /api/v1/decisions/{id}/advance` -- Avancer une decision
Avance une decision a l'etape suivante de son workflow. Complete l'etape active courante et active la prochaine etape en attente. Si toutes les etapes sont terminees, le statut global de la decision avance au statut suivant dans le cycle de vie (`draft` -> `qualification` -> `review` -> `voting` -> `executed` -> `closed`).
**Comportement** :
- S'il y a une etape `active` : elle passe a `completed`, la prochaine etape `pending` est activee.
- S'il n'y a pas d'etape active : la premiere etape `pending` est activee. Si la decision est en `draft`, elle passe a `qualification`.
- Si toutes les etapes sont terminees : le statut global avance.
**Preconditions** :
- La decision ne doit pas etre au statut `closed`.
- L'utilisateur doit etre authentifie.
**Reponse** : `200 OK` avec un `DecisionAdvanceOut` :
```json
{
"id": "uuid",
"title": "Runtime upgrade v3.2.0",
"description": "...",
"context": "...",
"decision_type": "runtime_upgrade",
"status": "review",
"voting_protocol_id": "uuid",
"created_by_id": "uuid",
"created_at": "2026-02-28T10:00:00Z",
"updated_at": "2026-02-28T12:00:00Z",
"steps": [
{"id": "uuid", "step_order": 0, "step_type": "qualification", "status": "completed", "...": "..."},
{"id": "uuid", "step_order": 1, "step_type": "review", "status": "active", "...": "..."},
{"id": "uuid", "step_order": 2, "step_type": "vote", "status": "pending", "...": "..."}
],
"message": "Etape 'Qualification' completee. Etape 'Examen' activee."
}
```
**Code 400** : Si la decision est deja cloturee ou qu'aucun avancement n'est possible.
---
### `DELETE /api/v1/decisions/{id}` -- Supprimer une decision
Supprime une decision. La suppression n'est autorisee que si la decision est au statut `draft`. Les etapes associees sont supprimees en cascade.
**Preconditions** :
- La decision doit etre au statut `draft`.
- L'utilisateur doit etre authentifie.
**Reponse** : `204 No Content`.
**Code 400** : Si la decision n'est pas au statut `draft`.
---
### `POST /api/v1/decisions/{id}/steps/{step_id}/create-vote-session` -- Creer une session de vote pour une etape de decision
Cree une session de vote liee a une etape specifique d'une decision. La session est configuree automatiquement a partir du protocole de vote de la decision.
**Comportement** :
1. Verifie que la decision et l'etape existent.
2. Verifie que l'etape est de type `vote` et au statut `active`.
3. Cree une session de vote avec le protocole de la decision.
4. Fait un snapshot des tailles WoT, Smith et TechComm.
5. Calcule la date de fin a partir de la duree de la formule.
6. Rattache la session a l'etape via `vote_session_id`.
**Reponse** : `201 Created` avec un `VoteSessionOut`.
**Code 400** : Si l'etape n'est pas de type `vote`, n'est pas `active`, ou si une session est deja liee.
---
### `POST /api/v1/mandates/{id}/advance` -- Avancer un mandat
Avance un mandat a l'etape suivante de son workflow. Fonctionne de maniere identique a l'avancement des decisions, avec le cycle de vie specifique aux mandats (`draft` -> `candidacy` -> `voting` -> `active` -> `reporting` -> `completed`).
**Comportement** :
- S'il y a une etape `active` : elle passe a `completed`, la prochaine etape `pending` est activee.
- S'il n'y a pas d'etape active : la premiere etape `pending` est activee. Si le mandat est en `draft`, il passe a `candidacy`.
- Si toutes les etapes sont terminees : le statut global avance.
**Preconditions** :
- Le mandat ne doit pas etre au statut `completed` ou `revoked`.
- L'utilisateur doit etre authentifie.
**Reponse** : `200 OK` avec un `MandateAdvanceOut` :
```json
{
"id": "uuid",
"title": "Membre Comite Technique 2026",
"description": "...",
"mandate_type": "techcomm",
"status": "candidacy",
"mandatee_id": null,
"decision_id": null,
"starts_at": null,
"ends_at": null,
"created_at": "2026-02-28T10:00:00Z",
"updated_at": "2026-02-28T12:00:00Z",
"steps": [
{"id": "uuid", "step_order": 0, "step_type": "formulation", "status": "completed", "...": "..."},
{"id": "uuid", "step_order": 1, "step_type": "candidacy", "status": "active", "...": "..."}
],
"message": "Etape 'Formulation' completee. Etape 'Candidature' activee."
}
```
**Code 400** : Si le mandat est deja en statut terminal (`completed` ou `revoked`).
---
### `POST /api/v1/mandates/{id}/assign` -- Assigner un mandataire
Assigne un mandataire (membre elu) a un mandat apres un vote reussi.
**Corps de la requete** :
```json
{
"mandatee_id": "uuid-de-l-identite-duniter"
}
```
**Comportement** :
1. Verifie que le mandat existe et qu'il est dans un statut permettant l'assignation.
2. Definit le `mandatee_id` du mandat.
3. Le mandat peut ensuite etre avance vers le statut `active`.
**Preconditions** :
- L'utilisateur doit etre authentifie.
- Le `mandatee_id` doit correspondre a une identite Duniter existante.
**Reponse** : `200 OK` avec un `MandateOut` mis a jour.
**Code 404** : Si le mandat ou l'identite Duniter n'existe pas.
---
### `POST /api/v1/mandates/{id}/revoke` -- Revoquer un mandat
Revoque un mandat actif de maniere anticipee. Le statut du mandat passe directement a `revoked`, mettant fin aux responsabilites du mandataire.
**Preconditions** :
- Le mandat doit etre au statut `active` ou `reporting`.
- L'utilisateur doit etre authentifie.
**Reponse** : `200 OK` avec un `MandateOut` mis a jour (statut `revoked`).
**Code 400** : Si le mandat n'est pas dans un statut permettant la revocation.
---
### `POST /api/v1/mandates/{id}/steps/{step_id}/create-vote-session` -- Creer une session de vote pour une etape de mandat
Cree une session de vote liee a une etape specifique d'un mandat. Fonctionne de maniere identique a la creation de session pour les decisions.
**Comportement** :
1. Verifie que le mandat et l'etape existent.
2. Verifie que l'etape est de type `vote` et au statut `active`.
3. Cree une session de vote avec le protocole associe.
4. Fait un snapshot des tailles WoT, Smith et TechComm.
5. Calcule la date de fin a partir de la duree de la formule.
6. Rattache la session a l'etape via `vote_session_id`.
**Reponse** : `201 Created` avec un `VoteSessionOut`.
**Code 400** : Si l'etape n'est pas de type `vote`, n'est pas `active`, ou si une session est deja liee.
---
## Pagination
Les endpoints de liste acceptent les parametres `skip` (offset, defaut 0) et `limit` (max 200, defaut 50).