Cataloguer les revues : une fiche, ses numéros à l'intérieur
Clôt la décision du premier lot, qui écartait les périodiques faute de modèle. Douze numéros d'un magazine ne font plus douze fiches identiques. Table à part, pour la troisième fois et pour le même motif que la liste d'envies et les séries : logée dans Livres, une revue entrerait dans le catalogue, ses compteurs, les doublons et les bibliographies, et il faudrait écrire « et qui n'est pas une revue » à chaque lecture. Un numéro est recensé, rien de plus — ni prêt ni statut, tous deux liés à Livre par clé étrangère. Réversible. « Créer ou retrouver » et non « créer » : scanner le numéro suivant du même magazine retombe forcément sur la même revue. L'unicité de l'ISSN est un index partiel, sans quoi les revues sans ISSN se bloqueraient entre elles. Le flux 977 mène désormais à la fiche de la revue, et ne pré-remplit plus le formulaire d'un livre. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
using MaBibli.Api.Services.Identite;
|
||||
using MaBibli.Api.Services.Revues;
|
||||
using MaBibli.Shared.Dtos;
|
||||
|
||||
namespace MaBibli.Api.Endpoints;
|
||||
|
||||
public static class RevuesEndpoints
|
||||
{
|
||||
/// <summary>
|
||||
/// Revues et magazines : une fiche par revue, les numéros à l'intérieur.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <b>Communes au foyer</b>, comme le catalogue : aucun point d'entrée ne prend d'identité,
|
||||
/// et « ajoutePar » n'est qu'une trace. La lecture est unique — <c>GET /api/revues</c> rend
|
||||
/// les revues avec leurs numéros, ce qui donne un seul instantané hors-ligne.
|
||||
/// </remarks>
|
||||
public static IEndpointRouteBuilder MapRevuesEndpoints(this IEndpointRouteBuilder routes)
|
||||
{
|
||||
var groupe = routes.MapGroup("/api/revues").WithTags("Revues");
|
||||
|
||||
groupe.MapGet("/", async (IServiceRevues service, CancellationToken ct) =>
|
||||
Results.Ok(await service.ListerAsync(ct)))
|
||||
.WithName("ListerRevues")
|
||||
.WithSummary("Toutes les revues, avec les numéros possédés, du plus récent au plus ancien.")
|
||||
.Produces<IReadOnlyList<RevueDto>>();
|
||||
|
||||
groupe.MapPost("/", async (
|
||||
EnregistrementRevue saisie,
|
||||
IServiceRevues service,
|
||||
IFournisseurUtilisateur utilisateurs,
|
||||
CancellationToken ct) =>
|
||||
{
|
||||
var resultat = await service.CreerOuRetrouverAsync(
|
||||
saisie, utilisateurs.Obtenir().Identifiant, ct);
|
||||
|
||||
return resultat.Erreur is not null
|
||||
? Results.BadRequest(new { erreur = resultat.Erreur })
|
||||
: Results.Ok(resultat.Revue);
|
||||
})
|
||||
.WithName("CreerRevue")
|
||||
.WithSummary("Crée la revue, ou rend celle qui existe déjà (même ISSN, ou même titre).")
|
||||
.WithDescription(
|
||||
"« Créer ou retrouver » et non « créer » : scanner le code-barres d'un second "
|
||||
+ "numéro retombe forcément sur la même revue, et le geste de l'utilisateur est "
|
||||
+ "toujours « voici un numéro de plus ».")
|
||||
.Produces<RevueDto>()
|
||||
.Produces(StatusCodes.Status400BadRequest);
|
||||
|
||||
groupe.MapPut("/{id:int}", async (
|
||||
int id, EnregistrementRevue saisie, IServiceRevues service, CancellationToken ct) =>
|
||||
Repondre(await service.ModifierAsync(id, saisie, ct)))
|
||||
.WithName("ModifierRevue")
|
||||
.Produces<RevueDto>()
|
||||
.Produces(StatusCodes.Status400BadRequest)
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
groupe.MapDelete("/{id:int}", async (int id, IServiceRevues service, CancellationToken ct) =>
|
||||
await service.SupprimerAsync(id, ct) ? Results.NoContent() : Results.NotFound())
|
||||
.WithName("SupprimerRevue")
|
||||
.WithSummary("Supprime la revue et les numéros qu'elle porte : ils n'existent que par elle.")
|
||||
.Produces(StatusCodes.Status204NoContent)
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
groupe.MapPost("/{id:int}/numeros", async (
|
||||
int id, AjoutNumeroRevue saisie, IServiceRevues service, CancellationToken ct) =>
|
||||
Repondre(await service.AjouterNumeroAsync(id, saisie, ct)))
|
||||
.WithName("AjouterNumeroRevue")
|
||||
.WithSummary("Ajoute un numéro possédé. Le numéro est obligatoire et unique dans la revue.")
|
||||
.Produces<RevueDto>()
|
||||
.Produces(StatusCodes.Status400BadRequest)
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
groupe.MapDelete("/numeros/{numeroId:int}", async (
|
||||
int numeroId, IServiceRevues service, CancellationToken ct) =>
|
||||
await service.RetirerNumeroAsync(numeroId, ct)
|
||||
? Results.NoContent()
|
||||
: Results.NotFound())
|
||||
.WithName("RetirerNumeroRevue")
|
||||
.Produces(StatusCodes.Status204NoContent)
|
||||
.Produces(StatusCodes.Status404NotFound);
|
||||
|
||||
return routes;
|
||||
}
|
||||
|
||||
private static IResult Repondre(ResultatRevue resultat)
|
||||
{
|
||||
if (resultat.EstIntrouvable)
|
||||
{
|
||||
return Results.NotFound();
|
||||
}
|
||||
|
||||
return resultat.Erreur is not null
|
||||
? Results.BadRequest(new { erreur = resultat.Erreur })
|
||||
: Results.Ok(resultat.Revue);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user