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_requestsloan_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 requiscorrigé 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 écranscorrigé 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).