Team (Backend)
Technisch Ontwerp
De module Team ontsluit medewerkersgegevens binnen dezelfde tenant. Team heeft geen eigen modellen; het aggregeert User, ProfileSettings (privacy) en Role (functietitel). De kernlogica zit in services.py en past de privacy-filtering server-side toe: alleen gebruikers met visible_to_team=True komen in de lijst, en telefoonnummer, e-mailadres en werkdagen worden alleen meegegeven als de medewerker de bijbehorende deeloptie heeft aangezet.
De query bouwt op auth.services.membership.member_users_qs(tenant) met is_active=True, plus select_related/prefetch_related op ProfileSettings en roles. Het telefoonnummer wordt versleuteld opgeslagen en pas ontsleuteld wanneer share_phone=True, zodat versleutelde velden niet onnodig worden gelezen. Vaste werkdagen komen uit features.rooster.services.get_vaste_werkdagen_by_employee en worden alleen opgehaald als minstens een teamlid op de pagina werkdagen deelt. De functietitel komt uit _role_label_for_user (alfabetisch samengevoegde rolnamen, anders "Geen functie gekoppeld"). Heeft een gebruiker geen ProfileSettings, dan geldt volledige zichtbaarheid als default.
flowchart TD
REQ[GET /api/team/members/] --> P{paginate == '1'?}
P -->|Nee| L1[services.list_visible_team_members] --> FLAT[Response: items]
P -->|Ja| L2[services.list_visible_team_members_page] --> Q[_apply_search op naam en functie]
Q --> PG[clamp_page_size 10/50/100 + parse_page]
PG --> FILTER[_member_payload: privacy-filtering]
FILTER --> PAGED[Response: results, page, total, total_pages, next]
FILTER --> S3[generate_signed_url avatar]
Datamodel (ERD)
Het teamoverzicht aggregeert User (basisgegevens), ProfileSettings (privacy-voorkeuren en avatar) en Role (functietitels).
erDiagram
User ||--o{ Role : "users m2m"
User ||--|| ProfileSettings : "profile_settings"
User {
int id PK
string first_name
string last_name
string email
string phone_number "versleuteld"
boolean is_active
}
ProfileSettings {
int id PK
int user_id FK
boolean visible_to_team
boolean share_phone
boolean share_email
boolean share_work_days_with_team
string avatar_s3_key
}
Role {
int id PK
int tenant_id FK
string name
string code
}
API & Communicatie
GET /api/team/members/: haalt de zichtbare teamleden op. De view kent twee responsvormen.
- Zonder
paginate=1(de standaard, gebruikt door de frontend): de platte vorm{ "items": [...] }. - Met
paginate=1: de gepagineerde vorm{ "results": [...], "page", "page_size", "total", "total_pages", "next" }. Parameters:page(1-gebaseerd),page_size(gesnapt naar 10, 50 of 100; ongeldige waarden vallen terug op 10) enq(zoeken op voornaam, achternaam of functienaam).
Elk teamlid bevat id, first_name, last_name, role, avatar_url (signed S3-URL of leeg), phone_number, email, vaste_werkdagen (lijst van {day_index, dagdeel_name}) en een privacy-object met share_phone, share_email, share_work_days en visible_to_team. Velden waarvoor geen toestemming geldt, komen leeg terug.
Foutafhandeling & Statuscodes
200 OK: succesvolle aanvraag. Zijn er geen zichtbare medewerkers, dan isitems(ofresults) leeg.401 Unauthorized: de gebruiker is niet geauthenticeerd.
Autorisatie & Beveiliging
- Toegang: de view gebruikt uitsluitend
IsAuthenticated. Team is een basismodule zonderrequired_permission; er is geen RBAC-gate. - Tenant-isolatie:
member_users_qs(tenant)beperkt de lijst tot actieve medewerkers van de eigen apotheek. - Privacy-enforcement: filtering gebeurt server-side in
_member_payload. Velden zonder toestemming worden leeggelaten en het telefoonnummer wordt alleen ontsleuteld bijshare_phone=True. Avatars worden via een signed S3-URL geleverd.
Bestandsstructuur & Verantwoordelijkheden
backend/features/team/views.py:TeamMemberListView, die de platte en gepagineerde respons afhandelt.backend/features/team/services.py:list_visible_team_members,list_visible_team_members_page,_member_payload,_base_team_queryset,_apply_searchen_role_label_for_user.backend/features/team/serializers.py:TeamMemberSerializer,TeamMemberPrivacySerializer,VasteWerkdagTeamSerializerenTeamMemberListResponseSerializer.backend/features/team/urls.py: hetmembers/endpoint.
Belangrijke bestanden
backend/features/team/services.pybackend/features/team/views.pybackend/features/team/serializers.py