Some checks are pending
CI / Lint bridge (Biome) (push) Waiting to run
CI / Type-check bridge (push) Blocked by required conditions
CI / Tests unit bridge (push) Blocked by required conditions
CI / Tests integration bridge (push) Blocked by required conditions
CI / Security scan (push) Waiting to run
CI / Docker build + healthcheck (push) Blocked by required conditions
Wiring HTTP du bridge service. 10 endpoints livres (cf docs/19 §6.1-6.5) :
- GET /api/v1/personnes (+ /:id, + /:id/dashboard)
- GET /api/v1/formations (+ /:id avec rollups blocs/modules)
- GET /api/v1/projets (+ /:id avec rollups taches)
- POST /api/v1/modules/:id/attribuer (RG-01 -> 422, role/heures invalides -> 400)
- POST /api/v1/interventions (validation role developpeur + heures > 0)
- PATCH /api/v1/attributions/:id/heures-realisees (409 si annule/realise)
Layers ajoutees :
- src/middleware/auth.ts : Bearer brg_*, scopes JSON-encoded BRIDGE_API_TOKENS, admin:* wildcard
- src/middleware/error-handler.ts : BridgeError -> JSON shape standard
- src/lib/container.ts : DI singleton (Baserow + Redis + 9 repos), setContainer testable
- src/lib/http.ts : parseListQuery + parseBody zod helper
- src/repos/baserow-repo.ts : BaseRepo<T> abstrait + 9 sous-classes (mapping Row<->Domain)
- src/routes/{personnes,formations,projets,modules,interventions,attributions}.ts
src/index.ts reecrit : buildApp() + initContainer + auth sur /api/v1/* + ready check Baserow+Redis.
Tests : 163/163 verts (12 suites domain + 8 nouvelles : auth, repos, 6 routes).
Coverage src global : 70.77% (cible 60%). Domain 97.86%, routes 96%, middleware 86%.
Choix : BaseRepo abstrait (pas mega-generic, Ockham) ; FakeRepos in-memory pour tests routes
(pas de testcontainers ici, c'est Bloc 7) ; mapping erreurs domain -> HTTP par message texte
(fragile, sera refactor en DomainError typees au Bloc 3.2).
Hors scope (a venir) :
- Bloc 5 : rate limiting Redis
- Bloc 7 : webhook handlers Baserow + sync bidirec + cache invalidation
- Bloc 3.2 : routes /docmost/*, /sync/*, /rapports/*
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
101 lines
2.6 KiB
TypeScript
101 lines
2.6 KiB
TypeScript
/**
|
|
* Fixtures domain partagees par les tests routes.
|
|
*/
|
|
|
|
import { Decimal } from 'decimal.js';
|
|
import { Attribution } from '../../src/domain/attribution.js';
|
|
import { Bloc } from '../../src/domain/bloc.js';
|
|
import { Formation } from '../../src/domain/formation.js';
|
|
import { Intervention } from '../../src/domain/intervention.js';
|
|
import { Module } from '../../src/domain/module.js';
|
|
import { Personne } from '../../src/domain/personne.js';
|
|
import { Projet } from '../../src/domain/projet.js';
|
|
import { Tache } from '../../src/domain/tache.js';
|
|
import type { Role } from '../../src/domain/types.js';
|
|
|
|
export function makePersonne(over: Partial<{ id: number; roles: Role[] }> = {}): Personne {
|
|
return new Personne({
|
|
id: over.id ?? 1,
|
|
nom: 'Dupont',
|
|
prenom: 'Pierre',
|
|
email: 'pierre@acadenice.fr',
|
|
capaciteAnnuelle: new Decimal(1000),
|
|
splitFormationPct: new Decimal(60),
|
|
splitAgencePct: new Decimal(40),
|
|
roles: new Set<Role>(over.roles ?? ['formateur']),
|
|
statut: 'actif',
|
|
});
|
|
}
|
|
|
|
export function makeFormation(id = 10): Formation {
|
|
return new Formation({
|
|
id,
|
|
nom: 'Dev Fullstack',
|
|
heuresTotales: new Decimal(500),
|
|
statut: 'actif',
|
|
});
|
|
}
|
|
|
|
export function makeBloc(id = 100, formationId = 10): Bloc {
|
|
return new Bloc({
|
|
id,
|
|
formationId,
|
|
nom: 'Bloc JS',
|
|
heuresPrevues: new Decimal(100),
|
|
ordre: 1,
|
|
});
|
|
}
|
|
|
|
export function makeModule(id = 200, blocId = 100): Module {
|
|
return new Module({
|
|
id,
|
|
blocId,
|
|
nom: 'JS Fondamentaux',
|
|
heuresPrevues: new Decimal(30),
|
|
});
|
|
}
|
|
|
|
export function makeAttribution(
|
|
over: Partial<{ id: number; moduleId: number; personneId: number }> = {},
|
|
): Attribution {
|
|
return new Attribution({
|
|
id: over.id ?? 500,
|
|
moduleId: over.moduleId ?? 200,
|
|
personneId: over.personneId ?? 1,
|
|
heuresAttribuees: new Decimal(10),
|
|
statut: 'planifie',
|
|
});
|
|
}
|
|
|
|
export function makeProjet(id = 300, clientId = 50): Projet {
|
|
return new Projet({
|
|
id,
|
|
clientId,
|
|
nom: 'Site Acme',
|
|
chargeHeures: new Decimal(80),
|
|
statut: 'en_cours',
|
|
});
|
|
}
|
|
|
|
export function makeTache(id = 400, projetId = 300): Tache {
|
|
return new Tache({
|
|
id,
|
|
projetId,
|
|
titre: 'Setup repo',
|
|
chargeHeures: new Decimal(8),
|
|
statut: 'todo',
|
|
});
|
|
}
|
|
|
|
export function makeIntervention(
|
|
over: Partial<{ id: number; tacheId: number; personneId: number }> = {},
|
|
): Intervention {
|
|
return new Intervention({
|
|
id: over.id ?? 600,
|
|
tacheId: over.tacheId ?? 400,
|
|
personneId: over.personneId ?? 2,
|
|
heures: new Decimal(2),
|
|
date: new Date('2026-05-01'),
|
|
statut: 'realise',
|
|
});
|
|
}
|