Skip to content

feat: Soll/Ist-Vergleich mit bestätigter Vertragshistorie (#45) - #49

Open
patrickschiller wants to merge 7 commits into
mainfrom
feat/45-contract-period-comparison
Open

patrickschiller wants to merge 7 commits into
mainfrom
feat/45-contract-period-comparison

Conversation

@patrickschiller

@patrickschiller patrickschiller commented Nov 7, 2026 •

Copy link
Copy Markdown
Owner

Paket #45 – vertragliches Soll / Netto-Ist je Zeitraum

Closes #45.

Abhängigkeit / Reihenfolge: #46 → #47 → #48 → dieser PR. Basis dieses Pakets ist der dokumentationskorrigierte #43-Head 53f961164245db69ac91912d3f123961ce846dd8. Der PR zielt absichtlich auf main, damit sämtliche bestehenden CI-Gates laufen. Der sichtbare Diff ist kumulativ #42 + #41 + #43 + #45, kein unabhängiger Ersatz für die drei Vorgänger. Kein Merge/Release/Tag/Versionsbump/Deployment wurde ausgeführt.

Umsetzung

  • Serverautorisierter Soll/Ist-Vergleich je Beschäftigtem für Woche/Monat/benutzerdefiniert, einschließlich Personen ohne Buchungen. HR organisationsweit; Manager nur sich selbst und unmittelbar zugeordnete Personen. Fremde/vermischte Filter-IDs werden auch bei leerem Zeitraum verweigert. Frische Rollen-/Team-Zustände werden im Berichtssnapshot erneut geprüft.
  • Echte datierte Vertragshistorie statt rückwirkend angewendeter aktueller Profilwerte: additive Prisma-Tabellen mit eigenständigen Wochenstunden-, Modell-, Arbeitstage-, Beschäftigungs- und Feiertagssnapshots; HR-Pflege in der bestehenden Mitarbeiterverwaltung. Explizite Bestätigung/Quellnotiz, validierte Grenzen, keine stillen Überlappungen. Revisionsgeprüfte Ablösung beendet nur die Vorperiode am Vortag; ursprüngliche Fakten und Before/After-Audit bleiben erhalten. Schreibzugriffe sind installations-/mitarbeitergesperrt und prüfen aktive HR-Identität, Sessionrevision und Team-Modus erneut.
  • Migration erfindet keine Altverträge oder HR-Akteure. Unbekannte Tage liefern Soll und Differenz null mit konkretem Grund/Datumsangaben; kein Null-Soll und keine vorgetäuschte Historie. HR kann bekannte vergangene oder zukünftige Perioden ausdrücklich bestätigen. Spätere operative Profil-/Arbeitszeitplanänderungen schreiben bestätigte Werte nicht um. Demo-Seed bestätigt ausschließlich synthetisch bekannte Fakten und überschreibt vorhandene Perioden nicht.
  • Tages-Soll mit bestehender Arbeitsmasken-/Minutenregel, Snapshot-Feiertagen, Beschäftigungsgrenzen und genehmigtem Urlaub/Sonderurlaub bzw. erfasster Krankheit/Fortbildung; Halbtage/maximale Tagesabdeckung verhindern doppelte Gutschriften. Befreiung reduziert nur Soll, nicht zusätzlich Ist. Homeoffice/Freizeitausgleich erhalten keine zusätzliche Befreiung.
  • Ist zählt geschlossene Pending/Approved-Einträge explizit vorläufig, netto mit gespeicherter Capture-Gruppen-Pause. Keine offenen/abgelehnten/entwerteten Zeiten. Echte Intervallüberlappung, lokale Mitternachts-/Zeitraum-Clips, DST/Sekunden, außerhalb liegende Gruppenmitglieder; keine GPS-Beobachtung auf künstlichen Schnittkanten. Tabelle und CSV verwenden die erklärte Berichtszeitzone, unabhängig vom Browser.
  • DE/EN, lokalisierte Stunden und signierte Periodendifferenz (Ist − Soll), zugänglicher Text plus Farbe, Unbekannt-/Leer-/Fehlerzustände. +10 h ist eine erklärte Zeitraum-Prüfschwelle, keine gesetzliche Grenze und kein fortgeschriebenes Zeitkonto. Solo bleibt unverändert, PDF bleibt HR-only; ein PDF-Funktionsausbau gehört nicht zu diesem Soll/Ist-Paket.
  • OpenAPI und generierter Client synchron; keine neuen Abhängigkeiten.

Verifiziert (Node 20.20.2 / pnpm 9.15.9, isoliertes PostgreSQL 16, Europe/Berlin)

Gate Ergebnis
Vollständige API-E2E 415/415 Tests, 41 Suites; darunter 49 neue Fälle (33 Vertrag / 16 Vergleich)
Vollständige Web-Tests 267/267 Tests, 37 Dateien (einschließlich #42-DST/Fold und #41/#43)
Shared-Domain 88/88 Tests, 7 Dateien
Operator-/DB-Zielsicherheit 27/27 Tests
API/Web/Shared/API-E2E Typechecks alle erfolgreich, Build und Typecheck getrennt
Lint derselben Projekte 0 Fehler, ausschließlich 13 bestehende Warnungen
API/Web/Shared Produktions-Builds alle erfolgreich, einschließlich PWA, API/Web nach finalen Änderungen separat nachgebaut
pnpm verify:api, staged/working diff checks erfolgreich
Befüllter Upgrade #43 → #45 (26 → 27 Migrationen) erfolgreich, Altdaten/Audits unverändert, keine erfundene Historie
Demo-Seed zweimal + Nachtest-SQL 9/9 Snapshots/Audits unverändert, zwei neue synthetische Personen/fünf Buchungen erfolgreich eingefügt

Die Anleitung dokumentiert auch Zwischenbefunde (ungültige Mehrfach-Open-Fixture, vorläufige TypeScript-Testfehler, eine ULP bei Mitternachtssummen und lokalen HTTP-Port-Ausreißer). Keine fachlichen Status-/Berechtigungsassertions wurden gelockert, keine automatischen Retries. Der E2E-Server besitzt jetzt genau einen Loopback-Listener je Suite.

Nachtest: docs/ISSUE_FIXES_MANUAL_TEST.de.md mit eigenem Docker-Projekt/Port, synthetischen Rollen, ausführbarer Fixture, Zahlenfällen und Negativtests. Ein manueller Docker-/Browserdurchlauf wird nicht als erfolgt behauptet. Vorhandene .agents/ und openspec/ im Hauptcheckout bleiben unberührt.

Alle fünf GitHub-Checks auf 3a2361d0d2d25f23ce030ce751cf67873aedbf8f erfolgreich:

Check Ergebnis
terminal-pin-browser grün
build-test-lint grün
dco-check grün
database-upgrade grün
api-e2e grün

Reopen returned drafts with their values and revision reason. Add owner-only versioned editing/resubmission, shared validation, balance/overlap self-exclusion, transactional concurrency guards, employee names, synchronized API contracts and regression/manual acceptance coverage.

Co-authored-by: patrickschiller <39913537+patrickschiller@users.noreply.github.com>
Signed-off-by: Patrick Schiller <39913537+patrickschiller@users.noreply.github.com>
Keep persisted timestamps unchanged until their time field is edited. Resolve wall-clock validation and payloads to identical instants, require explicit ambiguous-time choices, reject clock-change gaps, and cover seconds, both fold occurrences and reason-only save/resubmit cycles.

Co-authored-by: patrickschiller <39913537+patrickschiller@users.noreply.github.com>
Signed-off-by: Patrick Schiller <39913537+patrickschiller@users.noreply.github.com>
Keep the English DST selection regression independent of jsdom persisted locale on Node 20. Verify all 208 web tests with Node 20.20.2 and document the CI follow-up.

Co-authored-by: patrickschiller <39913537+patrickschiller@users.noreply.github.com>
Signed-off-by: Patrick Schiller <39913537+patrickschiller@users.noreply.github.com>
Add scoped, versioned TimeEntry review with distinct current-manager and HR stages, durable decision audit, legacy pending support and conservative edit invalidation. Surface employee guidance, reviewer actions and history in German/English, synchronize API contracts, and verify additive database upgrades and security/concurrency regressions. Based on accepted #42; no release or merge.

Co-authored-by: patrickschiller <39913537+patrickschiller@users.noreply.github.com>
Signed-off-by: Patrick Schiller <39913537+patrickschiller@users.noreply.github.com>
Bind correction requests to an owned eligible entry ID and original revision with immutable server snapshots. Revalidate targets, overlaps and required manager/HR stages, then update the same entry and linked audit atomically at final approval. Retain draft precision, metadata and break policies; add target selection/diffs, upgrade safety and focused rollback/concurrency regressions. Cumulative on accepted #42 and #41; no release or merge.

Co-authored-by: patrickschiller <39913537+patrickschiller@users.noreply.github.com>
Signed-off-by: Patrick Schiller <39913537+patrickschiller@users.noreply.github.com>
Distinguish forbidden foreign targets from ignored body employee identities; eligible own targets remain valid under the authenticated identity.

Co-authored-by: patrickschiller <39913537+patrickschiller@users.noreply.github.com>
Signed-off-by: Patrick Schiller <39913537+patrickschiller@users.noreply.github.com>
…#45)

Add HR-confirmed immutable contract snapshots, scoped period calculations, accessible DE/EN reports and complete regression/upgrade evidence.

Co-authored-by: patrickschiller <39913537+patrickschiller@users.noreply.github.com>
Signed-off-by: Patrick Schiller <39913537+patrickschiller@users.noreply.github.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-07T03:50:26.902040Z 3a2361d PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3a2361d0d2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 357 to 361
const report = await this.buildWorkingTimes(
actorId,
{ ...query, includeLocations: 'false' },
tx,
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Align the PDF explanation with the new clipped report rows

For HR PDF exports containing overnight bookings or bookings crossing the selected period boundary, buildWorkingTimes now supplies midnight-split, period-clipped rows with synthetic start/end timestamps. However, renderWorkingTimePdf still prints an intervalNote in both languages stating that overnight intervals remain complete and are not clipped at period boundaries (working-time-pdf.ts). The exported working-time record therefore describes the opposite of how its timestamps and totals were calculated, potentially making a partial booking look like the complete recorded interval. Update the PDF explanation to describe splitting/clipping, or retain the original interval semantics specifically for PDF exports.

Useful? React with 👍 / 👎.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feature] Arbeitszeiten

1 participant