La liste d'envies vit dans une table séparée (LivreSouhaite) plutôt que dans un statut de plus sur Livre : un livre souhaité n'est pas possédé, et le loger dans Livres l'aurait fait entrer dans le catalogue, les compteurs et les prêts, au prix d'un « et qui n'est pas souhaité » à répéter dans chaque lecture. La portée est personnelle, comme le statut de lecture — mais ici Utilisateur est une vraie frontière : toute lecture filtre dessus. Bibliographie : SRU BnF interrogé par bib.author, vérifié le 2026-08-18. Deux filtres mesurés sur des réponses réelles sont indispensables — le type de document (l'index mêle livres audio, jeux et spectacles) et surtout l'auteur réel de la notice, « all » rapprochant les mots sur l'ensemble des auteurs : « Émile Zola » remonte sinon toute l'œuvre de sa fille Denise Le Blond-Zola. Les rééditions sont regroupées par clé d'œuvre (183 notices Werber -> 51 œuvres). Le rapprochement avec l'étagère se fait par titre, pas par ISBN, qui désigne une édition et non une œuvre ; ses limites sont dites à l'écran. Export en deux formats, tous deux du texte sans dépendance : .txt groupé par auteur pour la librairie, .csv à séparateur point-virgule et BOM pour le tableur. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
86 lines
3.9 KiB
C#
86 lines
3.9 KiB
C#
using MaBibli.Shared.Textes;
|
|
|
|
namespace MaBibli.Shared.Entites;
|
|
|
|
/// <summary>
|
|
/// Un livre que l'on aimerait acquérir. <b>Personnel</b> : chacun sa liste.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <b>Pourquoi une entité séparée plutôt qu'un statut de plus sur <see cref="Livre"/> ?</b>
|
|
/// Un livre souhaité n'est pas un livre possédé. S'il était une ligne de <c>Livres</c>, il
|
|
/// entrerait mécaniquement dans le catalogue, dans les compteurs, dans les prêts et dans le
|
|
/// cache hors-ligne — et il faudrait ajouter « et qui n'est pas souhaité » à <b>chaque</b>
|
|
/// lecture du catalogue. Un invariant qu'il faut réécrire à chaque requête finit toujours par
|
|
/// être oublié quelque part ; ici l'inventaire et l'envie ne se croisent tout simplement pas,
|
|
/// parce qu'ils ne vivent pas dans la même table.
|
|
/// <para>
|
|
/// C'est aussi la seule forme qui accepte une envie <b>sans ISBN ni édition arrêtée</b> : on
|
|
/// souhaite une œuvre (« le dernier Werber »), on possède un exemplaire. Un souhait n'a donc
|
|
/// ni <see cref="Format"/> ni couverture obligatoire, et ne peut pas être prêté.
|
|
/// </para>
|
|
/// <para>
|
|
/// La portée personnelle suit <see cref="StatutLecture"/>, dont la documentation annonçait déjà
|
|
/// ce voisinage : <see cref="Utilisateur"/> <b>est</b> une frontière, contrairement à
|
|
/// <see cref="Livre.AjoutePar"/>. On ne lit jamais la liste d'envies de quelqu'un d'autre —
|
|
/// c'est précisément ce qui permet d'offrir un livre sans vendre la mèche.
|
|
/// </para>
|
|
/// </remarks>
|
|
public class LivreSouhaite
|
|
{
|
|
public int Id { get; set; }
|
|
|
|
/// <summary>
|
|
/// <c>YNH_USER</c> du propriétaire de l'envie. <b>Frontière</b> : toute lecture filtre dessus.
|
|
/// </summary>
|
|
public string Utilisateur { get; set; } = string.Empty;
|
|
|
|
public string Titre { get; set; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// Titre mis à plat, servant à la fois au dédoublonnage et au rapprochement avec le
|
|
/// catalogue (« ai-je déjà ce livre ? »). Recalculé à chaque écriture.
|
|
/// </summary>
|
|
public string TitreNormalise { get; set; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// Auteur en <b>texte libre</b>, volontairement pas une clé étrangère vers <see cref="Auteur"/>.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// La table <c>Auteurs</c> décrit qui est <i>dans la bibliothèque</i> : y insérer les auteurs
|
|
/// souhaités les ferait apparaître sur l'écran des auteurs avec « 0 livre », et exposerait la
|
|
/// liste d'envies d'une personne à tout le foyer — l'inverse de ce qu'on veut. Le texte libre
|
|
/// survit en outre à la disparition de l'auteur du catalogue.
|
|
/// </remarks>
|
|
public string? Auteur { get; set; }
|
|
|
|
/// <summary>
|
|
/// Auteur mis à plat. <b>Jamais <c>null</c></b> (chaîne vide si l'auteur est inconnu) :
|
|
/// SQLite considère deux <c>NULL</c> comme distincts, et l'index unique laisserait alors
|
|
/// passer des doublons d'envies sans auteur.
|
|
/// </summary>
|
|
public string AuteurNormalise { get; set; } = string.Empty;
|
|
|
|
public string? Editeur { get; set; }
|
|
|
|
/// <summary>Année de publication, telle que la source la donne. Texte : la BnF écrit « 2012 », mais aussi « [DL 2012] ».</summary>
|
|
public string? Annee { get; set; }
|
|
|
|
/// <summary>ISBN d'une édition repérée, quand il y en a une. Facultatif : on souhaite une œuvre, pas forcément une édition.</summary>
|
|
public string? Isbn { get; set; }
|
|
|
|
public string? CoverUrl { get; set; }
|
|
|
|
/// <summary>Note libre : « demandé à Noël », « en poche seulement », « chez Untel ».</summary>
|
|
public string? Note { get; set; }
|
|
|
|
public DateTime DateAjout { get; set; }
|
|
|
|
public void RecalculerFormes()
|
|
{
|
|
Titre = Titre.Trim();
|
|
TitreNormalise = CleOeuvre.Cle(Titre);
|
|
Auteur = string.IsNullOrWhiteSpace(Auteur) ? null : Auteur.Trim();
|
|
AuteurNormalise = RapprochementAuteurs.Cle(Auteur);
|
|
}
|
|
}
|