Skip to content

[Refactor] M11-05 — Découper services & composants métier #185

Description

@donovan-dev-web

Objectif

Responsabilités claires, effets de bord isolés, composants maintenables.

Périmètre

  • src/backup/backup-service.ts (498) : découper export/import/validation, isolation fichiers
  • src/components/magazine-form.tsx (453) : logique formulaire vs présentation
  • src/app/(tabs)/collection/index.tsx (436) et src/app/scan/search.tsx (414) : listes/recherche découpées
  • src/components/drawer-content.tsx (419), src/app/scan/multiple.tsx (216)

Livrables

  • Modules < 350 lignes ; logique métier testée unitairement
  • Aucun changement de comportement
  • PR + CI verte

Activity

  1. donovan-dev-web commented on Sep 8, 2026

    @donovan-dev-web
    OwnerAuthor

    Points relayés depuis la revue complète du code (#183, PR #193 mergée) — 3 à traiter en priorité (criticité Élevée) :

    1. backup-service.ts:399-407 (Élevée) : round-trip CSV — une édition sans exemplaire émet des lignes vides réimportées en exemplaire fantôme daté d'aujourd'hui (dump ≠ restore).
    2. backup-service.ts:285-312 (Élevée) : import CSV — fusion par clé publication::issueNumber : perte de edition/language/condition, collapse des éditions à issueNumber null.
    3. migrations.ts:26-31 (Élevée) : migrations hors transaction — un échec partiel laisse du DDL appliqué avec user_version inchangé (relance bloquante).

    Puis, à intégrer au découpage :

    1. use-collection-store.ts:88-98 (Moyenne) : addMagazine = create() + addCopy() hors transaction ⇒ édition orpheline possible.
    2. magazine-repository.ts:136 (Moyenne) : LIKE sans échappement de %/_ (recherche % ⇒ tout le catalogue).
    3. backup-service.ts:443 + native-file-gateway.ts:70 (Moyenne) : aucune borne de taille d'import (parse 2× du fichier en mémoire).
    4. scanBarcode.ts:83-88 (Moyenne) : code 10 chiffres à checksum ISBN-10 invalide rejeté invalid (codes CODE39/ITF longs bloqués) — la doc annonce un repli GENERIC.
    5. result.tsx + search.tsx (Moyenne) : resolved/owned/handleAddCopy + styles ownedText/absentText dupliqués.
    6. barcode.tsx/camera.tsx/form-barcode.tsx (Moyenne, partagé avec [Refactor] M11-04 — Découper les gros écrans (camera.tsx 830, barcode.tsx 551) #184) : styles caméra dupliqués.
    7. _layout.tsx:25-31 + collection/index.tsx:100-106 (Mineure) : calcul de la liste d'éditions dupliqué.
    8. backup-service.ts (Mineures) : \r CRLF dans les champs CSV quotés ; contrôles JSON/CSV asymétriques (issueNumber fractionnaire accepté en JSON) ; dateAdded/exportedAt non validés ; created_at/updated_at non exportés (historique perdu à la restauration).
    9. magazine-repository.ts:101 (Mineure) : lower() SQLite = repli ASCII (accents) — prétraiter en JS.

    Rapport complet : commentaire sur #183.

  2. donovan-dev-web commented on Sep 8, 2026

    @donovan-dev-web
    OwnerAuthor

    Compléments relayés par la passe de validation complémentaire de #183 (2ᵉ revue exhaustive) :

    Élevées

    1. Erreurs non interceptées dans les flux scan/ajout/suppression — aucune surface d'erreur ni état de reprise (UI bloquée « Recherche… ») : scan/search.tsx:58-75 (search() sans try/finally), scan/barcode.tsx:99-115, scan/camera.tsx:95-173 (intervalle try/finally sans catch, rejet relancé toutes les 500 ms), result.tsx:49-52, search.tsx:101, barcode.tsx:82,127, collection/[id]/index.tsx:44,55. Prévoir surface d'erreur + retry dans identificationService/callers.
    2. Échec d'init DB permanent + écran vide : dependencies.ts:41-44 + _layout.tsx:33-42 (affecté aussi à [Refactor] M11-04 — Découper les gros écrans (camera.tsx 830, barcode.tsx 551) #184).

    Moyennes
    3. findByPublicationAndIssue renvoie la variante arbitraire (la plus ancienne) quand (publication, issue_number) est dupliqué (légal depuis v4) → identification OCR liée à la mauvaise édition (FR vs BE, autre barcode) — rendre le choix déterministe et visible.
    4. Ids d'éditions dupliqués en JSON : passent validateCollection puis font échouer toute la restauration (violation PK après résumé « n éditions ») — rejeter en validation (InvalidBackupError).
    5. created_at/h historique : déjà relayé, ré-évalué Moyenne (la date « Ajouté le » de toutes les éditions devient la date de restauration).

    Mineures (ici)
    6. asCsvString (backup-service.ts:236-239) : valeur renvoyée non trimmée (barcode avec espaces persisté) — cohérence avec la sémantique trim utilisée ailleurs.
    7. Parser CSV : \r nu hors guillemets perdu (L222-225).
    8. Regex ISBN-10 /^[0-9X]{10}$/ : X accepté à toute position (L83).
    9. Tri ORDER BY publication en collation BINARY (casse) + lower() ASCII uniquement (L101).

    Contexte complet : commentaire de validation sur #183.

  3. donovan-dev-web commented on Sep 8, 2026

    @donovan-dev-web
    OwnerAuthor

    ✅ Correctifs #185 livrés (PR #197, merge 355697e)

    Tous les points de revue #183/PR #193 sont traités :

    Base de données

    • E3 : chaque migration est transactionnelle (BEGIN → DDL → user_version → COMMIT, ROLLBACK + relance en cas d'échec) + tests (migrations.test.ts).
    • M1 : addMagazine atomique via createWithCopy (magazine + exemplaire dans une transaction).
    • M2 : recherche réécrite en JS — insensible aux accents/casse, %/_ littéraux, tri déterministe (localeCompare 'fr').

    Backup

    • E1 : plus de copie fantôme à l'import CSV si copyNotes et dateAdded sont vides.
    • E2 : l'édition publication::issueNumber::edition::language::condition préserve les variantes (Édition n° vs n° simple) et corrige le collapse des issueNumber nuls.
    • M9 : rejet des IDs dupliqués, issueNumber fractionnaire, dates non-ISO.
    • M3 : import plafonné à 25 Mo (service + sélecteur de fichier).
    • M10 : created_at/updated_at exportés/importés (JSON + CSV rétro-compatible).
    • Mineures : trim des champs texte, CRLF/retour-chariot seul gérés.

    Scan

    • M4 : ISBN-10 X toléré en dernière position uniquement, 10 chiffres à checksum invalide → GENERIC.
    • M5 : mutex résolu/possédé et styles de statut dédupliqués via useScanResult (partagé result/search) ; styles ownedText/absentText mutualisés.
    • M8 : findByPublicationAndIssue confirmé déterministe + test du choix de la plus ancienne.

    Vérifié : 458 tests OK, couverture 100 % backup/identification, CI Quality verte.

    M6 (styles caméra) reste partagé avec #184 — traité sur sa branche.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    epic/backupExport / Importepic/collectionAjout & collectionpriority-mediumPriorité normalerefactorRefactoring sans changement de comportementsize/mMoyenne (≤ 1 j)

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions