Gulum 0b99cfd2bd
Some checks failed
CI / Backend Tests (.NET) (push) Successful in 1m16s
CI / Frontend Tests (Node/Vite) (push) Successful in 9m39s
CI / Docker Build & Push (push) Successful in 14m0s
CI / Deploy auf TrueNAS (Custom App) (push) Failing after 3s
feat(import): neue Stammbäume (12 Charts) + litterChildren.add + EMF-Fotos überspringen
Die Züchterin hat 24 neue/aktualisierte Stammbaum-xlsx geliefert (Ordner
"neuestammbäume"); sie liegen jetzt im kanonischen Quellverzeichnis
Sttammbäume (12 neue Charts, 7 aktualisierte, 3 identisch, das inhaltsgleiche
"Picus Son (2)" ausgelassen). Prod ist per Upload-Ingest aktualisiert:
2372 -> 2451 Tiere, 916 -> 965 Würfe, 432 -> 507 Fotos, 2198 -> 2275 Tiere
mit Geburtsdatum. Overrides/verified-Zeilen, manuelle Tiere und Tickets
haben den Ingest unverändert überlebt.

Zwei Datenfehler, die die neuen Charts aufgedeckt haben — datengetrieben und
re-ingest-stabil gefixt statt an der globalen Heuristik zu drehen:

- litterChildren kennt jetzt `add` [Name | {name, dob}] als Gegenstück zu
  `keep`: hängt ein Jungtier an DIESEN Wurf und entfernt den alten Wurf, wenn
  er dadurch kinderlos UND virtuell ist. Nötig, weil "Pukas Kids" Akanes
  Eltern komplett UNTER ihren Block setzt (N80 Roni = Vater, N81 Fumi =
  Mutter) — _reconstruct_parents griff eine Zeile zu hoch, paarte Irish
  Coffee (Bonapartes Mutter) mit Roni und riss Akane aus dem Z21-Wurf in
  einen Phantom-Wurf, der in der Wurfchronik auftauchte (Ticket 88389f8e).
- Merle: durch das neue Geburtsdatum (18.06.2023) mergt der addAnimals-Stub
  in den Chart-Datensatz und verliert dabei sein isResident -> expliziter
  resolutions-Override (Ticket 36a3fcde/a8f11ac0, Züchterin: Zuchttier).

Außerdem: Excel legt neben Fotos teils EMF/WMF-Vektorvorschauen ab, die
Browser nicht darstellen können (kaputte Bildkachel in der Tier-Akte) ->
extract._attach_photos überspringt .emf/.wmf (5 Fotos betroffen).

Regressionstests für alle drei Punkte; alle Python-Suites grün.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 22:27:18 +02:00
2023-10-30 16:39:14 +01:00

GerbilManager

A manager application for gerbil breeding data featuring a .NET Aspire backend and a React-based frontend.

  • GerbilManagerWebAPI/ — ASP.NET Core backend (Swagger under /swagger)
  • gerbil-manager-web/ — React Frontend (Vite + TypeScript), see gerbil-manager-web/README.md
  • tools/import/ — Python import pipeline scripts and database schemas

Requirements

To manage database migrations, install the EF Core CLI tool globally:

dotnet tool install --global dotnet-ef

Running the Application

To run the full stack (PostgreSQL database, WebAPI, and Frontend Vite app) in one command:

dotnet run --project GerbilManager.AppHost

📥 Data Import & Normalization Pipeline

The application features a Python-based import pipeline that compiles gerbil breeding records, lineage, photos, and contact information from source files (markdown logs, Excel spreadsheets, Word documents) into a unified JSON format, and ingests them into the PostgreSQL database.

1. Structure of the Pipeline

  • Source Data: Located at C:\Users\gulum\dev\Wurfchronik_Bilder (contains markdown files, .xlsx pedigree trees, and detail logs).
  • Compilation: merge_and_resolve.py processes the source files, extracts breeding details, resolves lineage links, maps colors/genotypes, and normalizes contact names.
  • Normalization Mapping: merge_and_resolve.py contains a norm_map dictionary of contact name normalizations. This maps various spelling variations and abbreviations to a single canonical name.

2. How to Run the Import

Automatic Way (All-in-One)

The PowerShell script in tools/import boots the Aspire stack, waits for the API to become ready, and automatically triggers the ingest:

powershell -ExecutionPolicy Bypass -File tools/import/run_app_and_import.ps1

Manual Way

  1. Recompile the import data: Run the compiler script from the root directory to parse raw sources and output a fresh resolved_import.json:
    python tools/import/merge_and_resolve.py
    
  2. Ingest into the running database: Ensure the application is running, then send an HTTP POST request to the API:
    Invoke-RestMethod -Uri "http://localhost:5179/import/ingest-resolved" -Method Post
    

👥 Contact Deduplication Workflow

When the database is wiped and re-imported, you can detect and resolve duplicate contacts (e.g. spelling mistakes, initials vs full names) using the deduplication checklist workflow.

1. Search for Duplicate Contacts

You can run duplicate checks using two different similarity parameter models:

  • Round 1 (Clever matching on first 4 characters):
    python tools/import/find_duplicates_v5.py
    
    Creates: tools/import/output/potential_duplicates_decision.md
  • Round 2 (Broader matching on initials, matching last names, phones, or emails):
    python tools/import/find_duplicates_round2.py
    
    Creates: tools/import/output/potential_duplicates_decision_round2.md

2. Fill out the Checklist

Open the generated markdown checklist file and edit the checkboxes:

  • Combine/Merge: Put an x in the checkbox [x] of the name you want to choose as the canonical name. Leave the checkboxes empty [ ] for any names you want to merge into the canonical name.
  • Standalone: Put an o in the checkbox [o] of any name that should remain a separate, standalone contact.
  • New Name: Put an x next to Custom name: and type your new desired name inside the backticks.
  • Keep all separate: Leave all checkboxes in a Choice empty [ ].

Example:

- [x] Max Mustermann   <-- canonical name
- [ ] Max M.           <-- merges into Max Mustermann
- [o] Moritz Mustermann <-- remains a separate standalone contact

3. Apply the Decisions

Once you have saved your decisions in the checklist file, run the parser:

python tools/import/parse_decisions.py

This automatically parses your selections, resolves the merges, and updates the norm_map inside merge_and_resolve.py so they are permanently saved in the codebase. Run the compilation pipeline again to produce the final deduplicated import JSON:

python tools/import/merge_and_resolve.py
Description
No description provided
Readme 13 MiB
Languages
C# 43%
TypeScript 34.5%
Python 18%
CSS 3.7%
Shell 0.5%
Other 0.1%