- add period-scoped holiday architecture end-to-end - model: scope `SchoolHoliday` to `academic_period_id` - migrations: add holiday-period scoping, academic-period archive lifecycle, and merge migration head - API: extend holidays with manual CRUD, period validation, duplicate prevention, and overlap merge/conflict handling - recurrence: regenerate holiday exceptions using period-scoped holiday sets - improve frontend settings and holiday workflows - bind holiday import/list/manual CRUD to selected academic period - show detailed import outcomes (inserted/updated/merged/skipped/conflicts) - fix file-picker UX (visible selected filename) - align settings controls/dialogs with defined frontend design rules - scope appointments/dashboard holiday loading to active period - add shared date formatting utility - strengthen academic period lifecycle handling - add archive/restore/delete flow and backend validations/blocker checks - extend API client support for lifecycle operations - release/docs updates and cleanup - bump user-facing version to `2026.1.0-alpha.15` with new changelog entry - add tech changelog entry for alpha.15 backend changes - refactor README to concise index and archive historical implementation docs - fix Copilot instruction link diagnostics via local `.github` design-rules reference
8.6 KiB
Academic Periods CRUD Build Plan
Goal
Add full academic period lifecycle management to the settings page and backend, including safe archive and hard-delete behavior, recurrence spillover blockers, and a UI restructuring where Perioden becomes the first sub-tab under Akademischer Kalender.
Frontend Design Rules
All UI implementation for this build must follow the project-wide frontend design rules:
Key points relevant to this build:
- Syncfusion Material3 components are the default for every UI element
- Use
DialogComponentfor all confirmations — neverwindow.confirm() - Follow the established card structure, button variants, badge colors, and tab patterns
- German strings only in all user-facing text
- No Tailwind classes
Agreed Rules
Permissions
- Create: admin or higher
- Edit: admin or higher
- Archive: admin or higher
- Restore: admin or higher
- Hard delete: admin or higher
- Activate: admin or higher
- Editors do not activate periods by default because activation changes global system state
Lifecycle
- Active: exactly one period at a time
- Inactive: saved period, not currently active
- Archived: retired period, hidden from normal operational selection
- Deleted: physically removed only when delete preconditions are satisfied
Validation
nameis required, trimmed, and unique among non-archived periodsstartDatemust be less than or equal toendDateperiodTypemust be one ofschuljahr,semester,trimester- Overlaps are disallowed within the same
periodType - Overlaps across different
periodTypevalues are allowed - Exactly one period may be active at a time
Archive Rules
- Active periods cannot be archived
- A period cannot be archived if it still has operational dependencies
- Operational dependencies include recurring master events assigned to that period that still generate current or future occurrences
Restore Rules
- Archived periods can be restored by admin or higher
- Restored periods return as inactive by default
Hard Delete Rules
- Only archived and inactive periods can be hard-deleted
- Hard delete is blocked if linked events exist
- Hard delete is blocked if linked media exist
- Hard delete is blocked if recurring master events assigned to the period still have current or future scheduling relevance
Recurrence Spillover Rule
- If a recurring master event belongs to an older period but still creates occurrences in the current or future timeframe, that older period is not eligible for archive or hard delete
- Admin must resolve the recurrence by ending, splitting, or reassigning the series before the period can be retired or deleted
Build-Oriented Task Plan
Phase 1: Lock The Contract
Files:
server/routes/academic_periods.pymodels/models.pydashboard/src/settings.tsx
Work:
- Freeze lifecycle rules, validation rules, and blocker rules
- Freeze the settings tab order so
Periodencomes beforeImport & Liste - Confirm response shape for new endpoints
Deliverable:
- Stable implementation contract for backend and frontend work
Phase 2: Extend The Data Model
Files:
models/models.py
Work:
- Add archive lifecycle fields to academic periods
- Recommended fields:
is_archived,archived_at,archived_by
Deliverable:
- Academic periods can be retired safely and restored later
Phase 3: Add The Database Migration
Files:
server/alembic.iniserver/alembic/server/initialize_database.py
Work:
- Add Alembic migration for archive-related fields and any supporting indexes
- Ensure existing periods default to non-archived
Deliverable:
- Schema upgrade path for current installations
Phase 4: Expand The Backend API
Files:
server/routes/academic_periods.py
Work:
- Implement full lifecycle endpoints:
GET /api/academic_periodsGET /api/academic_periods/:idPOST /api/academic_periodsPUT /api/academic_periods/:idPOST /api/academic_periods/:id/activatePOST /api/academic_periods/:id/archivePOST /api/academic_periods/:id/restoreGET /api/academic_periods/:id/usageDELETE /api/academic_periods/:id
Deliverable:
- Academic periods become a fully managed backend resource
Phase 5: Add Backend Validation And Guardrails
Files:
server/routes/academic_periods.pymodels/models.py
Work:
- Enforce required fields, type checks, date checks, overlap checks, and one-active-period behavior
- Block archive and delete when dependency rules fail
Deliverable:
- Backend owns all business-critical safeguards
Phase 6: Implement Recurrence Spillover Detection
Files:
server/routes/academic_periods.pyserver/routes/events.pymodels/models.py
Work:
- Detect recurring master events assigned to a period that still generate present or future occurrences
- Treat them as blockers for archive and hard delete
Deliverable:
- Old periods cannot be retired while they still affect the active schedule
Phase 7: Normalize API Serialization
Files:
server/routes/academic_periods.pyserver/serializers.py
Work:
- Return academic period responses in camelCase consistently with the rest of the API
Deliverable:
- Frontend receives normalized API payloads without special-case mapping
Phase 8: Expand The Frontend API Client
Files:
dashboard/src/apiAcademicPeriods.ts
Work:
- Add frontend client methods for create, update, activate, archive, restore, usage lookup, and hard delete
Deliverable:
- The settings page can manage academic periods through one dedicated API module
Phase 9: Reorder The Akademischer Kalender Sub-Tabs
Files:
dashboard/src/settings.tsx
Work:
- Move
Periodento the first sub-tab - Move
Import & Listeto the second sub-tab - Preserve controlled tab state behavior
Deliverable:
- The settings flow reflects setup before import work
Phase 10: Replace The Current Period Selector With A Management UI
Files:
dashboard/src/settings.tsx
Work:
- Replace the selector-only period card with a proper management surface
- Show period metadata, active state, archived state, and available actions
Deliverable:
- The periods tab becomes a real administration UI
Phase 11: Add Create And Edit Flows
Files:
dashboard/src/settings.tsx
Work:
- Add create and edit dialogs or form panels
- Validate input before save and surface backend errors clearly
Deliverable:
- Admins can maintain periods directly in settings
Phase 12: Add Archive, Restore, And Hard Delete UX
Files:
dashboard/src/settings.tsx
Work:
- Fetch usage or preflight data before destructive actions
- Show exact blockers for linked events, linked media, and recurrence spillover
- Use explicit confirmation dialogs for archive and hard delete
Deliverable:
- Destructive actions are safe and understandable
Phase 13: Add Archived Visibility Controls
Files:
dashboard/src/settings.tsx
Work:
- Hide archived periods by default or group them behind a toggle
Deliverable:
- Normal operational periods stay easy to manage while retired periods remain accessible
Phase 14: Add Backend Tests
Files:
- Backend academic period test targets to be identified during implementation
Work:
- Cover create, edit, activate, archive, restore, hard delete, overlap rejection, dependency blockers, and recurrence spillover blockers
Deliverable:
- Lifecycle rules are regression-safe
Phase 15: Add Frontend Verification
Files:
dashboard/src/settings.tsx- Frontend test targets to be identified during implementation
Work:
- Verify sub-tab order, CRUD refresh behavior, blocked action messaging, and activation behavior
Deliverable:
- Settings UX remains stable after the management upgrade
Phase 16: Update Documentation
Files:
.github/copilot-instructions.mdREADME.mdTECH-CHANGELOG.md
Work:
- Document academic period lifecycle behavior, blocker rules, and updated settings tab order as appropriate
Deliverable:
- Repo guidance stays aligned with implemented behavior
Suggested Build Sequence
- Freeze rules and response shape
- Change the model
- Add the migration
- Build backend endpoints
- Add blocker logic and recurrence checks
- Expand the frontend API client
- Reorder sub-tabs
- Build period management UI
- Add destructive-action preflight UX
- Add tests
- Update documentation
Recommended Delivery Split
-
Backend foundation
- Model
- Migration
- Routes
- Validation
- Blocker logic
-
Frontend management
- API client
- Tab reorder
- Management UI
- Dialogs
- Usage messaging
-
Verification and docs
- Tests
- Documentation