feat: agent-12 – Zwei-Stufen-Genehmigung für Abwesenheiten
Optionale zweistufige Freigabe (Feature-Parität mit Urlaubsverwaltung,
Second-Stage-Authority), ohne SSO:
- Firmen-Opt-in companies.two_stage_approval_enabled + two_stage_min_days
(nur Anträge ab X Arbeitstagen brauchen Stufe 2; 0 = alle).
- Ablauf PENDING → FIRST_APPROVED → APPROVED: erste Stufe durch Manager-Rollen,
finale Stufe nur HR/Admin und zwingend eine ANDERE Person als Stufe 1.
- Urlaubs-/FZA-Abzug, CalDAV-Sync und Vertreter-Mail erst bei finaler Genehmigung.
Ablehnen in beiden Stufen möglich; Eigentümer darf FIRST_APPROVED noch stornieren.
- pending_days, Kalender und Reminder-Digest berücksichtigen FIRST_APPROVED.
- Neuer Status-Wert + absences.first_approved_by; System-Kommentar bei Stufe 1.
Frontend: CompanySettingsPage (Toggle + Schwellwert), AbsencesPage
("Endgültig genehmigen"/Ablehnen für HR/Admin ≠ Erstgenehmiger, Status-Badge).
Migration 0038. 190/190 Tests grün. Deployed 137 + 164.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
"""Two-stage absence approval (agent-12)
|
||||
|
||||
Revision ID: 0038
|
||||
Revises: 0037
|
||||
Create Date: 2026-06-23
|
||||
|
||||
- AbsenceStatus.FIRST_APPROVED (erste Stufe erteilt, wartet auf finale Genehmigung)
|
||||
- absences.first_approved_by (Genehmiger Stufe 1; muss != finalem Genehmiger sein)
|
||||
- companies.two_stage_approval_enabled + two_stage_min_days (firmenweites Opt-in)
|
||||
"""
|
||||
from alembic import op
|
||||
|
||||
revision = "0038"
|
||||
down_revision = "0037"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.execute("ALTER TYPE absencestatus ADD VALUE IF NOT EXISTS 'first_approved'")
|
||||
op.execute(
|
||||
"ALTER TABLE absences ADD COLUMN IF NOT EXISTS first_approved_by UUID "
|
||||
"REFERENCES users(id) ON DELETE SET NULL"
|
||||
)
|
||||
op.execute(
|
||||
"ALTER TABLE companies ADD COLUMN IF NOT EXISTS "
|
||||
"two_stage_approval_enabled BOOLEAN NOT NULL DEFAULT FALSE"
|
||||
)
|
||||
op.execute(
|
||||
"ALTER TABLE companies ADD COLUMN IF NOT EXISTS "
|
||||
"two_stage_min_days INTEGER NOT NULL DEFAULT 0"
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# Enum-Wert bleibt (PostgreSQL kann ihn nicht entfernen).
|
||||
op.execute("ALTER TABLE companies DROP COLUMN IF EXISTS two_stage_min_days")
|
||||
op.execute("ALTER TABLE companies DROP COLUMN IF EXISTS two_stage_approval_enabled")
|
||||
op.execute("ALTER TABLE absences DROP COLUMN IF EXISTS first_approved_by")
|
||||
Reference in New Issue
Block a user