Fusionner la phase base de donnees (statut par utilisateur, table Auteur)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -310,20 +310,47 @@ Compilation **locale**, puis dépôt manuel de l'archive en release sur le Gitea
|
||||
|
||||
**Ne jamais compiler sur le serveur** à l'installation : cela imposerait le SDK .NET complet sur la machine YunoHost, pour une compilation lente — l'inverse exact de ce que permet le self-contained.
|
||||
|
||||
## Modèle de données (base de départ, à affiner)
|
||||
## Modèle de données
|
||||
|
||||
Schéma en vigueur depuis la migration `StatutPersonnelEtTableAuteurs` (2026-08-18).
|
||||
|
||||
```
|
||||
Livre
|
||||
├── Id
|
||||
├── Isbn
|
||||
├── Isbn (index)
|
||||
├── Titre
|
||||
├── Auteur
|
||||
├── TitreNormalise (index — minuscules sans accents, recalculé à chaque écriture)
|
||||
├── Editeur
|
||||
├── Format : Physique | Numerique
|
||||
├── Statut : ALire | EnCours | Lu
|
||||
├── CoverUrl
|
||||
├── DateAjout
|
||||
└── AjoutePar (YNH_USER — traçabilité, PAS un cloisonnement)
|
||||
⚠ pas de colonne Statut, pas de colonne Auteur
|
||||
|
||||
Auteur
|
||||
├── Id
|
||||
├── Nom (affichage : « Émile Zola »)
|
||||
├── NomNormalise (index — recherche : « emile zola »)
|
||||
└── CleRegroupement (index UNIQUE — mots normalisés triés : « emile zola »)
|
||||
|
||||
LivreAuteur (n-n : un livre peut avoir plusieurs auteurs)
|
||||
├── LivreId ─┐ clé primaire composite
|
||||
├── AuteurId ─┘ FK Livre = cascade, FK Auteur = restrict
|
||||
└── Position (rang sur la couverture, à partir de 0)
|
||||
|
||||
StatutLecture (le statut est PERSONNEL)
|
||||
├── Id
|
||||
├── LivreId (FK vers Livre, cascade)
|
||||
├── Utilisateur (YNH_USER)
|
||||
├── Statut : ALire | EnCours | Lu
|
||||
├── DateMaj
|
||||
└── UNIQUE (LivreId, Utilisateur)
|
||||
absence de ligne = « non commencé »
|
||||
|
||||
RapprochementRefuse (mémoire des « non » de l'utilisateur)
|
||||
├── Id
|
||||
├── AuteurAId ─┐ UNIQUE, couple toujours rangé (petit Id d'abord)
|
||||
└── AuteurBId ─┘ pour qu'un refus vaille dans les deux sens
|
||||
|
||||
Pret
|
||||
├── Id
|
||||
@@ -341,6 +368,26 @@ Garder `Pret` comme table séparée (pas un champ sur `Livre`) pour conserver l'
|
||||
|
||||
**L'auteur n'est plus un champ texte sur `Livre`.** Une table dédiée porte le nom d'affichage et une forme normalisée servant au regroupement et à la recherche. Le regroupement automatique ne s'applique qu'aux variantes **sûres** (casse, accents, initiales, ordre nom/prénom) ; les rapprochements ambigus — « Hamilton » seul vers « Peter F. Hamilton » — doivent être **proposés**, jamais appliqués silencieusement : une fusion erronée est difficile à défaire.
|
||||
|
||||
### Recherche sans accents : pourquoi des colonnes normalisées
|
||||
|
||||
**SQLite ne sait pas ignorer les accents.** Sa collation `NOCASE` ne couvre que l'ASCII et il n'existe pas de `unaccent()` intégré. La seule façon d'obtenir « Emile » → « Émile » sans charger tout le catalogue en mémoire est de stocker la forme mise à plat dans une colonne dédiée, et d'y chercher un terme passé par **exactement la même** fonction (`NormalisationTexte`).
|
||||
|
||||
Conséquence à ne pas oublier : **toute écriture doit recalculer ces colonnes** (`Livre.RecalculerFormes()`, `Auteur.RecalculerFormes()`).
|
||||
|
||||
Deux formes cohabitent sur `Auteur`, et ce n'est pas une redondance :
|
||||
|
||||
- `NomNormalise` garde l'ordre de saisie — c'est ce que la recherche parcourt en sous-chaîne ;
|
||||
- `CleRegroupement` trie les mots, ce qui rend `Zola, Émile` et `Émile Zola` identiques. C'est elle qui porte l'index **unique**, donc l'invariant « un auteur, une fiche ».
|
||||
|
||||
La clé ne sait pas rapprocher les **initiales** (`P.F. Hamilton` ↔ `Peter F. Hamilton`) : cela demande d'aligner les mots un à un, ce qui n'a pas d'équivalent SQL. Ce cas est traité en mémoire par `RapprochementAuteurs.Comparer`, sur une table qui compte au plus quelques centaines de lignes.
|
||||
|
||||
### Reprise des données existantes
|
||||
|
||||
La migration recopie l'ancien contenu avec les moyens du bord, puis **`ServiceRenormalisation` finit le travail en C# au démarrage** — idempotent, il sert aussi de filet si les règles de normalisation changent un jour.
|
||||
|
||||
- L'ancien `Livres.Statut`, commun à tout le foyer, est **rattaché à `AjoutePar`**, seule personne que la base associe au livre. Les statuts des livres sans `AjoutePar` sont **perdus** : les attribuer serait une invention.
|
||||
- L'ancien `Livres.Auteur` devient une fiche par valeur distincte. SQLite ne regroupant qu'à la casse près, les variantes accentuées ressortent en double — c'est le passage C# qui les réunit, en gardant le nom d'affichage le plus présentable (accents conservés, ni `NOM, Prénom` ni capitales intégrales).
|
||||
|
||||
**Les prêts ne concernent en pratique que les livres physiques** — les ebooks étant de simples fiches, il n'y a pas d'objet à prêter. `Emprunteur` reste un **texte libre**, sans lien avec les comptes YunoHost : on suit les prêts à des personnes extérieures au foyer, pas les échanges entre utilisateurs de l'app.
|
||||
|
||||
## Historique du projet (pourquoi ces choix)
|
||||
|
||||
Reference in New Issue
Block a user