Aller au contenu

Properties

Contrôleur HTTP d'administration des propriétés (création-publication, édition, médias, finance, notes internes, resale royalty). Source : properties.controller.ts.

Tous les endpoints requièrent une session admin BetterAuth valide (AdminAuthGuard).

GET /administration/property

Liste toutes les properties d'investissement obligataire ou prêt (investorContractType IN ('obligation', 'loan')) avec les jointures projet, SPV, porteur, échéancier, séquestre intérêts, budget travaux.

Décorateur : L110.

Response

Tableau d'objets enrichis :

[
  {
    "project": { "...": "champs property + address + interestSequestreSummary + constructionBudgetSummary" },
    "spv": { "...": "SpecialPurposeVehicule" },
    "projectOwner": { "...": "ProjectOwner" },
    "isReferralPaid": false,
    "echeancierExists": true
  }
]

GET /administration/property/royalty

Liste toutes les properties de type royalty triées createdAt DESC. Chaque entrée embarque un flag hasInternalNote.

Décorateur : L117.

Response

Tableau de Property étendu avec hasInternalNote: boolean.

GET /administration/property/properties-prices-history

Exporte l'historique des prix de bricks de toutes les properties au format Excel. Streame le fichier en réponse.

Décorateur : L221.

Response

Fichier .xlsx (Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet), nom : properties-brick-prices-history-YYYY-MM-DD.

Erreurs

Code Statut Cause
data-validation-error 400 Validation des données extraites échouée

GET /administration/property/simulate-automatic-investment

Lance une simulation de financement automatique en arrière-plan. La requête répond immédiatement ('Simulation en cours...') ; les résultats sont postés sur Slack #financement-automatique-simulation.

Note : route exposée dans ce contrôleur mais le @Controller est administration/property ; en pratique propertyId n'est pas un UUID réel ici, c'est une simulation.

Décorateur : L153 — voir aussi Property Funding.

GET /administration/property/:propertyId

Retourne une Property complète par ID.

Décorateur : L124.

Path param

  • propertyId — UUIDv4

Response

Entité Property (TypeORM) ou null.

POST /administration/property/:propertyId/resale/start

Démarre la phase de revente d'une property royalty. Une AdminAction PROPERTY_RESALE_START est créée via interceptor.

Décorateur : L134.

Path param + Request body (fusionnés et validés ensemble)

{
  "propertyId": "uuid-v4",
  "saleStartedAt": "2026-04-01T00:00:00Z"
}

Erreurs

Code Statut Cause
property.not-found 404 Property royalty introuvable
property.not-purchased-yet 400 Property pas encore achetée
property.resale-already-started 400 Resale déjà démarrée

POST /administration/property/:propertyId/resale/offer-accepted

Enregistre l'acceptation d'une offre de revente (partial / total). Annule en cascade les deals marketplace en attente. Une AdminAction PROPERTY_RESALE_OFFER_ACCEPTED est créée via interceptor.

Décorateur : L156.

Path param + Request body

{
  "propertyId": "uuid-v4",
  "offerAcceptedAt": "2026-04-15T00:00:00Z",
  "saleType": "partial"
}

saleType : 'partial' | 'total' (propertyResaleType).

Response

{ "property": { "...": "Property mise à jour" } }

Erreurs

Code Statut Cause
property.not-found 404 Property royalty introuvable
property.not-purchased-yet 400 Property pas encore achetée
property.resale-not-started 400 Resale non démarrée
property.offer-already-accepted 400 Offre déjà acceptée
property.resale-completed 400 Resale déjà clôturée

POST /administration/property/yearly-financial-update

Upload d'un fichier Excel (mime application/vnd.openxmlformats-officedocument.spreadsheetml.sheet) déclenchant la mise à jour financière annuelle de toutes les properties listées. Une AdminAction UPLOAD_YEARLY_PROPERTIES_UPDATE est créée via interceptor.

Décorateur : L183.

Multipart body

  • file — fichier .xlsx (interceptor FileInterceptor)

Erreurs

Code Statut Cause
missing-update-file 400 Aucun fichier dans la requête
cannot-validate-excel-data 400 Données Excel invalides
property-not-found 404 Au moins une property du fichier introuvable
brick-price-not-found 404 Brick price introuvable pour la period concernée
property-update-for-year-already-exist 409 Update annuelle déjà enregistrée pour cette year

POST /administration/property/upload-image

Upload jusqu'à 20 images (jpeg / jpg / png / webp) pour la galerie photo d'une property.

Décorateur : L247.

Multipart body

  • files — N×fichiers image (max 20, FilesInterceptor)

Response

Tableau d'URLs publiques des images uploadées.

Erreurs

Code Statut Cause
Failed to upload images 500 Aucune image n'a pu être uploadée

POST /administration/property/upload-property-document

Upload d'un document PDF lié à une property.

Décorateur : L267.

Multipart body

  • file — fichier application/pdf

Response

{ "url": "https://..." }

Erreurs

Code Statut Cause
<error> 500 Toute erreur d'upload propage result.error en 500

PATCH /administration/property/:propertyId

Édite une property (sauf royalty). En DRAFT, l'édition est complète (montant à financer, opération, contract specs). Hors DRAFT, seules certaines colonnes sont mises à jour via ce endpoint générique.

Pour modifier le séquestre d'intérêts (totalFundEscrow) ou le budget travaux (totalConstructionBudget) sur une property publiée, utiliser le endpoint dédié PATCH …/contract-budget — règles métier distinctes (échéancier, virements PDP, solde Lemonway).

Décorateur : L290.

Path param

  • propertyId — UUIDv4

Request body

Validé via propertyEditPayload (cf. properties.dto.ts). Champs principaux : name, investmentCase, imageGallery, videoGallery, documents, address, localisationDescription, surface, fundingStartDate, fundingMaxEndDate, revenueStartDate, investmentHorizonInMonths, amountToFundCents, minAmountToFundCents, advantages, finances, attributes, returnOnInvestment, lotCount, totalConstructionBudget, totalFundEscrow, investorContractType, operation (patch obligV1 ou obligV2 selon __variant existant).

Erreurs

Code Statut Cause
property.edit-does-not-support-royalty-operation 400 La property est de type royalty
<validation errors> 400 operation patch invalide pour la version (V1/V2)
min-amount-to-fund-should-be-less-than-amount-to-fund 400 Validation montant min/cible
max-end-date-should-be-after-start-date 400 Date max ≤ date de début

PATCH /administration/property/:propertyId/contract-budget

Édite le séquestre d'intérêts et/ou le budget travaux d'une property publiée (obligation V2 uniquement). Trace une AdminAction PROPERTY_EDIT_CONTRACT_BUDGET via interceptor.

Décorateur : L751.

Logique pure : published-contract-budget-edit.ts.

Path param

  • propertyId — UUIDv4

Request body

Validé via patchProjectContractBudgetPayload (@bricks-common/api-communication-bricksoffice). Champs optionnels (au moins un requis) :

{
  "totalFundEscrow": 15000000,
  "totalConstructionBudget": 5000000
}

Montants en centimes.

Règles métier

Champ Règle
totalFundEscrow (séquestre d'intérêts) Gelé dès qu'un échéancier existe — toute modification renvoie project.edit-contract-budget-interest-sequestre-locked-with-schedule (pas de recompute de l'échéancier, choix conservateur)
Les deux champs Baisse interdite après le premier virement au porteur (project.edit-contract-budget-decrease-after-transfer)
Les deux champs Hausse autorisée seulement si le solde Lemonway du SPV couvre la somme des augmentations (project.edit-contract-budget-increase-requires-lw-funds) ; indisponibilité LW → project.lemonway-balance-unavailable (500)
totalConstructionBudget Toujours éditable hors gel séquestre ci-dessus — valeur indicative côté ops

Le budget travaux reste modifiable même après déblocage des fonds au porteur ; seul le séquestre est figé par l'existence de l'échéancier.

Response

{
  "totalFundEscrow": 15000000,
  "totalConstructionBudget": 5000000
}

Erreurs

Code Statut Cause
project.not-found 404 Property introuvable
project.edit-only-supports-obligationV2 400 Property non obligation V2
project.edit-contract-budget-interest-sequestre-locked-with-schedule 400 Échéancier existant + tentative de modifier le séquestre
project.edit-contract-budget-decrease-after-transfer 400 Baisse après virement PDP
project.edit-contract-budget-increase-requires-lw-funds 400 Solde Lemonway insuffisant pour la hausse
project.lemonway-balance-unavailable 500 Impossible de lire le solde Lemonway

PATCH /administration/property/:propertyId/publish

Publie une property en DRAFT (passage à PUBLISHED). Effectue : insertion BrickPrice, création des bricks primaires, programmation des jobs auto-funding, annonce Slack et webhook Make.com (production uniquement).

Décorateur : L552.

Path param

  • propertyId — UUIDv4

Request body

{ "displayDate": "2026-04-30T08:00:00Z" }

displayDate optionnelle.

Erreurs

Code Statut Cause
property.not-found 404 Property introuvable
property.publish.must-be-draft 400 Property déjà publiée ou autre statut
property.publish.funding-start-date-cannot-be-before-display-date 400 displayDate > funding.startedAt
property.spv.not-found 500 SPV introuvable
spv.lemonway.wallet.not-found 404 SPV sans wallet Lemonway
<lemonway error message> 500 Échec de récupération du compte Lemonway
property.lemonway-account-not-validated 400 Compte Lemonway non validé
property.publish.must-be-2h-before-funding-start 400 Funding démarre dans moins de minFundingStartDateDelayFromNowInHours
property.publish.must-have-2-images 400 Moins de 2 images dans la galerie

GET /administration/property/:propertyId/advantages

Récupère la liste des avantages d'une property (FR uniquement).

Décorateur : L658.

Path param

  • propertyId — UUIDv4

Response

[
  { "id": "uuid", "title": "...", "description": "..." }
]

POST /administration/property/:propertyId/draft-token

Génère un token Redis (TTL 7 jours) permettant de prévisualiser une property en draft via le front. Retourne l'URL préviewable.

Décorateur : L673.

Path param

  • propertyId — UUIDv4

Response

{ "url": "https://app.bricks.co/project/<id>?draftToken=<nanoid>" }

Erreurs

Code Statut Cause
property.not-found 404 Property introuvable

DELETE /administration/property/:propertyId

Supprime une property en statut DRAFT.

Décorateur : L699.

Path param

  • propertyId — UUIDv4

Erreurs

Code Statut Cause
<deletion error> 400 Toute erreur métier propagée par PropertyDeletionService.deletePropertyInDraft

GET /administration/property/:propertyId/internal-note

Récupère la note interne admin (markdown) d'une property.

Décorateur : L712.

Path param

  • propertyId — UUIDv4

Response

InternalNote (contenu + version).

Erreurs

Code Statut Cause
Property not found 404 Property introuvable

PATCH /administration/property/:propertyId/internal-note

Met à jour la note interne avec contrôle de version optimiste.

Décorateur : L728.

Path param

  • propertyId — UUIDv4

Request body

{ "content": "...", "version": 3 }

Validé via patchProjectInternalNotePayload.

Erreurs

Code Statut Cause
Property not found 404 Property introuvable
NOTE_VERSION_CONFLICT 409 expectedVersion ne correspond pas à la version en base

POST /administration/property/:propertyId/solde-de-tout-compte/done

Marque le solde de tout compte comme effectué (étape temporaire avant automatisation).

Décorateur : L760.

Path param

  • propertyId — UUIDv4

Erreurs

Code Statut Cause
solde-de-tout-compte-already-done 400 Solde déjà marqué fait
project-must-be-in-repayment-finished-status 400 financialStatusrepayment-finished

Liens