Merge feature/seed-hell: Backend-Seed 61->66 append-only (IDs 62-66, bestehende ID->Name-Bindung unveraendert, Drift-Regressionstest) [god-QA validated]
Some checks failed
CI / Backend Tests (.NET) (push) Successful in 53s
CI / Docker Build & Push (push) Has been cancelled
CI / Frontend Tests (Node/Vite) (push) Has been cancelled

This commit is contained in:
2026-06-06 15:42:36 +02:00
5 changed files with 1466 additions and 0 deletions

View File

@@ -545,6 +545,32 @@ namespace GerbilManager.Tests
finally { try { Directory.Delete(dir, recursive: true); } catch { } } finally { try { Directory.Delete(dir, recursive: true); } catch { } }
} }
[Fact]
public void SeedGen3g_existing_varieties_preserve_id_name_binding()
{
// SEED-HELL bounce regression: the 61 existing entries must NOT change their
// Id->Name binding after GEN-3g. The 5 new entries (IDs 62-66) are appended.
// A hand-assigned Gerbil.ColorVarietyId pointing to "CP-Fuchs" (ID 58) must
// still map to CP-Fuchs after the migration runs (append-only, no rename-shift).
using var db = NewDb(); // EnsureCreated applies HasData including new 66-entry seed
// ID 58 (index 57 in old catalog, 0-based) = CP-Fuchs — must still be CP-Fuchs
var cpFuchsId = new Guid("00000000-0000-0000-0000-000000000058");
var cpFuchs = db.ColorVarieties.Find(cpFuchsId);
Assert.NotNull(cpFuchs);
Assert.Equal("CP-Fuchs", cpFuchs!.Name);
// New entries at IDs 62-66 exist with correct names
Assert.Equal("CP-Agouti-Hell", db.ColorVarieties.Find(new Guid("00000000-0000-0000-0000-000000000062"))!.Name);
Assert.Equal("CP-Silberagouti-Hell", db.ColorVarieties.Find(new Guid("00000000-0000-0000-0000-000000000063"))!.Name);
Assert.Equal("CP-Algierfuchs-Hell", db.ColorVarieties.Find(new Guid("00000000-0000-0000-0000-000000000064"))!.Name);
Assert.Equal("CP-Polarfuchs-Hell", db.ColorVarieties.Find(new Guid("00000000-0000-0000-0000-000000000065"))!.Name);
Assert.Equal("CP-Orangeschimmel-Hell", db.ColorVarieties.Find(new Guid("00000000-0000-0000-0000-000000000066"))!.Name);
// Total count is exactly 66
Assert.Equal(66, db.ColorVarieties.Count());
}
[Theory] [Theory]
[InlineData("01.02.2020", 2020, 2, 1)] [InlineData("01.02.2020", 2020, 2, 1)]
[InlineData("5.3.21", 2021, 3, 5)] [InlineData("5.3.21", 2021, 3, 5)]

View File

@@ -231,6 +231,10 @@ public class ApplicationContext : DbContext
/// </summary> /// </summary>
private static void SeedColorVarieties(ModelBuilder modelBuilder) private static void SeedColorVarieties(ModelBuilder modelBuilder)
{ {
// GEN-3g (Kevin): 5 CP-*-Hell variants appended at the end (IDs 62-66).
// Existing 61 entries are UNCHANGED (same ID->Name binding preserved).
// SortOrder for new entries is appended; Kevin's frontend catalog handles
// the interleaved display order via its own sortOrder values.
(string Name, string Genotype)[] catalog = (string Name, string Genotype)[] catalog =
{ {
("Pink Eyed White (PEW)", "AA chch DD EE GG pp spsp rere"), ("Pink Eyed White (PEW)", "AA chch DD EE GG pp spsp rere"),
@@ -294,6 +298,12 @@ public class ApplicationContext : DbContext
("CP-Fuchs-Hell", "AA cchmch dd ee GG PP spsp rere"), ("CP-Fuchs-Hell", "AA cchmch dd ee GG PP spsp rere"),
("CP-Blaufuchs", "AA cchmcchm dd ee gg PP spsp rere"), ("CP-Blaufuchs", "AA cchmcchm dd ee gg PP spsp rere"),
("CP-Orangeschimmel", "AA cchmcchm DD efef GG PP spsp rere"), ("CP-Orangeschimmel", "AA cchmcchm DD efef GG PP spsp rere"),
// GEN-3g: 5 new CP-*-Hell variants appended (IDs 62-66, no ID->Name drift)
("CP-Agouti-Hell", "AA cchmch DD EE GG PP spsp rere"),
("CP-Silberagouti-Hell", "AA cchmch DD EE gg PP spsp rere"),
("CP-Algierfuchs-Hell", "AA cchmch DD ee GG PP spsp rere"),
("CP-Polarfuchs-Hell", "AA cchmch DD ee gg PP spsp rere"),
("CP-Orangeschimmel-Hell","AA cchmch DD efef GG PP spsp rere"),
}; };
var rows = new ColorVariety[catalog.Length]; var rows = new ColorVariety[catalog.Length];

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,58 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
namespace GerbilManagerWebAPI.Migrations
{
/// <inheritdoc />
public partial class ReseedColorVarietiesGen3g : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.InsertData(
table: "ColorVarieties",
columns: new[] { "Id", "CanonicalGenotype", "Name", "SortOrder" },
values: new object[,]
{
{ new Guid("00000000-0000-0000-0000-000000000062"), "AA cchmch DD EE GG PP spsp rere", "CP-Agouti-Hell", 61 },
{ new Guid("00000000-0000-0000-0000-000000000063"), "AA cchmch DD EE gg PP spsp rere", "CP-Silberagouti-Hell", 62 },
{ new Guid("00000000-0000-0000-0000-000000000064"), "AA cchmch DD ee GG PP spsp rere", "CP-Algierfuchs-Hell", 63 },
{ new Guid("00000000-0000-0000-0000-000000000065"), "AA cchmch DD ee gg PP spsp rere", "CP-Polarfuchs-Hell", 64 },
{ new Guid("00000000-0000-0000-0000-000000000066"), "AA cchmch DD efef GG PP spsp rere", "CP-Orangeschimmel-Hell", 65 }
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "ColorVarieties",
keyColumn: "Id",
keyValue: new Guid("00000000-0000-0000-0000-000000000062"));
migrationBuilder.DeleteData(
table: "ColorVarieties",
keyColumn: "Id",
keyValue: new Guid("00000000-0000-0000-0000-000000000063"));
migrationBuilder.DeleteData(
table: "ColorVarieties",
keyColumn: "Id",
keyValue: new Guid("00000000-0000-0000-0000-000000000064"));
migrationBuilder.DeleteData(
table: "ColorVarieties",
keyColumn: "Id",
keyValue: new Guid("00000000-0000-0000-0000-000000000065"));
migrationBuilder.DeleteData(
table: "ColorVarieties",
keyColumn: "Id",
keyValue: new Guid("00000000-0000-0000-0000-000000000066"));
}
}
}

View File

@@ -605,6 +605,41 @@ namespace GerbilManagerWebAPI.Migrations
CanonicalGenotype = "AA cchmcchm DD efef GG PP spsp rere", CanonicalGenotype = "AA cchmcchm DD efef GG PP spsp rere",
Name = "CP-Orangeschimmel", Name = "CP-Orangeschimmel",
SortOrder = 60 SortOrder = 60
},
new
{
Id = new Guid("00000000-0000-0000-0000-000000000062"),
CanonicalGenotype = "AA cchmch DD EE GG PP spsp rere",
Name = "CP-Agouti-Hell",
SortOrder = 61
},
new
{
Id = new Guid("00000000-0000-0000-0000-000000000063"),
CanonicalGenotype = "AA cchmch DD EE gg PP spsp rere",
Name = "CP-Silberagouti-Hell",
SortOrder = 62
},
new
{
Id = new Guid("00000000-0000-0000-0000-000000000064"),
CanonicalGenotype = "AA cchmch DD ee GG PP spsp rere",
Name = "CP-Algierfuchs-Hell",
SortOrder = 63
},
new
{
Id = new Guid("00000000-0000-0000-0000-000000000065"),
CanonicalGenotype = "AA cchmch DD ee gg PP spsp rere",
Name = "CP-Polarfuchs-Hell",
SortOrder = 64
},
new
{
Id = new Guid("00000000-0000-0000-0000-000000000066"),
CanonicalGenotype = "AA cchmch DD efef GG PP spsp rere",
Name = "CP-Orangeschimmel-Hell",
SortOrder = 65
}); });
}); });