using MaBibli.Shared.Textes; namespace MaBibli.Shared.Entites; /// /// Un regroupement ordonné de livres : trilogie, série, cycle, intégrale. /// /// /// C'est la première notion du projet qui porte sur une relation entre livres plutôt que /// sur un livre. Trois choses en découlent, et un simple champ texte « série » sur /// n'en couvrirait aucune. /// /// 1. Deux niveaux, au moins. La Légende de Drizzt regroupe plusieurs trilogies. /// D'où , une auto-référence : un cycle est une série qui /// contient des séries. Un champ « cycle » séparé figerait la profondeur à deux et obligerait à /// tout refaire au troisième niveau. /// /// /// 2. L'ordre de lecture n'est pas l'ordre de publication. L'Elfe noir est une /// préquelle écrite après. C'est précisément l'information qu'on vient chercher : elle est /// stockée (), jamais déduite d'une année. /// /// /// 3. La portée est COMMUNE au foyer, comme le catalogue et les prêts, contrairement au /// statut de lecture et à la liste d'envies. L'ordre de lecture d'une saga est une propriété de /// l'œuvre : il ne change pas selon qui regarde. est donc une trace, /// pas une frontière — ne jamais filtrer dessus, comme . /// /// public class Serie { public int Id { get; set; } public string Titre { get; set; } = string.Empty; /// /// Titre mis à plat. Porte un index unique : une série, une fiche. /// /// /// L'unicité est globale et non « par série parente », parce que /// est nullable et que SQLite tient deux NULL pour /// distincts : une unicité incluant le parent laisserait passer autant de doublons qu'on /// veut à la racine — exactement le piège documenté sur LivreSouhaite.AuteurNormalise. /// public string TitreNormalise { get; set; } = string.Empty; /// La série qui contient celle-ci, quand c'en est une partie d'un cycle. public int? SerieParenteId { get; set; } public Serie? SerieParente { get; set; } public List SousSeries { get; set; } = []; /// Rang de cette série dans sa série parente. Sans objet à la racine. public int Position { get; set; } public List Elements { get; set; } = []; public DateTime DateAjout { get; set; } /// Qui a créé la série. Trace, pas frontière : la série est commune. public string? AjoutePar { get; set; } public void RecalculerFormes() { Titre = Titre.Trim(); TitreNormalise = NormalisationTexte.Normaliser(Titre); } } /// /// Une position dans une série : le tome n, qu'on le possède ou non. /// /// /// ⚠️ Ce n'est pas « un livre de la série » mais une place dans l'ordre de lecture. La /// nuance est tout l'intérêt de l'écran : sans position sans livre, on ne pourrait pas montrer /// les trous — « il vous manque le tome 3 » —, qui est la demande d'origine. Aucune source ne /// donne l'ordre de lecture d'une saga (la BnF ne l'expose pas, et l'ordre de publication est /// justement faux pour une préquelle) : les tomes absents n'existent que si on les saisit. /// /// est donc toujours renseigné, y compris quand /// l'est : c'est ce qui permet à la suppression d'un livre de laisser un /// trou nommé plutôt qu'une ligne muette. La clé étrangère est en SetNull pour cette /// raison précise — supprimer un livre ne doit pas trouer la structure de la saga. /// /// public class ElementSerie { public int Id { get; set; } public int SerieId { get; set; } public Serie? Serie { get; set; } /// Rang dans l'ordre de lecture, à partir de 0. public int Position { get; set; } /// Le livre du catalogue, s'il est possédé. null = un trou. public int? LivreId { get; set; } public Livre? Livre { get; set; } /// /// Titre du tome. Renseigné même quand le livre est là, pour survivre à sa suppression. /// public string Titre { get; set; } = string.Empty; public void RecalculerFormes() => Titre = Titre.Trim(); }