Project Presentation¶
Contrôleur HTTP de gestion de la présentation d'un projet (étape porteur de projet : nom, catégorie, montant demandé, lots, etc.). La présentation a deux statuts : draft (édition libre) et completed (verrouillé après validation des champs requis).
Source : project-presentation.controller.ts.
Tous les endpoints requièrent un porteur de projet authentifié via better-auth (ProjectFinancingRequestOwnerGuard). Comme la route porte un :projectId, le guard vérifie aussi que le projet appartient à ce porteur (sinon 403 Forbidden) et qu'il existe (sinon 404 Not Found).
GET /project-financing-request/:projectId/presentation¶
Récupère la présentation du projet. Si elle n'existe pas encore, en crée une vide en status='draft' (idempotent : pattern getOrCreate). Voir project-presentation.controller.ts#L15-L23.
Path params¶
projectId— id de la demande de financement
Response¶
Schéma getProjectPresentationResponseSchema — projection via getProjectPresentationView : chaque imageKey S3 devient une paire { key, url } (la key est renvoyée pour que le client la ré-émette au save, l'url est une URL GET presignée fraîche pour l'affichage) :
{
"id": "uuid",
"status": "draft | completed",
"mainImage": { "key": "s3-key", "url": "https://..." },
"secondaryImages": [{ "key": "s3-key", "url": "https://..." }],
"name": "string?",
"category": "marchandDeBiens | locatif | exploitation | promotion",
"fundingAmountRequested": 1000000,
"fundsNeededByDate": "ISO date?",
"description": "string?",
"address": "string?",
"localizationDescription": "string?",
"totalSurface": 250,
"lots": [
{ "id": "uuid", "name": "string", "surface": 50, "image": { "key": "s3-key", "url": "https://..." } }
]
}
Erreurs¶
| Code | Statut | Cause |
|---|---|---|
| Erreur S3 | 500 | Échec de signature d'une URL GET presignée (la view fail-fast pour ne pas décaler les indices côté front) |
not-found |
404 | Projet inconnu lors du getOrCreate initial (cf. project-not-found) |
PATCH /project-financing-request/:projectId/presentation/:presentationId¶
Auto-save déclaratif de la présentation. Le statut est forcé à draft. Voir project-presentation.controller.ts#L25-L42.
Sémantique par champ (images et fundsNeededByDate) : absent = inchangé, null = effacé, valeur = appliqué. Les lots sont mergés par id (stable côté client). Les autres champs texte : body.field ?? existant.
Les imageKey du body doivent avoir été confirmées au préalable (confirm-upload, qui vérifie leur existence sur S3). Au save : les clés conservées n'ont aucun tag ; les clés qui disparaissent de la galerie sont taguées pending (jamais supprimées directement — une lifecycle rule S3 fait l'expiry). Voir le cycle de vie des images.
Path params¶
projectId— id de la demande de financementpresentationId— id de la présentation à mettre à jour
Request body¶
Validé via saveProjectPresentationBodySchema :
{
"name": "string?",
"category": "marchandDeBiens | locatif | exploitation | promotion (optional)",
"fundingAmountRequested": 1000000,
"fundsNeededByDate": "ISO datetime?",
"description": "string?",
"address": "string?",
"localizationDescription": "string?",
"totalSurface": 250,
"lots": [{ "id": "uuid", "name": "string", "surface": 50, "imageKey": "s3-key | null?" }],
"mainImageKey": "s3-key | null?",
"secondaryImageKeys": ["s3-key"]
}
lots[].id est généré côté client (UUID stable) pour matcher les lots existants lors du save. mainImageKey / lots[].imageKey sont nullish : null efface l'image, l'absence la conserve.
Response¶
undefined (pas de payload). Le client doit re-fetch via GET pour récupérer la vue à jour.
Erreurs¶
| Code | Statut | Cause |
|---|---|---|
validation-body |
400 | Body invalide |
s3-key-invalid-prefix |
400 | Une imageKey n'appartient pas au préfixe S3 du projet |
image-key-not-found |
400 | Une imageKey n'existe pas dans S3 (jamais uploadée) |
presentation-id-mismatch |
409 | Le presentationId ne correspond pas à la présentation du projet |
project-not-found |
404 | Le projet est introuvable |
PUT /project-financing-request/:projectId/presentation/:presentationId/complete¶
Verrouille la présentation en status='completed'. Re-valide tous les champs requis via le schéma ProjectFinancingRequestPresentationPgSchema.completed. Idempotent : si déjà completed, renvoie une erreur de conflit. Voir project-presentation.controller.ts#L44-L56.
Path params¶
projectId— id de la demande de financementpresentationId— id de la présentation à compléter
Response¶
undefined.
Erreurs¶
| Code | Statut | Cause |
|---|---|---|
presentation-not-found |
404 | Aucune présentation pour ce projet |
presentation-already-completed |
409 | Présentation déjà en status='completed' |
presentation-incomplete |
400 | Champs requis manquants (le détail Zod est dans body) |
Liens¶
- Service :
project-presentation.service.ts - View (projection read) :
get-project-presentation.view.ts - Mise à jour des tags images au save : helper
updatePendingTagsAfterSavecolocalisé dansproject-presentation.service.ts - Endpoints DTOs :
getProjectPresentation.endpoint.ts,saveProjectPresentation.endpoint.ts - Guard :
project-financing-request-owner.guard.ts - Routes images associées : project-presentation-images.md