- Entities: Breeder->Contact, +Enclosure/ColorVariety/GerbilPhoto/HealthRecord/WeightRecord;
Gerbil expanded (single Genotype text col, Status/Gender enums-as-string, FK ids,
ImportSource/ExternalRef provenance); Litter Strength->TotalBorn +ExpectedGoHomeDate/Notes.
ColorVariety HasData seed = 18 from GEN-1 catalog. Gerbil<->Litter cycle handled
(SetNull/Restrict). Enums stored as strings.
- Minimal API (no controllers): Endpoints/*.cs MapGroup+TypedResults for gerbils, litters,
contacts, enclosures, color-varieties, health/weight-records, inbreeding (converted from
controller, same routes/shapes), photos (Oscar contract: GET array/POST multipart/DELETE,
url /photos/files/{fileName}). Gridify paged {items,totalCount,page,pageSize}, camelCase,
409 conflict-deletes, flat FK ids, litter parent-gender validation (400 {code,...}).
- Scalar replaces Swashbuckle (AddOpenApi/MapOpenApi + MapScalarApiReference at /scalar);
launchUrl swagger->scalar. GenericRepository/UnitOfWork/Converters deleted; DbContext direct.
- InbreedingService reads real FK props now; pure calculator + 8 tests untouched.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
108 lines
4.8 KiB
C#
108 lines
4.8 KiB
C#
using GerbilManagerWebAPI.Models;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
public class ApplicationContext : DbContext
|
|
{
|
|
public ApplicationContext(DbContextOptions options) : base(options)
|
|
{
|
|
}
|
|
|
|
public DbSet<Gerbil> Gerbils => Set<Gerbil>();
|
|
public DbSet<Litter> Litters => Set<Litter>();
|
|
public DbSet<Contact> Contacts => Set<Contact>();
|
|
public DbSet<Enclosure> Enclosures => Set<Enclosure>();
|
|
public DbSet<ColorVariety> ColorVarieties => Set<ColorVariety>();
|
|
public DbSet<GerbilPhoto> GerbilPhotos => Set<GerbilPhoto>();
|
|
public DbSet<HealthRecord> HealthRecords => Set<HealthRecord>();
|
|
public DbSet<WeightRecord> WeightRecords => Set<WeightRecord>();
|
|
|
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
|
{
|
|
modelBuilder.Entity<Gerbil>(e =>
|
|
{
|
|
// Enums persisted as their string names (readable, Gridify-friendly).
|
|
e.Property(g => g.Gender).HasConversion<string>();
|
|
e.Property(g => g.Status).HasConversion<string>();
|
|
|
|
e.HasOne(g => g.Litter).WithMany()
|
|
.HasForeignKey(g => g.LitterId).OnDelete(DeleteBehavior.SetNull);
|
|
e.HasOne(g => g.OriginContact).WithMany()
|
|
.HasForeignKey(g => g.OriginContactId).OnDelete(DeleteBehavior.Restrict);
|
|
e.HasOne(g => g.ReceiverContact).WithMany()
|
|
.HasForeignKey(g => g.ReceiverContactId).OnDelete(DeleteBehavior.Restrict);
|
|
e.HasOne(g => g.Enclosure).WithMany(en => en.Gerbils)
|
|
.HasForeignKey(g => g.EnclosureId).OnDelete(DeleteBehavior.SetNull);
|
|
e.HasOne(g => g.ColorVariety).WithMany()
|
|
.HasForeignKey(g => g.ColorVarietyId).OnDelete(DeleteBehavior.SetNull);
|
|
});
|
|
|
|
modelBuilder.Entity<Litter>(e =>
|
|
{
|
|
e.HasOne(l => l.Father).WithMany()
|
|
.HasForeignKey(l => l.FatherId).OnDelete(DeleteBehavior.Restrict);
|
|
e.HasOne(l => l.Mother).WithMany()
|
|
.HasForeignKey(l => l.MotherId).OnDelete(DeleteBehavior.Restrict);
|
|
});
|
|
|
|
modelBuilder.Entity<HealthRecord>(e =>
|
|
{
|
|
e.Property(h => h.Type).HasConversion<string>();
|
|
e.HasOne<Gerbil>().WithMany()
|
|
.HasForeignKey(h => h.GerbilId).OnDelete(DeleteBehavior.Cascade);
|
|
});
|
|
|
|
modelBuilder.Entity<WeightRecord>(e =>
|
|
e.HasOne<Gerbil>().WithMany()
|
|
.HasForeignKey(w => w.GerbilId).OnDelete(DeleteBehavior.Cascade));
|
|
|
|
modelBuilder.Entity<GerbilPhoto>(e =>
|
|
e.HasOne<Gerbil>().WithMany()
|
|
.HasForeignKey(p => p.GerbilId).OnDelete(DeleteBehavior.Cascade));
|
|
|
|
SeedColorVarieties(modelBuilder);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Seed the 18 base varieties from the GEN-1 catalog (gerbil-manager-web/src/genetics/catalog.ts).
|
|
/// Source of truth for names; the baseportal 78-variety extension lands in GEN-2 (re-seed later).
|
|
/// </summary>
|
|
private static void SeedColorVarieties(ModelBuilder modelBuilder)
|
|
{
|
|
(string Name, string Genotype)[] catalog =
|
|
{
|
|
("Pink Eyed White (PEW)", "AA chch DD EE GG pp spsp rere"),
|
|
("Hermelin", "aa chch DD EE GG PP spsp rere"),
|
|
("Himalaya", "AA chch DD EE GG PP spsp rere"),
|
|
("Zobel", "aa cchmcchm DD EE gg PP spsp rere"),
|
|
("Schwarzschimmel", "AA CC DD efef GG PP spsp rere"),
|
|
("Rotaugenschimmel", "AA CC DD efef GG pp spsp rere"),
|
|
("Agouti", "AA CC DD EE GG PP spsp rere"),
|
|
("Schwarz", "aa CC DD EE GG PP spsp rere"),
|
|
("Silberagouti", "AA CC DD EE gg PP spsp rere"),
|
|
("Anthrazit", "aa CC DD EE gg PP spsp rere"),
|
|
("Algierfuchs", "AA CC DD ee GG PP spsp rere"),
|
|
("Blau", "aa CC dd EE GG PP spsp rere"),
|
|
("Gold", "AA CC DD EE GG pp spsp rere"),
|
|
("Platin", "aa CC DD EE GG pp spsp rere"),
|
|
("Goldfuchs", "AA CC DD ee GG pp spsp rere"),
|
|
("Rotfuchs", "aa CC DD ee GG pp spsp rere"),
|
|
("dd Gold", "AA CC dd EE GG pp spsp rere"),
|
|
("dd Platin", "aa CC dd EE GG pp spsp rere"),
|
|
};
|
|
|
|
var rows = new ColorVariety[catalog.Length];
|
|
for (int i = 0; i < catalog.Length; i++)
|
|
{
|
|
rows[i] = new ColorVariety
|
|
{
|
|
// Stable, deterministic GUIDs so the HasData seed is migration-stable.
|
|
Id = new Guid($"00000000-0000-0000-0000-{(i + 1):D12}"),
|
|
Name = catalog[i].Name,
|
|
CanonicalGenotype = catalog[i].Genotype,
|
|
SortOrder = i,
|
|
};
|
|
}
|
|
modelBuilder.Entity<ColorVariety>().HasData(rows);
|
|
}
|
|
}
|