FEAT-8c: import loader — /import/dry-run + /import/execute (gated)

- Additive migration: Gerbil.RawImportData + Litter.PairingCode (Zuchtnummer der Verpaarung).
- ImportService consumes tools/import/output (animals.json + litters.json): litters first
  (authoritative), then conflict-free animals with a DOB; high-confidence (hoch) litter links
  set LitterId, date-only/ambiguous links quarantined; conflicts + stubs never loaded.
  Genotype mapped8locus -> frozen compact string; rawGenotype+unmappedTokens preserved in
  RawImportData; Farbschlag matched to ColorVariety; gender inferred from litter role;
  provenance ImportSource/ExternalRef; idempotent (ExternalRef / Name+Date). Photos copied to store.
- ImportEndpoints: POST /import/dry-run (no writes, Julian-readable report) + /import/execute (gated).
This commit is contained in:
2026-06-06 07:33:26 +02:00
parent e431c50347
commit ac5ab9d0ba
9 changed files with 1368 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
using GerbilManagerWebAPI.Import;
using Microsoft.AspNetCore.Http.HttpResults;
namespace GerbilManagerWebAPI.Endpoints
{
/// <summary>
/// FEAT-8 stage 3 — spreadsheet import loader. Consumes tools/import/output.
/// POST /import/dry-run -> report what WOULD be created/linked/quarantined (no writes)
/// POST /import/execute -> load the conflict-free subset (idempotent). GATED: only run
/// against Julian's DB under god-supervision after he approves the dry-run.
/// </summary>
public static class ImportEndpoints
{
public static IEndpointRouteBuilder MapImportEndpoints(this IEndpointRouteBuilder app)
{
var group = app.MapGroup("/import").WithTags("Import");
group.MapPost("/dry-run", async Task<Ok<ImportReport>> (
ApplicationContext db, IConfiguration config, IWebHostEnvironment env) =>
{
var report = await new ImportService(db, config, env).RunAsync(execute: false);
return TypedResults.Ok(report);
});
group.MapPost("/execute", async Task<Ok<ImportReport>> (
ApplicationContext db, IConfiguration config, IWebHostEnvironment env) =>
{
var report = await new ImportService(db, config, env).RunAsync(execute: true);
return TypedResults.Ok(report);
});
return app;
}
}
}