diff --git a/CLAUDE.md b/CLAUDE.md
index 9def96c..51d2d32 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -708,6 +708,70 @@ 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.
+## ⚠️ Les migrations ont été FUSIONNÉES en une seule (2026-08-22)
+
+`MaBibli.Api/Data/Migrations/` ne contient plus qu'**une** migration, `InitialCreate`,
+là où quinze se succédaient. Décidé avec l'utilisateur avant la sortie du projet.
+
+⚠️ **Ce fichier cite une dizaine de migrations par leur nom** — `StatutPersonnelEtTableAuteurs`,
+`RangDesEnvies`, `TypeDeDocument`, `SagasEtCycles`, `Revues`, `RolesDesAuteurs`,
+`ImagesEtUnesDesNumeros`, `NombreDePages`, `EnviesDeRevues`… **Ces noms n'existent plus
+comme fichiers.** Ils restent utiles : ils datent une décision et disent dans quel ordre le
+modèle s'est construit. Les lire comme de l'**histoire**, jamais comme des fichiers à ouvrir.
+
+### Ce que la fusion coûte, et qui était le prix à payer
+
+⚠️ **Aucune base antérieure n'est plus migrable.** `__EFMigrationsHistory` d'une
+installation existante contient les quinze anciens noms ; au démarrage, EF Core verrait
+`InitialCreate` non appliquée et tenterait de créer des tables déjà présentes. La mise à
+jour échouerait, **et son retour arrière aussi**.
+
+**La seule voie sur un serveur déjà installé est donc `yunohost app remove mabibli --purge`
+puis une réinstallation**, avec perte du catalogue. ⚠️ Sans le `--purge`, `data_dir` survit
+(c'est documenté plus haut) et l'ancienne base revient avec son historique incompatible —
+le symptôme serait alors incompréhensible.
+
+⚠️ **Deux SQL de reprise de données ont disparu avec leurs migrations** :
+`StatutPersonnelEtTableAuteurs` (recopie de l'ancien `Statut` et de l'ancien `Auteur`
+texte) et `RangDesEnvies` (reconduction de l'ordre d'affichage des envies). Sans objet sur
+une base vierge, mais leur perte est définitive. `MigrationRangDesEnviesTests`, qui migrait
+jusqu'à `ListeDEnvies` pour éprouver le second, a été supprimé : 628 tests → **626**.
+
+### La fusion a été vérifiée, pas supposée
+
+Le schéma des quinze migrations et celui de `InitialCreate` ont été appliqués sur deux
+bases SQLite vierges, puis comparés :
+
+| | Résultat |
+|---|---|
+| Colonnes (nom, type, NOT NULL, PK) | **97 des deux côtés, aucun écart** |
+| Index | **27 des deux côtés, aucun écart** |
+| Clés étrangères et modes `ON DELETE` | **11 des deux côtés, aucun écart** |
+
+Les `SET NULL` d'`ElementsSerie.LivreId` et de `Series.SerieParenteId`, le `RESTRICT` de
+`LivreAuteurs.AuteurId`, les trois index uniques **partiels** et les **deux** index qui
+cohabitent sur `Prets.LivreId` sont tous préservés.
+
+⚠️ **Deux écarts subsistent, tous deux sans effet, et il faut savoir pourquoi** :
+
+- **l'ordre physique des colonnes** diffère — les colonnes ajoutées par `AddColumn` se
+ rangeaient en fin de table, elles sont maintenant à leur place logique. SQLite accède par
+ nom ;
+- **les `DEFAULT 0`** de `Role`, `TypeDocument` et `Rang` ont disparu. Ils n'existaient que
+ pour remplir les lignes **déjà présentes** au moment de l'ajout de colonne. Sur une table
+ neuve il n'y a rien à remplir, et EF fournit toujours la valeur à l'insertion. ⚠️ En
+ revanche un `INSERT` en **SQL brut** omettant ces colonnes échouerait désormais — à savoir
+ si un test venait à en écrire un.
+
+Vérifié en exécution sur une base créée de zéro : 18 tables, l'unique migration inscrite
+dans `__EFMigrationsHistory`, création d'un livre (201), recherche sans accents
+(« emile » → « Émile Zola »), prêt (201), et second prêt **refusé** (400) — l'index unique
+partiel tient.
+
+⚠️ **La base de développement garnie a été perdue** dans l'opération (son historique de
+migrations était incompatible). Ce fichier la notait comme utile aux vérifications d'écran :
+elle est à regarnir avant le prochain balayage.
+
## Modèle de données
Schéma en vigueur depuis la migration `StatutPersonnelEtTableAuteurs` (2026-08-18).
diff --git a/MaBibli.Api/Data/Migrations/20260817195059_InitialCreate.Designer.cs b/MaBibli.Api/Data/Migrations/20260817195059_InitialCreate.Designer.cs
deleted file mode 100644
index c9eb49d..0000000
--- a/MaBibli.Api/Data/Migrations/20260817195059_InitialCreate.Designer.cs
+++ /dev/null
@@ -1,108 +0,0 @@
-//
-using System;
-using MaBibli.Api.Data;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-
-#nullable disable
-
-namespace MaBibli.Api.Data.Migrations
-{
- [DbContext(typeof(MaBibliDbContext))]
- [Migration("20260817195059_InitialCreate")]
- partial class InitialCreate
- {
- ///
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder.HasAnnotation("ProductVersion", "10.0.11");
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Livre", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("AjoutePar")
- .HasColumnType("TEXT");
-
- b.Property("Auteur")
- .HasColumnType("TEXT");
-
- b.Property("CoverUrl")
- .HasColumnType("TEXT");
-
- b.Property("DateAjout")
- .HasColumnType("TEXT");
-
- b.Property("Editeur")
- .HasColumnType("TEXT");
-
- b.Property("Format")
- .HasColumnType("INTEGER");
-
- b.Property("Isbn")
- .HasColumnType("TEXT");
-
- b.Property("Statut")
- .HasColumnType("INTEGER");
-
- b.Property("Titre")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex("Isbn");
-
- b.ToTable("Livres");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Pret", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("DatePret")
- .HasColumnType("TEXT");
-
- b.Property("DateRetour")
- .HasColumnType("TEXT");
-
- b.Property("Emprunteur")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("LivreId")
- .HasColumnType("INTEGER");
-
- b.HasKey("Id");
-
- b.HasIndex("LivreId");
-
- b.ToTable("Prets");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Pret", b =>
- {
- b.HasOne("MaBibli.Shared.Entites.Livre", "Livre")
- .WithMany("Prets")
- .HasForeignKey("LivreId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Livre");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Livre", b =>
- {
- b.Navigation("Prets");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/MaBibli.Api/Data/Migrations/20260817195059_InitialCreate.cs b/MaBibli.Api/Data/Migrations/20260817195059_InitialCreate.cs
deleted file mode 100644
index 8de8b11..0000000
--- a/MaBibli.Api/Data/Migrations/20260817195059_InitialCreate.cs
+++ /dev/null
@@ -1,78 +0,0 @@
-using System;
-using Microsoft.EntityFrameworkCore.Migrations;
-
-#nullable disable
-
-namespace MaBibli.Api.Data.Migrations
-{
- ///
- public partial class InitialCreate : Migration
- {
- ///
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.CreateTable(
- name: "Livres",
- columns: table => new
- {
- Id = table.Column(type: "INTEGER", nullable: false)
- .Annotation("Sqlite:Autoincrement", true),
- Isbn = table.Column(type: "TEXT", nullable: true),
- Titre = table.Column(type: "TEXT", nullable: false),
- Auteur = table.Column(type: "TEXT", nullable: true),
- Editeur = table.Column(type: "TEXT", nullable: true),
- Format = table.Column(type: "INTEGER", nullable: false),
- Statut = table.Column(type: "INTEGER", nullable: false),
- CoverUrl = table.Column(type: "TEXT", nullable: true),
- DateAjout = table.Column(type: "TEXT", nullable: false),
- AjoutePar = table.Column(type: "TEXT", nullable: true)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_Livres", x => x.Id);
- });
-
- migrationBuilder.CreateTable(
- name: "Prets",
- columns: table => new
- {
- Id = table.Column(type: "INTEGER", nullable: false)
- .Annotation("Sqlite:Autoincrement", true),
- LivreId = table.Column(type: "INTEGER", nullable: false),
- Emprunteur = table.Column(type: "TEXT", nullable: false),
- DatePret = table.Column(type: "TEXT", nullable: false),
- DateRetour = table.Column(type: "TEXT", nullable: true)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_Prets", x => x.Id);
- table.ForeignKey(
- name: "FK_Prets_Livres_LivreId",
- column: x => x.LivreId,
- principalTable: "Livres",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- });
-
- migrationBuilder.CreateIndex(
- name: "IX_Livres_Isbn",
- table: "Livres",
- column: "Isbn");
-
- migrationBuilder.CreateIndex(
- name: "IX_Prets_LivreId",
- table: "Prets",
- column: "LivreId");
- }
-
- ///
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.DropTable(
- name: "Prets");
-
- migrationBuilder.DropTable(
- name: "Livres");
- }
- }
-}
diff --git a/MaBibli.Api/Data/Migrations/20260818000335_StatutPersonnelEtTableAuteurs.Designer.cs b/MaBibli.Api/Data/Migrations/20260818000335_StatutPersonnelEtTableAuteurs.Designer.cs
deleted file mode 100644
index 0cac4c6..0000000
--- a/MaBibli.Api/Data/Migrations/20260818000335_StatutPersonnelEtTableAuteurs.Designer.cs
+++ /dev/null
@@ -1,242 +0,0 @@
-//
-using System;
-using MaBibli.Api.Data;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-
-#nullable disable
-
-namespace MaBibli.Api.Data.Migrations
-{
- [DbContext(typeof(MaBibliDbContext))]
- [Migration("20260818000335_StatutPersonnelEtTableAuteurs")]
- partial class StatutPersonnelEtTableAuteurs
- {
- ///
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder.HasAnnotation("ProductVersion", "10.0.11");
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Auteur", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("CleRegroupement")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("Nom")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("NomNormalise")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex("CleRegroupement")
- .IsUnique();
-
- b.HasIndex("NomNormalise");
-
- b.ToTable("Auteurs");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Livre", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("AjoutePar")
- .HasColumnType("TEXT");
-
- b.Property("CoverUrl")
- .HasColumnType("TEXT");
-
- b.Property("DateAjout")
- .HasColumnType("TEXT");
-
- b.Property("Editeur")
- .HasColumnType("TEXT");
-
- b.Property("Format")
- .HasColumnType("INTEGER");
-
- b.Property("Isbn")
- .HasColumnType("TEXT");
-
- b.Property("Titre")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("TitreNormalise")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex("Isbn");
-
- b.HasIndex("TitreNormalise");
-
- b.ToTable("Livres");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.LivreAuteur", b =>
- {
- b.Property("LivreId")
- .HasColumnType("INTEGER");
-
- b.Property("AuteurId")
- .HasColumnType("INTEGER");
-
- b.Property("Position")
- .HasColumnType("INTEGER");
-
- b.HasKey("LivreId", "AuteurId");
-
- b.HasIndex("AuteurId");
-
- b.ToTable("LivreAuteurs");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Pret", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("DatePret")
- .HasColumnType("TEXT");
-
- b.Property("DateRetour")
- .HasColumnType("TEXT");
-
- b.Property("Emprunteur")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("LivreId")
- .HasColumnType("INTEGER");
-
- b.HasKey("Id");
-
- b.HasIndex("LivreId");
-
- b.ToTable("Prets");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.RapprochementRefuse", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("AuteurAId")
- .HasColumnType("INTEGER");
-
- b.Property("AuteurBId")
- .HasColumnType("INTEGER");
-
- b.HasKey("Id");
-
- b.HasIndex("AuteurAId", "AuteurBId")
- .IsUnique();
-
- b.ToTable("RapprochementsRefuses");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.StatutLecture", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("DateMaj")
- .HasColumnType("TEXT");
-
- b.Property("LivreId")
- .HasColumnType("INTEGER");
-
- b.Property("Statut")
- .HasColumnType("INTEGER");
-
- b.Property("Utilisateur")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex("Utilisateur");
-
- b.HasIndex("LivreId", "Utilisateur")
- .IsUnique();
-
- b.ToTable("StatutsLecture");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.LivreAuteur", b =>
- {
- b.HasOne("MaBibli.Shared.Entites.Auteur", "Auteur")
- .WithMany("Livres")
- .HasForeignKey("AuteurId")
- .OnDelete(DeleteBehavior.Restrict)
- .IsRequired();
-
- b.HasOne("MaBibli.Shared.Entites.Livre", "Livre")
- .WithMany("Auteurs")
- .HasForeignKey("LivreId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Auteur");
-
- b.Navigation("Livre");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Pret", b =>
- {
- b.HasOne("MaBibli.Shared.Entites.Livre", "Livre")
- .WithMany("Prets")
- .HasForeignKey("LivreId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Livre");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.StatutLecture", b =>
- {
- b.HasOne("MaBibli.Shared.Entites.Livre", "Livre")
- .WithMany("Statuts")
- .HasForeignKey("LivreId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Livre");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Auteur", b =>
- {
- b.Navigation("Livres");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Livre", b =>
- {
- b.Navigation("Auteurs");
-
- b.Navigation("Prets");
-
- b.Navigation("Statuts");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/MaBibli.Api/Data/Migrations/20260818000335_StatutPersonnelEtTableAuteurs.cs b/MaBibli.Api/Data/Migrations/20260818000335_StatutPersonnelEtTableAuteurs.cs
deleted file mode 100644
index 5a20fac..0000000
--- a/MaBibli.Api/Data/Migrations/20260818000335_StatutPersonnelEtTableAuteurs.cs
+++ /dev/null
@@ -1,278 +0,0 @@
-using System;
-using Microsoft.EntityFrameworkCore.Migrations;
-
-#nullable disable
-
-namespace MaBibli.Api.Data.Migrations
-{
- ///
- /// Sort le statut de lecture et l'auteur de la table Livres.
- ///
- ///
- /// Ce que deviennent les données existantes.
- ///
- /// -
- /// Livres.Statut était commun à tout le foyer. Il est rattaché à
- /// AjoutePar, la seule personne que la base associe au livre. Les statuts des
- /// livres sans AjoutePar (saisis sans identité) sont perdus : les attribuer à
- /// quelqu'un serait une invention, et les garder pour tout le monde serait exactement le
- /// défaut que cette migration corrige. Les trois valeurs sont reprises telles quelles, « À
- /// lire » compris : c'est ce que l'ancienne interface affichait, et le taire changerait ce
- /// que l'utilisateur voit.
- ///
- /// -
- /// Livres.Auteur devient une ligne de Auteurs par valeur distincte, plus un lien
- /// en position 0. Le regroupement se fait ici sur une simple mise en minuscules — SQLite ne
- /// sait pas retirer les accents. La normalisation complète, et la fusion des variantes qu'elle
- /// révèle, sont faites en C# au démarrage suivant (voir ServiceRenormalisation).
- ///
- ///
- /// L'ordre des opérations compte : tout est recopié avant que les anciennes colonnes
- /// ne soient supprimées.
- ///
- public partial class StatutPersonnelEtTableAuteurs : Migration
- {
- ///
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- // Mise à l'abri du contenu des deux colonnes condamnées. Supprimer une colonne sous
- // SQLite reconstruit la table : on le fait pendant que Livres n'a pas encore
- // d'enfants à préserver, et on recopie ensuite depuis cette table de transit.
- migrationBuilder.Sql(
- """
- CREATE TABLE _RepriseLivres AS
- SELECT Id, Auteur, Statut FROM Livres;
- """);
-
- migrationBuilder.DropColumn(
- name: "Auteur",
- table: "Livres");
-
- migrationBuilder.DropColumn(
- name: "Statut",
- table: "Livres");
-
- migrationBuilder.AddColumn(
- name: "TitreNormalise",
- table: "Livres",
- type: "TEXT",
- nullable: false,
- defaultValue: "");
-
- migrationBuilder.CreateTable(
- name: "Auteurs",
- columns: table => new
- {
- Id = table.Column(type: "INTEGER", nullable: false)
- .Annotation("Sqlite:Autoincrement", true),
- Nom = table.Column(type: "TEXT", nullable: false),
- NomNormalise = table.Column(type: "TEXT", nullable: false),
- CleRegroupement = table.Column(type: "TEXT", nullable: false)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_Auteurs", x => x.Id);
- });
-
- migrationBuilder.CreateTable(
- name: "RapprochementsRefuses",
- columns: table => new
- {
- Id = table.Column(type: "INTEGER", nullable: false)
- .Annotation("Sqlite:Autoincrement", true),
- AuteurAId = table.Column(type: "INTEGER", nullable: false),
- AuteurBId = table.Column(type: "INTEGER", nullable: false)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_RapprochementsRefuses", x => x.Id);
- });
-
- migrationBuilder.CreateTable(
- name: "StatutsLecture",
- columns: table => new
- {
- Id = table.Column(type: "INTEGER", nullable: false)
- .Annotation("Sqlite:Autoincrement", true),
- LivreId = table.Column(type: "INTEGER", nullable: false),
- Utilisateur = table.Column(type: "TEXT", nullable: false),
- Statut = table.Column(type: "INTEGER", nullable: false),
- DateMaj = table.Column(type: "TEXT", nullable: false)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_StatutsLecture", x => x.Id);
- table.ForeignKey(
- name: "FK_StatutsLecture_Livres_LivreId",
- column: x => x.LivreId,
- principalTable: "Livres",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- });
-
- migrationBuilder.CreateTable(
- name: "LivreAuteurs",
- columns: table => new
- {
- LivreId = table.Column(type: "INTEGER", nullable: false),
- AuteurId = table.Column(type: "INTEGER", nullable: false),
- Position = table.Column(type: "INTEGER", nullable: false)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_LivreAuteurs", x => new { x.LivreId, x.AuteurId });
- table.ForeignKey(
- name: "FK_LivreAuteurs_Auteurs_AuteurId",
- column: x => x.AuteurId,
- principalTable: "Auteurs",
- principalColumn: "Id",
- onDelete: ReferentialAction.Restrict);
- table.ForeignKey(
- name: "FK_LivreAuteurs_Livres_LivreId",
- column: x => x.LivreId,
- principalTable: "Livres",
- principalColumn: "Id",
- onDelete: ReferentialAction.Cascade);
- });
-
- migrationBuilder.CreateIndex(
- name: "IX_Livres_TitreNormalise",
- table: "Livres",
- column: "TitreNormalise");
-
- migrationBuilder.CreateIndex(
- name: "IX_Auteurs_CleRegroupement",
- table: "Auteurs",
- column: "CleRegroupement",
- unique: true);
-
- migrationBuilder.CreateIndex(
- name: "IX_Auteurs_NomNormalise",
- table: "Auteurs",
- column: "NomNormalise");
-
- migrationBuilder.CreateIndex(
- name: "IX_LivreAuteurs_AuteurId",
- table: "LivreAuteurs",
- column: "AuteurId");
-
- migrationBuilder.CreateIndex(
- name: "IX_RapprochementsRefuses_AuteurAId_AuteurBId",
- table: "RapprochementsRefuses",
- columns: new[] { "AuteurAId", "AuteurBId" },
- unique: true);
-
- migrationBuilder.CreateIndex(
- name: "IX_StatutsLecture_LivreId_Utilisateur",
- table: "StatutsLecture",
- columns: new[] { "LivreId", "Utilisateur" },
- unique: true);
-
- migrationBuilder.CreateIndex(
- name: "IX_StatutsLecture_Utilisateur",
- table: "StatutsLecture",
- column: "Utilisateur");
-
- // ── Reprise des données depuis la table de transit ──────────────────────────────
-
- // Le titre normalisé n'est qu'approché ici (lower() de SQLite ne touche pas aux
- // accents) ; le passage C# du démarrage le recalculera correctement.
- migrationBuilder.Sql("UPDATE Livres SET TitreNormalise = lower(trim(Titre));");
-
- // Une fiche auteur par valeur distincte, à la casse près. Le nom d'affichage retenu
- // est le premier dans l'ordre alphabétique : arbitraire, mais déterministe, et
- // l'utilisateur peut le corriger depuis n'importe quel livre.
- migrationBuilder.Sql(
- """
- INSERT INTO Auteurs (Nom, NomNormalise, CleRegroupement)
- SELECT min(trim(Auteur)), lower(trim(Auteur)), lower(trim(Auteur))
- FROM _RepriseLivres
- WHERE Auteur IS NOT NULL AND trim(Auteur) <> ''
- GROUP BY lower(trim(Auteur));
- """);
-
- migrationBuilder.Sql(
- """
- INSERT INTO LivreAuteurs (LivreId, AuteurId, Position)
- SELECT r.Id, a.Id, 0
- FROM _RepriseLivres r
- JOIN Auteurs a ON a.CleRegroupement = lower(trim(r.Auteur))
- JOIN Livres l ON l.Id = r.Id
- WHERE r.Auteur IS NOT NULL AND trim(r.Auteur) <> '';
- """);
-
- // Le statut commun devient celui de la personne qui a saisi le livre. Sans AjoutePar,
- // il n'y a personne à qui l'attribuer : la ligne n'est pas créée.
- migrationBuilder.Sql(
- """
- INSERT INTO StatutsLecture (LivreId, Utilisateur, Statut, DateMaj)
- SELECT l.Id, trim(l.AjoutePar), r.Statut, l.DateAjout
- FROM Livres l
- JOIN _RepriseLivres r ON r.Id = l.Id
- WHERE l.AjoutePar IS NOT NULL AND trim(l.AjoutePar) <> '';
- """);
-
- migrationBuilder.Sql("DROP TABLE _RepriseLivres;");
- }
-
- ///
- ///
- /// Retour en arrière. Une partie de l'information est perdue par nature : l'ancien
- /// modèle n'a qu'une case pour un auteur et une pour un statut. On y remet le premier
- /// auteur et le statut de AjoutePar ; les co-auteurs et les statuts des autres
- /// membres du foyer disparaissent.
- ///
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.AddColumn(
- name: "Auteur",
- table: "Livres",
- type: "TEXT",
- nullable: true);
-
- migrationBuilder.AddColumn(
- name: "Statut",
- table: "Livres",
- type: "INTEGER",
- nullable: false,
- defaultValue: 0);
-
- migrationBuilder.Sql(
- """
- UPDATE Livres SET Auteur = (
- SELECT a.Nom FROM LivreAuteurs la
- JOIN Auteurs a ON a.Id = la.AuteurId
- WHERE la.LivreId = Livres.Id
- ORDER BY la.Position LIMIT 1);
- """);
-
- migrationBuilder.Sql(
- """
- UPDATE Livres SET Statut = coalesce((
- SELECT s.Statut FROM StatutsLecture s
- WHERE s.LivreId = Livres.Id AND s.Utilisateur = trim(Livres.AjoutePar)
- LIMIT 1), 0);
- """);
-
- migrationBuilder.DropTable(
- name: "LivreAuteurs");
-
- migrationBuilder.DropTable(
- name: "RapprochementsRefuses");
-
- migrationBuilder.DropTable(
- name: "StatutsLecture");
-
- migrationBuilder.DropTable(
- name: "Auteurs");
-
- migrationBuilder.DropIndex(
- name: "IX_Livres_TitreNormalise",
- table: "Livres");
-
- migrationBuilder.DropColumn(
- name: "TitreNormalise",
- table: "Livres");
- }
- }
-}
diff --git a/MaBibli.Api/Data/Migrations/20260818003150_IndexPretEnCours.Designer.cs b/MaBibli.Api/Data/Migrations/20260818003150_IndexPretEnCours.Designer.cs
deleted file mode 100644
index dcbb3bb..0000000
--- a/MaBibli.Api/Data/Migrations/20260818003150_IndexPretEnCours.Designer.cs
+++ /dev/null
@@ -1,246 +0,0 @@
-//
-using System;
-using MaBibli.Api.Data;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-
-#nullable disable
-
-namespace MaBibli.Api.Data.Migrations
-{
- [DbContext(typeof(MaBibliDbContext))]
- [Migration("20260818003150_IndexPretEnCours")]
- partial class IndexPretEnCours
- {
- ///
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder.HasAnnotation("ProductVersion", "10.0.11");
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Auteur", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("CleRegroupement")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("Nom")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("NomNormalise")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex("CleRegroupement")
- .IsUnique();
-
- b.HasIndex("NomNormalise");
-
- b.ToTable("Auteurs");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Livre", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("AjoutePar")
- .HasColumnType("TEXT");
-
- b.Property("CoverUrl")
- .HasColumnType("TEXT");
-
- b.Property("DateAjout")
- .HasColumnType("TEXT");
-
- b.Property("Editeur")
- .HasColumnType("TEXT");
-
- b.Property("Format")
- .HasColumnType("INTEGER");
-
- b.Property("Isbn")
- .HasColumnType("TEXT");
-
- b.Property("Titre")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("TitreNormalise")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex("Isbn");
-
- b.HasIndex("TitreNormalise");
-
- b.ToTable("Livres");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.LivreAuteur", b =>
- {
- b.Property("LivreId")
- .HasColumnType("INTEGER");
-
- b.Property("AuteurId")
- .HasColumnType("INTEGER");
-
- b.Property("Position")
- .HasColumnType("INTEGER");
-
- b.HasKey("LivreId", "AuteurId");
-
- b.HasIndex("AuteurId");
-
- b.ToTable("LivreAuteurs");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Pret", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("DatePret")
- .HasColumnType("TEXT");
-
- b.Property("DateRetour")
- .HasColumnType("TEXT");
-
- b.Property("Emprunteur")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("LivreId")
- .HasColumnType("INTEGER");
-
- b.HasKey("Id");
-
- b.HasIndex(new[] { "LivreId" }, "IX_Prets_LivreId");
-
- b.HasIndex(new[] { "LivreId" }, "IX_Prets_LivreId_EnCours")
- .IsUnique()
- .HasFilter("\"DateRetour\" IS NULL");
-
- b.ToTable("Prets");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.RapprochementRefuse", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("AuteurAId")
- .HasColumnType("INTEGER");
-
- b.Property("AuteurBId")
- .HasColumnType("INTEGER");
-
- b.HasKey("Id");
-
- b.HasIndex("AuteurAId", "AuteurBId")
- .IsUnique();
-
- b.ToTable("RapprochementsRefuses");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.StatutLecture", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("DateMaj")
- .HasColumnType("TEXT");
-
- b.Property("LivreId")
- .HasColumnType("INTEGER");
-
- b.Property("Statut")
- .HasColumnType("INTEGER");
-
- b.Property("Utilisateur")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex("Utilisateur");
-
- b.HasIndex("LivreId", "Utilisateur")
- .IsUnique();
-
- b.ToTable("StatutsLecture");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.LivreAuteur", b =>
- {
- b.HasOne("MaBibli.Shared.Entites.Auteur", "Auteur")
- .WithMany("Livres")
- .HasForeignKey("AuteurId")
- .OnDelete(DeleteBehavior.Restrict)
- .IsRequired();
-
- b.HasOne("MaBibli.Shared.Entites.Livre", "Livre")
- .WithMany("Auteurs")
- .HasForeignKey("LivreId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Auteur");
-
- b.Navigation("Livre");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Pret", b =>
- {
- b.HasOne("MaBibli.Shared.Entites.Livre", "Livre")
- .WithMany("Prets")
- .HasForeignKey("LivreId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Livre");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.StatutLecture", b =>
- {
- b.HasOne("MaBibli.Shared.Entites.Livre", "Livre")
- .WithMany("Statuts")
- .HasForeignKey("LivreId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Livre");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Auteur", b =>
- {
- b.Navigation("Livres");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Livre", b =>
- {
- b.Navigation("Auteurs");
-
- b.Navigation("Prets");
-
- b.Navigation("Statuts");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/MaBibli.Api/Data/Migrations/20260818003150_IndexPretEnCours.cs b/MaBibli.Api/Data/Migrations/20260818003150_IndexPretEnCours.cs
deleted file mode 100644
index 2952e0a..0000000
--- a/MaBibli.Api/Data/Migrations/20260818003150_IndexPretEnCours.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using Microsoft.EntityFrameworkCore.Migrations;
-
-#nullable disable
-
-namespace MaBibli.Api.Data.Migrations
-{
- ///
- public partial class IndexPretEnCours : Migration
- {
- ///
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.CreateIndex(
- name: "IX_Prets_LivreId_EnCours",
- table: "Prets",
- column: "LivreId",
- unique: true,
- filter: "\"DateRetour\" IS NULL");
- }
-
- ///
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.DropIndex(
- name: "IX_Prets_LivreId_EnCours",
- table: "Prets");
- }
- }
-}
diff --git a/MaBibli.Api/Data/Migrations/20260818052834_ListeDEnvies.Designer.cs b/MaBibli.Api/Data/Migrations/20260818052834_ListeDEnvies.Designer.cs
deleted file mode 100644
index ce19c4d..0000000
--- a/MaBibli.Api/Data/Migrations/20260818052834_ListeDEnvies.Designer.cs
+++ /dev/null
@@ -1,301 +0,0 @@
-//
-using System;
-using MaBibli.Api.Data;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-
-#nullable disable
-
-namespace MaBibli.Api.Data.Migrations
-{
- [DbContext(typeof(MaBibliDbContext))]
- [Migration("20260818052834_ListeDEnvies")]
- partial class ListeDEnvies
- {
- ///
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder.HasAnnotation("ProductVersion", "10.0.11");
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Auteur", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("CleRegroupement")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("Nom")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("NomNormalise")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex("CleRegroupement")
- .IsUnique();
-
- b.HasIndex("NomNormalise");
-
- b.ToTable("Auteurs");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Livre", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("AjoutePar")
- .HasColumnType("TEXT");
-
- b.Property("CoverUrl")
- .HasColumnType("TEXT");
-
- b.Property("DateAjout")
- .HasColumnType("TEXT");
-
- b.Property("Editeur")
- .HasColumnType("TEXT");
-
- b.Property("Format")
- .HasColumnType("INTEGER");
-
- b.Property("Isbn")
- .HasColumnType("TEXT");
-
- b.Property("Titre")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("TitreNormalise")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex("Isbn");
-
- b.HasIndex("TitreNormalise");
-
- b.ToTable("Livres");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.LivreAuteur", b =>
- {
- b.Property("LivreId")
- .HasColumnType("INTEGER");
-
- b.Property("AuteurId")
- .HasColumnType("INTEGER");
-
- b.Property("Position")
- .HasColumnType("INTEGER");
-
- b.HasKey("LivreId", "AuteurId");
-
- b.HasIndex("AuteurId");
-
- b.ToTable("LivreAuteurs");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.LivreSouhaite", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("Annee")
- .HasColumnType("TEXT");
-
- b.Property("Auteur")
- .HasColumnType("TEXT");
-
- b.Property("AuteurNormalise")
- .IsRequired()
- .ValueGeneratedOnAdd()
- .HasColumnType("TEXT")
- .HasDefaultValue("");
-
- b.Property("CoverUrl")
- .HasColumnType("TEXT");
-
- b.Property("DateAjout")
- .HasColumnType("TEXT");
-
- b.Property("Editeur")
- .HasColumnType("TEXT");
-
- b.Property("Isbn")
- .HasColumnType("TEXT");
-
- b.Property("Note")
- .HasColumnType("TEXT");
-
- b.Property("Titre")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("TitreNormalise")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("Utilisateur")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex(new[] { "Utilisateur" }, "IX_LivresSouhaites_Utilisateur");
-
- b.HasIndex(new[] { "Utilisateur", "TitreNormalise", "AuteurNormalise" }, "IX_LivresSouhaites_Utilisateur_Oeuvre")
- .IsUnique();
-
- b.ToTable("LivresSouhaites");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Pret", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("DatePret")
- .HasColumnType("TEXT");
-
- b.Property("DateRetour")
- .HasColumnType("TEXT");
-
- b.Property("Emprunteur")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("LivreId")
- .HasColumnType("INTEGER");
-
- b.HasKey("Id");
-
- b.HasIndex(new[] { "LivreId" }, "IX_Prets_LivreId");
-
- b.HasIndex(new[] { "LivreId" }, "IX_Prets_LivreId_EnCours")
- .IsUnique()
- .HasFilter("\"DateRetour\" IS NULL");
-
- b.ToTable("Prets");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.RapprochementRefuse", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("AuteurAId")
- .HasColumnType("INTEGER");
-
- b.Property("AuteurBId")
- .HasColumnType("INTEGER");
-
- b.HasKey("Id");
-
- b.HasIndex("AuteurAId", "AuteurBId")
- .IsUnique();
-
- b.ToTable("RapprochementsRefuses");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.StatutLecture", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("DateMaj")
- .HasColumnType("TEXT");
-
- b.Property("LivreId")
- .HasColumnType("INTEGER");
-
- b.Property("Statut")
- .HasColumnType("INTEGER");
-
- b.Property("Utilisateur")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex("Utilisateur");
-
- b.HasIndex("LivreId", "Utilisateur")
- .IsUnique();
-
- b.ToTable("StatutsLecture");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.LivreAuteur", b =>
- {
- b.HasOne("MaBibli.Shared.Entites.Auteur", "Auteur")
- .WithMany("Livres")
- .HasForeignKey("AuteurId")
- .OnDelete(DeleteBehavior.Restrict)
- .IsRequired();
-
- b.HasOne("MaBibli.Shared.Entites.Livre", "Livre")
- .WithMany("Auteurs")
- .HasForeignKey("LivreId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Auteur");
-
- b.Navigation("Livre");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Pret", b =>
- {
- b.HasOne("MaBibli.Shared.Entites.Livre", "Livre")
- .WithMany("Prets")
- .HasForeignKey("LivreId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Livre");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.StatutLecture", b =>
- {
- b.HasOne("MaBibli.Shared.Entites.Livre", "Livre")
- .WithMany("Statuts")
- .HasForeignKey("LivreId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Livre");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Auteur", b =>
- {
- b.Navigation("Livres");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Livre", b =>
- {
- b.Navigation("Auteurs");
-
- b.Navigation("Prets");
-
- b.Navigation("Statuts");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/MaBibli.Api/Data/Migrations/20260818052834_ListeDEnvies.cs b/MaBibli.Api/Data/Migrations/20260818052834_ListeDEnvies.cs
deleted file mode 100644
index ac731db..0000000
--- a/MaBibli.Api/Data/Migrations/20260818052834_ListeDEnvies.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-using System;
-using Microsoft.EntityFrameworkCore.Migrations;
-
-#nullable disable
-
-namespace MaBibli.Api.Data.Migrations
-{
- ///
- public partial class ListeDEnvies : Migration
- {
- ///
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.CreateTable(
- name: "LivresSouhaites",
- columns: table => new
- {
- Id = table.Column(type: "INTEGER", nullable: false)
- .Annotation("Sqlite:Autoincrement", true),
- Utilisateur = table.Column(type: "TEXT", nullable: false),
- Titre = table.Column(type: "TEXT", nullable: false),
- TitreNormalise = table.Column(type: "TEXT", nullable: false),
- Auteur = table.Column(type: "TEXT", nullable: true),
- AuteurNormalise = table.Column(type: "TEXT", nullable: false, defaultValue: ""),
- Editeur = table.Column(type: "TEXT", nullable: true),
- Annee = table.Column(type: "TEXT", nullable: true),
- Isbn = table.Column(type: "TEXT", nullable: true),
- CoverUrl = table.Column(type: "TEXT", nullable: true),
- Note = table.Column(type: "TEXT", nullable: true),
- DateAjout = table.Column(type: "TEXT", nullable: false)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_LivresSouhaites", x => x.Id);
- });
-
- migrationBuilder.CreateIndex(
- name: "IX_LivresSouhaites_Utilisateur",
- table: "LivresSouhaites",
- column: "Utilisateur");
-
- migrationBuilder.CreateIndex(
- name: "IX_LivresSouhaites_Utilisateur_Oeuvre",
- table: "LivresSouhaites",
- columns: new[] { "Utilisateur", "TitreNormalise", "AuteurNormalise" },
- unique: true);
- }
-
- ///
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.DropTable(
- name: "LivresSouhaites");
- }
- }
-}
diff --git a/MaBibli.Api/Data/Migrations/20260818213512_RangDesEnvies.Designer.cs b/MaBibli.Api/Data/Migrations/20260818213512_RangDesEnvies.Designer.cs
deleted file mode 100644
index 0044516..0000000
--- a/MaBibli.Api/Data/Migrations/20260818213512_RangDesEnvies.Designer.cs
+++ /dev/null
@@ -1,304 +0,0 @@
-//
-using System;
-using MaBibli.Api.Data;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-
-#nullable disable
-
-namespace MaBibli.Api.Data.Migrations
-{
- [DbContext(typeof(MaBibliDbContext))]
- [Migration("20260818213512_RangDesEnvies")]
- partial class RangDesEnvies
- {
- ///
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder.HasAnnotation("ProductVersion", "10.0.11");
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Auteur", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("CleRegroupement")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("Nom")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("NomNormalise")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex("CleRegroupement")
- .IsUnique();
-
- b.HasIndex("NomNormalise");
-
- b.ToTable("Auteurs");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Livre", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("AjoutePar")
- .HasColumnType("TEXT");
-
- b.Property("CoverUrl")
- .HasColumnType("TEXT");
-
- b.Property("DateAjout")
- .HasColumnType("TEXT");
-
- b.Property("Editeur")
- .HasColumnType("TEXT");
-
- b.Property("Format")
- .HasColumnType("INTEGER");
-
- b.Property("Isbn")
- .HasColumnType("TEXT");
-
- b.Property("Titre")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("TitreNormalise")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex("Isbn");
-
- b.HasIndex("TitreNormalise");
-
- b.ToTable("Livres");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.LivreAuteur", b =>
- {
- b.Property("LivreId")
- .HasColumnType("INTEGER");
-
- b.Property("AuteurId")
- .HasColumnType("INTEGER");
-
- b.Property("Position")
- .HasColumnType("INTEGER");
-
- b.HasKey("LivreId", "AuteurId");
-
- b.HasIndex("AuteurId");
-
- b.ToTable("LivreAuteurs");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.LivreSouhaite", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("Annee")
- .HasColumnType("TEXT");
-
- b.Property("Auteur")
- .HasColumnType("TEXT");
-
- b.Property("AuteurNormalise")
- .IsRequired()
- .ValueGeneratedOnAdd()
- .HasColumnType("TEXT")
- .HasDefaultValue("");
-
- b.Property("CoverUrl")
- .HasColumnType("TEXT");
-
- b.Property("DateAjout")
- .HasColumnType("TEXT");
-
- b.Property("Editeur")
- .HasColumnType("TEXT");
-
- b.Property("Isbn")
- .HasColumnType("TEXT");
-
- b.Property("Note")
- .HasColumnType("TEXT");
-
- b.Property("Rang")
- .HasColumnType("INTEGER");
-
- b.Property("Titre")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("TitreNormalise")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("Utilisateur")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex(new[] { "Utilisateur" }, "IX_LivresSouhaites_Utilisateur");
-
- b.HasIndex(new[] { "Utilisateur", "TitreNormalise", "AuteurNormalise" }, "IX_LivresSouhaites_Utilisateur_Oeuvre")
- .IsUnique();
-
- b.ToTable("LivresSouhaites");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Pret", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("DatePret")
- .HasColumnType("TEXT");
-
- b.Property("DateRetour")
- .HasColumnType("TEXT");
-
- b.Property("Emprunteur")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("LivreId")
- .HasColumnType("INTEGER");
-
- b.HasKey("Id");
-
- b.HasIndex(new[] { "LivreId" }, "IX_Prets_LivreId");
-
- b.HasIndex(new[] { "LivreId" }, "IX_Prets_LivreId_EnCours")
- .IsUnique()
- .HasFilter("\"DateRetour\" IS NULL");
-
- b.ToTable("Prets");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.RapprochementRefuse", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("AuteurAId")
- .HasColumnType("INTEGER");
-
- b.Property("AuteurBId")
- .HasColumnType("INTEGER");
-
- b.HasKey("Id");
-
- b.HasIndex("AuteurAId", "AuteurBId")
- .IsUnique();
-
- b.ToTable("RapprochementsRefuses");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.StatutLecture", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("DateMaj")
- .HasColumnType("TEXT");
-
- b.Property("LivreId")
- .HasColumnType("INTEGER");
-
- b.Property("Statut")
- .HasColumnType("INTEGER");
-
- b.Property("Utilisateur")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex("Utilisateur");
-
- b.HasIndex("LivreId", "Utilisateur")
- .IsUnique();
-
- b.ToTable("StatutsLecture");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.LivreAuteur", b =>
- {
- b.HasOne("MaBibli.Shared.Entites.Auteur", "Auteur")
- .WithMany("Livres")
- .HasForeignKey("AuteurId")
- .OnDelete(DeleteBehavior.Restrict)
- .IsRequired();
-
- b.HasOne("MaBibli.Shared.Entites.Livre", "Livre")
- .WithMany("Auteurs")
- .HasForeignKey("LivreId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Auteur");
-
- b.Navigation("Livre");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Pret", b =>
- {
- b.HasOne("MaBibli.Shared.Entites.Livre", "Livre")
- .WithMany("Prets")
- .HasForeignKey("LivreId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Livre");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.StatutLecture", b =>
- {
- b.HasOne("MaBibli.Shared.Entites.Livre", "Livre")
- .WithMany("Statuts")
- .HasForeignKey("LivreId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Livre");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Auteur", b =>
- {
- b.Navigation("Livres");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Livre", b =>
- {
- b.Navigation("Auteurs");
-
- b.Navigation("Prets");
-
- b.Navigation("Statuts");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/MaBibli.Api/Data/Migrations/20260818213512_RangDesEnvies.cs b/MaBibli.Api/Data/Migrations/20260818213512_RangDesEnvies.cs
deleted file mode 100644
index 449d8a1..0000000
--- a/MaBibli.Api/Data/Migrations/20260818213512_RangDesEnvies.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using Microsoft.EntityFrameworkCore.Migrations;
-
-#nullable disable
-
-namespace MaBibli.Api.Data.Migrations
-{
- ///
- /// Ajoute le rang manuel de la liste d'envies (du plus désiré au moins désiré).
- ///
- ///
- /// ⚠️ La colonne seule ne suffit pas : à 0 partout, l'ordre retomberait sur l'Id,
- /// c'est-à-dire l'ordre d'ajout, et les listes existantes se réordonneraient sous les yeux
- /// de leur propriétaire sans qu'il ait rien demandé. Le remplissage ci-dessous reconduit
- /// exactement l'ordre affiché jusqu'ici — auteurs renseignés d'abord, puis par auteur,
- /// puis par titre — de sorte que la mise à jour ne se voie pas.
- ///
- /// Le rang est personnel, comme toute la table : la numérotation repart de zéro pour
- /// chaque Utilisateur, d'où la corrélation sur cette colonne dans la sous-requête.
- ///
- ///
- public partial class RangDesEnvies : Migration
- {
- ///
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.AddColumn(
- name: "Rang",
- table: "LivresSouhaites",
- type: "INTEGER",
- nullable: false,
- defaultValue: 0);
-
- // Row values (a, b) < (c, d) : SQLite les gère depuis la 3.15, et c'est ce qui
- // permet d'exprimer « combien de lignes se classaient avant celle-ci » en une
- // seule comparaison lexicographique. L'Id ferme le tri : sans lui, deux envies
- // de même auteur et même titre recevraient le même rang.
- migrationBuilder.Sql("""
- UPDATE LivresSouhaites SET Rang = (
- SELECT COUNT(*)
- FROM LivresSouhaites AS autre
- WHERE autre.Utilisateur = LivresSouhaites.Utilisateur
- AND (
- CASE WHEN autre.AuteurNormalise = '' THEN 1 ELSE 0 END,
- autre.AuteurNormalise,
- autre.TitreNormalise,
- autre.Id
- ) < (
- CASE WHEN LivresSouhaites.AuteurNormalise = '' THEN 1 ELSE 0 END,
- LivresSouhaites.AuteurNormalise,
- LivresSouhaites.TitreNormalise,
- LivresSouhaites.Id
- )
- );
- """);
- }
-
- ///
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.DropColumn(
- name: "Rang",
- table: "LivresSouhaites");
- }
- }
-}
diff --git a/MaBibli.Api/Data/Migrations/20260819194040_TypeDeDocument.Designer.cs b/MaBibli.Api/Data/Migrations/20260819194040_TypeDeDocument.Designer.cs
deleted file mode 100644
index 56e47ab..0000000
--- a/MaBibli.Api/Data/Migrations/20260819194040_TypeDeDocument.Designer.cs
+++ /dev/null
@@ -1,307 +0,0 @@
-//
-using System;
-using MaBibli.Api.Data;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-
-#nullable disable
-
-namespace MaBibli.Api.Data.Migrations
-{
- [DbContext(typeof(MaBibliDbContext))]
- [Migration("20260819194040_TypeDeDocument")]
- partial class TypeDeDocument
- {
- ///
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder.HasAnnotation("ProductVersion", "10.0.11");
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Auteur", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("CleRegroupement")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("Nom")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("NomNormalise")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex("CleRegroupement")
- .IsUnique();
-
- b.HasIndex("NomNormalise");
-
- b.ToTable("Auteurs");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Livre", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("AjoutePar")
- .HasColumnType("TEXT");
-
- b.Property("CoverUrl")
- .HasColumnType("TEXT");
-
- b.Property("DateAjout")
- .HasColumnType("TEXT");
-
- b.Property("Editeur")
- .HasColumnType("TEXT");
-
- b.Property("Format")
- .HasColumnType("INTEGER");
-
- b.Property("Isbn")
- .HasColumnType("TEXT");
-
- b.Property("Titre")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("TitreNormalise")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("TypeDocument")
- .HasColumnType("INTEGER");
-
- b.HasKey("Id");
-
- b.HasIndex("Isbn");
-
- b.HasIndex("TitreNormalise");
-
- b.ToTable("Livres");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.LivreAuteur", b =>
- {
- b.Property("LivreId")
- .HasColumnType("INTEGER");
-
- b.Property("AuteurId")
- .HasColumnType("INTEGER");
-
- b.Property("Position")
- .HasColumnType("INTEGER");
-
- b.HasKey("LivreId", "AuteurId");
-
- b.HasIndex("AuteurId");
-
- b.ToTable("LivreAuteurs");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.LivreSouhaite", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("Annee")
- .HasColumnType("TEXT");
-
- b.Property("Auteur")
- .HasColumnType("TEXT");
-
- b.Property("AuteurNormalise")
- .IsRequired()
- .ValueGeneratedOnAdd()
- .HasColumnType("TEXT")
- .HasDefaultValue("");
-
- b.Property("CoverUrl")
- .HasColumnType("TEXT");
-
- b.Property("DateAjout")
- .HasColumnType("TEXT");
-
- b.Property("Editeur")
- .HasColumnType("TEXT");
-
- b.Property("Isbn")
- .HasColumnType("TEXT");
-
- b.Property("Note")
- .HasColumnType("TEXT");
-
- b.Property("Rang")
- .HasColumnType("INTEGER");
-
- b.Property("Titre")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("TitreNormalise")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("Utilisateur")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex(new[] { "Utilisateur" }, "IX_LivresSouhaites_Utilisateur");
-
- b.HasIndex(new[] { "Utilisateur", "TitreNormalise", "AuteurNormalise" }, "IX_LivresSouhaites_Utilisateur_Oeuvre")
- .IsUnique();
-
- b.ToTable("LivresSouhaites");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Pret", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("DatePret")
- .HasColumnType("TEXT");
-
- b.Property("DateRetour")
- .HasColumnType("TEXT");
-
- b.Property("Emprunteur")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("LivreId")
- .HasColumnType("INTEGER");
-
- b.HasKey("Id");
-
- b.HasIndex(new[] { "LivreId" }, "IX_Prets_LivreId");
-
- b.HasIndex(new[] { "LivreId" }, "IX_Prets_LivreId_EnCours")
- .IsUnique()
- .HasFilter("\"DateRetour\" IS NULL");
-
- b.ToTable("Prets");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.RapprochementRefuse", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("AuteurAId")
- .HasColumnType("INTEGER");
-
- b.Property("AuteurBId")
- .HasColumnType("INTEGER");
-
- b.HasKey("Id");
-
- b.HasIndex("AuteurAId", "AuteurBId")
- .IsUnique();
-
- b.ToTable("RapprochementsRefuses");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.StatutLecture", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("DateMaj")
- .HasColumnType("TEXT");
-
- b.Property("LivreId")
- .HasColumnType("INTEGER");
-
- b.Property("Statut")
- .HasColumnType("INTEGER");
-
- b.Property("Utilisateur")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex("Utilisateur");
-
- b.HasIndex("LivreId", "Utilisateur")
- .IsUnique();
-
- b.ToTable("StatutsLecture");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.LivreAuteur", b =>
- {
- b.HasOne("MaBibli.Shared.Entites.Auteur", "Auteur")
- .WithMany("Livres")
- .HasForeignKey("AuteurId")
- .OnDelete(DeleteBehavior.Restrict)
- .IsRequired();
-
- b.HasOne("MaBibli.Shared.Entites.Livre", "Livre")
- .WithMany("Auteurs")
- .HasForeignKey("LivreId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Auteur");
-
- b.Navigation("Livre");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Pret", b =>
- {
- b.HasOne("MaBibli.Shared.Entites.Livre", "Livre")
- .WithMany("Prets")
- .HasForeignKey("LivreId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Livre");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.StatutLecture", b =>
- {
- b.HasOne("MaBibli.Shared.Entites.Livre", "Livre")
- .WithMany("Statuts")
- .HasForeignKey("LivreId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
-
- b.Navigation("Livre");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Auteur", b =>
- {
- b.Navigation("Livres");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Livre", b =>
- {
- b.Navigation("Auteurs");
-
- b.Navigation("Prets");
-
- b.Navigation("Statuts");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/MaBibli.Api/Data/Migrations/20260819194040_TypeDeDocument.cs b/MaBibli.Api/Data/Migrations/20260819194040_TypeDeDocument.cs
deleted file mode 100644
index 6b42a17..0000000
--- a/MaBibli.Api/Data/Migrations/20260819194040_TypeDeDocument.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-using Microsoft.EntityFrameworkCore.Migrations;
-
-#nullable disable
-
-namespace MaBibli.Api.Data.Migrations
-{
- ///
- /// Ajoute le type de document, à « non précisé » pour tout l'existant.
- ///
- ///
- /// ⚠️ Contrairement à RangDesEnvies, cette migration se réduit bien à un
- /// AddColumn, et c'est le choix de la valeur par défaut qui l'explique : 0 vaut
- /// NonPrecise, c'est-à-dire « on ne sait pas ». Si le défaut avait été « Roman », il
- /// aurait fallu écrire quelque chose de faux sur chaque fiche existante — ou renoncer au
- /// défaut. Rien à reprendre, donc rien à deviner.
- ///
- public partial class TypeDeDocument : Migration
- {
- ///
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.AddColumn(
- name: "TypeDocument",
- table: "Livres",
- type: "INTEGER",
- nullable: false,
- defaultValue: 0);
- }
-
- ///
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.DropColumn(
- name: "TypeDocument",
- table: "Livres");
- }
- }
-}
diff --git a/MaBibli.Api/Data/Migrations/20260819195104_SagasEtCycles.Designer.cs b/MaBibli.Api/Data/Migrations/20260819195104_SagasEtCycles.Designer.cs
deleted file mode 100644
index 7335d9e..0000000
--- a/MaBibli.Api/Data/Migrations/20260819195104_SagasEtCycles.Designer.cs
+++ /dev/null
@@ -1,410 +0,0 @@
-//
-using System;
-using MaBibli.Api.Data;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-
-#nullable disable
-
-namespace MaBibli.Api.Data.Migrations
-{
- [DbContext(typeof(MaBibliDbContext))]
- [Migration("20260819195104_SagasEtCycles")]
- partial class SagasEtCycles
- {
- ///
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder.HasAnnotation("ProductVersion", "10.0.11");
-
- modelBuilder.Entity("MaBibli.Shared.Entites.Auteur", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("CleRegroupement")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("Nom")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.Property("NomNormalise")
- .IsRequired()
- .HasColumnType("TEXT");
-
- b.HasKey("Id");
-
- b.HasIndex("CleRegroupement")
- .IsUnique();
-
- b.HasIndex("NomNormalise");
-
- b.ToTable("Auteurs");
- });
-
- modelBuilder.Entity("MaBibli.Shared.Entites.ElementSerie", b =>
- {
- b.Property("Id")
- .ValueGeneratedOnAdd()
- .HasColumnType("INTEGER");
-
- b.Property("LivreId")
- .HasColumnType("INTEGER");
-
- b.Property("Position")
- .HasColumnType("INTEGER");
-
- b.Property("SerieId")
- .HasColumnType("INTEGER");
-
- b.Property