Skip to main content

Configuration des prêts

backend/src/controllers/loan_document_requirements.controller.js + loan_field_requirements.controller.js + loan_parameters.controller.js + frontend/src/views/backoffice/LoanDocumentsConfigView.vue + LoanFieldsConfigView.vue.

Le formulaire public de prêt scolaire charge ses documents/champs/paramètres requis depuis ces trois tables, décrites comme "configurables côté backoffice" sans jamais expliquer comment — c'est l'objet de cette page.

Dernière vérification contre le code

Vérifié le 2026-08-13.

1. Trois tables indépendantes, sans lien entre elles​

  • loan_document_requirements : loan_type, label, is_required, is_active. Un document requis par type de prêt.
  • loan_field_requirements : loan_type, field_key, label, field_type, is_required, is_active. Un champ dynamique par type de prêt.
  • loan_parameters : loan_type (unique), interest_rate, max_duration, max_amount, default_amount, is_active. Un seul jeu de paramètres par type.

Aucune clé étrangère entre elles ni vers loan_requests — loan_type est une simple chaîne libre, pas un enum en base.

is_active = désactivation douce (le document/champ reste en base mais disparaît du formulaire public). is_required = obligatoire ou optionnel. Pas de champ d'ordre : l'affichage backoffice trie par created_at desc, le formulaire public par created_at asc — ordres incohérents entre les deux écrans, et aucun réordonnancement manuel n'est possible.

2. field_key — généré côté frontend, jamais vérifié côté backend​

LoanFieldsConfigView.vue génère automatiquement field_key depuis le libellé saisi (slug ASCII, préfixe client_), et fige ce champ (non modifiable) une fois affiché. Le backend n'impose aucune contrainte d'unicité sur field_key pour un même loan_type — deux champs avec la même clé peuvent coexister silencieusement, avec des conséquences imprévisibles côté additional_data.fields (une clé écrase l'autre selon l'ordre de saisie du client).

3. loan_parameters​

Auto-seed au premier GET si la table est vide, avec des valeurs par défaut codées en dur pour 5 types (immo, auto, conso, scolaire, bancassurance). Modifiable uniquement via PUT /api/loan-parameters/:id (protégé verifyToken, corrigé le 2026-08-13 — voir ci-dessous) — loan_type, label et icon ne sont pas modifiables via cet endpoint, seuls interest_rate, max_duration, max_amount, default_amount, is_active le sont. Pas de création possible : les 5 types sont figés à la liste seedée.

Corrigé le 2026-08-13

loan_parameters.routes.js n'appliquait aucun middleware sur PUT /:id, contrairement aux deux autres routers de config — n'importe qui pouvait modifier un taux d'intérêt ou un plafond de prêt sans authentification. verifyToken a été ajouté sur PUT uniquement ; GET reste public (consommé par les formulaires publics).

4. Aucune protection contre la casse d'un formulaire en production​

Supprimer un document ou un champ requis (DELETE) ne vérifie jamais si des demandes existantes référencent déjà ce field_key dans additional_data.fields, ni si des documents déjà uploadés correspondent à cette pièce. Seule trace : une entrée dans le journal d'activité après coup, aucune contrainte bloquante avant suppression.

5. Pièges connus pour un futur développeur​

  1. Bug de routing sur la suppression d'un document requis — corrigé le 2026-08-13 (LoanDocumentsConfigView.vue appelait DELETE /loan-requirements/:id au lieu de /loan-document-requirements/:id).
  2. loan_document_requirements (verifyToken seul) vs loan_field_requirements (isSuperAdmin) — corrigé le 2026-08-13 : les deux exigent désormais uniformément verifyToken seul (la restriction isSuperAdmin a été retirée de loan_field_requirements, pas ajoutée à l'autre — décision : cohérence avec la sensibilité réelle de cette configuration, pas de raison de la réserver aux SUPER_ADMIN).
  3. bancassurance non configurable depuis ces écrans — corrigé le 2026-08-13 : bancassurance ajouté à loanTypes dans LoanDocumentsConfigView.vue et LoanFieldsConfigView.vue (liste codée en dur côté frontend, qui l'omettait alors que loan_parameters gérait déjà ce type).