Property Payment Schedule¶
Contrôleur HTTP de l'échéancier d'une property (création, simulation, prorogation, gestion des virements à assigner, séquestre d'intérêts). Source : property-payment-schedule.controller.ts.
Tous les endpoints requièrent une session admin BetterAuth valide (AdminAuthGuard). Les endpoints muteurs sont tracés via CreateAdminActionInterceptor.
Préfixe de routes : /administration/property.
POST /payment-schedule/simulation¶
Simule un échéancier sans le persister. Retourne les échéances calculées par PaymentScheduleComputing.generateSimulation.
Request body¶
{
"totalFundedAmount": 100000,
"initialCapitalLoaned": { "date": "2025-01-15", "amount": 100000 },
"durationInMonths": 12,
"annualInterestPercentage": 10,
"managementFeesPercentage": 1.5,
"spvCountry": "France",
"interestSequestre": 0,
"events": []
}
Validation via un sous-ensemble de EcheancierConfigModel.validator.props (totalFundedAmount, initialCapitalLoaned, durationInMonths, annualInterestPercentage, managementFeesPercentage, interestSequestre, events) (source), plus spvCountry (SpecialPurposeVehicule.countryValidator). paymentMode n'est pas validé ici.
Response¶
Echeance[] — tableau d'échéances simulées.
POST /payment-schedule/v2¶
Crée et persiste l'échéancier v2 d'une property.
Request body¶
{
"propertyId": "uuid",
"echeancierConfig": { "...": "EcheancierConfigModel.validator" },
"totalConstructionBudget": 100000
}
Validé via PropertyEcheancierModel.createEcheancierV2_Payload (source).
Response¶
Erreurs¶
| Code | Statut | Cause |
|---|---|---|
payment-schedule.already-exist |
400 | Un échéancier existe déjà pour cette property |
spv-not-found |
400 | SPV introuvable pour cette property |
initial-capital-loaned-is-greater-than-total-funded-amount |
400 | Validation config |
interest-sequestre-is-greater-than-total-funded-amount |
400 | Validation config |
sum-repayment-is-greater-than-sum-loaned |
400 | Validation config |
PATCH /:propertyId/payment-schedule/simulation/capital-event¶
Simule l'application d'un événement de capital (capitalLoaned ou capitalRepaymentUnplanned) sur l'échéancier existant. Ne mute pas la base.
Path param¶
propertyId— UUIDv4
Request body¶
Le type peut être capitalLoaned ou capitalRepaymentUnplanned (source).
Response¶
L'échéancier simulé avec l'événement appliqué.
Erreurs¶
| Code | Statut | Cause |
|---|---|---|
echeancier-not-found |
400 | Pas d'échéancier pour cette property |
echeance-not-found |
400 | Échéance correspondant à la date introuvable |
echeancePeriod-does-not-match-event-date |
400 | Date de l'événement hors période |
interest-sequestre-remaining-is-not-enough |
400 | Séquestre insuffisant pour le repayment |
event-date-is-out-of-bound |
400 | Date de l'événement hors bornes de l'échéancier |
echeancier-config-is-invalid |
400 | Config résultante incohérente |
PUT /:propertyId/payment-schedule/mandate¶
Associe (ou met à jour) le mandat de prélèvement bancaire (SDD Lemonway) à l'échéancier d'une property.
Path param¶
propertyId— UUIDv4
Request body¶
Response¶
200 OK avec un corps vide (le handler n'a pas de @HttpCode, NestJS retourne donc 200 par défaut).
GET /:propertyId/payment-schedule¶
Récupère l'échéancier persisté d'une property.
Path param¶
propertyId— UUIDv4
Response¶
Échéancier complet via PropertyPaymentScheduleRepository.getPaymentScheduleForProperty.
PUT /:propertyId/payment-schedule/unprogram-scheduled-mensualite-payment¶
Annule la programmation d'un prélèvement bancaire SDD (mensualité) prévu pour une échéance. Trace une PROPERTY_PAYMENT_SCHEDULE_UNPROGRAM_ONE_PAYMENT.
Path param¶
propertyId— UUIDv4
Request body¶
Erreurs¶
| Code | Statut | Cause |
|---|---|---|
echeance-not-found |
400 | Échéance introuvable |
echeance-mensualite-must-be-unpaid |
400 | La mensualité a déjà été payée |
echeance-mensualite-scheduled-payment-must-be-scheduled |
400 | Aucun prélèvement programmé à annuler |
failed-at-provider |
500 | Échec côté Lemonway |
PUT /:propertyId/payment-schedule/program-unscheduled-mensualite-payment¶
Programme un prélèvement bancaire pour une échéance pas encore planifiée. Trace une PROPERTY_PAYMENT_SCHEDULE_PROGRAM_ONE_PAYMENT.
Path param¶
propertyId— UUIDv4
Request body¶
Erreurs¶
| Code | Statut | Cause |
|---|---|---|
echeance-not-found |
400 | Échéance introuvable |
echeance-mensualite-must-be-unpaid |
400 | Mensualité déjà payée |
echeance-mensualite-must-be-not-scheduled |
400 | Mensualité déjà programmée |
echeance-nothing-to-pay |
400 | Rien à payer pour cette échéance |
echeancier-config-payment-mode-not-direct-debit |
400 | Mode de paiement n'est pas SDD |
failed-at-provider |
500 | Échec côté Lemonway |
GET /payment-schedule/payment/:period¶
Liste les paiements (avec statut financier projet) pour un mois donné.
Path param¶
period— au formatYYYY-MM(validé viayearMonthDate)
Response¶
Tableau de paiements avec leur statut financier projet.
GET /payment-schedule/wire-to-be-assigned¶
Liste les virements en attente d'assignation à une échéance.
Response¶
Vue des virements EcheancierWireToBeAssigned au statut waiting.
GET /payment-schedule/payment-to-be-assigned/history¶
Liste en lecture seule les paiements déjà assignés (assigned) ou archivés (archivedNotAssigned).
Response¶
Même forme enrichie que la liste waiting (projet, SPV, lien Lemonway) avec en plus, pour les assignés, le numéro et la période de l'échéance cible. Le champ JSON porte le nom paymentToBeAssigned.
POST /payment-schedule/wire-to-be-assigned/switch-project¶
Réassigne un virement reçu à un autre projet (changement de SPV destinataire). Trace une PROPERTY_PAYMENT_SCHEDULE_SWITCH_PROJECT_OF_WIRE_WAITING_TO_BE_ASSIGNED.
Request body¶
Erreurs¶
| Code | Statut | Cause |
|---|---|---|
wire-not-found |
400 | Virement introuvable |
wire-not-waiting |
400 | Virement n'est pas en statut waiting |
only-parent-wires-can-be-project-switched |
400 | Le virement est un enfant (split) |
only-wire-payments-can-be-project-switched |
400 | Le paiement n'est pas un virement entrant (p2p, other) |
spv-current-project-not-found |
400 | SPV courant introuvable |
new-project-not-found |
400 | Projet cible introuvable |
new-project-spv-not-found |
400 | SPV du projet cible introuvable |
p2p-failed-at-provider |
400 | Échec P2P Lemonway |
POST /payment-schedule/wire-to-be-assigned/assign¶
Assigne un virement à une échéance (mensualité ou capital repayment). Trace une PROPERTY_PAYMENT_SCHEDULE_ASSIGN_WIRE_TO_ECHEANCE.
Request body¶
{
"wireToBeAssignedId": "uuid-v4",
"paymentFor": "mensualite",
"echeanceId": "uuid-v4",
"comment": "optionnel",
"isSimulation": false
}
paymentFor ∈ 'capitalRepayment' | 'mensualite'.
Response¶
L'échéancier mis à jour.
Erreurs¶
| Code | Statut | Cause |
|---|---|---|
wire-not-found |
400 | Virement introuvable |
wire-not-waiting |
400 | Virement déjà assigné/archivé |
echeance-not-found |
400 | Échéance introuvable |
capital-repayment-no-payment-due |
400 | Pas de capital à rembourser sur l'échéance |
POST /payment-schedule/wire-to-be-assigned/split¶
Découpe un virement reçu en deux pour pouvoir l'assigner partiellement. Trace une PROPERTY_PAYMENT_SCHEDULE_SPLIT_WIRE_TO_ECHEANCE.
Request body¶
newAmount en cents (positif, doit être inférieur au montant initial).
Erreurs¶
| Code | Statut | Cause |
|---|---|---|
wire-not-found |
400 | Virement introuvable |
wire-not-waiting |
400 | Virement déjà traité |
new-amount-must-be-less-than-original-amount |
400 | Montant nouveau ≥ montant initial |
POST /payment-schedule/wire-to-be-assigned/archive¶
Archive un virement reçu sans l'assigner (cas erreur de saisie, virement non lié à un projet, etc.). Trace une PROPERTY_PAYMENT_SCHEDULE_ARCHIVE_WIRE.
Request body¶
comment requis (notEmptyString).
Erreurs¶
| Code | Statut | Cause |
|---|---|---|
wire-not-found |
400 | Virement introuvable |
wire-not-waiting |
400 | Virement déjà traité |
GET /payment-schedule/payment-to-be-assigned/eligible-projects¶
Liste les projets éligibles à la création manuelle d'un paiement à assigner (back-office). Source : property-payment-schedule.controller.ts L475.
Response¶
Liste de projets avec identifiants et métadonnées utiles au formulaire de création.
POST /payment-schedule/payment-to-be-assigned¶
Crée un paiement à assigner (virement entrant en attente d'affectation à une échéance). Trace une PROJECT_PAYMENT_SCHEDULE_CREATE_PAYMENT_TO_BE_ASSIGNED. Validator partagé : createPaymentToBeAssignedPayload (@bricks-common/api-communication-bricksoffice).
Request body¶
{
"projectId": "uuid-v4",
"amount": 100000,
"date": "2025-06-15",
"payment": {
"kind": "p2p",
"execution": "auto",
"debitAccountId": "compte-lemonway-debiteur",
"comment": "Paiement porteur juin"
}
}
amount en cents (positif). payment est une union discriminée sur kind :
| Variante | Champs |
|---|---|
p2p + auto |
debitAccountId, comment — déclenche un P2P Lemonway synchrone vers le wallet SPV du projet |
p2p + manual |
paymentId (entier Lemonway), comment — rattache un P2P Lemonway existant |
other |
comment — enregistrement sans mouvement Lemonway |
Comportement P2P auto en échec¶
Si le P2P Lemonway échoue après création de l'enregistrement : le virement reste en status: waiting sans wireId, une alerte Slack est envoyée (InternalAlertSlackService + PaymentScheduleSlackService), et la réponse HTTP reste un succès avec l'enregistrement créé. Le retry se fait via POST .../payment-to-be-assigned/retry-p2p (idempotent via attemptP2PAtLemonway).
Response¶
L'enregistrement waitingWire créé.
Erreurs¶
| Code | Statut | Cause |
|---|---|---|
project-not-eligible |
400 | Projet non éligible |
spv-not-found |
400 | SPV introuvable |
spv-lemonway-wallet-not-found |
400 | Wallet Lemonway SPV introuvable |
debit-account-not-found |
400 | Compte débiteur introuvable (P2P auto) |
debit-account-insufficient-balance |
400 | Solde débiteur insuffisant (P2P auto) |
lemonway-p2p-not-found |
400 | P2P Lemonway introuvable (P2P manual) |
lemonway-p2p-not-success |
400 | P2P Lemonway pas en succès (P2P manual) |
lemonway-p2p-amount-mismatch |
400 | Montant P2P ≠ montant demandé (P2P manual) |
lemonway-p2p-receiver-account-mismatch |
400 | Compte receveur P2P ≠ wallet SPV (P2P manual) |
lemonway-p2p-validation-failed |
500 | Échec technique de validation Lemonway |
POST /payment-schedule/payment-to-be-assigned/retry-p2p¶
Relance le P2P Lemonway pour un paiement à assigner créé en mode p2p + auto dont le P2P initial a échoué. Trace une PROJECT_PAYMENT_SCHEDULE_RETRY_PAYMENT_TO_BE_ASSIGNED_P2P.
Request body¶
Response¶
L'enregistrement waitingWire mis à jour.
Erreurs¶
| Code | Statut | Cause |
|---|---|---|
payment-to-be-assigned-not-found |
400 | Enregistrement introuvable |
payment-to-be-assigned-not-waiting |
400 | Déjà traité |
payment-to-be-assigned-not-p2p-auto-execution |
400 | Pas un paiement P2P auto |
payment-to-be-assigned-already-has-lemonway-wire-id |
400 | P2P déjà lié |
spv-not-found |
400 | SPV introuvable |
spv-lemonway-wallet-not-found |
400 | Wallet Lemonway SPV introuvable |
p2p-failed |
500 | Échec technique du P2P Lemonway |
POST /:propertyId/payment-schedule/prorogation¶
Proroge l'échéancier (prolonge la durée), avec optionnellement un nouveau taux d'intérêt sur la période de prorogation. Trace une PROPERTY_PAYMENT_SCHEDULE_PROROGATE_ECHEANCIER.
Path param¶
propertyId— UUIDv4
Request body¶
interestRateDuringProrogation est optionnel.
Response¶
L'échéancier prorogé.
Erreurs¶
| Code | Statut | Cause |
|---|---|---|
prorogation-duration-should-be-greater-than-nominal-duration |
400 | Durée demandée ≤ durée nominale |
prorogation-duration-should-be-greater-than-current-duration |
400 | Durée demandée ≤ durée courante |
POST /:propertyId/payment-schedule/recompute-from-echeance¶
Recalcule l'échéancier à partir d'une période donnée. Réservé à denis@bricks.co (beta dev — check email-only dans le contrôleur). Trace une PROPERTY_PAYMENT_SCHEDULE_RECOMPUTE_FROM_ECHEANCE.
Path param¶
propertyId— UUIDv4
Request body¶
Pré-conditions¶
- Email admin ∈
denis@bricks.co(sinon403 Forbidden)
Response¶
L'échéancier recalculé.
Erreurs¶
| Code | Statut | Cause |
|---|---|---|
| (forbidden) | 403 | Email admin non autorisé |
| (internal) | 500 | Échec du recalcul |
POST /echeancier/interest-sequestre/transfer-to-echeance-payment-to-be-assigned¶
Transfère du séquestre d'intérêts vers une échéance comme paiement à assigner. Trace une PROPERTY_ECHEANCIER_TRANSFER_SEQUESTRE_TO_ECHEANCE_PAYMENT_TO_BE_ASSIGNED.
Request body¶
{
"propertyId": "uuid",
"echeanceId": "uuid-v4",
"interestSequestreAmountToTransfer": 1500,
"paymentDate": "2025-06-15"
}
Erreurs¶
| Code | Statut | Cause |
|---|---|---|
| (internal) | 500 | Échec du transfert (séquestre insuffisant, échéance introuvable, etc.) |
GET /payment-schedule/capital-repayment/unpaid¶
Liste les remboursements de capital non payés à travers tous les échéanciers.
Response¶
Vue retournée par EcheancierViewService.getUnpaidCapitalRepayments.
Liens¶
- Service échéancier :
property-payment-schedule.service.ts - Service prélèvement bancaire :
property-payment-schedule.bank-debit-programming.service.ts - Service virements à assigner :
echeancier-wire-to-be-assigned.service.ts - Service séquestre :
echeancier.interest-sequestre.service.ts - Modèle config :
echeancier-config.model.ts - Modèle événement :
echeancier-event.model.ts - Modèle échéancier :
property-payment-schedule.model.ts - Computing :
property-payment-schedule.computing.ts