Skip to main content

7. Communicatie en notificaties

Deze pagina is de ERD-inzoomlaag voor het databasehoofdstuk 04_communicatie-en-notificaties.md. De tabeldefinities in dat brondocument blijven leidend; deze pagina helpt vooral om de scheiding tussen systeemberichten, privéberichtthreads, mailboxweergave en sitebrede notificatieconcepten goed te lezen.

7.1 Afbakening van deze inzoomlaag

Het communicatiedomein bevat bewust twee verschillende vormen van communicatie:

  1. Mailbox-systeemberichten: individuele berichten aan een gebruiker via SystemMessages, eventueel met een functionele verwijzing naar een relatie-uitnodiging, ticket, privéthread of gedeelde oefening.
  2. Privéberichtthreads: conversaties met deelnemers, berichten, leespositie per deelnemer en thread-events.

Sitebrede systeemnotificaties, popupdefinities en systeemberichttemplates zijn functioneel communicatie-gerelateerd, maar staan database-technisch in 05_configuratie-en-contentbeheer.md. Zij worden daarom op deze pagina als context getoond en niet als harde interne FK-relaties van het communicatiedomein.

7.2 Leesroute

VraagBegin bijReden
Waar komt een ongelezen badge vandaan?Mailbox-readmodelBadges worden afgeleid uit SystemMessages.ReadAtUtc, participant-readstate, berichten en thread-events.
Hoe opent een systeembericht een onderliggend object?Systeemberichten en domeinverwijzingenEntityType + EntityId vormt een bewuste logische verwijzing zonder harde FK.
Hoe werkt een privégesprek?Privéberichtthread kern-ERDThread, deelnemers, berichten en events vormen samen de conversatie.
Waar zitten templates, popups en sitebrede notificaties?Communicatiecontext buiten dit domeinDie tabellen horen bij configuratie/contentbeheer, maar sturen wel communicatiegedrag.
Wat gebeurt er tijdens een actieve leerling-oefening?Afleidingsvrije oefencontextOnderliggende data blijft bestaan, maar zichtbare signalering wordt tijdelijk uitgesteld.

7.3 Privéberichtthread kern-ERD

Dit diagram toont alleen de relationele kern van privéberichten. Het is bewust kleiner dan de mailboxweergave, omdat systeemberichten technisch geen onderdeel zijn van een privéthread.

Soft links binnen en buiten het communicatiedomein worden apart getoond, zodat zij niet als harde database-FK worden gelezen:

Interpretatie

  • PrivateMessageThreads is de container voor onderwerp en laatste berichtactiviteit.
  • PrivateMessageThreadParticipants bepaalt per gebruiker zichtbaarheid, deelname, soft-delete en leespositie.
  • PrivateMessages bevat de feitelijke privéberichten, inclusief de uitzonderingssituatie waarin een beheerder een bericht namens een gebruiker laat ontstaan via SendAsUserId.
  • PrivateMessageThreadEvents bevat threadinterne gebeurtenissen zoals onderwerpwijziging of deelnemerwijziging. Dit zijn geen mailbox-systeemberichten.
  • LastReadMessageId is een soft link naar het laatst gelezen normale privébericht; LastReadAtUtc blijft nodig omdat thread-events ook ongelezenstatus kunnen veroorzaken en omdat privéberichtretentie de readstate niet mag blokkeren.

7.4 Systeemberichten en domeinverwijzingen

SystemMessages is een aparte mailboxbron. RecipientUserId is een soft link naar identity.Users.Id en geen harde database-FK vanwege de modulegrens. De functionele doorklik naar een onderliggend object gebeurt via de combinatie EntityType + EntityId.

De logische verwijzing kan naar precies vier domeinobjecttypen wijzen:

Waarom geen harde FK?

Er is bewust geen database-FK op EntityId, omdat één kolom afhankelijk van EntityType naar verschillende tabellen kan verwijzen. Dit is geen vrij generiek polymorf platformmechanisme, maar een beperkte functionele domeinverwijzing binnen SystemMessages. Geldigheid wordt daarom bewaakt via enumvalidatie, applicatielogica, autorisatiecontrole en tests.

Consequenties voor het ERD

AspectBetekenis
Harde database-FKNiet van toepassing binnen SystemMessages.
Logische verwijzingRecipientUserId als soft link naar identity.Users.Id; EntityType + EntityId naar RelationshipInvitations, Tickets, PrivateMessageThreads of SharedExercises.
AutorisatieOpenen van het bericht is niet voldoende; de vervolgactie controleert opnieuw of het doelobject nog toegankelijk is.
RetentieSysteemberichten worden niet hetzelfde behandeld als privéberichten met drie maanden retentie.
NavigatieEr wordt geen losse ActionUrl opgeslagen; de frontend routeert op basis van het domeintype.

7.5 Mailbox-readmodel en ongelezenlogica

7.5.0 Threadpresentatie en timeline-readmodel

PrivateMessageThreads bevat de stabiele threadpresentatie voor mailbox en detail, zoals threadkleur en icon key. PrivateMessageThreadParticipants bevat de participantgebonden zichtbaarheid, readstate en threadspecifieke accentkleur. Het mailboxreadmodel leidt het label Privégesprek of Groepsgesprek af uit de zichtbare actieve participants.

Voor privéthreads toont het readmodel bij ongelezen activiteit de eerste nieuwe activiteit voor de ingelogde participant als preview. Zonder nieuwe activiteit toont het de laatste zichtbare activiteit. De detailweergave laadt een timelinevenster oud-naar-nieuw rond #new of #latest; oudere items worden met een beveiligde cursor opgehaald.

De mailbox in de GUI is geen aparte tabel. Het is een afgeleid readmodel over twee bronnen:

Belangrijk hierbij:

  • Systeemberichten en privéthreads mogen in dezelfde mailboxweergave staan, maar blijven database-technisch gescheiden.
  • Ongelezen systeemberichten worden bepaald via SystemMessages.ReadAtUtc.
  • Ongelezen privéthreads worden per deelnemer afgeleid uit PrivateMessageThreadParticipants.LastReadMessageId, LastReadAtUtc, nieuwe PrivateMessages en nieuwe PrivateMessageThreadEvents.
  • DeletedAtUtc op de participantregel verwijdert de thread alleen uit de mailbox van die deelnemer.
  • Filters, zoekresultaten, aantallen en badges worden niet in een aparte mailbox- of teller-tabel opgeslagen.

7.6 Privébericht lifecycle

Een nieuw privébericht en een antwoord op een bestaande thread hebben een andere database-impact.

7.7 Systeembericht lifecycle

Systeemberichten zijn informatief en kunnen doorklikken naar een onderliggend object, maar voeren de onderliggende domeinactie niet automatisch uit.

Voorbeelden:

EntityTypeTypische herkomstVervolgcontext
RelationshipInvitationRelatiebeheer / accountprovisioningUitnodiging accepteren of afwijzen na hercontrole.
TicketMeldingenTicketdetail, discussie of oplossing na autorisatiecontrole.
PrivateMessageThreadPrivéberichtenThread openen wanneer participantcontext geldig is.
SharedExerciseGedeelde oefeningenGedeelde-oefeningcontext openen; start niet automatisch een run.

7.8 Communicatiecontext buiten dit domein

De volgende communicatie-gerelateerde tabellen staan niet in databasehoofdstuk 4, maar zijn wel belangrijk voor het totaalbeeld.

OnderdeelStaat inRelatie met communicatie
SystemMessageTemplatesConfiguratie & contentbeheerBeheerbare sjablonen voor verplichte systeemcommunicatie; geen runtime mailboxitem.
SiteNotificationsConfiguratie & contentbeheerSitebrede overlay na frontpageload; geen mailbox-systeembericht en geen popupregister-popup.
PopupDetailsConfiguratie & contentbeheerBeheerbare popupteksten voor feedback en foutafhandeling; geen bericht of notificatiebron.
SiteFeatureTogglesConfiguratie & contentbeheerKan functies zoals privéberichten, live meekijken of meldingen beschikbaar/niet beschikbaar maken.

7.9 Afleidingsvrije oefencontext

Tijdens een actieve leerling-oefenrun wordt zichtbare communicatie-uiting tijdelijk onderdrukt, maar de onderliggende data blijft correct opgeslagen.

Dit is een UI- en timingregel, geen databasemutatie die berichten tijdelijk anders opslaat.

7.10 Tabellen in dit domein

TabelCategorieDoel / verantwoordelijkheid
SystemMessagesCommunicatieMailbox-items voor systeemberichten die gebruikers informeren en vanuit de GUI kunnen doorverwijzen naar een concreet domeinobject of vervolghandeling.
PrivateMessageThreadsCommunicatieBovenliggende conversatie-entiteit voor privéberichten. Bevat threadmetadata zoals onderwerp en laatste activiteit.
PrivateMessageThreadParticipantsCommunicatieDeelnemers per privébericht-thread, inclusief mailboxspecifieke zichtbaarheid en leespositie per gebruiker.
PrivateMessagesCommunicatieIndividuele privéberichten binnen een thread. Ondersteunt reguliere berichten en berichten die namens een andere gebruiker worden verstuurd.
PrivateMessageThreadEventsCommunicatieSysteemachtige gebeurtenissen binnen een privébericht-thread, zoals onderwerpwijzigingen of deelnemers die de thread verlaten.

7.11 Relatie-inventaris binnen dit domein

BrontabelVeldVerwijst naarNullableRelatietypeBetekenis in ERD
SystemMessagesRecipientUserIdUsers.IdNSoft linkOntvanger van het systeembericht; geen harde FK naar identity.
PrivateMessageThreadsCreatedByUserIdUsers.IdNSoft linkInitiator van de thread; geen harde FK naar identity.
PrivateMessageThreadParticipantsThreadIdPrivateMessageThreads.IdNHarde FKDeelnemer hoort bij thread.
PrivateMessageThreadParticipantsUserIdUsers.IdNSoft linkDeelnemende gebruiker; geen harde FK naar identity.
PrivateMessageThreadParticipantsLastReadMessageIdPrivateMessages.IdJSoft linkLaatst gelezen normaal privébericht; bewust geen harde FK vanwege berichtretentie.
PrivateMessagesThreadIdPrivateMessageThreads.IdNHarde FKBericht hoort bij thread.
PrivateMessagesSenderUserIdUsers.IdNSoft linkTechnische afzender; geen harde FK naar identity.
PrivateMessagesSendAsUserIdUsers.IdJSoft linkFunctionele afzenderweergave namens gebruiker; geen harde FK naar identity.
PrivateMessageThreadEventsThreadIdPrivateMessageThreads.IdNHarde FKEvent hoort bij thread.
PrivateMessageThreadEventsActorUserIdUsers.IdJSoft linkGebruiker die event veroorzaakte; geen harde FK naar identity.
PrivateMessageThreadEventsAffectedUserIdUsers.IdJSoft linkGebruiker waarop event betrekking heeft; geen harde FK naar identity.

7.12 Bewuste uitzonderingen en aandachtspunten

  • SystemMessages.EntityType + EntityId moet visueel als logische verwijzing worden getoond, niet als harde database-FK.
  • PrivateMessageThreadEvents zijn geen SystemMessages; zij horen binnen de threadtijdlijn.
  • Ticketdiscussie staat in TicketDiscussionMessages en niet in PrivateMessages, behalve de expliciete doorzet-naar-docentflow die een normale privéthread kan genereren.
  • Systeemnotificaties staan in SiteNotifications en zijn geen mailboxitems.
  • Privébericht-retentie en systeembericht-retentie verschillen functioneel.
  • Badge- en tellerwaarden blijven afgeleid en horen niet als aparte mailbox-tabel te ontstaan.

7.13 Status en raakvlakken

Het communicatiedomein is in eerste diepte uitgewerkt en vormt de brug tussen relatiebeheer, tickets, gedeelde oefeningen en configuratiegedreven notificaties. Vooral de koppelingen SystemMessages.EntityType = Ticket, TicketForwardedToTeacher.GeneratedPrivateMessageThreadId en TicketForwardedToTeacher.GeneratedPrivateMessageId moeten consistent blijven met Ticket- en meldingsbeheer.

Voor verdere review hoort SystemMessages.EntityType + EntityId steeds als logische verwijzing te worden beoordeeld en niet als harde FK. Nieuwe verwijstypen mogen pas worden toegevoegd wanneer zij ook in de communicatieroutering, popup-/templatebeheer en cross-domein documentatie zijn verwerkt.