Files
Claude Code DTP Worker d7dbda9e2b [DTP-Worker 20260805_084202] FIX RÉEL : « 6 sections » périmé dans les 2 docs d'IMPLÉMENTATION de crm/financement_bancaire alors que le module en livre 7
Classe prose FACT count ungated (prose-facts-vs-numeric-drift). Défaut : README:9 « la structure des 6 sections » + fiche CRM AGENT.md:47 « cœur du gate + 6 sections » décrivaient le livrable avec un compte périmé. Le bon compte = 7 est triple-sourcé et byte-gaté : out/MANIFEST.json counts.sections=7 · financement_spec.json bloc sections=7 (apport_initial,info_achat,choix_banque,formulaires,exigences,autorisations,envoi) · et le README se contredisait lui-même (L49 énumère 7, L57 « 7 sections » annotée source=MANIFEST). Origine du 6 : la DIRECTIVE originale énumérait 6 sections non-gating puis fut amendée pour ajouter apport_initial (gating, pos.1) → 7 ; spec+module ont suivi, les 2 prose L9/L47 non.

Correctif 6→7 sur les 2 SEULES surfaces d'implémentation. Les 4 « 6 sections » restantes sont des snapshots directive gelés (DIRECTIVE_FINANCEMENT L106/122/131 + DIRECTIVE_WORKFLOW_V10 L22/47) — input-specs datés de Michel, jamais réécrits (directive-vs-implementation · spec=authority) ; leur « 6 » est exact au cadre pré-amendement → INTACTS.

0 gate ajouté (#5 · un gate structuré ne mordrait pas la prose L9, hors-cible ; SIGNAL surfacé : financement seul module dont MANIFEST.counts n'est pas recompté par check_readme_claims). 0 chiffre inventé (#6). 0 production éditée. 0 commande VPS (#8). run_ci.sh 33 PASS 0 FAIL 0 SKIP.

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

112 lines
6.1 KiB
Markdown
Raw Permalink 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 7 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.