Aller au contenu

Échéancier

Extrait du domain map API, qui était chargé dans chaque session agent. La rule garde l'index module → contexte ; le détail vit ici, à côté du code.

Un echeancier par bien (obligation/loan), configure apres funding success.

Logique de calcul : - Interets calcules jour par jour (30 jours/mois comptable), le capital restant evolue a chaque evenement - Mensualite = interets + remboursement capital - Sequestre d'interets : montant pre-collecte deduit des mensualites. Peut reduire amountDue a zero (echeance sans paiement du) - amountDue = max(0, mensualite + penalites - sequestre restant). remainingToBePaid = amountDue - deja paye

Evenements qui recomputent l'echeancier a partir de leur date (en preservant les echeances passees) : - capitalLoaned : nouvelle tranche versee (augmente capital restant) - capitalRepaymentPlanned / capitalRepaymentUnplanned : remboursement (diminue capital restant) - prorogation : prolongation de duree (doit etre > duree actuelle) - interestRateChange, vatRateChange, decreaseInterestSequestre

Subtilites : - Prorogation contractuelle prevue (contractSpecifications.durationInMonths.prorogation = duree totale apres prorogation, strictement > nominale) mais pas encore appliquee a l'echeancier : simulation sans ecriture DB via GET /administration/espace-financement/project/:projectId/echeancier/prorogation-simulation (espace-financement-ext) et GET /administration/property/:projectId/payment-schedule/prorogation-simulation (BO) ; 400 prorogation-not-planned si absente, 400 prorogation-duration-should-be-greater-than-nominal-duration si prorogation <= nominal. Si deja appliquee, renvoie l'echeancier courant - GET .../echeancier/start-and-end-date (espace-financement-ext) expose endDateWithProrogation : date du dernier capitalRepaymentPlanned apres simulation de prorogation (null si prorogation absente / simulation impossible) - Penalites de retard : poussees par gestion-des-defauts (webhook POST /administration/gestion-defauts/echeancier/penalties), stockees en jsonb penalty {total, forInvestors, forBricks, discount?} sur l'echeance. Seule la part forInvestors entre dans amountDue ; forBricks n'est pas encaisse via l'echeancier — reclame en une fois au solde de tout compte (somme des forBricks sur le dernier virement). Echeance / echeancier introuvable : skip du projet (TX rollback) + Slack, le batch continue — un id fantome ne doit pas bloquer la synchro des autres projets (HTTP 201) - Le meme webhook porte le statut projet (delay | default | null) : il ecrit financialStatus (etat courant, recalcule a la regularisation) et leve hasBeenInDelayOrDefaultOnce, jamais efface a la regularisation — c'est ce flag qui maintient l'acces au suivi detaille apres retour a la normale, financialStatus distinguant deja retard et defaut. Historique anterieur irrecuperable (financialStatus ecrase sur place) : backfill via export gestion-des-defauts (scripts/property/backfill-has-been-in-delay-or-default-once.script.ts) - L'echeancier PDP (project-financing-request-echeancier) expose penalty (total + les deux parts) quand total > 0 — affiche dans l'Espace Financement avec le detail du calcul - L'echeancier PDP expose mensualite (theorique) et amountDue (du post-sequestre), et derive en vue mensualiteStatus: 'coveredByInterestSequestre' (amountDue = 0 && mensualite > 0 && interestSequestreRemaining > 0) — jamais persiste, le noPayment en base reste surcharge. La jauge "echeances restantes" compte les couvertes dans le total mais pas dans le restant. Detection BO / notaire / PDF via deriveMensualiteDisplayStatus (@bricks-common/api-communication-bricksoffice, le contrat admin reste brut) ; la vue PDP derive le meme predicat sequestre cote serveur — changer les deux ensemble - Edit BO du contract budget (totalFundEscrow/totalConstructionBudget, action admin property.edit-contract-budget) : sequestre d'interets gele des qu'un echeancier existe (pas de recompute, choix conservateur) ; sinon baisse interdite apres le premier virement PDP, hausse conditionnee au solde Lemonway. Budget travaux indicatif, toujours editable - Remboursement anticipe (capitalRepaymentUnplanned) interdit si echeances passees impayees - Le remboursement anticipe ne peut pas depasser le capital restant a rembourser - Frais de gestion mensuels transferes separement des revenus investisseurs (SPV -> compte Bricks) - Frais de gestion executes seulement si la mensualite n'est pas impayee (inclut noPayment quand le sequestre couvre tout) - TVA sur frais de gestion depend du pays du SPV, et peut changer via evenement vatRateChange - Cloture anticipee : les frais de gestion du dernier mois contractuel sont proratas au jour pres (pas factures pour le mois complet) - Switch BO du paymentMode (prélèvement ↔ virement) : PUT .../echeancier/payment-mode. Le dayOfMonth est conservé. Passage virement → prélèvement : mandat SDD Lemonway obligatoire (liste via proxy GET /administration/spv/:spvId/sdd-mandates). paymentMode ne pilote que la programmation des SDD ; le cron echeancier-bank-debit-status-update synchro toute ligne qui a déjà un prélèvement Lemonway, y compris après un switch en wire. - Sync prelevements SEPA (echeancier-bank-debit-status-update cron, quotidien) : mois recap (20 N → 8 N+1) + prelevements scheduled + rescan chargeback des prelevements executed sur businessRules.echeancier.bankDebitChargebackResyncWindowDays (meme echeance deja paid) — le webhook Lemonway chargeback ne met pas a jour l'echeancier SPV. Un refund sur echeance paid hors BANK_DEBIT_PAYOUT_HOLD_BUSINESS_DAYS (7j ouvrés français Paris, meme hold que le script 02a) poste une alerte dediee dans #suivi-projet-echeances (hors recap mensuel). Un refund encore dans le hold reste dans le recap quotidien.