using MaBibli.Shared.Textes; namespace MaBibli.Shared.Entites; /// /// Une revue — magazine, périodique —, et non l'un de ses numéros. /// /// /// Pourquoi une table à part et non une ligne de Livres ? Même raisonnement que /// pour et , et il vaut d'être répété : logée /// dans Livres, une revue entrerait mécaniquement dans le catalogue, ses /// compteurs, la détection de doublons, les séries et les bibliographies par auteur — et il /// faudrait écrire « et qui n'est pas une revue » à chaque lecture. Un invariant qu'on réécrit /// partout finit par être oublié quelque part. /// /// Une fiche par revue, les numéros à l'intérieur. C'est ce qui évite le défaut redouté /// dès le premier lot : douze numéros d'un même magazine ne font pas douze fiches identiques, /// puisqu'ils partagent la fiche de leur revue. /// /// /// ⚠️ L' est un identifiant de revue, jamais un ISBN. Ranger un code /// 977 dans Livre.Isbn ferait échouer tout lookup ultérieur sur cette fiche — /// c'est précisément ce que cette table évite. /// /// public class Revue { public int Id { get; set; } public string Titre { get; set; } = string.Empty; /// Titre mis à plat. Index unique : une revue, une fiche. public string TitreNormalise { get; set; } = string.Empty; /// /// ISSN sous sa forme canonique à tiret (2466-6718), quand on le connaît. /// /// /// Facultatif : une revue se catalogue à la main sans que personne n'ait scanné son /// code-barres. Son unicité est portée par un index partiel — deux NULL sont /// distincts pour SQLite, une unicité simple laisserait donc passer autant de revues sans /// ISSN qu'on veut, ce qui est justement le comportement voulu. /// public string? Issn { get; set; } public string? Editeur { get; set; } public DateTime DateAjout { get; set; } /// Trace de saisie. Pas une frontière : les revues sont communes au foyer. public string? AjoutePar { get; set; } public List Numeros { get; set; } = []; public void RecalculerFormes() { Titre = Titre.Trim(); TitreNormalise = NormalisationTexte.Normaliser(Titre); Issn = string.IsNullOrWhiteSpace(Issn) ? null : Issn.Trim(); } } /// /// Un numéro possédé d'une revue. /// /// /// Décidé le 2026-08-19 : un numéro est recensé, rien de plus. Ni prêt, ni statut de /// lecture — ces deux mécanismes sont attachés à par clé étrangère, et les /// rouvrir demanderait une seconde table de prêts ou une parenté commune, pour un usage non /// confirmé. Le choix est réversible : les ajouter plus tard ne détruit rien de ce qui /// est enregistré ici. /// public class NumeroRevue { public int Id { get; set; } public int RevueId { get; set; } public Revue? Revue { get; set; } /// /// Le numéro tel qu'il est imprimé (« 43 », « hors-série 7 »). Obligatoire : /// sans lui, deux numéros de la même revue seraient indiscernables. /// public string Numero { get; set; } = string.Empty; /// Forme mise à plat, porteuse de l'unicité au sein de la revue. public string NumeroNormalise { get; set; } = string.Empty; /// Date de parution, quand elle est connue. En UTC comme toutes les dates. public DateTime? DateParution { get; set; } /// Note libre : « dossier sur l'eau », « prêté à Paul », « acheté en gare ». public string? Note { get; set; } public DateTime DateAjout { get; set; } public void RecalculerFormes() { Numero = Numero.Trim(); NumeroNormalise = NormalisationTexte.Normaliser(Numero); } }