diff --git a/GerbilManager.Tests/GerbilStatusTests.cs b/GerbilManager.Tests/GerbilStatusTests.cs
index 7101b33..173ca73 100644
--- a/GerbilManager.Tests/GerbilStatusTests.cs
+++ b/GerbilManager.Tests/GerbilStatusTests.cs
@@ -38,9 +38,9 @@ public class GerbilStatusTests
Assert.Equal(GerbilStatus.GivenAway, status);
}
- // 3) Age > 7y, no death, not abgegeben → Deceased (presumed)
+ // 3) Age > 6y, no death, not abgegeben → Deceased (presumed)
[Fact]
- public void OlderThan7y_without_death_returns_Deceased()
+ public void OlderThan6y_without_death_returns_Deceased()
{
var dob = Today.AddYears(-GerbilStatusService.MaxAgeYears).AddDays(-1); // 1 day past threshold
var status = GerbilStatusService.Derive(
@@ -48,14 +48,14 @@ public class GerbilStatusTests
Assert.Equal(GerbilStatus.Deceased, status);
}
- // Exactly 7 years old is NOT presumed dead (threshold is strictly >)
+ // Exactly 6 years old is NOT presumed dead (threshold is strictly >)
[Fact]
public void ExactlyMaxAge_is_not_Deceased()
{
- var dob = Today.AddYears(-GerbilStatusService.MaxAgeYears); // exactly 7y today
+ var dob = Today.AddYears(-GerbilStatusService.MaxAgeYears); // exactly 6y today
var status = GerbilStatusService.Derive(
GerbilStatus.Breeding, dob, dateOfDeath: null, isAbgegeben: false, Today);
- // today >= dob.AddYears(7) → exactly equal → IS presumed dead
+ // today >= dob.AddYears(6) → exactly equal → IS presumed dead
// (threshold = "older than" so >= means Deceased)
Assert.Equal(GerbilStatus.Deceased, status);
}
@@ -70,11 +70,11 @@ public class GerbilStatusTests
Assert.Equal(GerbilStatus.Breeding, status);
}
- // 3a) Age > 7y but Abgegeben → stays GivenAway (not Deceased)
+ // 3a) Age > 6y but Abgegeben → stays GivenAway (not Deceased)
[Fact]
- public void OlderThan7y_but_Abgegeben_stays_GivenAway()
+ public void OlderThan6y_but_Abgegeben_stays_GivenAway()
{
- var dob = Today.AddYears(-8);
+ var dob = Today.AddYears(-7);
var status = GerbilStatusService.Derive(
GerbilStatus.GivenAway, dob, dateOfDeath: null, isAbgegeben: true, Today);
Assert.Equal(GerbilStatus.GivenAway, status);
diff --git a/GerbilManagerWebAPI/Contracts/ContractData.cs b/GerbilManagerWebAPI/Contracts/ContractData.cs
index 3c19e97..a18a6ba 100644
--- a/GerbilManagerWebAPI/Contracts/ContractData.cs
+++ b/GerbilManagerWebAPI/Contracts/ContractData.cs
@@ -13,11 +13,14 @@ public sealed record ContractBuyer(
/// Deutscher Anzeigetext („Weiblich“/„Männlich“) — die
/// Abbildung vom Gender-Enum passiert im Aufrufer (Phase B), der
/// Generator bleibt frei von Modell-Abhängigkeiten.
+/// Optionales Tierfoto (Rohbytes der Bilddatei) fürs Vertragsbild;
+/// nur der PDF-Generator wertet es aus, der .docx-Generator ignoriert es.
public sealed record ContractAnimal(
string Name,
string Geschlecht,
DateOnly? Geburtsdatum = null,
- string? Farbschlag = null);
+ string? Farbschlag = null,
+ byte[]? Photo = null);
///
/// Alle Eingaben des Vertragsgenerators. Reines Daten-Objekt, keine EF-Typen.
diff --git a/GerbilManagerWebAPI/Contracts/ContractPdfGenerator.cs b/GerbilManagerWebAPI/Contracts/ContractPdfGenerator.cs
new file mode 100644
index 0000000..faa7e4b
--- /dev/null
+++ b/GerbilManagerWebAPI/Contracts/ContractPdfGenerator.cs
@@ -0,0 +1,241 @@
+using System.Globalization;
+using QuestPDF.Fluent;
+using QuestPDF.Helpers;
+using QuestPDF.Infrastructure;
+
+namespace GerbilManagerWebAPI.Contracts;
+
+///
+/// FEAT-13 (PDF): erzeugt den Abgabevertrag als druckfertiges PDF (A4) aus
+/// — gleiche Daten wie der .docx-Generator, reiner
+/// .NET-Code (QuestPDF), keine externen Konverter. Der Fließtext der Abschnitte
+/// 4–8 entspricht dem Mustervertrag (Vorlage Abgabevertrag.docx).
+///
+public static class ContractPdfGenerator
+{
+ static ContractPdfGenerator()
+ {
+ // QuestPDF Community License (kostenlos für Einzelpersonen / kleine Firmen).
+ QuestPDF.Settings.License = LicenseType.Community;
+ }
+
+ private static readonly CultureInfo German = CultureInfo.GetCultureInfo("de-DE");
+ private static string Price(decimal p) => p.ToString("N2", German) + " €";
+ private static string D(DateOnly d) => d.ToString("dd.MM.yyyy", German);
+ private static string Or(string? v, string fallback = "—") => string.IsNullOrWhiteSpace(v) ? fallback : v!;
+
+ private const string Accent = "#A85F2E";
+ private const string Ink = "#3D2E23";
+ private const string Line = "#D9CCB4";
+
+ public static byte[] Generate(ContractData data)
+ {
+ ArgumentNullException.ThrowIfNull(data);
+
+ return Document.Create(doc =>
+ {
+ doc.Page(page =>
+ {
+ page.Size(PageSizes.A4);
+ page.Margin(1.8f, Unit.Centimetre);
+ page.DefaultTextStyle(x => x.FontSize(9.5f).FontColor(Ink).LineHeight(1.25f));
+
+ page.Header().PaddingBottom(8).Column(h =>
+ {
+ h.Item().Text("Schutzvertrag / Kaufvertrag").FontSize(18).Bold().FontColor(Accent);
+ h.Item().Text("Mongolische Rennmäuse").FontSize(10).FontColor("#8C7F6E");
+ });
+
+ page.Content().PaddingTop(6).Column(col =>
+ {
+ col.Spacing(12);
+ Parties(col, data);
+ Animals(col, data);
+ Subject(col, data);
+ Clauses(col);
+ Signatures(col, data);
+ });
+
+ page.Footer().AlignCenter().Text(t =>
+ {
+ t.DefaultTextStyle(x => x.FontSize(8).FontColor("#8C7F6E"));
+ t.Span("Seite ");
+ t.CurrentPageNumber();
+ t.Span(" / ");
+ t.TotalPages();
+ });
+ });
+ }).GeneratePdf();
+ }
+
+ private static void Heading(ColumnDescriptor col, string text) =>
+ col.Item().PaddingTop(4).Text(text).FontSize(12).Bold().FontColor(Accent);
+
+ private static void Kv(ColumnDescriptor col, string label, string value) =>
+ col.Item().Row(r =>
+ {
+ r.ConstantItem(150).Text(label).FontColor("#8C7F6E");
+ r.RelativeItem().Text(value).SemiBold();
+ });
+
+ private static void Bullet(ColumnDescriptor col, string text) =>
+ col.Item().Row(r =>
+ {
+ r.ConstantItem(14).Text("•").FontColor(Accent);
+ r.RelativeItem().Text(text);
+ });
+
+ private static void Parties(ColumnDescriptor col, ContractData data)
+ {
+ var s = data.Seller;
+ var b = data.Buyer;
+ Heading(col, "1. Vertragspartner");
+ col.Item().Text("Verkäufer / Züchter").SemiBold();
+ col.Item().Column(c =>
+ {
+ c.Spacing(2);
+ Kv(c, "Zuchtname:", Or(s.ZuchtName));
+ Kv(c, "Vor- und Nachname:", Or(s.Name));
+ Kv(c, "Adresse:", Or(s.Address));
+ Kv(c, "Telefon:", Or(s.Phone, ""));
+ Kv(c, "E-Mail:", Or(s.Email, ""));
+ Kv(c, "Homepage:", Or(s.Homepage, ""));
+ });
+ col.Item().PaddingTop(4).Text("Käufer / Abnehmer").SemiBold();
+ col.Item().Column(c =>
+ {
+ c.Spacing(2);
+ Kv(c, "Vor- und Nachname:", Or(b.Name));
+ Kv(c, "Adresse:", Or(b.Address));
+ Kv(c, "Telefon:", Or(b.Phone, ""));
+ Kv(c, "E-Mail:", Or(b.Email, ""));
+ });
+ }
+
+ private static void Animals(ColumnDescriptor col, ContractData data)
+ {
+ Heading(col, "2. Angaben zu den Tieren");
+ col.Item().Column(list =>
+ {
+ list.Spacing(10);
+ foreach (var a in data.Animals)
+ {
+ // Ein Block je Tier: links das (optionale) Foto, rechts die Stammdaten —
+ // wie im Mustervertrag (das große Rechteck links).
+ list.Item().Border(1).BorderColor(Line).Row(row =>
+ {
+ row.RelativeItem(2f).MinHeight(150).BorderRight(1).BorderColor(Line)
+ .Padding(4).Element(box =>
+ {
+ if (a.Photo is { Length: > 0 } bytes)
+ box.AlignMiddle().Image(bytes).FitArea();
+ else
+ box.AlignMiddle().AlignCenter().Text("Kein Foto")
+ .FontSize(8).FontColor("#B8AC97");
+ });
+
+ row.RelativeItem(3f).Column(kv =>
+ {
+ AnimalRow(kv, "Name:", Or(a.Name, ""));
+ AnimalRow(kv, "Tierart:", "Mongolische Rennmaus");
+ AnimalRow(kv, "Geschlecht:", Or(a.Geschlecht));
+ AnimalRow(kv, "Geburtsdatum:", a.Geburtsdatum is { } born ? D(born) : "—");
+ AnimalRow(kv, "Farbschlag:", Or(a.Farbschlag, ""), last: true);
+ });
+ });
+ }
+ });
+ }
+
+ private static void AnimalRow(ColumnDescriptor col, string label, string value, bool last = false)
+ {
+ var cell = col.Item();
+ if (!last) cell = cell.BorderBottom(1).BorderColor(Line);
+ cell.PaddingVertical(7).PaddingHorizontal(8).Row(r =>
+ {
+ r.ConstantItem(100).Text(label).FontColor("#8C7F6E");
+ r.RelativeItem().Text(value).SemiBold();
+ });
+ }
+
+ private static void Subject(ColumnDescriptor col, ContractData data)
+ {
+ Heading(col, "3. Gegenstand des Vertrages");
+ col.Item().Text(
+ $"Der Züchter verkauft dem Käufer mit Unterzeichnung des vorliegenden Vertrages die oben " +
+ $"erwähnten Tiere zu einem Kaufpreis von {Price(data.Price)}. Der Kaufpreis ist bei Übergabe " +
+ $"der Tiere vollständig bezahlt worden. Die Tiere wurden am {D(data.HandoverDate)} dem Käufer " +
+ $"von dem Züchter übergeben.");
+ }
+
+ private static void Clauses(ColumnDescriptor col)
+ {
+ Heading(col, "4. Einverständniserklärung zur Erhebung personenbezogener Daten");
+ col.Item().Text(
+ "Der Käufer stimmt der Erhebung und der Verarbeitung seiner oben aufgeführten Daten durch den " +
+ "Verkäufer zu. Diese werden von dem Züchter vertraulich im Rahmen seiner Zucht behandelt. Darüber " +
+ "hinaus benötigt es für jede weitere Datenerhebung die Zustimmung des Käufers. Der Abnehmer hat das " +
+ "Recht, diese Einwilligung jederzeit ohne Angabe einer Begründung zu widerrufen. Weiterhin können " +
+ "erhobene Daten bei Bedarf korrigiert, gelöscht oder deren Erhebung eingeschränkt werden.");
+
+ Heading(col, "5. Pflichten des Käufers");
+ col.Item().Text(
+ "Tiere sind keine Sache, sondern empfindungs- und leidensfähige Lebewesen. Der Abnehmer ist sich " +
+ "seiner hohen Verantwortung bewusst und übernimmt folgende Pflichten:");
+ col.Item().Column(c =>
+ {
+ c.Spacing(3);
+ Bullet(c, "Der Käufer verpflichtet sich, die Tiere artgerecht zu halten, zu füttern und zu pflegen. Er verpflichtet sich, die stets aktuellen Vorschriften des Tierschutzgesetzes einzuhalten. Die schriftlichen Anweisungen des Züchters über Haltung, Pflege und Unterkunft der Tiere sind zu befolgen.");
+ Bullet(c, "Der Abnehmer verpflichtet sich, die Tiere in Krankheitsfällen oder bei Anzeichen auf diese unverzüglich veterinärmedizinisch behandeln zu lassen. Die Tiere dürfen nicht ohne zwingende veterinärmedizinische Gründe euthanasiert werden.");
+ Bullet(c, "Dem Käufer ist eine Weitergabe der Tiere ohne die Zustimmung des Züchters nicht gestattet. Eine Abgabe an ein Tierheim oder eine Auffangstation ist ohne vorherige Absprache untersagt.");
+ Bullet(c, "Der Abnehmer verpflichtet sich, die Tiere niemals zu misshandeln, für Versuchszwecke oder als Zuchttier einzusetzen oder als Futtertier zu verwenden.");
+ Bullet(c, "Die Einzelhaltung der Tiere ist dem Käufer untersagt. Er verpflichtet sich im Falle eines einzelnen Tieres zur artgerechten Vergesellschaftung mit der Trenngitter-Methode.");
+ Bullet(c, "Der Käufer setzt den Verkäufer über das Versterben sowie die Todesursache der Tiere in Kenntnis.");
+ Bullet(c, "Ernsthafte Erkrankungen genetischer Ursache sind nach gestellter Diagnose unverzüglich dem Züchter zu melden.");
+ });
+
+ Heading(col, "6. Rechte des Käufers");
+ col.Item().Column(c =>
+ {
+ c.Spacing(3);
+ Bullet(c, "Der Käufer hat das Recht, den Züchter für die unentgeltliche Weitervermittlung der Tiere zu beauftragen. Dies schließt jedoch nicht die Aufnahme der Rennmäuse bei dem Züchter ein.");
+ Bullet(c, "Der Verkäufer steht dem Käufer für Fragen zur Tierhaltung zur Verfügung. Der Käufer kann diese Dienste in beschränktem Umfang unentgeltlich in Anspruch nehmen.");
+ Bullet(c, "Der Käufer hat das Recht, gegen Vorlage einer aktuellen negativen Kotuntersuchung den kostenpflichtigen Vergesellschaftungsservice für die Rennmaus in Anspruch zu nehmen.");
+ });
+
+ Heading(col, "7. Haftung / Zuwiderhandlung");
+ col.Item().Column(c =>
+ {
+ c.Spacing(3);
+ Bullet(c, "Bei Vertragsverstoß ist der Züchter berechtigt, den Vertrag fristlos zu kündigen.");
+ Bullet(c, "Im Falle des Verstoßes ist der Käufer zur entschädigungslosen Rückgabe der Tiere an den Züchter verpflichtet.");
+ Bullet(c, "Zur Sicherstellung der Käuferpflichten wird eine Vertragsstrafe in Höhe von 200,- € festgelegt.");
+ });
+
+ Heading(col, "8. Besondere Vereinbarungen / Bemerkungen");
+ col.Item().Text(
+ "Mündliche Vereinbarungen haben keine Gültigkeit. Jede Änderung oder Ergänzung des Vertrages bedarf " +
+ "der Schriftform. Die Vertragsparteien verzichten auf jegliche Sachgewährleistungsansprüche. " +
+ "Gerichtsstand für beide Parteien ist der Wohnort des Züchters. Der Vertrag wird zweifach ausgefertigt " +
+ "und unterzeichnet. Käufer und Verkäufer erhalten je ein Exemplar. Mit der Unterschrift wird versichert, " +
+ "den Vertragsinhalt gelesen und akzeptiert zu haben und sich an diesen zu halten.");
+ }
+
+ private static void Signatures(ColumnDescriptor col, ContractData data)
+ {
+ var ort = string.IsNullOrWhiteSpace(data.Seller.City) ? "" : data.Seller.City + ", ";
+ col.Item().PaddingTop(14).Text($"{ort}den {D(data.ContractDate ?? data.HandoverDate)}");
+ col.Item().PaddingTop(28).Row(r =>
+ {
+ r.RelativeItem().Column(c =>
+ {
+ c.Item().BorderTop(1).BorderColor(Ink).PaddingTop(4).Text("Unterschrift des Verkäufers");
+ });
+ r.ConstantItem(40);
+ r.RelativeItem().Column(c =>
+ {
+ c.Item().BorderTop(1).BorderColor(Ink).PaddingTop(4).Text("Unterschrift des Käufers");
+ });
+ });
+ }
+}
diff --git a/GerbilManagerWebAPI/Dtos/ApiDtos.cs b/GerbilManagerWebAPI/Dtos/ApiDtos.cs
index 55eda6a..74281f0 100644
--- a/GerbilManagerWebAPI/Dtos/ApiDtos.cs
+++ b/GerbilManagerWebAPI/Dtos/ApiDtos.cs
@@ -37,7 +37,7 @@ namespace GerbilManagerWebAPI.Dtos
public record LitterDto(
Guid Id,
string Name,
- DateOnly Date,
+ DateOnly? Date,
int? TotalBorn,
int? DeathsWithin8Weeks,
Guid? FatherId,
@@ -89,7 +89,7 @@ namespace GerbilManagerWebAPI.Dtos
public record LitterInput(
string Name,
- DateOnly Date,
+ DateOnly? Date,
int? TotalBorn,
int? DeathsWithin8Weeks,
Guid? FatherId,
diff --git a/GerbilManagerWebAPI/Dtos/ContractDtos.cs b/GerbilManagerWebAPI/Dtos/ContractDtos.cs
index c8998a0..afce2d6 100644
--- a/GerbilManagerWebAPI/Dtos/ContractDtos.cs
+++ b/GerbilManagerWebAPI/Dtos/ContractDtos.cs
@@ -19,7 +19,9 @@ namespace GerbilManagerWebAPI.Dtos
List GerbilIds,
decimal Price,
DateOnly HandoverDate,
- DateOnly? ContractDate);
+ DateOnly? ContractDate,
+ // Optionales Tierfoto je Tier (GerbilId -> GerbilPhoto-Id) fürs Vertragsbild.
+ Dictionary? AnimalPhotos = null);
/// Zuchtprofil — Antwort UND Request-Body von /settings/breeder-profile.
public record BreederProfileDto(
diff --git a/GerbilManagerWebAPI/Endpoints/ContractEndpoints.cs b/GerbilManagerWebAPI/Endpoints/ContractEndpoints.cs
index 9d49a99..6e0dbf7 100644
--- a/GerbilManagerWebAPI/Endpoints/ContractEndpoints.cs
+++ b/GerbilManagerWebAPI/Endpoints/ContractEndpoints.cs
@@ -23,6 +23,7 @@ namespace GerbilManagerWebAPI.Endpoints
{
private const string DocxContentType =
"application/vnd.openxmlformats-officedocument.wordprocessingml.document";
+ private const string PdfContentType = "application/pdf";
public static IEndpointRouteBuilder MapContractEndpoints(this IEndpointRouteBuilder app)
{
@@ -50,6 +51,7 @@ namespace GerbilManagerWebAPI.Endpoints
var errors = new Dictionary();
var gerbilIds = (input.GerbilIds ?? []).Distinct().ToList();
+ var photoChoice = input.AnimalPhotos ?? [];
if (gerbilIds.Count == 0)
errors["gerbilIds"] = ["Mindestens ein Tier auswählen."];
if (input.Price < 0)
@@ -100,7 +102,11 @@ namespace GerbilManagerWebAPI.Endpoints
ContractDate = contractDate,
FileName = fileName,
CreatedAt = DateTimeOffset.UtcNow,
- Animals = gerbilIds.Select(id => new SaleContractAnimal { GerbilId = id }).ToList(),
+ Animals = gerbilIds.Select(id => new SaleContractAnimal
+ {
+ GerbilId = id,
+ PhotoId = photoChoice.TryGetValue(id, out var pid) ? pid : null,
+ }).ToList(),
};
db.SaleContracts.Add(entity);
@@ -144,6 +150,49 @@ namespace GerbilManagerWebAPI.Endpoints
return TypedResults.PhysicalFile(path, DocxContentType, download);
});
+ // GET /contracts/{id}/pdf — druckfertiges PDF, aus den (aktuellen) Daten regeneriert.
+ group.MapGet("/{id:guid}/pdf", async Task> (
+ Guid id, ApplicationContext db, IConfiguration config, IWebHostEnvironment env) =>
+ {
+ var c = await db.SaleContracts.AsNoTracking()
+ .Include(x => x.Contact)
+ .Include(x => x.Animals)
+ .FirstOrDefaultAsync(x => x.Id == id);
+ if (c is null || c.Contact is null) return TypedResults.NotFound();
+
+ var gerbilIds = c.Animals.Select(a => a.GerbilId).ToList();
+ var gerbils = await db.Gerbils.AsNoTracking()
+ .Include(g => g.ColorVariety)
+ .Where(g => gerbilIds.Contains(g.Id))
+ .ToListAsync();
+ var settings = await db.BreederSettings.AsNoTracking()
+ .FirstOrDefaultAsync(s => s.Id == BreederSettings.SingletonId)
+ ?? new BreederSettings();
+
+ // Gewählte Vertragsfotos nachladen (Foto muss zum Tier gehören und die Datei
+ // existieren — sonst bleibt das Bild leer statt zu scheitern).
+ var photoByGerbil = c.Animals
+ .Where(a => a.PhotoId is not null)
+ .ToDictionary(a => a.GerbilId, a => a.PhotoId!.Value);
+ var photoBytes = await LoadAnimalPhotos(db, photoByGerbil, PhotoRoot(config, env));
+
+ var data = new ContractData(
+ Seller: ToSeller(settings),
+ Buyer: new ContractBuyer(c.Contact.Name, c.Contact.Address ?? "", c.Contact.Phone, c.Contact.Email),
+ Animals: gerbils
+ .Select(g => new ContractAnimal(
+ g.Name, GeschlechtText(g.Gender), g.DateOfBirth, g.ColorVariety?.Name,
+ photoBytes.GetValueOrDefault(g.Id)))
+ .ToList(),
+ Price: c.Price,
+ HandoverDate: c.HandoverDate,
+ ContractDate: c.ContractDate);
+
+ var pdf = ContractPdfGenerator.Generate(data);
+ var download = $"Abgabevertrag_{c.ContractDate:yyyy-MM-dd}_{Sanitize(c.Contact.Name)}.pdf";
+ return TypedResults.File(pdf, PdfContentType, download);
+ });
+
// DELETE /contracts/{id} — Zeile + Datei; Tier-Status wird NICHT zurückgedreht
// (das wäre Magie — Status korrigiert man am Tier selbst).
group.MapDelete("/{id:guid}", async Task> (
@@ -166,6 +215,34 @@ namespace GerbilManagerWebAPI.Endpoints
private static string ContractRoot(IConfiguration config, IWebHostEnvironment env) =>
config["Contracts:RootPath"] ?? Path.Combine(env.ContentRootPath, "contract-storage");
+ /// Foto-Dateiroot (geteilt mit den Foto-Endpoints).
+ private static string PhotoRoot(IConfiguration config, IWebHostEnvironment env) =>
+ config["Photos:RootPath"] ?? Path.Combine(env.ContentRootPath, "photo-storage");
+
+ /// Lädt die gewählten Vertragsfotos als Rohbytes (GerbilId -> Bytes).
+ /// Überspringt Fotos, die nicht zum Tier gehören oder deren Datei fehlt.
+ private static async Task> LoadAnimalPhotos(
+ ApplicationContext db, Dictionary photoByGerbil, string photoRoot)
+ {
+ var result = new Dictionary();
+ if (photoByGerbil.Count == 0) return result;
+
+ var photoIds = photoByGerbil.Values.ToList();
+ var photos = await db.GerbilPhotos.AsNoTracking()
+ .Where(p => photoIds.Contains(p.Id))
+ .ToListAsync();
+
+ foreach (var (gerbilId, photoId) in photoByGerbil)
+ {
+ var photo = photos.FirstOrDefault(p => p.Id == photoId && p.GerbilId == gerbilId);
+ if (photo is null) continue;
+ var path = Path.Combine(photoRoot, photo.FileName);
+ if (File.Exists(path))
+ result[gerbilId] = await File.ReadAllBytesAsync(path);
+ }
+ return result;
+ }
+
private static BreederProfile ToSeller(BreederSettings s) => new()
{
ZuchtName = s.ZuchtName,
diff --git a/GerbilManagerWebAPI/GerbilManagerWebAPI.csproj b/GerbilManagerWebAPI/GerbilManagerWebAPI.csproj
index b9d9d35..8901b96 100644
--- a/GerbilManagerWebAPI/GerbilManagerWebAPI.csproj
+++ b/GerbilManagerWebAPI/GerbilManagerWebAPI.csproj
@@ -20,6 +20,7 @@
+
diff --git a/GerbilManagerWebAPI/Import/ImportDocxService.cs b/GerbilManagerWebAPI/Import/ImportDocxService.cs
index 96a00bf..f9d304e 100644
--- a/GerbilManagerWebAPI/Import/ImportDocxService.cs
+++ b/GerbilManagerWebAPI/Import/ImportDocxService.cs
@@ -81,7 +81,8 @@ namespace GerbilManagerWebAPI.Import
.Select(l => new { l.Id, l.Date })
.ToListAsync();
var littersByDayNumber = littersInDb
- .GroupBy(l => l.Date.DayNumber)
+ .Where(l => l.Date.HasValue)
+ .GroupBy(l => l.Date!.Value.DayNumber)
.ToDictionary(g => g.Key, g => g.ToList());
// normalize(name)+litterDob → Gerbil snapshot (main-import enrich path)
diff --git a/GerbilManagerWebAPI/Import/ImportService.cs b/GerbilManagerWebAPI/Import/ImportService.cs
index db0b6fe..a97fd0c 100644
--- a/GerbilManagerWebAPI/Import/ImportService.cs
+++ b/GerbilManagerWebAPI/Import/ImportService.cs
@@ -83,7 +83,7 @@ namespace GerbilManagerWebAPI.Import
var existingLitterData = await _db.Litters
.Select(l => new { l.Name, l.Date, l.ExternalRef }).ToListAsync();
var existingLitterKeySet = existingLitterData
- .Select(x => $"{x.Name}|{x.Date:yyyy-MM-dd}").ToHashSet();
+ .Select(x => $"{x.Name}|{(x.Date.HasValue ? x.Date.Value.ToString("yyyy-MM-dd") : "")}").ToHashSet();
var existingLitterExtRefSet = existingLitterData
.Where(x => x.ExternalRef != null)
.Select(x => x.ExternalRef!).ToHashSet();
@@ -307,13 +307,13 @@ namespace GerbilManagerWebAPI.Import
var litterByParentsDate = new Dictionary();
foreach (var l in existingLitterRows)
{
- litterByParentsDate[$"{l.FatherId}|{l.MotherId}|{l.Date:yyyy-MM-dd}"] = l.Id;
+ litterByParentsDate[$"{l.FatherId}|{l.MotherId}|{(l.Date.HasValue ? l.Date.Value.ToString("yyyy-MM-dd") : "")}"] = l.Id;
litterParents[l.Id] = (l.FatherId, l.MotherId);
}
foreach (var sl in synthLitters.Values.ToList())
{
- var reuseKey = $"{sl.Father}|{sl.Mother}|{sl.Date:yyyy-MM-dd}";
+ var reuseKey = $"{sl.Father}|{sl.Mother}|{(sl.Date.HasValue ? sl.Date.Value.ToString("yyyy-MM-dd") : "")}";
if (litterByParentsDate.TryGetValue(reuseKey, out var existingId))
{
// remap offspring to the existing litter; don't create a duplicate.
@@ -329,8 +329,8 @@ namespace GerbilManagerWebAPI.Import
_db.Litters.Add(new Litter
{
Id = sl.Id,
- Name = $"Wurf (aus Diagramm) {sl.Date:yyyy-MM-dd}".Trim(),
- Date = sl.Date ?? default,
+ Name = $"Wurf (aus Diagramm) {(sl.Date.HasValue ? sl.Date.Value.ToString("yyyy-MM-dd") : "")}".Trim(),
+ Date = sl.Date,
FatherId = null, // deferred — applied after gerbils SaveChanges
MotherId = null, // deferred — applied after gerbils SaveChanges
Notes = $"aus Stammbaum-Diagramm abgeleitet (Konfidenz: {sl.Confidence})",
diff --git a/GerbilManagerWebAPI/Import/IngestResolvedService.cs b/GerbilManagerWebAPI/Import/IngestResolvedService.cs
index 604a7c8..14852f1 100644
--- a/GerbilManagerWebAPI/Import/IngestResolvedService.cs
+++ b/GerbilManagerWebAPI/Import/IngestResolvedService.cs
@@ -2,6 +2,7 @@ using System.Text.Json;
using System.Text.Json.Serialization;
using GerbilManagerWebAPI.Models;
using Microsoft.EntityFrameworkCore;
+using GerbilManagerWebAPI.Services;
namespace GerbilManagerWebAPI.Import
{
@@ -61,6 +62,7 @@ namespace GerbilManagerWebAPI.Import
_db.GerbilPhotos.RemoveRange(_db.GerbilPhotos);
_db.WeightRecords.RemoveRange(_db.WeightRecords);
_db.HealthRecords.RemoveRange(_db.HealthRecords);
+ _db.SaleContracts.RemoveRange(_db.SaleContracts);
_db.Gerbils.RemoveRange(_db.Gerbils);
_db.Litters.RemoveRange(_db.Litters);
_db.Contacts.RemoveRange(_db.Contacts);
@@ -79,6 +81,7 @@ namespace GerbilManagerWebAPI.Import
await _db.GerbilPhotos.ExecuteDeleteAsync();
await _db.WeightRecords.ExecuteDeleteAsync();
await _db.HealthRecords.ExecuteDeleteAsync();
+ await _db.SaleContracts.ExecuteDeleteAsync();
await _db.Gerbils.ExecuteDeleteAsync();
await _db.Litters.ExecuteDeleteAsync();
await _db.Contacts.ExecuteDeleteAsync();
@@ -137,7 +140,7 @@ namespace GerbilManagerWebAPI.Import
var gerbilsToInsert = new List();
foreach (var g in data.Gerbils)
{
- gerbilsToInsert.Add(new Gerbil
+ var importedGerbil = new Gerbil
{
Id = g.Id,
Name = g.Name,
@@ -163,7 +166,9 @@ namespace GerbilManagerWebAPI.Import
CharacterNote = g.CharacterNote,
IsDeaf = g.IsDeaf,
IsResident = g.IsResident
- });
+ };
+ GerbilStatusService.Apply(importedGerbil, DateOnly.FromDateTime(DateTime.UtcNow));
+ gerbilsToInsert.Add(importedGerbil);
}
_db.Gerbils.AddRange(gerbilsToInsert);
await _db.SaveChangesAsync();
diff --git a/GerbilManagerWebAPI/Migrations/20260613114528_MakeLitterDateNullable.Designer.cs b/GerbilManagerWebAPI/Migrations/20260613114528_MakeLitterDateNullable.Designer.cs
new file mode 100644
index 0000000..ce176a5
--- /dev/null
+++ b/GerbilManagerWebAPI/Migrations/20260613114528_MakeLitterDateNullable.Designer.cs
@@ -0,0 +1,1491 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace GerbilManagerWebAPI.Migrations
+{
+ [DbContext(typeof(ApplicationContext))]
+ [Migration("20260613114528_MakeLitterDateNullable")]
+ partial class MakeLitterDateNullable
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "10.0.8")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Block", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Data")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Order")
+ .HasColumnType("integer");
+
+ b.Property("PageId")
+ .HasColumnType("uuid");
+
+ b.Property("Type")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("PageId");
+
+ b.ToTable("Blocks");
+
+ b.HasData(
+ new
+ {
+ Id = new Guid("51720002-0000-0000-0000-000000000001"),
+ Data = "{\"text\":\"Startseite\",\"level\":1}",
+ Order = 0,
+ PageId = new Guid("51720001-0000-0000-0000-000000000001"),
+ Type = "Heading"
+ },
+ new
+ {
+ Id = new Guid("51720002-0000-0000-0000-000000000002"),
+ Data = "{\"text\":\"Über die Zucht\",\"level\":1}",
+ Order = 0,
+ PageId = new Guid("51720001-0000-0000-0000-000000000002"),
+ Type = "Heading"
+ },
+ new
+ {
+ Id = new Guid("51720002-0000-0000-0000-000000000003"),
+ Data = "{\"text\":\"Abgabetiere\",\"level\":1}",
+ Order = 0,
+ PageId = new Guid("51720001-0000-0000-0000-000000000003"),
+ Type = "Heading"
+ },
+ new
+ {
+ Id = new Guid("51720002-0000-0000-0000-000000000004"),
+ Data = "{\"text\":\"Abgabebedingungen\",\"level\":1}",
+ Order = 0,
+ PageId = new Guid("51720001-0000-0000-0000-000000000004"),
+ Type = "Heading"
+ },
+ new
+ {
+ Id = new Guid("51720002-0000-0000-0000-000000000005"),
+ Data = "{\"text\":\"Farben & Genetik\",\"level\":1}",
+ Order = 0,
+ PageId = new Guid("51720001-0000-0000-0000-000000000005"),
+ Type = "Heading"
+ },
+ new
+ {
+ Id = new Guid("51720002-0000-0000-0000-000000000006"),
+ Data = "{\"text\":\"Kontakt\",\"level\":1}",
+ Order = 0,
+ PageId = new Guid("51720001-0000-0000-0000-000000000006"),
+ Type = "Heading"
+ },
+ new
+ {
+ Id = new Guid("51720002-0000-0000-0000-000000000010"),
+ Data = "{\"mode\":\"auto\",\"intro\":\"\"}",
+ Order = 1,
+ PageId = new Guid("51720001-0000-0000-0000-000000000003"),
+ Type = "AbgabetiereList"
+ },
+ new
+ {
+ Id = new Guid("51720002-0000-0000-0000-000000000007"),
+ Data = "{\"text\":\"Impressum\",\"level\":1}",
+ Order = 0,
+ PageId = new Guid("51720001-0000-0000-0000-000000000007"),
+ Type = "Heading"
+ },
+ new
+ {
+ Id = new Guid("51720002-0000-0000-0000-000000000070"),
+ Data = "{\"markdown\":\"**Angaben gemäß § 5 TMG**\\n\\nSeitenbetreiber: [Name und vollständige Adresse eintragen]\\n\\nE-Mail: [E-Mail-Adresse eintragen]\\n\\n---\\n\\n*Diese Seite wird vom Seitenbetreiber noch vervollständigt.*\"}",
+ Order = 1,
+ PageId = new Guid("51720001-0000-0000-0000-000000000007"),
+ Type = "RichText"
+ },
+ new
+ {
+ Id = new Guid("51720002-0000-0000-0000-000000000008"),
+ Data = "{\"text\":\"Datenschutz\",\"level\":1}",
+ Order = 0,
+ PageId = new Guid("51720001-0000-0000-0000-000000000008"),
+ Type = "Heading"
+ },
+ new
+ {
+ Id = new Guid("51720002-0000-0000-0000-000000000080"),
+ Data = "{\"markdown\":\"**Datenschutzerklärung**\\n\\nDiese Webseite dient der Vorstellung unserer Rennmauszucht. Es werden keine personenbezogenen Daten gespeichert oder weitergegeben.\\n\\nBei datenschutzbezogenen Fragen: [E-Mail-Adresse eintragen]\\n\\n---\\n\\n*Diese Seite wird vom Seitenbetreiber noch vervollständigt.*\"}",
+ Order = 1,
+ PageId = new Guid("51720001-0000-0000-0000-000000000008"),
+ Type = "RichText"
+ });
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.BreederSettings", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Address")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("City")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Email")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Homepage")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("NameSuffix")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Phone")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("ZuchtName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("BreederSettings");
+
+ b.HasData(
+ new
+ {
+ Id = new Guid("11111111-1111-1111-1111-000000000001"),
+ Address = "",
+ City = "",
+ Email = "",
+ Homepage = "",
+ Name = "",
+ NameSuffix = "",
+ Phone = "",
+ ZuchtName = ""
+ });
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.ColorVariety", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("CanonicalGenotype")
+ .HasColumnType("text");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text")
+ .UseCollation("de-x-icu");
+
+ b.Property("SortOrder")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.ToTable("ColorVarieties");
+
+ b.HasData(
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000001"),
+ CanonicalGenotype = "AA chch DD EE GG pp spsp rere",
+ Name = "REW",
+ SortOrder = 0
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000002"),
+ CanonicalGenotype = "aa chch DD EE GG PP spsp rere",
+ Name = "Hermelin",
+ SortOrder = 1
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000003"),
+ CanonicalGenotype = "AA chch DD EE GG PP spsp rere",
+ Name = "Himalaya",
+ SortOrder = 2
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000004"),
+ CanonicalGenotype = "aa cchmcchm DD EE gg PP spsp rere",
+ Name = "Zobel",
+ SortOrder = 3
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000005"),
+ CanonicalGenotype = "AA CC DD efef GG pp spsp rere",
+ Name = "Rotaugenschimmel",
+ SortOrder = 4
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000006"),
+ CanonicalGenotype = "AA CC DD EE GG PP spsp rere",
+ Name = "Agouti",
+ SortOrder = 5
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000007"),
+ CanonicalGenotype = "aa CC DD EE GG PP spsp rere",
+ Name = "Schwarz",
+ SortOrder = 6
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000008"),
+ CanonicalGenotype = "AA CC DD EE gg PP spsp rere",
+ Name = "Silberagouti",
+ SortOrder = 7
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000009"),
+ CanonicalGenotype = "aa CC DD EE gg PP spsp rere",
+ Name = "Anthrazit",
+ SortOrder = 8
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000010"),
+ CanonicalGenotype = "AA CC DD ee GG PP spsp rere",
+ Name = "Algierfuchs",
+ SortOrder = 9
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000011"),
+ CanonicalGenotype = "aa CC dd EE GG PP spsp rere",
+ Name = "Blau",
+ SortOrder = 10
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000012"),
+ CanonicalGenotype = "AA CC DD EE GG pp spsp rere",
+ Name = "Gold",
+ SortOrder = 11
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000013"),
+ CanonicalGenotype = "aa CC DD EE GG pp spsp rere",
+ Name = "Platin",
+ SortOrder = 12
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000014"),
+ CanonicalGenotype = "AA CC DD ee GG pp spsp rere",
+ Name = "Goldfuchs",
+ SortOrder = 13
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000015"),
+ CanonicalGenotype = "aa CC DD ee GG pp spsp rere",
+ Name = "Rotfuchs",
+ SortOrder = 14
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000016"),
+ CanonicalGenotype = "AA CC dd EE GG pp spsp rere",
+ Name = "Dilute Gold",
+ SortOrder = 15
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000017"),
+ CanonicalGenotype = "aa CC dd EE GG pp spsp rere",
+ Name = "Dilute Platin",
+ SortOrder = 16
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000018"),
+ CanonicalGenotype = "aa CC DD EE gg pp spsp rere",
+ Name = "Altweiss (REW)",
+ SortOrder = 17
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000019"),
+ CanonicalGenotype = "AA CC DD ee gg pp spsp rere",
+ Name = "Apricot (Blassfuchs)",
+ SortOrder = 18
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000020"),
+ CanonicalGenotype = "aa CC DD ee gg PP spsp rere",
+ Name = "Blaufuchs",
+ SortOrder = 19
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000021"),
+ CanonicalGenotype = "aa CC DD ee gg pp spsp rere",
+ Name = "C-Separator",
+ SortOrder = 20
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000022"),
+ CanonicalGenotype = "AA CC DD EE gg pp spsp rere",
+ Name = "Elfenbein",
+ SortOrder = 21
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000023"),
+ CanonicalGenotype = "aa CC DD ee GG PP spsp rere",
+ Name = "Kohlfuchs",
+ SortOrder = 22
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000024"),
+ CanonicalGenotype = "AA CC DD ee gg PP spsp rere",
+ Name = "Polarfuchs",
+ SortOrder = 23
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000025"),
+ CanonicalGenotype = "aa CC DD EE GG pp spsp rere",
+ Name = "Saphir",
+ SortOrder = 24
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000026"),
+ CanonicalGenotype = "AA CC DD efef GG PP spsp rere",
+ Name = "Orangeschimmel",
+ SortOrder = 25
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000027"),
+ CanonicalGenotype = "AA CC DD EE GG pp spsp rere",
+ Name = "Topas",
+ SortOrder = 26
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000028"),
+ CanonicalGenotype = "aa CC DD EE GG pp spsp rere",
+ Name = "Platin-Hell",
+ SortOrder = 27
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000029"),
+ CanonicalGenotype = "AA CC dd EE GG PP spsp rere",
+ Name = "Dilute Agouti",
+ SortOrder = 28
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000030"),
+ CanonicalGenotype = "AA CC dd EE gg PP spsp rere",
+ Name = "Dilute Silberagouti",
+ SortOrder = 29
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000031"),
+ CanonicalGenotype = "aa CC dd ee GG PP spsp rere",
+ Name = "Dilute Kohlfuchs",
+ SortOrder = 30
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000032"),
+ CanonicalGenotype = "aa CC dd EE gg PP spsp rere",
+ Name = "Dilute Anthrazit",
+ SortOrder = 31
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000033"),
+ CanonicalGenotype = "AA CC DD efef gg PP spsp rere",
+ Name = "Silberschimmel",
+ SortOrder = 36
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000034"),
+ CanonicalGenotype = "AA CC DD efef gg PP spsp rere",
+ Name = "Polarfuchsschimmel",
+ SortOrder = 37
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000035"),
+ CanonicalGenotype = "AA CC DD efef GG PP spsp rere",
+ Name = "Algierfuchsschimmel",
+ SortOrder = 38
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000036"),
+ CanonicalGenotype = "aa CC DD efef GG PP spsp rere",
+ Name = "Kohlfuchsschimmel",
+ SortOrder = 39
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000037"),
+ CanonicalGenotype = "aa CC DD efef gg PP spsp rere",
+ Name = "Blaufuchsschimmel",
+ SortOrder = 40
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000038"),
+ CanonicalGenotype = "aa CC DD ee GG PP spsp rere",
+ Name = "Kohlfuchs, hell",
+ SortOrder = 41
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000039"),
+ CanonicalGenotype = "AA CC DD ee GG pp spsp rere",
+ Name = "Goldfuchs, hell",
+ SortOrder = 42
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000040"),
+ CanonicalGenotype = "AA CC DD efef GG pp spsp rere",
+ Name = "Goldfuchsschimmel",
+ SortOrder = 43
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000041"),
+ CanonicalGenotype = "AA CC DD EE GG pp spsp rere",
+ Name = "Gold-Hell",
+ SortOrder = 44
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000042"),
+ CanonicalGenotype = "aa CC DD ee gg PP spsp rere",
+ Name = "Blaufuchs, hell",
+ SortOrder = 45
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000043"),
+ CanonicalGenotype = "aa CC DD efef GG pp spsp rere",
+ Name = "Rotfuchsschimmel",
+ SortOrder = 46
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000044"),
+ CanonicalGenotype = "AA CC DD ee gg PP spsp rere",
+ Name = "Polarfuchs, hell",
+ SortOrder = 47
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000045"),
+ CanonicalGenotype = "aa CC DD efef GG PP spsp rere",
+ Name = "Kohlfuchsschimmel, hell",
+ SortOrder = 48
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000046"),
+ CanonicalGenotype = "aa CC DD ee GG pp spsp rere",
+ Name = "Rotfuchs, hell",
+ SortOrder = 49
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000047"),
+ CanonicalGenotype = "aa CC DD ee GG PP spsp rere",
+ Name = "Kohlfuchs-Hell",
+ SortOrder = 50
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000048"),
+ CanonicalGenotype = "AA CC DD ee GG PP spsp rere",
+ Name = "Algierfuchs, hell",
+ SortOrder = 51
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000049"),
+ CanonicalGenotype = "AA CC dd EE GG pp spsp rere",
+ Name = "Dilute Topas",
+ SortOrder = 52
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000050"),
+ CanonicalGenotype = "aa CC dd ee gg pp spsp rere",
+ Name = "Dilute Blaufuchs",
+ SortOrder = 53
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000051"),
+ CanonicalGenotype = "aa cchmcchm DD EE GG PP spsp rere",
+ Name = "Marder",
+ SortOrder = 54
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000052"),
+ CanonicalGenotype = "aa cchmch DD EE GG PP spsp rere",
+ Name = "Siam",
+ SortOrder = 55
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000053"),
+ CanonicalGenotype = "aa cchmch DD EE gg PP spsp rere",
+ Name = "Zobel-Hell",
+ SortOrder = 56
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000054"),
+ CanonicalGenotype = "AA cchmcchm DD EE GG PP spsp rere",
+ Name = "CP-Agouti",
+ SortOrder = 57
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000055"),
+ CanonicalGenotype = "AA cchmcchm DD EE gg PP spsp rere",
+ Name = "CP-Silberagouti",
+ SortOrder = 59
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000056"),
+ CanonicalGenotype = "AA cchmcchm DD ee GG PP spsp rere",
+ Name = "CP-Algierfuchs",
+ SortOrder = 61
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000057"),
+ CanonicalGenotype = "AA cchmcchm DD ee gg PP spsp rere",
+ Name = "CP-Polarfuchs",
+ SortOrder = 63
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000058"),
+ CanonicalGenotype = "AA cchmcchm dd ee GG PP spsp rere",
+ Name = "CP-Fuchs",
+ SortOrder = 65
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000059"),
+ CanonicalGenotype = "AA cchmch dd ee GG PP spsp rere",
+ Name = "CP-Fuchs-Hell",
+ SortOrder = 66
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000060"),
+ CanonicalGenotype = "AA cchmcchm dd ee gg PP spsp rere",
+ Name = "CP-Blaufuchs",
+ SortOrder = 67
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000061"),
+ CanonicalGenotype = "AA cchmcchm DD efef GG PP spsp rere",
+ Name = "CP-Orangeschimmel",
+ SortOrder = 68
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000062"),
+ CanonicalGenotype = "AA cchmch DD EE GG PP spsp rere",
+ Name = "CP-Agouti-Hell",
+ SortOrder = 58
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000063"),
+ CanonicalGenotype = "AA cchmch DD EE gg PP spsp rere",
+ Name = "CP-Silberagouti-Hell",
+ SortOrder = 60
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000064"),
+ CanonicalGenotype = "AA cchmch DD ee GG PP spsp rere",
+ Name = "CP-Algierfuchs-Hell",
+ SortOrder = 62
+ },
+ 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 = 69
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000067"),
+ CanonicalGenotype = "AA CC dd ee GG PP spsp rere",
+ Name = "Dilute Algierfuchs",
+ SortOrder = 32
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000068"),
+ CanonicalGenotype = "AA CC dd ee GG pp spsp rere",
+ Name = "Dilute Goldfuchs",
+ SortOrder = 33
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000069"),
+ CanonicalGenotype = "aa CC dd ee GG pp spsp rere",
+ Name = "Dilute Rotfuchs",
+ SortOrder = 34
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000070"),
+ CanonicalGenotype = "AA CC dd ee gg PP spsp rere",
+ Name = "Dilute Polarfuchs",
+ SortOrder = 35
+ });
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Contact", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Address")
+ .HasColumnType("text");
+
+ b.Property("Email")
+ .HasColumnType("text");
+
+ b.Property("IsBreeder")
+ .HasColumnType("boolean");
+
+ b.Property("IsReceiver")
+ .HasColumnType("boolean");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text")
+ .UseCollation("de-x-icu");
+
+ b.Property("NameSuffix")
+ .HasColumnType("text");
+
+ b.Property("Notes")
+ .HasColumnType("text");
+
+ b.Property("Phone")
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Contacts");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Enclosure", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Notes")
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Enclosures");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.EnclosurePhoto", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Caption")
+ .HasColumnType("text");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("EnclosureId")
+ .HasColumnType("uuid");
+
+ b.Property("FileName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("SortOrder")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("EnclosureId");
+
+ b.ToTable("EnclosurePhotos");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Gerbil", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("CauseOfDeath")
+ .HasColumnType("text");
+
+ b.Property("CharacterNote")
+ .HasColumnType("text");
+
+ b.Property("CharacterTraits")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("ColorVarietyId")
+ .HasColumnType("uuid");
+
+ b.Property("DateOfBirth")
+ .HasColumnType("date");
+
+ b.Property("DateOfDeath")
+ .HasColumnType("date");
+
+ b.Property("EnclosureId")
+ .HasColumnType("uuid");
+
+ b.Property("ExternalRef")
+ .HasColumnType("text");
+
+ b.Property("Gender")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Genotype")
+ .HasColumnType("text");
+
+ b.Property("GoHomeDate")
+ .HasColumnType("date");
+
+ b.Property("ImportSource")
+ .HasColumnType("text");
+
+ b.Property("IsCastrated")
+ .HasColumnType("boolean");
+
+ b.Property("IsDeaf")
+ .HasColumnType("boolean");
+
+ b.Property("IsResident")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("boolean")
+ .HasDefaultValue(true);
+
+ b.Property("LitterId")
+ .HasColumnType("uuid");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text")
+ .UseCollation("de-x-icu");
+
+ b.Property("NameSearch")
+ .HasColumnType("text")
+ .UseCollation("de-x-icu");
+
+ b.Property("Notes")
+ .HasColumnType("text");
+
+ b.Property("OriginBreeder")
+ .HasColumnType("text")
+ .UseCollation("de-x-icu");
+
+ b.Property("OriginContactId")
+ .HasColumnType("uuid");
+
+ b.Property("RawImportData")
+ .HasColumnType("text");
+
+ b.Property("ReceiverContactId")
+ .HasColumnType("uuid");
+
+ b.Property("SpottingType")
+ .HasColumnType("text");
+
+ b.Property("Status")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ColorVarietyId");
+
+ b.HasIndex("EnclosureId");
+
+ b.HasIndex("ExternalRef")
+ .IsUnique()
+ .HasFilter("\"ExternalRef\" IS NOT NULL");
+
+ b.HasIndex("LitterId");
+
+ b.HasIndex("OriginContactId");
+
+ b.HasIndex("ReceiverContactId");
+
+ b.ToTable("Gerbils");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.GerbilPhoto", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Caption")
+ .HasColumnType("text");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("FileName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("GerbilId")
+ .HasColumnType("uuid");
+
+ b.Property("SortOrder")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("GerbilId");
+
+ b.ToTable("GerbilPhotos");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.HealthRecord", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Date")
+ .HasColumnType("date");
+
+ b.Property("Description")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("GerbilId")
+ .HasColumnType("uuid");
+
+ b.Property("Type")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Veterinarian")
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("GerbilId");
+
+ b.ToTable("HealthRecords");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Litter", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Date")
+ .HasColumnType("date");
+
+ b.Property("DeathsWithin8Weeks")
+ .HasColumnType("integer");
+
+ b.Property("ExpectedGoHomeDate")
+ .HasColumnType("date");
+
+ b.Property("ExternalRef")
+ .HasColumnType("text");
+
+ b.Property("FatherId")
+ .HasColumnType("uuid");
+
+ b.Property("LitterLetter")
+ .HasColumnType("text");
+
+ b.Property("MotherId")
+ .HasColumnType("uuid");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Notes")
+ .HasColumnType("text");
+
+ b.Property("PairingCode")
+ .HasColumnType("text");
+
+ b.Property("TotalBorn")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ExternalRef")
+ .IsUnique()
+ .HasFilter("\"ExternalRef\" IS NOT NULL");
+
+ b.HasIndex("FatherId");
+
+ b.HasIndex("MotherId");
+
+ b.ToTable("Litters");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.MailSettings", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("AppPasswordProtected")
+ .HasColumnType("text");
+
+ b.Property("BackgroundPollEnabled")
+ .HasColumnType("boolean");
+
+ b.Property("Folder")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("GmailAddress")
+ .HasColumnType("text");
+
+ b.Property("LastUid")
+ .HasColumnType("bigint");
+
+ b.Property("PollIntervalMinutes")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.ToTable("MailSettings");
+
+ b.HasData(
+ new
+ {
+ Id = new Guid("ab0c0000-0000-0000-0000-000000000001"),
+ BackgroundPollEnabled = false,
+ Folder = "INBOX",
+ LastUid = 0L,
+ PollIntervalMinutes = 15
+ });
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Media", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Alt")
+ .HasColumnType("text");
+
+ b.Property("FileName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Height")
+ .HasColumnType("integer");
+
+ b.Property("Url")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Width")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.ToTable("Media");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Page", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("SeoDescription")
+ .HasColumnType("text");
+
+ b.Property("Slug")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Status")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Title")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Slug")
+ .IsUnique();
+
+ b.ToTable("Pages");
+
+ b.HasData(
+ new
+ {
+ Id = new Guid("51720001-0000-0000-0000-000000000001"),
+ Slug = "start",
+ Status = "Published",
+ Title = "Startseite"
+ },
+ new
+ {
+ Id = new Guid("51720001-0000-0000-0000-000000000002"),
+ Slug = "ueber-die-zucht",
+ Status = "Published",
+ Title = "Über die Zucht"
+ },
+ new
+ {
+ Id = new Guid("51720001-0000-0000-0000-000000000003"),
+ Slug = "abgabetiere",
+ Status = "Published",
+ Title = "Abgabetiere"
+ },
+ new
+ {
+ Id = new Guid("51720001-0000-0000-0000-000000000004"),
+ Slug = "abgabebedingungen",
+ Status = "Published",
+ Title = "Abgabebedingungen"
+ },
+ new
+ {
+ Id = new Guid("51720001-0000-0000-0000-000000000005"),
+ Slug = "farben-genetik",
+ Status = "Published",
+ Title = "Farben & Genetik"
+ },
+ new
+ {
+ Id = new Guid("51720001-0000-0000-0000-000000000006"),
+ Slug = "kontakt",
+ Status = "Published",
+ Title = "Kontakt"
+ },
+ new
+ {
+ Id = new Guid("51720001-0000-0000-0000-000000000007"),
+ Slug = "impressum",
+ Status = "Published",
+ Title = "Impressum"
+ },
+ new
+ {
+ Id = new Guid("51720001-0000-0000-0000-000000000008"),
+ Slug = "datenschutz",
+ Status = "Published",
+ Title = "Datenschutz"
+ });
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Request", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("AnsweredAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("AssignedContactId")
+ .HasColumnType("uuid");
+
+ b.Property("BodyText")
+ .HasColumnType("text");
+
+ b.Property("DraftReply")
+ .HasColumnType("text");
+
+ b.Property("FromAddress")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("FromName")
+ .HasColumnType("text");
+
+ b.Property("GmailMessageId")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("InReplyToMessageId")
+ .HasColumnType("text");
+
+ b.Property("ReceivedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("ReferencesHeader")
+ .HasColumnType("text");
+
+ b.Property("Status")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Subject")
+ .HasColumnType("text");
+
+ b.Property("ThreadId")
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AssignedContactId");
+
+ b.HasIndex("GmailMessageId")
+ .IsUnique();
+
+ b.ToTable("Requests");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.SaleContract", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("ContactId")
+ .HasColumnType("uuid");
+
+ b.Property("ContractDate")
+ .HasColumnType("date");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("FileName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("HandoverDate")
+ .HasColumnType("date");
+
+ b.Property("Price")
+ .HasPrecision(10, 2)
+ .HasColumnType("numeric(10,2)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ContactId");
+
+ b.ToTable("SaleContracts");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.SaleContractAnimal", b =>
+ {
+ b.Property("SaleContractId")
+ .HasColumnType("uuid");
+
+ b.Property("GerbilId")
+ .HasColumnType("uuid");
+
+ b.HasKey("SaleContractId", "GerbilId");
+
+ b.HasIndex("GerbilId");
+
+ b.ToTable("SaleContractAnimal");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Site", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("DefaultLocale")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("NavOrder")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Sites");
+
+ b.HasData(
+ new
+ {
+ Id = new Guid("5172e000-0000-0000-0000-000000000001"),
+ DefaultLocale = "de",
+ NavOrder = "[\"51720001-0000-0000-0000-000000000001\",\"51720001-0000-0000-0000-000000000002\",\"51720001-0000-0000-0000-000000000003\",\"51720001-0000-0000-0000-000000000004\",\"51720001-0000-0000-0000-000000000005\",\"51720001-0000-0000-0000-000000000006\"]"
+ });
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.WeightRecord", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Date")
+ .HasColumnType("date");
+
+ b.Property("GerbilId")
+ .HasColumnType("uuid");
+
+ b.Property("Notes")
+ .HasColumnType("text");
+
+ b.Property("WeightGrams")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("GerbilId");
+
+ b.ToTable("WeightRecords");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Block", b =>
+ {
+ b.HasOne("GerbilManagerWebAPI.Models.Page", null)
+ .WithMany("Blocks")
+ .HasForeignKey("PageId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.EnclosurePhoto", b =>
+ {
+ b.HasOne("GerbilManagerWebAPI.Models.Enclosure", null)
+ .WithMany()
+ .HasForeignKey("EnclosureId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Gerbil", b =>
+ {
+ b.HasOne("GerbilManagerWebAPI.Models.ColorVariety", "ColorVariety")
+ .WithMany()
+ .HasForeignKey("ColorVarietyId")
+ .OnDelete(DeleteBehavior.SetNull);
+
+ b.HasOne("GerbilManagerWebAPI.Models.Enclosure", "Enclosure")
+ .WithMany("Gerbils")
+ .HasForeignKey("EnclosureId")
+ .OnDelete(DeleteBehavior.SetNull);
+
+ b.HasOne("GerbilManagerWebAPI.Models.Litter", "Litter")
+ .WithMany()
+ .HasForeignKey("LitterId")
+ .OnDelete(DeleteBehavior.SetNull);
+
+ b.HasOne("GerbilManagerWebAPI.Models.Contact", "OriginContact")
+ .WithMany()
+ .HasForeignKey("OriginContactId")
+ .OnDelete(DeleteBehavior.Restrict);
+
+ b.HasOne("GerbilManagerWebAPI.Models.Contact", "ReceiverContact")
+ .WithMany()
+ .HasForeignKey("ReceiverContactId")
+ .OnDelete(DeleteBehavior.Restrict);
+
+ b.Navigation("ColorVariety");
+
+ b.Navigation("Enclosure");
+
+ b.Navigation("Litter");
+
+ b.Navigation("OriginContact");
+
+ b.Navigation("ReceiverContact");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.GerbilPhoto", b =>
+ {
+ b.HasOne("GerbilManagerWebAPI.Models.Gerbil", null)
+ .WithMany()
+ .HasForeignKey("GerbilId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.HealthRecord", b =>
+ {
+ b.HasOne("GerbilManagerWebAPI.Models.Gerbil", null)
+ .WithMany()
+ .HasForeignKey("GerbilId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Litter", b =>
+ {
+ b.HasOne("GerbilManagerWebAPI.Models.Gerbil", "Father")
+ .WithMany()
+ .HasForeignKey("FatherId")
+ .OnDelete(DeleteBehavior.Restrict);
+
+ b.HasOne("GerbilManagerWebAPI.Models.Gerbil", "Mother")
+ .WithMany()
+ .HasForeignKey("MotherId")
+ .OnDelete(DeleteBehavior.Restrict);
+
+ b.Navigation("Father");
+
+ b.Navigation("Mother");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Request", b =>
+ {
+ b.HasOne("GerbilManagerWebAPI.Models.Contact", "AssignedContact")
+ .WithMany()
+ .HasForeignKey("AssignedContactId")
+ .OnDelete(DeleteBehavior.Restrict);
+
+ b.Navigation("AssignedContact");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.SaleContract", b =>
+ {
+ b.HasOne("GerbilManagerWebAPI.Models.Contact", "Contact")
+ .WithMany()
+ .HasForeignKey("ContactId")
+ .OnDelete(DeleteBehavior.Restrict)
+ .IsRequired();
+
+ b.Navigation("Contact");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.SaleContractAnimal", b =>
+ {
+ b.HasOne("GerbilManagerWebAPI.Models.Gerbil", "Gerbil")
+ .WithMany()
+ .HasForeignKey("GerbilId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("GerbilManagerWebAPI.Models.SaleContract", null)
+ .WithMany("Animals")
+ .HasForeignKey("SaleContractId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Gerbil");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.WeightRecord", b =>
+ {
+ b.HasOne("GerbilManagerWebAPI.Models.Gerbil", null)
+ .WithMany()
+ .HasForeignKey("GerbilId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Enclosure", b =>
+ {
+ b.Navigation("Gerbils");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Page", b =>
+ {
+ b.Navigation("Blocks");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.SaleContract", b =>
+ {
+ b.Navigation("Animals");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/GerbilManagerWebAPI/Migrations/20260613114528_MakeLitterDateNullable.cs b/GerbilManagerWebAPI/Migrations/20260613114528_MakeLitterDateNullable.cs
new file mode 100644
index 0000000..092b542
--- /dev/null
+++ b/GerbilManagerWebAPI/Migrations/20260613114528_MakeLitterDateNullable.cs
@@ -0,0 +1,37 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace GerbilManagerWebAPI.Migrations
+{
+ ///
+ public partial class MakeLitterDateNullable : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AlterColumn(
+ name: "Date",
+ table: "Litters",
+ type: "date",
+ nullable: true,
+ oldClrType: typeof(DateOnly),
+ oldType: "date");
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AlterColumn(
+ name: "Date",
+ table: "Litters",
+ type: "date",
+ nullable: false,
+ defaultValue: new DateOnly(1, 1, 1),
+ oldClrType: typeof(DateOnly),
+ oldType: "date",
+ oldNullable: true);
+ }
+ }
+}
diff --git a/GerbilManagerWebAPI/Migrations/20260613120908_AddContractAnimalPhoto.Designer.cs b/GerbilManagerWebAPI/Migrations/20260613120908_AddContractAnimalPhoto.Designer.cs
new file mode 100644
index 0000000..8dff225
--- /dev/null
+++ b/GerbilManagerWebAPI/Migrations/20260613120908_AddContractAnimalPhoto.Designer.cs
@@ -0,0 +1,1494 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace GerbilManagerWebAPI.Migrations
+{
+ [DbContext(typeof(ApplicationContext))]
+ [Migration("20260613120908_AddContractAnimalPhoto")]
+ partial class AddContractAnimalPhoto
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "10.0.8")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Block", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Data")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Order")
+ .HasColumnType("integer");
+
+ b.Property("PageId")
+ .HasColumnType("uuid");
+
+ b.Property("Type")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("PageId");
+
+ b.ToTable("Blocks");
+
+ b.HasData(
+ new
+ {
+ Id = new Guid("51720002-0000-0000-0000-000000000001"),
+ Data = "{\"text\":\"Startseite\",\"level\":1}",
+ Order = 0,
+ PageId = new Guid("51720001-0000-0000-0000-000000000001"),
+ Type = "Heading"
+ },
+ new
+ {
+ Id = new Guid("51720002-0000-0000-0000-000000000002"),
+ Data = "{\"text\":\"Über die Zucht\",\"level\":1}",
+ Order = 0,
+ PageId = new Guid("51720001-0000-0000-0000-000000000002"),
+ Type = "Heading"
+ },
+ new
+ {
+ Id = new Guid("51720002-0000-0000-0000-000000000003"),
+ Data = "{\"text\":\"Abgabetiere\",\"level\":1}",
+ Order = 0,
+ PageId = new Guid("51720001-0000-0000-0000-000000000003"),
+ Type = "Heading"
+ },
+ new
+ {
+ Id = new Guid("51720002-0000-0000-0000-000000000004"),
+ Data = "{\"text\":\"Abgabebedingungen\",\"level\":1}",
+ Order = 0,
+ PageId = new Guid("51720001-0000-0000-0000-000000000004"),
+ Type = "Heading"
+ },
+ new
+ {
+ Id = new Guid("51720002-0000-0000-0000-000000000005"),
+ Data = "{\"text\":\"Farben & Genetik\",\"level\":1}",
+ Order = 0,
+ PageId = new Guid("51720001-0000-0000-0000-000000000005"),
+ Type = "Heading"
+ },
+ new
+ {
+ Id = new Guid("51720002-0000-0000-0000-000000000006"),
+ Data = "{\"text\":\"Kontakt\",\"level\":1}",
+ Order = 0,
+ PageId = new Guid("51720001-0000-0000-0000-000000000006"),
+ Type = "Heading"
+ },
+ new
+ {
+ Id = new Guid("51720002-0000-0000-0000-000000000010"),
+ Data = "{\"mode\":\"auto\",\"intro\":\"\"}",
+ Order = 1,
+ PageId = new Guid("51720001-0000-0000-0000-000000000003"),
+ Type = "AbgabetiereList"
+ },
+ new
+ {
+ Id = new Guid("51720002-0000-0000-0000-000000000007"),
+ Data = "{\"text\":\"Impressum\",\"level\":1}",
+ Order = 0,
+ PageId = new Guid("51720001-0000-0000-0000-000000000007"),
+ Type = "Heading"
+ },
+ new
+ {
+ Id = new Guid("51720002-0000-0000-0000-000000000070"),
+ Data = "{\"markdown\":\"**Angaben gemäß § 5 TMG**\\n\\nSeitenbetreiber: [Name und vollständige Adresse eintragen]\\n\\nE-Mail: [E-Mail-Adresse eintragen]\\n\\n---\\n\\n*Diese Seite wird vom Seitenbetreiber noch vervollständigt.*\"}",
+ Order = 1,
+ PageId = new Guid("51720001-0000-0000-0000-000000000007"),
+ Type = "RichText"
+ },
+ new
+ {
+ Id = new Guid("51720002-0000-0000-0000-000000000008"),
+ Data = "{\"text\":\"Datenschutz\",\"level\":1}",
+ Order = 0,
+ PageId = new Guid("51720001-0000-0000-0000-000000000008"),
+ Type = "Heading"
+ },
+ new
+ {
+ Id = new Guid("51720002-0000-0000-0000-000000000080"),
+ Data = "{\"markdown\":\"**Datenschutzerklärung**\\n\\nDiese Webseite dient der Vorstellung unserer Rennmauszucht. Es werden keine personenbezogenen Daten gespeichert oder weitergegeben.\\n\\nBei datenschutzbezogenen Fragen: [E-Mail-Adresse eintragen]\\n\\n---\\n\\n*Diese Seite wird vom Seitenbetreiber noch vervollständigt.*\"}",
+ Order = 1,
+ PageId = new Guid("51720001-0000-0000-0000-000000000008"),
+ Type = "RichText"
+ });
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.BreederSettings", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Address")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("City")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Email")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Homepage")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("NameSuffix")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Phone")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("ZuchtName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("BreederSettings");
+
+ b.HasData(
+ new
+ {
+ Id = new Guid("11111111-1111-1111-1111-000000000001"),
+ Address = "",
+ City = "",
+ Email = "",
+ Homepage = "",
+ Name = "",
+ NameSuffix = "",
+ Phone = "",
+ ZuchtName = ""
+ });
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.ColorVariety", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("CanonicalGenotype")
+ .HasColumnType("text");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text")
+ .UseCollation("de-x-icu");
+
+ b.Property("SortOrder")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.ToTable("ColorVarieties");
+
+ b.HasData(
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000001"),
+ CanonicalGenotype = "AA chch DD EE GG pp spsp rere",
+ Name = "REW",
+ SortOrder = 0
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000002"),
+ CanonicalGenotype = "aa chch DD EE GG PP spsp rere",
+ Name = "Hermelin",
+ SortOrder = 1
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000003"),
+ CanonicalGenotype = "AA chch DD EE GG PP spsp rere",
+ Name = "Himalaya",
+ SortOrder = 2
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000004"),
+ CanonicalGenotype = "aa cchmcchm DD EE gg PP spsp rere",
+ Name = "Zobel",
+ SortOrder = 3
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000005"),
+ CanonicalGenotype = "AA CC DD efef GG pp spsp rere",
+ Name = "Rotaugenschimmel",
+ SortOrder = 4
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000006"),
+ CanonicalGenotype = "AA CC DD EE GG PP spsp rere",
+ Name = "Agouti",
+ SortOrder = 5
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000007"),
+ CanonicalGenotype = "aa CC DD EE GG PP spsp rere",
+ Name = "Schwarz",
+ SortOrder = 6
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000008"),
+ CanonicalGenotype = "AA CC DD EE gg PP spsp rere",
+ Name = "Silberagouti",
+ SortOrder = 7
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000009"),
+ CanonicalGenotype = "aa CC DD EE gg PP spsp rere",
+ Name = "Anthrazit",
+ SortOrder = 8
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000010"),
+ CanonicalGenotype = "AA CC DD ee GG PP spsp rere",
+ Name = "Algierfuchs",
+ SortOrder = 9
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000011"),
+ CanonicalGenotype = "aa CC dd EE GG PP spsp rere",
+ Name = "Blau",
+ SortOrder = 10
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000012"),
+ CanonicalGenotype = "AA CC DD EE GG pp spsp rere",
+ Name = "Gold",
+ SortOrder = 11
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000013"),
+ CanonicalGenotype = "aa CC DD EE GG pp spsp rere",
+ Name = "Platin",
+ SortOrder = 12
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000014"),
+ CanonicalGenotype = "AA CC DD ee GG pp spsp rere",
+ Name = "Goldfuchs",
+ SortOrder = 13
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000015"),
+ CanonicalGenotype = "aa CC DD ee GG pp spsp rere",
+ Name = "Rotfuchs",
+ SortOrder = 14
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000016"),
+ CanonicalGenotype = "AA CC dd EE GG pp spsp rere",
+ Name = "Dilute Gold",
+ SortOrder = 15
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000017"),
+ CanonicalGenotype = "aa CC dd EE GG pp spsp rere",
+ Name = "Dilute Platin",
+ SortOrder = 16
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000018"),
+ CanonicalGenotype = "aa CC DD EE gg pp spsp rere",
+ Name = "Altweiss (REW)",
+ SortOrder = 17
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000019"),
+ CanonicalGenotype = "AA CC DD ee gg pp spsp rere",
+ Name = "Apricot (Blassfuchs)",
+ SortOrder = 18
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000020"),
+ CanonicalGenotype = "aa CC DD ee gg PP spsp rere",
+ Name = "Blaufuchs",
+ SortOrder = 19
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000021"),
+ CanonicalGenotype = "aa CC DD ee gg pp spsp rere",
+ Name = "C-Separator",
+ SortOrder = 20
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000022"),
+ CanonicalGenotype = "AA CC DD EE gg pp spsp rere",
+ Name = "Elfenbein",
+ SortOrder = 21
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000023"),
+ CanonicalGenotype = "aa CC DD ee GG PP spsp rere",
+ Name = "Kohlfuchs",
+ SortOrder = 22
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000024"),
+ CanonicalGenotype = "AA CC DD ee gg PP spsp rere",
+ Name = "Polarfuchs",
+ SortOrder = 23
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000025"),
+ CanonicalGenotype = "aa CC DD EE GG pp spsp rere",
+ Name = "Saphir",
+ SortOrder = 24
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000026"),
+ CanonicalGenotype = "AA CC DD efef GG PP spsp rere",
+ Name = "Orangeschimmel",
+ SortOrder = 25
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000027"),
+ CanonicalGenotype = "AA CC DD EE GG pp spsp rere",
+ Name = "Topas",
+ SortOrder = 26
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000028"),
+ CanonicalGenotype = "aa CC DD EE GG pp spsp rere",
+ Name = "Platin-Hell",
+ SortOrder = 27
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000029"),
+ CanonicalGenotype = "AA CC dd EE GG PP spsp rere",
+ Name = "Dilute Agouti",
+ SortOrder = 28
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000030"),
+ CanonicalGenotype = "AA CC dd EE gg PP spsp rere",
+ Name = "Dilute Silberagouti",
+ SortOrder = 29
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000031"),
+ CanonicalGenotype = "aa CC dd ee GG PP spsp rere",
+ Name = "Dilute Kohlfuchs",
+ SortOrder = 30
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000032"),
+ CanonicalGenotype = "aa CC dd EE gg PP spsp rere",
+ Name = "Dilute Anthrazit",
+ SortOrder = 31
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000033"),
+ CanonicalGenotype = "AA CC DD efef gg PP spsp rere",
+ Name = "Silberschimmel",
+ SortOrder = 36
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000034"),
+ CanonicalGenotype = "AA CC DD efef gg PP spsp rere",
+ Name = "Polarfuchsschimmel",
+ SortOrder = 37
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000035"),
+ CanonicalGenotype = "AA CC DD efef GG PP spsp rere",
+ Name = "Algierfuchsschimmel",
+ SortOrder = 38
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000036"),
+ CanonicalGenotype = "aa CC DD efef GG PP spsp rere",
+ Name = "Kohlfuchsschimmel",
+ SortOrder = 39
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000037"),
+ CanonicalGenotype = "aa CC DD efef gg PP spsp rere",
+ Name = "Blaufuchsschimmel",
+ SortOrder = 40
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000038"),
+ CanonicalGenotype = "aa CC DD ee GG PP spsp rere",
+ Name = "Kohlfuchs, hell",
+ SortOrder = 41
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000039"),
+ CanonicalGenotype = "AA CC DD ee GG pp spsp rere",
+ Name = "Goldfuchs, hell",
+ SortOrder = 42
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000040"),
+ CanonicalGenotype = "AA CC DD efef GG pp spsp rere",
+ Name = "Goldfuchsschimmel",
+ SortOrder = 43
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000041"),
+ CanonicalGenotype = "AA CC DD EE GG pp spsp rere",
+ Name = "Gold-Hell",
+ SortOrder = 44
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000042"),
+ CanonicalGenotype = "aa CC DD ee gg PP spsp rere",
+ Name = "Blaufuchs, hell",
+ SortOrder = 45
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000043"),
+ CanonicalGenotype = "aa CC DD efef GG pp spsp rere",
+ Name = "Rotfuchsschimmel",
+ SortOrder = 46
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000044"),
+ CanonicalGenotype = "AA CC DD ee gg PP spsp rere",
+ Name = "Polarfuchs, hell",
+ SortOrder = 47
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000045"),
+ CanonicalGenotype = "aa CC DD efef GG PP spsp rere",
+ Name = "Kohlfuchsschimmel, hell",
+ SortOrder = 48
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000046"),
+ CanonicalGenotype = "aa CC DD ee GG pp spsp rere",
+ Name = "Rotfuchs, hell",
+ SortOrder = 49
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000047"),
+ CanonicalGenotype = "aa CC DD ee GG PP spsp rere",
+ Name = "Kohlfuchs-Hell",
+ SortOrder = 50
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000048"),
+ CanonicalGenotype = "AA CC DD ee GG PP spsp rere",
+ Name = "Algierfuchs, hell",
+ SortOrder = 51
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000049"),
+ CanonicalGenotype = "AA CC dd EE GG pp spsp rere",
+ Name = "Dilute Topas",
+ SortOrder = 52
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000050"),
+ CanonicalGenotype = "aa CC dd ee gg pp spsp rere",
+ Name = "Dilute Blaufuchs",
+ SortOrder = 53
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000051"),
+ CanonicalGenotype = "aa cchmcchm DD EE GG PP spsp rere",
+ Name = "Marder",
+ SortOrder = 54
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000052"),
+ CanonicalGenotype = "aa cchmch DD EE GG PP spsp rere",
+ Name = "Siam",
+ SortOrder = 55
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000053"),
+ CanonicalGenotype = "aa cchmch DD EE gg PP spsp rere",
+ Name = "Zobel-Hell",
+ SortOrder = 56
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000054"),
+ CanonicalGenotype = "AA cchmcchm DD EE GG PP spsp rere",
+ Name = "CP-Agouti",
+ SortOrder = 57
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000055"),
+ CanonicalGenotype = "AA cchmcchm DD EE gg PP spsp rere",
+ Name = "CP-Silberagouti",
+ SortOrder = 59
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000056"),
+ CanonicalGenotype = "AA cchmcchm DD ee GG PP spsp rere",
+ Name = "CP-Algierfuchs",
+ SortOrder = 61
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000057"),
+ CanonicalGenotype = "AA cchmcchm DD ee gg PP spsp rere",
+ Name = "CP-Polarfuchs",
+ SortOrder = 63
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000058"),
+ CanonicalGenotype = "AA cchmcchm dd ee GG PP spsp rere",
+ Name = "CP-Fuchs",
+ SortOrder = 65
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000059"),
+ CanonicalGenotype = "AA cchmch dd ee GG PP spsp rere",
+ Name = "CP-Fuchs-Hell",
+ SortOrder = 66
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000060"),
+ CanonicalGenotype = "AA cchmcchm dd ee gg PP spsp rere",
+ Name = "CP-Blaufuchs",
+ SortOrder = 67
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000061"),
+ CanonicalGenotype = "AA cchmcchm DD efef GG PP spsp rere",
+ Name = "CP-Orangeschimmel",
+ SortOrder = 68
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000062"),
+ CanonicalGenotype = "AA cchmch DD EE GG PP spsp rere",
+ Name = "CP-Agouti-Hell",
+ SortOrder = 58
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000063"),
+ CanonicalGenotype = "AA cchmch DD EE gg PP spsp rere",
+ Name = "CP-Silberagouti-Hell",
+ SortOrder = 60
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000064"),
+ CanonicalGenotype = "AA cchmch DD ee GG PP spsp rere",
+ Name = "CP-Algierfuchs-Hell",
+ SortOrder = 62
+ },
+ 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 = 69
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000067"),
+ CanonicalGenotype = "AA CC dd ee GG PP spsp rere",
+ Name = "Dilute Algierfuchs",
+ SortOrder = 32
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000068"),
+ CanonicalGenotype = "AA CC dd ee GG pp spsp rere",
+ Name = "Dilute Goldfuchs",
+ SortOrder = 33
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000069"),
+ CanonicalGenotype = "aa CC dd ee GG pp spsp rere",
+ Name = "Dilute Rotfuchs",
+ SortOrder = 34
+ },
+ new
+ {
+ Id = new Guid("00000000-0000-0000-0000-000000000070"),
+ CanonicalGenotype = "AA CC dd ee gg PP spsp rere",
+ Name = "Dilute Polarfuchs",
+ SortOrder = 35
+ });
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Contact", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Address")
+ .HasColumnType("text");
+
+ b.Property("Email")
+ .HasColumnType("text");
+
+ b.Property("IsBreeder")
+ .HasColumnType("boolean");
+
+ b.Property("IsReceiver")
+ .HasColumnType("boolean");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text")
+ .UseCollation("de-x-icu");
+
+ b.Property("NameSuffix")
+ .HasColumnType("text");
+
+ b.Property("Notes")
+ .HasColumnType("text");
+
+ b.Property("Phone")
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Contacts");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Enclosure", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Notes")
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Enclosures");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.EnclosurePhoto", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Caption")
+ .HasColumnType("text");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("EnclosureId")
+ .HasColumnType("uuid");
+
+ b.Property("FileName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("SortOrder")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("EnclosureId");
+
+ b.ToTable("EnclosurePhotos");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Gerbil", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("CauseOfDeath")
+ .HasColumnType("text");
+
+ b.Property("CharacterNote")
+ .HasColumnType("text");
+
+ b.Property("CharacterTraits")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("ColorVarietyId")
+ .HasColumnType("uuid");
+
+ b.Property("DateOfBirth")
+ .HasColumnType("date");
+
+ b.Property("DateOfDeath")
+ .HasColumnType("date");
+
+ b.Property("EnclosureId")
+ .HasColumnType("uuid");
+
+ b.Property("ExternalRef")
+ .HasColumnType("text");
+
+ b.Property("Gender")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Genotype")
+ .HasColumnType("text");
+
+ b.Property("GoHomeDate")
+ .HasColumnType("date");
+
+ b.Property("ImportSource")
+ .HasColumnType("text");
+
+ b.Property("IsCastrated")
+ .HasColumnType("boolean");
+
+ b.Property("IsDeaf")
+ .HasColumnType("boolean");
+
+ b.Property("IsResident")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("boolean")
+ .HasDefaultValue(true);
+
+ b.Property("LitterId")
+ .HasColumnType("uuid");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text")
+ .UseCollation("de-x-icu");
+
+ b.Property("NameSearch")
+ .HasColumnType("text")
+ .UseCollation("de-x-icu");
+
+ b.Property("Notes")
+ .HasColumnType("text");
+
+ b.Property("OriginBreeder")
+ .HasColumnType("text")
+ .UseCollation("de-x-icu");
+
+ b.Property("OriginContactId")
+ .HasColumnType("uuid");
+
+ b.Property("RawImportData")
+ .HasColumnType("text");
+
+ b.Property("ReceiverContactId")
+ .HasColumnType("uuid");
+
+ b.Property("SpottingType")
+ .HasColumnType("text");
+
+ b.Property("Status")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ColorVarietyId");
+
+ b.HasIndex("EnclosureId");
+
+ b.HasIndex("ExternalRef")
+ .IsUnique()
+ .HasFilter("\"ExternalRef\" IS NOT NULL");
+
+ b.HasIndex("LitterId");
+
+ b.HasIndex("OriginContactId");
+
+ b.HasIndex("ReceiverContactId");
+
+ b.ToTable("Gerbils");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.GerbilPhoto", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Caption")
+ .HasColumnType("text");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("FileName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("GerbilId")
+ .HasColumnType("uuid");
+
+ b.Property("SortOrder")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("GerbilId");
+
+ b.ToTable("GerbilPhotos");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.HealthRecord", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Date")
+ .HasColumnType("date");
+
+ b.Property("Description")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("GerbilId")
+ .HasColumnType("uuid");
+
+ b.Property("Type")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Veterinarian")
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("GerbilId");
+
+ b.ToTable("HealthRecords");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Litter", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Date")
+ .HasColumnType("date");
+
+ b.Property("DeathsWithin8Weeks")
+ .HasColumnType("integer");
+
+ b.Property("ExpectedGoHomeDate")
+ .HasColumnType("date");
+
+ b.Property("ExternalRef")
+ .HasColumnType("text");
+
+ b.Property("FatherId")
+ .HasColumnType("uuid");
+
+ b.Property("LitterLetter")
+ .HasColumnType("text");
+
+ b.Property("MotherId")
+ .HasColumnType("uuid");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Notes")
+ .HasColumnType("text");
+
+ b.Property("PairingCode")
+ .HasColumnType("text");
+
+ b.Property("TotalBorn")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ExternalRef")
+ .IsUnique()
+ .HasFilter("\"ExternalRef\" IS NOT NULL");
+
+ b.HasIndex("FatherId");
+
+ b.HasIndex("MotherId");
+
+ b.ToTable("Litters");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.MailSettings", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("AppPasswordProtected")
+ .HasColumnType("text");
+
+ b.Property("BackgroundPollEnabled")
+ .HasColumnType("boolean");
+
+ b.Property("Folder")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("GmailAddress")
+ .HasColumnType("text");
+
+ b.Property("LastUid")
+ .HasColumnType("bigint");
+
+ b.Property("PollIntervalMinutes")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.ToTable("MailSettings");
+
+ b.HasData(
+ new
+ {
+ Id = new Guid("ab0c0000-0000-0000-0000-000000000001"),
+ BackgroundPollEnabled = false,
+ Folder = "INBOX",
+ LastUid = 0L,
+ PollIntervalMinutes = 15
+ });
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Media", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Alt")
+ .HasColumnType("text");
+
+ b.Property("FileName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Height")
+ .HasColumnType("integer");
+
+ b.Property("Url")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Width")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.ToTable("Media");
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Page", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("SeoDescription")
+ .HasColumnType("text");
+
+ b.Property("Slug")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Status")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Title")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Slug")
+ .IsUnique();
+
+ b.ToTable("Pages");
+
+ b.HasData(
+ new
+ {
+ Id = new Guid("51720001-0000-0000-0000-000000000001"),
+ Slug = "start",
+ Status = "Published",
+ Title = "Startseite"
+ },
+ new
+ {
+ Id = new Guid("51720001-0000-0000-0000-000000000002"),
+ Slug = "ueber-die-zucht",
+ Status = "Published",
+ Title = "Über die Zucht"
+ },
+ new
+ {
+ Id = new Guid("51720001-0000-0000-0000-000000000003"),
+ Slug = "abgabetiere",
+ Status = "Published",
+ Title = "Abgabetiere"
+ },
+ new
+ {
+ Id = new Guid("51720001-0000-0000-0000-000000000004"),
+ Slug = "abgabebedingungen",
+ Status = "Published",
+ Title = "Abgabebedingungen"
+ },
+ new
+ {
+ Id = new Guid("51720001-0000-0000-0000-000000000005"),
+ Slug = "farben-genetik",
+ Status = "Published",
+ Title = "Farben & Genetik"
+ },
+ new
+ {
+ Id = new Guid("51720001-0000-0000-0000-000000000006"),
+ Slug = "kontakt",
+ Status = "Published",
+ Title = "Kontakt"
+ },
+ new
+ {
+ Id = new Guid("51720001-0000-0000-0000-000000000007"),
+ Slug = "impressum",
+ Status = "Published",
+ Title = "Impressum"
+ },
+ new
+ {
+ Id = new Guid("51720001-0000-0000-0000-000000000008"),
+ Slug = "datenschutz",
+ Status = "Published",
+ Title = "Datenschutz"
+ });
+ });
+
+ modelBuilder.Entity("GerbilManagerWebAPI.Models.Request", b =>
+ {
+ b.Property