Commit Graph

399 Commits

Author SHA1 Message Date
459c66bc3e Hotfix: gerbil search contains operator — drop trailing '*' (Gridify =* is contains; name=*a not name=*a*) + e2e mock mirrors real Gridify 2026-06-06 08:52:02 +02:00
0cee3e2710 Merge feature/polish-1: canonical Gridify '=', InvalidParentGender German message, Abgabe-abschliessen->wizard wiring, de.ts sweep, e2e mock accepts both operators [god-QA: 55/47/58] 2026-06-06 08:18:08 +02:00
385cccb352 POLISH-1: e2e mock accepts canonical '=' (and legacy '==') equals operator [QA-1 coordination] 2026-06-06 08:16:57 +02:00
e73b561b77 POLISH-1: move stray UI strings to de.ts (pageNav/moreData), gitignore Playwright artefacts, wire 'Abgabe abschliessen' -> /vertraege/neu?tiere= (FEAT-13b) 2026-06-06 08:14:52 +02:00
55a72bfe12 POLISH-1: gridify emits canonical '='; localize litter InvalidParentGender 400 (ApiError body) + de strings 2026-06-06 08:14:52 +02:00
e87d0aafea Merge feature/export-1: Datenexport (zip JSON+German CSVs) on /einstellungen + CI flake-cap [god-QA pending result-gate]
# Conflicts:
#	GerbilManager.Tests/GerbilManager.Tests.csproj
#	GerbilManagerWebAPI/Program.cs
#	gerbil-manager-web/src/App.tsx
#	gerbil-manager-web/src/components/AppShell.tsx
#	gerbil-manager-web/src/pages/EinstellungenPage.tsx
2026-06-06 08:06:38 +02:00
db53fad5a4 Merge feature/feat-13: Abgabevertrag phase B — SaleContract+wizard, /einstellungen Zuchtprofil, contract endpoints w/ transactional Abgabe, Kontakt structured fields [god-QA: 40/40+47/47+e2e 56/56]
# Conflicts:
#	GerbilManager.Tests/GerbilManager.Tests.csproj
#	GerbilManagerWebAPI/Program.cs
2026-06-06 08:00:55 +02:00
d3f38b9be4 FEAT-13: resolve leftover rebase conflict markers in App.tsx routes (hilfe + vertraege/einstellungen union)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 07:58:01 +02:00
f08dbd2219 QA-1: CI-Flake-Schutz - Worker-Cap 4 unter CI (geteilter Vite-Dev-Server, Dwights Beobachtung) 2026-06-06 07:57:27 +02:00
cd795d3831 Merge feature/feat-8c: Excel import loader — /import/dry-run + gated /import/execute, quarantine policy, provenance + idempotency [god-QA: 43/43] 2026-06-06 07:57:21 +02:00
be62e785db FEAT-13: e2e an strukturierte Kontaktfelder angepasst + 2 Abdeckungstests (Patch von Oscar, e2e-Owner)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 07:56:48 +02:00
d8ccb451d9 FEAT-13: singular-aware contract count text (1 Vertrag / n Vertraege)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 07:56:48 +02:00
9c3bcfc9f9 FEAT-13: Abgabe wizard (/vertraege/neu, 4 steps, ?tiere= prefill), Vertraege list w/ download+delete, /einstellungen Zuchtprofil form, contracts/settings API clients, nav entries, detail-page entry point + replace orphaned contactInfo with email/phone/address across Kontakt pages
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 07:56:48 +02:00
0c05a5acf1 FEAT-13: SaleContract + BreederSettings entities (additive migration, join table justified in code docs), /contracts + /settings/breeder-profile Minimal-API endpoints w/ Abgabe-completion transaction + SQLite-backed endpoint round-trip tests (21/21)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 07:55:34 +02:00
b7ee48401a FEAT-8c: loader tests (in-memory DB + fixture) + public test helpers
6 tests: dry-run categorisation (no writes), execute loads conflict-free + links
high-confidence + quarantines conflict/stub, idempotency, ComposeGenotype (caret strip
+ ?? fill), ParseDate. Added EF InMemory to the test project.
2026-06-06 07:55:30 +02:00
ac5ab9d0ba FEAT-8c: import loader — /import/dry-run + /import/execute (gated)
- Additive migration: Gerbil.RawImportData + Litter.PairingCode (Zuchtnummer der Verpaarung).
- ImportService consumes tools/import/output (animals.json + litters.json): litters first
  (authoritative), then conflict-free animals with a DOB; high-confidence (hoch) litter links
  set LitterId, date-only/ambiguous links quarantined; conflicts + stubs never loaded.
  Genotype mapped8locus -> frozen compact string; rawGenotype+unmappedTokens preserved in
  RawImportData; Farbschlag matched to ColorVariety; gender inferred from litter role;
  provenance ImportSource/ExternalRef; idempotent (ExternalRef / Name+Date). Photos copied to store.
- ImportEndpoints: POST /import/dry-run (no writes, Julian-readable report) + /import/execute (gated).
2026-06-06 07:55:30 +02:00
a1549266c3 EXPORT-1: e2e - Download-Smoke (/einstellungen) + Mock: /export-Zip, /settings/breeder-profile, URL-Praedikat fuer /api-relative Basis (OPS-1-proof) 2026-06-06 07:55:14 +02:00
8fa02a5d49 EXPORT-1: Datenexport-Karte auf /einstellungen (Anker-Download, deutsche Erklaertexte + Foto-Hinweis) 2026-06-06 07:55:14 +02:00
e431c50347 FEAT-8c: mark conflict animals in animals.json for the API loader
Adds a machine-readable conflict:bool to each merged animal (true when files
disagree on genotype/farbschlag/death) so the import loader can quarantine the
32 conflicts without parsing the German review report.
2026-06-06 07:55:08 +02:00
f86a044143 EXPORT-1: GET /export - Zip mit export.json (volle Treue) + deutschen Excel-CSVs (Semikolon, BOM, TT.MM.JJJJ) + LIESMICH; 9 Tests (Escaping + API-Round-Trip) 2026-06-06 07:50:42 +02:00
ce1e578bf2 Merge feature/help-1: in-app German user guide /hilfe (9 accordion sections, du-Form, rename-safe labels) [god-QA: 37/37+47/47+e2e 54/54] 2026-06-06 07:49:47 +02:00
98060b890b HELP-1: in-app German user guide (/hilfe, accordion, 9 sections)
HilfePage.tsx: accordion via <details>/<summary> (native, accessible, mobile-first);
9 sections in du-Form: Erste Schritte, Rennmaeuse, Becken, Wuerfe, Genetik,
Stammbaum, Abgabe-Ablauf, Statistik, Datensicherung. All UI labels imported from
de.ts (rename-safe); SCHECKE/Rex warnings verbatim from genetics.warnings.

de.ts: de.nav.help + de.hilfe (title, subtitle, 9 section keys)
AppShell.tsx: Hilfe (heart question mark) added to SECONDARY nav (Mehr-sheet on phone,
sidebar on desktop)
App.tsx: Route path=hilfe -> <HilfePage />
hilfe.css: accordion, hint boxes, warning colour; piggybacks on existing CSS vars

e2e/hilfe.spec.ts: 3 smoke tests x 2 viewports = 6 new tests
  -- Hilfe reachable via nav
  -- First accordion section expands on click
  -- SCHECKE warning visible in Genetik section

Full evidence: dotnet test 18/18, npm test 47/47, npm run build ok,
npm run e2e 54/54 (48 existing + 6 new hilfe tests).

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-06 07:47:45 +02:00
78da534c7c FEAT-13: e2e an strukturierte Kontaktfelder angepasst + 2 Abdeckungstests (drops on rebase once Kelly commits the same patch) 2026-06-06 07:46:51 +02:00
42718606a9 Merge feature/ops-1: TrueNAS deployment (compose + backup sidecar + nginx proxy + prod Dockerfiles), Gitea CI draft, German ops guide [god-QA: 18/18+47/47+e2e 48/48] 2026-06-06 07:42:18 +02:00
d6bf6c6fe3 OPS-1: fix e2e regression -- API_BASE_URL conditional on import.meta.env.PROD
Dev (Vite dev server / e2e mock mode): falls back to 'http://localhost:5179' so
Playwright route interception on http://localhost:5179/** keeps working.
Production (npm run build -> PROD=true): falls back to '/api' so nginx proxy
strips the prefix without any hostname baked in at build time.
VITE_API_BASE_URL (set by Aspire in dev, injected LAN IP) always wins over both.

Evidence: npm run e2e 48/48 PASS (mock mode, both viewports).

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-06 07:39:33 +02:00
04f9e087aa Merge feature/feat-12a-backend: provider-agnostic AI sale-ad endpoint (Gemini/Groq/Mistral/Ollama via OpenAI-compat, env config, graceful 503) [god-QA: 37/37] 2026-06-06 07:39:26 +02:00
95ecb1c0ee FEAT-12a: provider setup docs (env vars per provider incl. TrueNAS compose placement) 2026-06-06 07:37:42 +02:00
36c97e8a7a FEAT-12a: tests - prompt assembly, 503-unconfigured matrix, stub-provider parsing/auth, completions-URL config matrix (Gemini/Groq/Mistral/Ollama) 2026-06-06 07:37:42 +02:00
d9e5a757e9 FEAT-12a: POST /gerbils/sale-ad endpoint (503 AiKeyMissing when unconfigured, 502 AiUpstreamError) + DI wiring 2026-06-06 07:37:42 +02:00
f6bb13ca2f FEAT-12a: provider-agnostic sale-ad AI core - AiOptions (env-only), German prompt builder w/ few-shot, OpenAI-compatible chat-completions client (no SDK) 2026-06-06 07:37:42 +02:00
a221e366e6 FEAT-13: singular-aware contract count text (1 Vertrag / n Vertraege)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 07:34:25 +02:00
3ec4f660b0 FEAT-13: Abgabe wizard (/vertraege/neu, 4 steps, ?tiere= prefill), Vertraege list w/ download+delete, /einstellungen Zuchtprofil form, contracts/settings API clients, nav entries, detail-page entry point + replace orphaned contactInfo with email/phone/address across Kontakt pages
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 07:34:25 +02:00
daa6683405 FEAT-13: SaleContract + BreederSettings entities (additive migration, join table justified in code docs), /contracts + /settings/breeder-profile Minimal-API endpoints w/ Abgabe-completion transaction + SQLite-backed endpoint round-trip tests (21/21)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 07:34:25 +02:00
69a0279bb7 OPS-1: TrueNAS compose, backup sidecar, Gitea CI draft, ops docs
deploy/truenas/compose.yaml:
  - 4 services: db (postgres:17), api (.NET), frontend (nginx), backup sidecar
  - Named volumes as NAS bind-mounts (paths configured in .env)
  - Healthchecks: db pg_isready, api /health, frontend waits on api
  - ANTHROPIC_API_KEY placeholder for FEAT-12a AI stub

deploy/truenas/.env.example: POSTGRES_PASSWORD, PORT, REGISTRY, dataset paths

deploy/truenas/scripts/:
  - entrypoint.sh: installs daily 03:00 cron, starts crond in foreground
  - backup.sh: pg_dump -> .sql + tar czf photos -> .tar.gz + rotation
  - restore.sh: psql < dump + tar xzf photos; confirmation prompt (-f to skip)
  Predecessor logic (commit 6a37f9e) translated from PowerShell to POSIX sh
  for Alpine containers. Same pg_dump/restore semantics, same KEEP_DAYS rotation.

.gitea/workflows/ci.yml (DRAFT -- inactive until Julian confirms Actions):
  dotnet test + npm test/build on push/PR to main;
  docker build+push to Gitea registry on main push only

docs/ops.md:
  German ops guide -- architecture diagram, first-install checklist,
  start/stop/update commands, backup runbook (manual + auto), ZFS-snapshot
  layering strategy, CI activation steps, open questions, troubleshooting table

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-06 07:31:19 +02:00
2f2e5b1f56 OPS-1: Dockerfiles (net10 API + nginx frontend) + production config
- GerbilManagerWebAPI/Dockerfile: net7->net10 multi-stage; build context=repo
  root (includes ServiceDefaults); port 8080 (.NET 10 container default)
- gerbil-manager-web/Dockerfile: drop VITE_API_BASE_URL build-arg; nginx proxies
  /api/* to api:8080 (strip prefix), /scalar, /openapi/ -- one published port 80
- gerbil-manager-web/src/api/client.ts: default API_BASE_URL /api (relative),
  no hostname coupling at build time; Aspire still injects absolute LAN URL in dev
- GerbilManagerWebAPI/Program.cs: run EF Migrate() at startup always (not Dev-only)
- GerbilManager.ServiceDefaults/Extensions.cs: expose /health + /alive in all
  environments (compose healthcheck requires them in Production)

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-06 07:31:19 +02:00
adea82a0e7 QA-1: document e2e usage (mock/live modes, viewports) in web README 2026-06-06 07:21:27 +02:00
ebd61d73a5 QA-1: smoke specs - Navigation, Tiere CRUD+Tabs, Becken/Kontakte+409, Wuerfe+Jungtier, Probeverpaarung+SCHECKE-Warnung, Stammbaum re-root+print, Statistik (24 flows x 2 viewports, German assertions) 2026-06-06 07:16:52 +02:00
ec5e755e72 QA-1: stateful in-memory mock API per route interception (DATA-2 contract: Gridify paging, camelCase DTOs, 409 delete-conflicts) + fixtures 2026-06-06 07:16:52 +02:00
8d7999c4a5 QA-1: Playwright e2e harness - config (phone 390px + desktop projects, mock/live via E2E_BASE_URL), npm run e2e, vitest excludes e2e/ 2026-06-06 07:16:43 +02:00
c9723d2fc8 Merge feature/feat-12a: Abgeben flow — multi-select ForSale, /abgabe group composer, paste-package, AI stub [god-QA: 47/47 + build] 2026-06-06 07:16:26 +02:00
07dd5c9b8e FEAT-12a: multi-select bulk 'Zur Abgabe stellen' on the Tiere list 2026-06-06 07:13:30 +02:00
aa79f9dbe5 Revert OPS-1 Windows-plan commits (dada3af, 6a37f9e): superseded by TrueNAS deployment target; re-landed on main against GIT-3 — content preserved on Dwight's branch-to-be 2026-06-06 07:12:20 +02:00
3b3497079b Merge feature/feat-13: Abgabevertrag generator phase A (template + pure OpenXml generator + 10 tests) [god-QA: 18/18] 2026-06-06 07:11:30 +02:00
dada3af968 OPS-1: startup scripts, autostart task, backup task, ops README, production config
- appsettings.Production.json: Photos:RootPath -> C:\gerbil-data\photos so
  photo files land on a stable host path when ASPNETCORE_ENVIRONMENT=Production
- Start-GerbilManager.ps1: creates data dirs, sets Production env, launches
  AppHost minimised; saves PID for Stop script
- Stop-GerbilManager.ps1: kills AppHost + Vite node processes by PID / port
- Register-AutoStart.ps1: Windows Scheduled Task on user logon (RunLevel Highest)
- Register-BackupTask.ps1: daily 03:00 Scheduled Task for Backup script
- deploy/README.md: Julian ops guide — start/stop commands, phone URL, DHCP
  reservation, firewall rule (Public-profile Wi-Fi), backup/restore procedures,
  prerequisites checklist, troubleshooting table (German)

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-06 07:11:09 +02:00
6a37f9e46e OPS-1: fix backup/restore scripts — ASCII-only + array coerce for Count
- Replace em dashes (UTF-8 multi-byte) with ASCII hyphens; PowerShell 5.1
  reads ps1 files as CP1252 by default so any non-ASCII in source causes
  cascading parse errors
- Extract POSTGRES_PASSWORD from container env (Aspire uses scram-sha-256;
  peer/trust auth does not work) and pass as PGPASSWORD env var to pg_dump
  and psql in both Backup and Restore scripts
- @() wrap on Get-ChildItem result to force array before .Count under
  Set-StrictMode -Version Latest (single-item returns a bare object in PS5)
- Restore-test evidence: 73 ColorVarieties -> DELETE 12 -> 61 -> pg_restore
  -> 73 confirmed (run 2026-06-06 07:09 against postgres-gatkzrgq)

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-06 07:09:53 +02:00
44f306d18f FEAT-12a: Abgabe page — Becken-default grouping + per-group listing composer, clipboard/zip export, AI stub 2026-06-06 07:09:48 +02:00
cbe77c927a FEAT-13: ContractGenerator (pure OpenXml, embedded template, per-animal table cloning) + BreederProfile/ContractData records + 10 xUnit tests incl. schema validation & PII guard
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 07:09:07 +02:00
e4b7558abd FEAT-12a: ForSale scaffolding — status+ForSale, abgabe strings, /abgabe route+nav, sale-ad API stub, detail action, jszip 2026-06-06 01:07:43 +02:00
188b33618e DATA-2: amendments — GerbilStatus.ForSale, Contact structured fields, 73-variety seed
- GerbilStatus += ForSale ("Abzugeben", FEAT-12 sale listing); enum-as-string, no DB change.
- Contact: contactInfo -> structured email/phone/address (FEAT-13 sale contracts); name/notes kept.
- ColorVariety seed 18 -> 73 from Kevin's GEN-2 colorVarietySeed.generated.json (18 frozen first).
- Regenerated InitialCreate migration (Contacts email/phone/address cols, 73 seed rows).
2026-06-06 01:07:19 +02:00
f3b1ecb7a3 FEAT-13: Abgabevertrag placeholder template from her sample contract (18 {{tokens}}, PII scrubbed incl. docProps/mailto-rel, animal photos removed, Zucht logo kept, boilerplate verbatim)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 01:03:25 +02:00