Distinguer scénario, dessin et couleurs sur chaque livre
Le rôle vit sur le LIEN livre-auteur, jamais sur l'auteur : le même auteur scénarise un album et dessine le suivant, et il ne doit pas exister en deux fiches pour autant — ce que l'index unique sur la clé de regroupement interdit de toute façon. Les rôles se retrouvent par clé d'auteur résolue et non par position : ResoudreAsync écarte les noms vides et fusionne les variantes, donc sa liste peut être plus courte que la saisie. Piège traité : le champ des noms reconstruit la liste à chaque frappe. Decouper reprend les rôles connus en rapprochant sur la forme normalisée, sans quoi corriger une faute de frappe les effacerait tous. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -288,8 +288,10 @@ public sealed class ServiceCatalogue(MaBibliDbContext db, IServiceAuteurs auteur
|
||||
db.Livres.AsNoTracking().Include(l => l.Auteurs).ThenInclude(la => la.Auteur);
|
||||
|
||||
/// <summary>Un des auteurs du livre catalogué est-il l'un de ceux qu'on est en train de saisir ?</summary>
|
||||
private static bool MemeAuteur(Livre livre, IReadOnlyList<string> saisis) =>
|
||||
RapprochementAuteurs.PartagentUnAuteur(livre.Auteurs.Select(la => la.Auteur?.Nom), saisis);
|
||||
/// <remarks>Le rôle n'entre pas dans la comparaison : c'est la personne qui compte ici.</remarks>
|
||||
private static bool MemeAuteur(Livre livre, IReadOnlyList<AuteurSaisi> saisis) =>
|
||||
RapprochementAuteurs.PartagentUnAuteur(
|
||||
livre.Auteurs.Select(la => la.Auteur?.Nom), saisis.Select(a => a.Nom));
|
||||
|
||||
/// <summary>Phrase d'avertissement, écrite pour être lue telle quelle par l'utilisateur.</summary>
|
||||
/// <remarks>
|
||||
@@ -399,11 +401,18 @@ public sealed class ServiceCatalogue(MaBibliDbContext db, IServiceAuteurs auteur
|
||||
await db.SaveChangesAsync(ct);
|
||||
}
|
||||
|
||||
/// <summary>Remplace les auteurs du livre par ceux de la saisie, en conservant leur ordre.</summary>
|
||||
/// <summary>
|
||||
/// Remplace les auteurs du livre par ceux de la saisie, en conservant leur ordre et leur rôle.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// ⚠️ Le <b>rôle vit sur le lien</b>, pas sur la fiche de l'auteur : le même dessinateur
|
||||
/// peut avoir scénarisé un autre album, et il ne doit pas exister en deux fiches pour
|
||||
/// autant. C'est pour cela que <c>ResoudreAsync</c> ne reçoit que des noms.
|
||||
/// </remarks>
|
||||
private async Task RattacherAuteursAsync(
|
||||
Livre livre, IEnumerable<string> noms, CancellationToken ct)
|
||||
Livre livre, IReadOnlyList<AuteurSaisi> saisis, CancellationToken ct)
|
||||
{
|
||||
var resolus = await auteurs.ResoudreAsync(noms, ct);
|
||||
var resolus = await auteurs.ResoudreAsync(saisis.Select(a => a.Nom), ct);
|
||||
|
||||
// Les liens existants sont retirés puis reconstruits : c'est la façon la plus simple de
|
||||
// gérer à la fois l'ajout, le retrait et le réordonnancement des auteurs.
|
||||
@@ -413,9 +422,23 @@ public sealed class ServiceCatalogue(MaBibliDbContext db, IServiceAuteurs auteur
|
||||
livre.Auteurs.Clear();
|
||||
}
|
||||
|
||||
// ResoudreAsync écarte les noms vides et fusionne les variantes : sa liste peut être
|
||||
// plus courte que la saisie. Les rôles se retrouvent donc par NOM RÉSOLU, jamais par
|
||||
// position — sans quoi un nom vide au milieu décalerait tous les rôles suivants.
|
||||
var roles = new Dictionary<string, RoleAuteur>(StringComparer.Ordinal);
|
||||
foreach (var saisi in saisis)
|
||||
{
|
||||
roles.TryAdd(RapprochementAuteurs.Cle(saisi.Nom), saisi.Role);
|
||||
}
|
||||
|
||||
for (var i = 0; i < resolus.Count; i++)
|
||||
{
|
||||
livre.Auteurs.Add(new LivreAuteur { Auteur = resolus[i], Position = i });
|
||||
livre.Auteurs.Add(new LivreAuteur
|
||||
{
|
||||
Auteur = resolus[i],
|
||||
Position = i,
|
||||
Role = roles.GetValueOrDefault(resolus[i].CleRegroupement, RoleAuteur.NonPrecise),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -464,7 +487,7 @@ public sealed class ServiceCatalogue(MaBibliDbContext db, IServiceAuteurs auteur
|
||||
Auteurs = livre.Auteurs
|
||||
.OrderBy(la => la.Position)
|
||||
.Where(la => la.Auteur is not null)
|
||||
.Select(la => new AuteurDto { Id = la.Auteur!.Id, Nom = la.Auteur.Nom })
|
||||
.Select(la => new AuteurDto { Id = la.Auteur!.Id, Nom = la.Auteur.Nom, Role = la.Role })
|
||||
.ToList(),
|
||||
Editeur = livre.Editeur,
|
||||
Format = livre.Format,
|
||||
|
||||
Reference in New Issue
Block a user