Files
oto-enterprise-os-dtp/05_deliverables_mvp/crm/financement_bancaire/README.md
T
Claude Code DTP Worker d6cc09da0d [DTP-Worker 20260805_081202] FIX RÉEL : le module crm/financement_bancaire s'auto-étiquetait « Sprint 5 » dans une CITATION ROADMAP-GLOBALE (roadmap L52) alors que L52 ∈ Sprint 4 → label corrigé S5→S4 sur ses 2 seules surfaces manuscrites (README:3 prose + gen.py:4 docstring) · clôt le SIGNAL surfacé non tranché par la session 071201
- Finding : ligne 3 du README « Sprint 5 · roadmap L52 (workflow vente end-to-end · volet financement) » = citation roadmap-GLOBALE (cite L52 + reprend le texte du deliverable S4), PAS un cadre agent-interne → tranchée fausse par 4 autorités concordantes :
  · fichier roadmap : ## SPRINT 4 = L48, deliverable L52 ; ## SPRINT 5 = L54 « ONAPI + Compliance + Mobile » (rien à voir) → « Sprint 5 · roadmap L52 » auto-contradictoire
  · autorité byte-gatée acceptance_spec.json (partition INV5) : crm/financement_bancaire ∈ S4 · roadmap_line 52
  · 3 modules frères du bucket S4 tous « Sprint 4 » (workflow_vente/dossier_vente/commissions · L51-52) → financement seul outlier
  · fiche 03_agents/crm/AGENT.md liste déjà « 4 (roadmap L52) » → le module contredisait sa propre fiche
- Provenance surfacée non éditée : DIRECTIVE Michel :140 cadre « [Sprint 5 · Financement] » (son snapshot d'entrée) transcrit à tort dans un slot roadmap-global ; directive laissée INTACTE (input immuable, comme daily_reports)
- Balayage exhaustif : exactement 2 surfaces manuscrites (README:3 + gen.py:4) ; aucun spec/artefact/out/gate ne porte de champ sprint → build ne régénère aucun artefact (check_artifacts vert)
- 0 gate ajouté (#5 · label sprint = piège à 2 cadres légitimes, gate aveugle = faux positifs sur frames agent-internes) · 0 édition d'autorité (acceptance disait déjà S4) · 0 chiffre inventé (#6) · 0 commande VPS (#8) · CI 33 PASS

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-05 08:16:29 +00:00

112 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Financement Bancaire · parcours hypothécaire immobilier RD
**Sprint 4 · CRM natif ERPNext · roadmap L52 (workflow vente end-to-end · volet
financement).** Matérialise la
[`DIRECTIVE_FINANCEMENT_BANCAIRE_COMPLET_20260803.md`](../../../DIRECTIVE_FINANCEMENT_BANCAIRE_COMPLET_20260803.md)
(Michel, 2026-08-03) : un module **complet** de financement bancaire pour un vrai
parcours hypothécaire dominicain, à la place du module « trop simpliste »
antérieur. Livrable **Phase 1 (P0 · MVP)** : le contrat de données + le **cœur
métier du gate check** + la structure des 6 sections + la bannière critique.
> Ce worker **n'écrit jamais sur le VPS** (contrainte #8). Il produit le contrat
> et les artefacts en-repo ; le backend `/api/hypotheque/*` et le frontend
> `renderHypotheque` réels sont appliqués côté serveur (agents ERPNext Backend /
> Frontend Console). La **Phase 2** (vrais formulaires PDF des 6 banques) attend
> les démarches relationship-manager de Michel — hors périmètre worker.
## Le cœur du livrable · le gate check 4 conditions
L'exigence non-négociable de Michel : **aucun document n'est transmis à la banque**
tant que **les 4 conditions** ne sont pas remplies. La logique vit dans
[`finlib/gate.py`](finlib/gate.py) — fonctions **pures**, testées, sans I/O :
| # | Condition (`key`) | Règle vérifiée |
|---|---|---|
| 1 | `apport_initial_complet` | `Σ paiements ≥ prix × taux`**20 % résident RD · 30 % étranger** (amendement Michel · aussi exigence des banques RD · Ley 189-11). |
| 2 | `documents_exiges` | Tous les documents `is_required` de la banque choisie au statut **« Validé WAG »** ou **« Envoyé banque »**. |
| 3 | `autorisations_signees` | Toutes les autorisations signées (`signature_date` non nulle). |
| 4 | `validation_wag` | Un conseiller WAG référent a validé (`wag_validated_by`). |
```python
from finlib import gate
cfg = gate.GateConfig.from_spec(spec)
ok, reasons = gate.can_submit_dossier(dossier, cfg) # (False, ["Apport initial incomplet : …", …])
status = gate.gate_status(dossier, cfg) # forme de l'endpoint gate-status (barres 0-100 %)
```
Si **une** condition manque, `can_submit` est `False` et `reasons` liste chaque
blocage (ordre canonique). Le backend `POST /…/submit` doit renvoyer **403 + ces
raisons** ; le frontend grise le bouton « Envoyer à la banque » et affiche une
barre de progression par condition. Tant que l'**apport initial** est incomplet,
toutes les sections aval sont **grisées** (section `apport_initial` = seule
section `gating`, en position 1).
## Ce qui est généré (`out/`, commité — hand-off direct)
| Fichier | Contenu |
|---|---|
| `banques.json` | Profils des banques partenaires (type, taux/LTV/durée, spécialités, devises). |
| `sections.json` | Structure accordéon (apport → info achat → choix banque → formulaires → exigences → autorisations → envoi). |
| `documents.json` | Catalogue des documents exigés par catégorie (client / immobilier / étrangers). |
| `autorisations.json` | Autorisations à signer (OTO Sign) + base légale. |
| `gate_spec.json` | Les 4 conditions + **bannière critique** + endpoints + rôle validation résolu + workflow suivi banque. |
| `gate_status_example.json` | Exemple **calculé** (dossier P07 volontairement bloqué) — auditable, jamais fabriqué. |
| `MANIFEST.json` | Traçabilité (sources, comptes dérivés, rôles RBAC utilisés). |
Comptes courants (source de vérité = `MANIFEST.json`) : **6 banques**,
**7 sections**, **15 documents** (requis **9** résident · **13** étranger),
**4 autorisations**, **4 conditions** de gate.
## Anti-invention (#6)
- **Aucun taux d'apport codé en dur** : 20/30 viennent du contrat
(`apport.residence_types`), sourcés de la DIRECTIVE. Changer le contrat change
le gate, sans toucher au code.
- **Aucun taux/LTV bancaire fabriqué** : les fourchettes non données par la
DIRECTIVE restent `null` (`a_confirmer` · démarche relationship manager). Seules
les valeurs que la DIRECTIVE énonce (ex. Scotiabank LTV 70 %, BHD León 30 ans)
sont encodées.
- **Aucun nom de rôle Frappe en dur** : les rôles (`ventes-conseiller` pour la
validation WAG, etc.) sont résolus depuis
[`rbac_50_roles.json`](../../rbac/rbac_50_roles.json) via `finlib/rbac.py`
(source unique · zéro duplication · #5).
## Validation · schéma + 12 invariants
`validate` re-génère le bundle en mémoire et vérifie le schéma de sortie
([`financement.schema.json`](financement.schema.json)) **plus 12 invariants**
métier (unicité des ids ; `0 < résident < étranger ≤ 100` ; fourchettes banque
`min ≤ max` ; rôles résolus dans RBAC ; sections contiguës + section gating en
tête ; gate = 4 conditions alignées sur la bannière ; documents étrangers
strictement additionnels ; statuts recevables ⊆ statuts ; exemple de gate
recalculé cohérent ; comptes du manifeste cohérents). Un invariant qui casse
**refuse** le build (anti-régression).
## Utilisation
```bash
cd 05_deliverables_mvp/crm/financement_bancaire
python3 financement_bancaire_gen.py validate # schéma + 12 invariants
python3 financement_bancaire_gen.py build # écrit les 7 artefacts out/
python3 -m unittest discover -s tests -v # suite (gate + générateur)
```
Sortie **déterministe** (tri stable, aucun horodatage) → l'artefact commité est
reproductible bit-à-bit et vérifié par `ci/check_artifacts.sh`.
## Endpoints backend visés (Phase 1 · à implémenter côté serveur)
Contrat exposé par `gate_spec.json` :
- `GET /api/hypotheque/banques` · profils banques (⇐ `banques.json`)
- `GET /api/hypotheque/dossier/{id}/gate-status` · état des 4 conditions (forme de `gate_status_example.json`)
- `POST /api/hypotheque/dossier/{id}/submit` · **403 + raisons** tant que le gate n'est pas vert
- `GET /api/hypotheque/dossier/{id}/journal` · historique horodaté
## Périmètre
-**Phase 1 (ce module)** : contrat, gate check, sections, bannière, exemple calculé.
-**Phase 2 (hors worker)** : vrais formulaires PDF officiels des 6 banques
(démarche relationship-manager Michel) + implémentation runtime des endpoints /
du `renderHypotheque` côté VPS.