Appearance
BDD-137 — Fix le rechargement d'une source type API référençant les fiches
1. User Story
En tant qu'administrateur, je veux recharger une source à partir d'une Fiche d'une connexion API (en plus des Formulaires), afin d'accéder aux données à jour.
Ce ticket est un correctif du rechargement des sources API [BDD-119] : aujourd'hui nous pouvons recharger une source dont l'origine API est typée comme un formulaire, mais pas comme une fiche, où le message d'erreur « Source ou fichier introuvable. » s'affiche.
2. Critères d'acceptance
| # | Critère | Statut |
|---|---|---|
| 1 | Depuis /sources, depuis le rechargement d'une source API, je dois pouvoir aussi bien recharger les données d'un formulaire que les données d'une fiche | ✅ |
3. Périmètre fonctionnel
Backend — outil-bdd (Sources)
| Fichier | Rôle |
|---|---|
back/prisma/schema.prisma | Nouveau. Enum ApiResourceType (form | card) + colonne sources.api_resource_type (nullable) |
sql/tool_25_add_api_resource_type_to_sources.sql | Nouveau. Migration SQL correspondante (CREATE TYPE + ADD COLUMN IF NOT EXISTS) |
back/src/api/sources/sources.service.ts | buildApiFormSourceContext persiste désormais api_resource_type à la création ; reloadApiFormSource branche loadCardSubmissions ou loadFormResponses selon ce champ au lieu d'appeler systématiquement loadFormResponses |
back/src/api/sources/sources.service.spec.ts | Tests création (assertion api_resource_type persisté) + nouveau test de rechargement d'une source fiche |
Backend — formulaires (Export)
| Fichier | Rôle |
|---|---|
back/src/export/export.service.ts | buildCardSubmissionsTable calculait un filtre where scopé à la fiche mais ne le transmettait jamais à submissionService.getSubmissions (qui reconstruit son propre where à partir de query.filters) — les soumissions de toutes les fiches de l'entreprise remontaient au lieu de celles de la fiche demandée. Ajout de card: { uuid } dans filters (même mécanisme que le chemin formulaire et que le front), suppression du where mort et des console.log de debug laissés en place |
4. Détail des correctifs
A. Persistance du type de ressource API (formulaire vs fiche)
- Avant :
source_typevalait toujoursAPI_FORM, qu'il s'agisse d'un formulaire ou d'une fiche — l'UUID de la ressource atterrissait dans la même colonneform_uuid. Aucune trace du type d'origine n'était conservée après la création. Au rechargement,reloadApiFormSourceappelait donc systématiquementconnectionBrowse.loadFormResponses, qui renvoie 404 (ApiConnectionFormNotFoundException) quand l'UUID est en réalité celui d'une fiche. - Après : un champ dédié
api_resource_type('form' | 'card') est persisté à la création (buildApiFormSourceContext) et relu au rechargement pour choisir le bon appel (loadCardSubmissionsvsloadFormResponses). - Alternative envisagée et écartée : ajouter une valeur
API_CARDà l'enumSourceType, conformément à l'intention initiale de [BDD-119]. Écartée au profit d'un champ séparé carsource_typerépond à « d'où viennent les données » (document / API / workflow) alors queapi_resource_typerépond à « quelle ressource API précisément » — deux axes distincts. Un nouveausource_typeaurait aussi obligé à élargir tous les testssourceType === 'API_FORM'déjà présents côté front (SourceReloadDialog.vue,SourceListItem.vue,WorkflowHeriadeSourcePanel.vue), qui restent valides tels quels avec un champ séparé. - Sources historiques : les sources fiche créées avant ce correctif ont
api_resource_type = NULL, traité comme'form'par le code (comportement identique à avant, aucune régression). Elles resteront en échec au rechargement tant qu'elles ne sont pas recréées — aucun backfill n'a été fait, la perte de ces quelques sources est acceptée.
B. Filtrage manquant sur l'export des soumissions d'une fiche (formulaires)
- Découvert pendant la vérification manuelle du correctif A : une fois le rechargement d'une fiche débloqué, les données remontées mélangeaient les soumissions de plusieurs fiches.
- Cause :
buildCardSubmissionsTablevérifiait que la fiche existait puis appelaitsubmissionService.getSubmissions(user, { where, filters: { ...filterQuery } })—whereétait calculé mais jamais utilisé (getSubmissionsreconstruit son proprewhereuniquement à partir dequery.filters), etfiltersne contenait aucune référence à la fiche demandée. - Correctif :
filters: { ...filterQuery, card: { uuid } }, à l'identique du chemin formulaire (filters: { ...filterQuery, form: { uuid, type: 'general' } }) et du front, qui utilise déjà cette forme (SubmissionCardPage.vue:{ card: { uuid: cardId } }). - Effet de bord positif : ce mélange de données inter-fiches provoquait aussi un plantage non maîtrisé au rechargement côté
outil-bdd(normalizeNumericValuededecimal.jslevant une erreur brute sur une valeur texte injectée dans une colonne inféréenumber), puisqu'une colonne majoritairement numérique récupérait occasionnellement une valeur texte issue d'une fiche différente.
5. Règles métier implémentées
- Le rechargement d'une source
API_FORMlitapi_resource_type(traité comme'form'si absent) pour choisir l'appel externe adéquat. attachConnection(rattachement à une autre connexion) n'a pas été modifié :source_typeresteAPI_FORMdans tous les cas, le filtre de recherche de la source n'avait donc pas besoin d'évoluer ;api_resource_typen'est pas touché par ce flux.- L'export/rechargement d'une fiche est désormais strictement scopé à la fiche demandée côté
formulaires.
6. Points de vérification
- Créer une source depuis une Fiche →
api_resource_typevautcarden base. - Recharger cette source → succès (plus de « Source ou fichier introuvable. »), et les données rechargées appartiennent uniquement à la fiche d'origine (plus de mélange inter-fiches).
- Recharger une source Formulaire existante → comportement inchangé (
loadFormResponses). - Une source fiche créée avant ce correctif (
api_resource_typeNULL) → comportement inchangé (tentative vialoadFormResponses, échoue toujours ; à recréer si besoin).
7. Tests associés
Backend outil-bdd (unitaires)
back/src/api/sources/sources.service.spec.ts:- persistance de
api_resource_type: 'form'/'card'à la création (formulaire et fiche) ; - nouveau test de rechargement : une source
api_resource_type: 'card'appelleloadCardSubmissionset n'appelle jamaisloadFormResponses. - 74 tests, tous verts.
- persistance de
Backend outil-bdd (e2e)
back/test/e2e/sources-controller.e2e-spec.ts— non modifié. La suite existante sur/reloadet/attach-connectionne couvre que les cas guard / validation / 404 (aucun scénario n'y crée ni ne recharge une vraie sourceAPI_FORM, ce qui nécessiterait de mocker l'appel externe Formulaires — hors périmètre de la suite actuelle). Le correctif ne change aucun de ces comportements.
Backend formulaires
- Pas de test ajouté :
ExportService/SubmissionServicen'ont aucune couverture de test existante dans ce dépôt (seulapp.controller.spec.tsgénéré par défaut), donc pas de convention à suivre. Correctif vérifié manuellement.
8. Notes d'implémentation
- Hors scope (volontairement) :
- garde
validateTypedColumnsmanquante dansreloadApiFormSource(présente danscreateSourcemais jamais portée au rechargement API) — un type de colonne inféré à tort peut toujours faire planternormalizeNumericValueavec une erreur brute non catchée. Générique aux deux types de ressource, pas spécifique fiche/formulaire, identifié mais non corrigé dans ce ticket ; - libellés front (
SourceListItem.vue,SourceReloadDialog.vue) distinguant visuellement « Formulaire » et « Fiche » —sourceTyperesteAPI_FORMpour les deux, ces libellés ne sont donc pas cassés, seulement pas différenciés davantage qu'avant ; - rattachement (
attachConnection) d'une source fiche vers une nouvelle ressource fiche explicite — le DTO n'accepte queformUuid, limitation déjà existante avant ce ticket.
- garde
9. Variables d'environnement
Aucune nouvelle variable.
