Cycle Validation
Endpoints for managing the multi-level validation workflow of payment cycles.
Validation Levels
| Level | Role | Description |
|---|---|---|
| 0 | Not submitted | Cycle in preparation (draft) |
| 1 | Agent | Initial validation |
| 2 | Supervisor | Intermediate validation |
| 3 | Director | Advanced validation |
| 4 | General Management | Final validation |
The number of required levels is configurable per program (default: 2).
POST /api/cycles/{id}/soumettre
Submits the cycle for validation.
Endpoint
POST /api/cycles/{id}/soumettre
Headers
| Header | Value | Required |
|---|---|---|
| Authorization | Bearer {token} | Yes |
Prerequisites
- The cycle must be in
brouillonstatus - The cycle must have calculated beneficiaries
Success Response
Code: 200 OK
{
"success": true,
"statutValidation": "en_attente",
"niveauValidation": 0,
"prochainNiveau": "Agent",
"message": "Cycle soumis pour validation"
}
cURL Example
curl -X POST https://sig.ucp-pch.org/api/cycles/770e8400-e29b-41d4-a716-446655440003/soumettre \
-H "Authorization: Bearer TOKEN"
POST /api/cycles/{id}/valider
Validates the cycle at the current level.
Endpoint
POST /api/cycles/{id}/valider
Request Body
{
"commentaire": "Validé après vérification des bénéficiaires"
}
Fields
| Field | Type | Required | Description |
|---|---|---|---|
| commentaire | string | No | Validation comment |
Success Response
Code: 200 OK
{
"success": true,
"statutValidation": "valide",
"niveauValidation": 2,
"niveauxRequis": 2,
"estCompletementValide": true,
"message": "Cycle validé - Validation complète"
}
Success Response (partial validation)
{
"success": true,
"statutValidation": "en_attente",
"niveauValidation": 1,
"niveauxRequis": 2,
"estCompletementValide": false,
"prochainNiveau": "Superviseur",
"message": "Cycle validé au niveau Agent - En attente validation Superviseur"
}
cURL Example
curl -X POST https://sig.ucp-pch.org/api/cycles/770e8400-e29b-41d4-a716-446655440003/valider \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{"commentaire": "Validé"}'
POST /api/cycles/{id}/rejeter
Rejects the cycle.
Endpoint
POST /api/cycles/{id}/rejeter
Request Body
{
"motif": "Incohérence dans le nombre de bénéficiaires"
}
Fields
| Field | Type | Required | Description |
|---|---|---|---|
| motif | string | Yes | Rejection reason |
Success Response
Code: 200 OK
{
"success": true,
"statutValidation": "rejete",
"niveauValidation": 1,
"message": "Cycle rejeté"
}
cURL Example
curl -X POST https://sig.ucp-pch.org/api/cycles/770e8400-e29b-41d4-a716-446655440003/rejeter \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{"motif": "Incohérence dans le nombre de bénéficiaires"}'
GET /api/cycles/{id}/historique-validations
Retrieves the cycle's validation history.
Endpoint
GET /api/cycles/{id}/historique-validations
Success Response
Code: 200 OK
{
"cycle": {
"id": "770e8400-e29b-41d4-a716-446655440003",
"code": "CYC-2024-003",
"nom": "Cycle Mars 2024"
},
"statutValidation": "valide",
"niveauValidation": 2,
"niveauxRequis": 2,
"historique": [
{
"action": "soumission",
"niveau": 0,
"niveauLabel": "Non soumis",
"user": "agent@pch-sig.sn",
"userName": "Agent Terrain",
"date": "2024-02-20T10:00:00+00:00",
"commentaire": null
},
{
"action": "validation",
"niveau": 1,
"niveauLabel": "Agent",
"user": "superviseur@pch-sig.sn",
"userName": "Superviseur PCH",
"date": "2024-02-20T11:00:00+00:00",
"commentaire": "Conforme"
},
{
"action": "validation",
"niveau": 2,
"niveauLabel": "Superviseur",
"user": "directeur@pch-sig.sn",
"userName": "Directeur PCH",
"date": "2024-02-20T14:00:00+00:00",
"commentaire": "Approuvé pour exécution"
}
]
}
POST /api/cycles/{id}/reinitialiser-validation
Resets validation (returns to draft status).
Endpoint
POST /api/cycles/{id}/reinitialiser-validation
Prerequisites
- The cycle must not be in execution
- Special permission required
Success Response
Code: 200 OK
{
"success": true,
"statutValidation": "brouillon",
"niveauValidation": 0,
"message": "Validation réinitialisée"
}
Complete Examples
JavaScript
class CycleValidationAPI {
constructor(token) {
this.token = token;
this.baseUrl = 'https://sig.ucp-pch.org/api';
}
async getCycle(cycleId) {
const response = await fetch(
`${this.baseUrl}/cycles/${cycleId}`,
{
headers: { 'Authorization': `Bearer ${this.token}` }
}
);
return response.json();
}
async soumettre(cycleId) {
const response = await fetch(
`${this.baseUrl}/cycles/${cycleId}/soumettre`,
{
method: 'POST',
headers: { 'Authorization': `Bearer ${this.token}` }
}
);
return response.json();
}
async valider(cycleId, commentaire = null) {
const response = await fetch(
`${this.baseUrl}/cycles/${cycleId}/valider`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${this.token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ commentaire })
}
);
return response.json();
}
async rejeter(cycleId, motif) {
const response = await fetch(
`${this.baseUrl}/cycles/${cycleId}/rejeter`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${this.token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ motif })
}
);
return response.json();
}
async getHistorique(cycleId) {
const response = await fetch(
`${this.baseUrl}/cycles/${cycleId}/historique-validations`,
{
headers: { 'Authorization': `Bearer ${this.token}` }
}
);
return response.json();
}
}
// Usage - Complete workflow
const api = new CycleValidationAPI(token);
const cycleId = '770e8400-e29b-41d4-a716-446655440003';
// 1. Submit
await api.soumettre(cycleId);
// 2. Level 1 validation
let result = await api.valider(cycleId, 'Validated by Agent');
console.log(`Level: ${result.niveauValidation}/${result.niveauxRequis}`);
// 3. Level 2 validation (if required)
if (!result.estCompletementValide) {
result = await api.valider(cycleId, 'Validated by Supervisor');
}
// Check history
const historique = await api.getHistorique(cycleId);
historique.historique.forEach(entry => {
console.log(`${entry.date}: ${entry.action} by ${entry.userName}`);
});
Python
import requests
class CycleValidationAPI:
def __init__(self, token):
self.token = token
self.base_url = 'https://sig.ucp-pch.org/api'
self.headers = {'Authorization': f'Bearer {token}'}
def soumettre(self, cycle_id):
response = requests.post(
f'{self.base_url}/cycles/{cycle_id}/soumettre',
headers=self.headers
)
return response.json()
def valider(self, cycle_id, commentaire=None):
response = requests.post(
f'{self.base_url}/cycles/{cycle_id}/valider',
headers={**self.headers, 'Content-Type': 'application/json'},
json={'commentaire': commentaire}
)
return response.json()
def rejeter(self, cycle_id, motif):
response = requests.post(
f'{self.base_url}/cycles/{cycle_id}/rejeter',
headers={**self.headers, 'Content-Type': 'application/json'},
json={'motif': motif}
)
return response.json()
def get_historique(self, cycle_id):
response = requests.get(
f'{self.base_url}/cycles/{cycle_id}/historique-validations',
headers=self.headers
)
return response.json()
# Usage
api = CycleValidationAPI(token)
# Validation workflow
api.soumettre(cycle_id)
# Validate until complete
while True:
result = api.valider(cycle_id, 'Automatic validation')
print(f"Level {result['niveauValidation']}/{result['niveauxRequis']}")
if result['estCompletementValide']:
print("Cycle fully validated!")
break
# Display history
historique = api.get_historique(cycle_id)
for entry in historique['historique']:
print(f"- {entry['niveauLabel']}: {entry['action']} by {entry['userName']}")
Workflow Diagram
+--------------+ POST /soumettre +--------------+
| brouillon | ----------------------> | en_attente |
+--------------+ +------+-------+
|
POST /valider | POST /rejeter
+-----------------+-----------------+
| | |
v | v
+--------------+ | +----------+
| Level N | | | rejete |
| validated | | +----------+
+------+-------+ |
| |
niveauValidation | |
< niveauxRequis | |
| |
+------+------+ |
| | |
v v |
+--------------+ +----------+ |
| en_attente | | valide | |
| level N+1 | | complete | |
+--------------+ +----------+ |
| |
+-------------------------+
Notes
- Validation is multi-level and configurable
- Each level requires a user with appropriate permissions
- Complete validation history is maintained
- A rejected cycle can be modified and re-submitted
- The number of required levels is defined at cycle creation