Project Analysis¶
Flux d'analyse d'un dossier de financement : lecture côté porteur, réponses aux compléments, et endpoints internes consommés par Projet Analyse (app hors monorepo).
Sources :
- Porteur :
project-analysis.controller.ts - Projet Analyse :
project-analysis-internal.controller.ts
Machine à états (rappel)¶
| Statut projet | Vue analyse porteur (GET …/analysis/status) |
Projet Analyse |
|---|---|---|
draft |
pending |
— |
in-analysis |
pending |
peut pousser questions / demandes de docs / refuser un fichier / commentaire analyste |
blocked |
blocked (commentaire analyste + questions + demandes de docs) |
idem + lit reanalysisComment via GET interne |
offer, finalization, completed |
409 project-analysis-status-unsupported |
hors périmètre analyse (offre / collecte) |
rejected |
declined (rejectionComment) |
— |
Passage blocked → in-analysis : le porteur appelle POST …/analysis/reanalysis (optionnellement avec un commentaire). Projet Analyse est notifié via ProjetAnalyseApi.notifyProjectUpdated avec reason: 'reanalysis-requested'.
Endpoints porteur (ProjectFinancingRequestOwnerGuard)¶
Préfixe : /project-financing-request/project/:projectId/analysis.
GET /status¶
Retourne l'état de l'analyse pour l'écran « Analyse » du funnel.
Réponses (contrat getProjectAnalysisStatusResponseValidator) :
ou, si le dossier est blocked :
{
"status": "blocked",
"comment": "Merci de préciser le montant des travaux restants.",
"questions": [{ "id": "uuid", "question": "…", "answer": "…" }],
"documentRequests": [
{
"id": "uuid",
"title": "…",
"description": "…",
"documents": [
{
"id": "uuid",
"name": "kbis.pdf",
"type": "application/pdf",
"size": 12345,
"createdAt": "2026-07-01T10:00:00.000Z",
"comment": "…",
"isRefused": false
}
]
}
]
}
isRefused est dérivé de refusedAt sur le document (voir Documents).
| Erreur | HTTP | Cause |
|---|---|---|
project-analysis-status-unsupported |
409 | Projet offer, finalization ou completed |
POST /question/:questionId/answer¶
Répond à une question posée par Projet Analyse. Corps : { "answer": "…" }.
| Erreur | HTTP | Cause |
|---|---|---|
project-not-blocked |
409 | Projet pas en blocked |
question-project-mismatch |
409 | Question rattachée à un autre projet |
POST /reanalysis¶
Demande une ré-analyse après avoir traité les compléments. Corps optionnel : { "comment": "…" }.
- Passe le projet de
blocked→in-analysis - Persiste
reanalysisComment(écrasé ànullsi le corps ometcommentaprès une demande commentée) - Notifie Projet Analyse, puis renvoie le même shape que
GET /status(pending)
| Erreur | HTTP | Cause |
|---|---|---|
project-cannot-be-reanalyzed |
409 | Projet pas en blocked |
Endpoints internes Projet Analyse¶
Préfixe : /internal/projet-analyse/project/:projectId. Auth : x-api-key consommateur projet-analyse.
La forme des payloads (params, bodies, réponses) fait foi dans l'OpenAPI — les descriptors vivent dans
@bricks-common/api-communication-internal, la doc est servie sur/internal/docs/json(voir le guide consommateur). Cette page ne documente que les invariants métier que le schéma ne dit pas.
GET /¶
État complet de la phase 1 (source de vérité côté Bricks) : l'état d'instruction et le dossier lui-même — présentation, emprunteur, documents déposés.
missingDocumentsFromAnalysis n'est renvoyé que si status === 'blocked' (sinon {}).
presentation et borrower valent null tant que l'entité n'existe pas, et leurs champs sont majoritairement optionnels en draft : l'analyse lit un dossier en cours de remplissage. L'emprunteur reste facultatif jusqu'à l'acceptation de l'offre.
comment est le commentaire que le porteur a joint à son fichier (null s'il n'en a pas laissé), à ne pas confondre avec le comment racine, qui est celui de l'analyste.
documents liste tous les fichiers du projet — dépôt d'onboarding compris (documentRequestId: null) et documents refusés (refusedAt horodaté), que l'analyse doit continuer de voir. s3Key accompagne l'URL signée : c'est la référence stable une fois le bucket partagé, l'URL expirant à brève échéance.
finalization porte ce que l'analyse assemble pour son bundle de signature : coordonnées bancaires, LEI, notaire, avantages investisseurs et les 4 pièces société. Le bloc vaut null tant que le porteur n'a pas validé sa finalisation — c'est le passage de la société en finalized qui le renseigne, et ce même geste émet le ping finalized. L'emprunteur n'y est pas repris : il vit à la racine.
POST /comment¶
Pousse un commentaire analyste affiché en tête de l'écran analyse bloquée côté porteur. Corps : { "comment": "…" }.
- Idempotent : re-push écrase le scalaire
commentsur le projet - Passe le projet en
blockedsi besoin (in-analysis→blocked)
| Erreur | HTTP | Cause |
|---|---|---|
project-not-under-analysis |
409 | Statut hors in-analysis / blocked |
POST /questions¶
Pousse une question. Corps : { "questionId": "uuid", "text": "…" }.
- Idempotent sur
questionId(re-push assureblockedsans doublon) - Dérive
in-analysis→blockedsi besoin
| Erreur | HTTP | Cause |
|---|---|---|
question-project-mismatch |
409 | questionId déjà utilisé sur un autre projet |
project-cannot-be-blocked |
409 | Statut incompatible (ex. offer) |
POST /document-requests¶
Pousse une demande de document complémentaire. Corps : { "requestId": "uuid", "label": "…", "description": "…?" }.
Même sémantique d'idempotence et de passage en blocked que les questions.
PUT /document/:documentId/refuse¶
Marque un fichier déjà uploadé par le porteur comme refusé (refusedAt horodaté). Idempotent : un second appel conserve le premier refusedAt.
Autorisé uniquement si le projet est in-analysis ou blocked.
| Erreur | HTTP | Cause |
|---|---|---|
project-not-under-analysis |
409 | Statut hors analyse |
document-not-found |
404 | Document inconnu ou autre projet |
Voir aussi Documents — sync missing (PUT /internal/…/missing-documents).
Liens¶
- Lecture :
project-analysis-read.service.ts - Écriture porteur :
project-analysis-write.service.ts - Écriture Projet Analyse :
project-analysis.service.ts - Contrat :
getProjectAnalysisStatus.endpoint.ts,requestProjectReanalysis.endpoint.ts