De omnivere (tenant) database
Op dit moment werken we met SQL Server als database.
Schemas
De architectuur van Omnivere is losjes gebaseerd op het principe van DDD (domain driven design). Hierin zijn een een aantal domeinen gedefineerd die weerspiegeld worden in de database schema's.
- crm: beheer van resources, mensen & materieel
- pubtrans: alles rond beheer en configuratie van publiek transport
- roster: alles voor werken met roosters
- planning: alles voor planning en operationele opvolging
- payroll: alles rond loonadministratie
- shared: algemene zaken zoals files, settings
- secure: bevat alles rond security
shared schema
| DB Object | Info |
|---|---|
| shared.Enums | Eerder technische tabel die de labels bevat voor bepaalde enumaraties, zoals type detail lijnen van een dienst, soorten planningscodes, types van periodes, ... |
| shared.Files | Centrale lijst van alle input/output bestanden |
| shared.Migrations | Hierin wordt bijgehouden welke migraties wanneer uitgevoerd zijn. Zie ook database |
| shared.Settings | Globale instellingen/variabele voor deze tenant. |
crm schema
| DB Object | Info |
|---|---|
| crm.Busses | Configuratie van de bussen |
| crm.Persons | Alle persoonsgegevens |
| crm.Companies | De ondernemingen |
| crm.Certificates | Diploma's/getuigschriften van personen. |
| crm.Drivers | De chauffeurs. Een persoon die een contract heeft met een onderneming |
pubtrans schema
| DB Object | Info |
|---|---|
| pubtrans.Regios | De vervoersregios |
| pubtrans.DayTypes | De mogelijke type dagen. |
| pubtrans.RegioCalendar | Configuratie van type dag per kalenderdag, in een bepaalde vervoersregio |
| pubtrans.Services | Overzicht van alle diensten in een bepaalde vervoersregio |
| pubtrans.ServiceLines | De theoretische detail lijnen per dienst |
| pubtrans.Stops | Alle stopplaatsen van de bus in een vervoersregio. Zowel bediende haltes als stelplaatsen (Depot=1) |
| pubtrans.Lines | De verschillende lijnen in de vervoersregio |
| pubtrans.Operator | De exploitanten, gekoppeld aan een onderneming (crm.Companies) |
| pubtrans.Operations | De explotatieperiodes. Link tussen de exploitanten en de vervoersregios; de exploitant neemt in een bepaalde periode (een deel van) de dienstregeling op voor een bepaalde vervoersregio |
| pubtrans.OperationTeams | De link tussen team (planning.team) en exploitatieperiode (pubtrans.operation) |
| pubtrans.OperationRoles | Welk teamlid neemt welke rol uit het rooster op |
| pubtrans.OperationsPlanning | Configuratie van de verwachte diensten, per type dag, voor een bepaalde exploitatie |
| pubtrans.ServicePlanning | De operationele planning van welke dienst op welke dag gepland is. Deze info is aanvullend op de informatie in de algemene planning (planning.Planning) |
| pubtrans.ServicePlanningLines | De effectieve detaillijnen van de geplande diensten. |
planning schema
| DB Object | Info |
|---|---|
| planning.Codes | De bouwstenen van de planning. Kan een dienst zijn, maar ook een code die een afwezigheid voorstelt. De codes vormend ook de basis van de loonsberekening. |
| planning.Teams | De definitie van een team. Op niveau van een team wordt de planning gemaakt. |
| planning.Teammembers | De mensen die deel uitmaken van een team. Kan een tijdelijk invulling zijn dmv een start en einddatum. |
| planning.TeamCodes | Welke codes kunnen gebruikt worden in welk team? |
| planning.Planning | De effectieve planning van alle teamleden, per kalenderdag, met behulp van codes. |
| planning.Mutations | De wijzigingen aan de planning. Elke wijziging wordt op deze manier geregistreerd, en heeft vaak een motivering nodig. Er zijn verschillende soort mutaties, zie ook opvolging |
| planning.PlanningMutations | Op welke planning heeft de mutatie een impact? |
roster schema
| DB Object | Info |
|---|---|
| roster.Roster | De roosters, met een verwijzing naar de exploitatieperiode waarvoor deze geldt. |
| roster.Schedules | DEPRECATED! |
| roster.Weeks | De configuratie van de verschillende weken in een rooster. Er is een afzonderlijke configuratie per type periode (schoolweken/vakantieweken/examenweken). In één week wordt er een code van maandag tem zondag gedefinieerd. |
| roster.Planning | DEPRECATED! Deze tabel bevatte het resultaat van de berekende rooster. Maar dit is gewoon een opslag van het resultaat van de functie roster.CalculatePlanning. Deze is heel snel, dus in principe is het niet nodig om dit op te slaan. |
security schema
| DB Object | Info |
|---|---|
| secure.Users | Gebruikers van Omnivere, met verwijzing naar persoon. Een gebruiker heeft ook een bepaalde rol. |
| secure.Environments | Concept dat de "functionele omgeving" definieerd waarin een gebruiker inlogt. Dit moet nog verder uitgewerkt worden, maar het idee is dat je op deze manier de GUI beter kan afstemmen op de rol van de gebruiker. Zo kan er een omgeving gemaakt worden voor de planning van een team. Of er kan een administratieve omgeving gemaakt worden voor het beheer van bussen, personen, ondernemingen, ... |
User context
In Omnivere werken we momenteel met user context propagation, wat wil zeggen dat de identiteit van de gebruiker wordt meegenomen door alle lagen van de applicatie, ook in de database dus.
Dit principe zorgt voor:
- Volledige traceerbaarheid: Het kunnen volgen van een actie (en de bijbehorende wijzigingen) terug naar de initiërende gebruiker, wat essentieel is voor debugging, auditing en het begrijpen van systeemgedrag.
- Auditing: Het bijhouden van wie wat heeft gedaan en wanneer, vaak een vereiste voor naleving van regelgeving.
- Logging: Het verrijken van logberichten met gebruikersinformatie, wat het analyseren van logbestanden en het opsporen van problemen aanzienlijk vergemakkelijkt.
- Security: Het handhaven van beveiligingscontext (bijvoorbeeld gebruikersrollen en permissies) door de verschillende lagen heen.
Om dit te verwezenlijken wordt de identiteit van de ingelogde gebruiker doorgegeven via de CONTEXT_INFO van de database. Voor elk database call die gebeurd zal de middle tier er dus voor zorgen dat dit doorgegeven word. Zie PersistContextInfo in de code.
Er is ook security op database niveau die ervoor zorgt dat er geen enkele wijziging kan gebeuren als deze identiteit niet gekend is. Hiervoor worden triggers gebruikt, zie het bestand secure.sql om te zien hoe deze triggers aangemaakt worden.
Een gevolg hiervan is dat ook rechtstreekse database manipulaties niet toegelaten zijn, tenzij eerst de identiteit wordt bepaald. Dit kan in een script via de procedure secure.SetCurrentUser gebeuren, waarbij je de ID van de gebruiker meegeeft. Omgekeerd kan je de function secure.GetCurrentUser gebruiken om de huidige gebruiker op te vragen.
De backend service bevat code waardoor automatisch een aantal "systeem" gebrukers aangemaakt worden. Deze gebruikers hebben een negatieve ID. Zie CreateDefaultUsers in module DMConnection.