Beschikbaarheid (Backend)
De backend van de module Beschikbaarheid beheert de opslag en validatie van de inzetbaarheid van medewerkers. De logica is ondergebracht in de features.beschikbaarheid Django-app. De opgeslagen beschikbaarheid dient als invoer voor de roosterplanning; de module maakt zelf geen rooster.
Technisch Ontwerp
De module gebruikt een "full-replace" strategie bij het opslaan van beschikbaarheid per week: bij een PUT worden alle bestaande records van de ingelogde gebruiker voor die week eerst verwijderd en daarna opnieuw aangemaakt. Dit houdt de database schoon en voorkomt synchronisatievraagstukken tussen oude en nieuwe selecties.
Opslagproces (Flowchart)
flowchart TD
A[PUT /api/beschikbaarheid/] --> B{week_start geldig?}
B -- Nee --> C[400 Bad Request]
B -- Ja --> D{availability een object?}
D -- Nee --> C
D -- Ja --> E{Binnen limieten?<br/>max 7 dagen,<br/>max 50 dagdelen/dag}
E -- Nee --> C
E -- Ja --> F[services.save_availability]
F --> G[Verwijder bestaande records<br/>user + week_start_date]
G --> H[bulk_create nieuwe records<br/>voor request.user]
H --> I[services.get_availability<br/>Return JSON]
De caps BESCHIKBAARHEID_MAX_DAGEN (7) en BESCHIKBAARHEID_MAX_DAGDELEN_PER_DAG (50) worden in de view afgedwongen voordat de payload bulk_create bereikt, zodat een enkel verzoek nooit duizenden rijen kan aanmaken.
Automatische vulling
De service fill_beschikbaarheid_from_vaste_werkdagen maakt voor elke VasteWerkdag (uit de module Rooster) records met available=True aan voor de huidige week plus de komende weken (standaard 12). Het proces is idempotent: bulk_create(..., ignore_conflicts=True) overschrijft bestaande records, inclusief handmatige overrides, nooit. De service draait via de Celery-task fill_beschikbaarheid_weekly en wordt daarnaast direct aangeroepen wanneer vaste werkdagen in de module Rooster worden opgeslagen.
Datamodel (ERD)
De kern van de module is het Beschikbaarheid model. Elke rij beschrijft de beschikbaarheid van een medewerker voor een enkel dagdeel in een enkele week.
erDiagram
User ||--o{ Beschikbaarheid : "heeft"
Beschikbaarheid {
uuid id PK
bigint user_id FK
date week_start_date "altijd een maandag, db_index"
smallint day_index "0-6 (ma-zo)"
uuid dagdeel_id "db_index, geen FK"
bool available "default true"
datetime updated_at
}
- user_id: verwijst naar
accounts.User(bigint primary key,BigAutoField). De foreign key gebruiktdb_constraint=False. - dagdeel_id: slaat de UUID van het dagdeel op als los veld zonder Foreign Key. Hierdoor blijven beschikbaarheidsrecords behouden als de configuratie van dagdelen in de module Rooster wijzigt of wordt verwijderd.
- Constraints:
UniqueConstraintop de combinatieuser,week_start_date,day_indexendagdeel_id. Indexen op(user, week_start_date)en(week_start_date, dagdeel_id).
API & Communicatie
De communicatie verloopt via een enkele APIView (BeschikbaarheidView) op /api/beschikbaarheid/. De querystring week_start=YYYY-MM-DD (een maandag) is op beide methoden verplicht.
- GET
/api/beschikbaarheid/?week_start=YYYY-MM-DD: haalt de beschikbaarheid voor de gevraagde week op. Standaard ziet een gebruiker alleen de eigen data. Een gebruiker metroster.editziet de data van alle medewerkers, zodat de planner de beschikbaarheid kan inplannen. - PUT
/api/beschikbaarheid/?week_start=YYYY-MM-DD: slaat de beschikbaarheid van de ingelogde gebruiker voor de gevraagde week op (full-replace). De body heeft de vorm{ "availability": { "<day_index>": { "<dagdeel_id>": true|false } } }.
Beide methoden geven hetzelfde antwoord terug:
{
"week_start_date": "2026-03-16",
"availability": {
"42": { "0": { "<dagdeel-uuid>": true, "<dagdeel-uuid>": false } }
}
}
De sleutels van availability zijn medewerker-id, day_index en dagdeel_id (alle als string). Bij een gewone gebruiker bevat de map alleen de eigen user_id.
Foutafhandeling & Statuscodes
400 Bad Request: ontbrekende of ongeldigeweek_startparameter,availabilityis geen object, een dag-map is geen object, of de limieten (BESCHIKBAARHEID_MAX_DAGEN,BESCHIKBAARHEID_MAX_DAGDELEN_PER_DAG) worden overschreden.401 Unauthorized: geen geldige sessie of token.
Ongeldige entries binnen een verder geldige payload (een niet-numerieke day_index of een ongeldige dagdeel_id UUID) worden in save_availability stil overgeslagen; de overige records worden gewoon opgeslagen.
Autorisatie & Beveiliging
- Tenant Isolatie: alle queries lopen binnen het schema van de huidige tenant via
TenantEnforcedJWTAuthenticationen de django-tenants middleware. - Basis-teammodule, geen schrijf-RBAC:
BeschikbaarheidViewgebruiktHasPermissionCodezonderrequired_permission, dus elke ingelogde medewerker mag de eigen beschikbaarheid opslaan.save_availabilityschrijft uitsluitend records voorrequest.user; een gebruiker kan de beschikbaarheid van een ander niet bewerken. Er bestaat geenavailability.editpermissiecode. - Inzage in andermans beschikbaarheid:
get_availabilityverbreedt de GET alleen tot alle medewerkers wanneer de gebruikerroster.editheeft. Zonder die code wordt de queryset gefilterd op de eigen gebruiker.
Bestandsstructuur & Verantwoordelijkheden
models.py: definieert hetBeschikbaarheidmodel (constraints en indexen).services.py: business logic voorget_availability,save_availability(full-replace) enfill_beschikbaarheid_from_vaste_werkdagen(automatische vulling).views.py:BeschikbaarheidViewmet GET en PUT, parameter-validatie en de payload-limieten.serializers.py:BeschikbaarheidSerializervoor de transformatie naar JSON.urls.py: koppelt de view aan/api/beschikbaarheid/.tasks.py: Celery-takencleanup_old_beschikbaarheid(verwijdert records ouder dan 4 weken) enfill_beschikbaarheid_weekly(automatische vulling per tenant).
Belangrijke bestanden
backend/features/beschikbaarheid/models.pybackend/features/beschikbaarheid/services.pybackend/features/beschikbaarheid/views.py
API & Communicatie (Swagger)
De volledige API-specificatie voor deze module is hieronder beschikbaar: