90 lines
4.1 KiB
C#
90 lines
4.1 KiB
C#
using GerbilManagerWebAPI.Dtos;
|
|
using GerbilManagerWebAPI.Models;
|
|
using Microsoft.AspNetCore.Http.HttpResults;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace GerbilManagerWebAPI.Endpoints
|
|
{
|
|
/// <summary>
|
|
/// ERWERB: acquisition data per animal (purchase date/price/note).
|
|
/// GET /acquisitions?gerbilId=… -> records for one animal (or all), newest date first.
|
|
/// GET /acquisitions/{id} -> a single record.
|
|
/// POST /acquisitions -> create, returns 201.
|
|
/// PUT /acquisitions/{id} -> update, returns 204.
|
|
/// DELETE /acquisitions/{id} -> delete, returns 204.
|
|
/// Decoupled from gerbils/contacts (loose nullable Guid columns, no FK), so rows survive
|
|
/// the import re-ingest wipe (mirrors Feedback).
|
|
/// </summary>
|
|
public static class AcquisitionEndpoints
|
|
{
|
|
public static IEndpointRouteBuilder MapAcquisitionEndpoints(this IEndpointRouteBuilder app)
|
|
{
|
|
var group = app.MapGroup("/acquisitions").WithTags("Acquisitions");
|
|
|
|
group.MapGet("/", async (ApplicationContext db, Guid? gerbilId) =>
|
|
{
|
|
var rows = await db.AcquisitionRecords.AsNoTracking()
|
|
.Where(a => gerbilId == null || a.GerbilId == gerbilId)
|
|
.ToListAsync();
|
|
// Order in memory: SQLite (test host) cannot ORDER BY a DateTimeOffset column,
|
|
// and DateOnly ordering stays consistent across providers this way.
|
|
return TypedResults.Ok(rows
|
|
.OrderByDescending(a => a.Date ?? DateOnly.MinValue)
|
|
.ThenByDescending(a => a.CreatedAt)
|
|
.Select(ToDto)
|
|
.ToList());
|
|
});
|
|
|
|
group.MapGet("/{id:guid}", async Task<Results<Ok<AcquisitionDto>, NotFound>> (Guid id, ApplicationContext db) =>
|
|
{
|
|
var a = await db.AcquisitionRecords.AsNoTracking().FirstOrDefaultAsync(x => x.Id == id);
|
|
return a is null ? TypedResults.NotFound() : TypedResults.Ok(ToDto(a));
|
|
});
|
|
|
|
group.MapPost("/", async (AcquisitionInput input, ApplicationContext db) =>
|
|
{
|
|
var a = new AcquisitionRecord
|
|
{
|
|
Id = Guid.NewGuid(),
|
|
GerbilId = input.GerbilId,
|
|
SourceContactId = input.SourceContactId,
|
|
Date = input.Date,
|
|
Price = input.Price,
|
|
Note = string.IsNullOrWhiteSpace(input.Note) ? null : input.Note.Trim(),
|
|
CreatedAt = DateTimeOffset.UtcNow,
|
|
};
|
|
db.AcquisitionRecords.Add(a);
|
|
await db.SaveChangesAsync();
|
|
return TypedResults.Created($"/acquisitions/{a.Id}", ToDto(a));
|
|
});
|
|
|
|
group.MapPut("/{id:guid}", async Task<Results<NoContent, NotFound>> (Guid id, AcquisitionInput input, ApplicationContext db) =>
|
|
{
|
|
var a = await db.AcquisitionRecords.FirstOrDefaultAsync(x => x.Id == id);
|
|
if (a is null) return TypedResults.NotFound();
|
|
a.GerbilId = input.GerbilId;
|
|
a.SourceContactId = input.SourceContactId;
|
|
a.Date = input.Date;
|
|
a.Price = input.Price;
|
|
a.Note = string.IsNullOrWhiteSpace(input.Note) ? null : input.Note.Trim();
|
|
await db.SaveChangesAsync();
|
|
return TypedResults.NoContent();
|
|
});
|
|
|
|
group.MapDelete("/{id:guid}", async Task<Results<NoContent, NotFound>> (Guid id, ApplicationContext db) =>
|
|
{
|
|
var a = await db.AcquisitionRecords.FirstOrDefaultAsync(x => x.Id == id);
|
|
if (a is null) return TypedResults.NotFound();
|
|
db.AcquisitionRecords.Remove(a);
|
|
await db.SaveChangesAsync();
|
|
return TypedResults.NoContent();
|
|
});
|
|
|
|
return app;
|
|
}
|
|
|
|
private static AcquisitionDto ToDto(AcquisitionRecord a) =>
|
|
new(a.Id, a.GerbilId, a.SourceContactId, a.Date, a.Price, a.Note, a.CreatedAt);
|
|
}
|
|
}
|