Gestion de bibliothèque personnelle auto-hébergée : catalogue, prêts, scan de code-barres, consultation hors-ligne. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
109 lines
5.0 KiB
C#
109 lines
5.0 KiB
C#
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.MapPut("/numeros/{numeroId:int}", async (
|
|
int numeroId, AjoutNumeroRevue saisie, IServiceRevues service, CancellationToken ct) =>
|
|
Repondre(await service.ModifierNumeroAsync(numeroId, saisie, ct)))
|
|
.WithName("ModifierNumeroRevue")
|
|
.WithSummary("Modifie un numéro : numéro, parution, note, couverture et articles à la une.")
|
|
.WithDescription(
|
|
"La couverture d'un numéro et sa une ne viennent d'aucune source — l'ISSN "
|
|
+ "désigne la revue, pas la parution — et se saisissent donc après coup.")
|
|
.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);
|
|
}
|
|
}
|