6 juli 2021 · Joeri Bekker · community
Deel 2: Koppelen met Open Zaak
Tijdens de Demodam Hackathon (5 t/m 9 juli 2021) heb ik er voor gekozen om eens niet te programmeren maar een aantal artikelen te schrijven over de VNG API standaarden voor Zaakgericht werken (ZGW API's). Meer specifiek kijk ik naar Open Zaak omdat dit een open source component is dat de ZGW API's aanbiedt.
Documentatie
Vanuit een ontwikkelaarsperspectief is er niet heel veel "leesbare" documentatie beschikbaar. Er is wel veel documentatie beschikbaar (informatiemodellen, API-specificaties, thema's en definities) maar nergens is eigenlijk te lezen hoe je de ZGW API's nu precies gebruikt, tenzij je de Github Pages documentatie hebt gevonden. Om deze reden is het voor ontwikkelaars ook lastig om Open Zaak te koppelen aan hun eigen applicatie(s). Samen met VNG heb ik een tijd geleden wel een poging gedaan om hier verbetering in te brengen maar het blijft vooral een wereld van informatie-architectecten en modeleurs, en niet van ontwikkelaars die deze standaarden moeten implementeren in software.
Pijn delen
Voor het ontwikkelen van een Zakenmagazijn voor gemeente Haarlem, dat StUF-ZDS 1.2 implementeert (de "oude" standaard), hebben we bij Maykin de documentatie moeten doornemen van die StUF-ZDS standaard. Voor de niet ingewijden: StUF-ZDS staat voor Standaard Uitwisselings Formaat - Zaak- en Documentservices; een SOAP-standaard.
StUF-ZDS is overigens een subset van de standaard StUF-Zaken omdat niemand echt alles nodig had wat in StUF-Zaken zat. Desalniettemin, heb je dezelfde documentatie nodig.
Ten grondslag hieraan liggen een aantal informatiemodellen (lees: databaseschema's), zoals beschreven staan in het RGBZ 2.0, RSGB 2.0 en ImZTC 2.1 (bij elkaar zo'n 1011 pagina's!). Die verwijzen overigens naar nog eens zo veel (bijna onvindbare) documenten, en dan zijn er nog de documenten die de StUF-standaard zelf beschrijven, en de "verStUFfings-documenten" die beschrijven hoe de informatiemodellen relateren aan de StUF-standaard. Gekkenhuis.
TL;DR (Too long; didn't read)
Al die documentatie niet gelezen? Ik neem het niemand kwalijk!
Het meest leesbare stukje documentatie om te begrijpen hoe zaakgericht werken toegepast kan worden in applicaties, staat in de toelichting op het RGBZ.
Praktijk
Veel bedrijven die beginnen met het koppelen aan gemeentelijke software krijgen van de gemeente vaak te horen dat er StUF-ZDS wordt gebruikt. De leverancier van die gemeentelijke software waar mee gekoppeld moet worden zegt vaak: We hebben ook een eigen protocol (vaak REST/JSON) dat veel simpeler is! Je moet sterk in je schoenen staan om jezelf het leven moeilijk te maken en te zeggen "Doe mij die complexe koppeling maar".
Met de ZGW API's hopen we veel van de complexiteit en de berg documentatie, die niet echt voor ontwikkelaars is, terug te brengen naar een setje Open API specificaties, waardoor leveranciers ook kunnen zeggen: Koppel daar mee!
Koppelen!
Deel 1 kan ik kort samenvatten als "alles bij de gemeente is een zaak". Dat betekent dus dat voor zo'n beetje alles een proces is waarvoor een zaak wordt aangemaakt: Interne begroting opstellen, geboorteaangifte doen, bouwvergunning aanvragen, klachten afhandelen, toezicht houden, etc.
Enfin, Open Zaak draait, wat nu? Er zijn grofweg 3 high level use cases voor het koppelen met Open Zaak:
- Mijn applicatie is het startpunt van een proces (zaken starten)
- Mijn applicatie brengt het proces verder (zaken afhandelen)
- Mijn applicatie geeft vooral inzicht (zaken inzien)
Overigens kan een applicatie prima meerdere scenario's combineren, of slechts 1 van deze scenario's hanteren. En er zijn natuurlijk nog meer scenario's die we nu buiten beschouwing laten.
Signalen is een voorbeeld van een applicatie waarin alles gebeurt: Klanten kunnen meldingen doen (zaken starten). De meldingen worden bekeken, toegewezen aan de juiste instantie of persoon, en de melding wordt afgehandeld (zaken afhandelen). Ten slotte kan de buitendienst alle meldingen zien, voor als ze toch in de buurt zijn (zaken inzien).
Open Formulieren geeft klanten de mogelijkheid een afspraak te maken of een product aan te vragen (zaken starten). Een andere applicatie pikt deze zaken verder op (voor zaken afhandelen), afhankelijk van het zaaktype dat is meegegeven.
Het een is niet beter of slechter dan het ander, het hangt helemaal van de use case af.
Hieronder ga ik in op het eerste scenario's aan de hand van een Bouwvergunningsaanvraag behandelen.
Zaken starten
LET OP: Het wordt een beetje technisch hieronder maar dit stuk is dan ook vooral bedoeld voor applicatie ontwikkelaars.
1. Zaaktype opvragen via de Catalogi API
Het Zaaktype beschrijft op hoofdlijnen het proces, wie typische Betrokkenen zijn, wat voor Documenttypen we verwachten, mogelijke Resultaten, etc. Je maakt normaal gesproken niet zelf een Zaaktype aan via de Catalogi API. Het Zaaktype zal typisch reeds bestaan of moet eenmalig ingericht worden.
Je hebt het Zaaktype nodig om een Zaak aan te maken. Je kan dit Zaaktype configureren in je applicatie door de URL op te slaan maar beter is het om de catalogus en de identificatie van het Zaaktype op te slaan, en deze real-time op te vragen. Je voorkomt hiermee dat je werkt met oudere versies van een Zaaktype.
GET /catalogi/api/v1/zaaktypen?catalogus=<catalogi-url>&identificatie=bouwvergunning HTTP/1.1
De informatie uit het Zaaktype kan je gebruiken voor "sane defaults" en communicatie naar buiten.
2. Zaak aanmaken in de Zaken API
Je maakt een Zaak aan, waarbij je ook het Zaaktype meegeeft dat je hierboven hebt opgevraagd (LET OP: Er zijn 2 extra headers nodig om het geo-formaat te bepalen).
POST /zaken/api/v1/zaken HTTP/1.1
Accept-Crs: EPSG:4326
Content-Crs: EPSG:4326
{
"identificatie": "ZAAK-2021-0000000001",
"bronorganisatie": "286130270",
"zaaktype": "/catalogi/api/v1/zaaktypen/<uuid>",
"verantwoordelijkeOrganisatie": "286130270",
"startdatum": "2021-07-06"
}
3. Indiener aan de Zaak koppelen
Degene die de bouwvergunningsaanvraag indient, is de initiator van de Zaak. Die moeten we apart toevoegen. Het Zaaktype uit stap 1 definieert als het goed is ook de Roltypen in de Catalogi API. We zoeken de rol van de initiator op:
GET /catalogi/api/v1/roltypen?zaaktype=<zaaktype-url>&omschrijvingGeneriek=initiator HTTP/1.1
Deze kan geconfigureerd zijn in de applicatie op dezelfde wijze als het Zaaktype. Vervolgens kan de indiener, in zijn rol als initiator van de zaak, worden toegevoegd aan de Zaak:
POST /zaken/api/v1/rollen HTTP/1.1
{
"zaak": "<zaak-url>",
"betrokkene": "<ingeschreven-persoon-url>",
"betrokkeneType": "natuurlijk_persoon",
"roltype": "/catalogi/api/v1/roltypen/<uuid>",
"roltoelichting": "Indiener van de vergunning"
}
Het attribuut "betrokkene" vergt wat uitleg. Als de indiener is ingelogd met DigiD, dan is het BSN van deze persoon bekend. Op basis van zijn BSN is de verwijzing naar deze persoon te maken in de BRP API. Deze verwijziging nemen we op bij de Rol. In de praktijk is dit vaak nog niet goed geregeld. Daarom kan een deel van de persoonsinformatie ook direct worden toegevoegd in plaats van een verwijzing te maken naar de persoon in de BRP API. Dat gaat dan ongeveer zo:
POST /zaken/api/v1/rollen HTTP/1.1
{
"zaak": "<zaak-url>",
"betrokkeneType": "natuurlijk_persoon",
"roltype": "/catalogi/api/v1/roltypen/<uuid>",
"roltoelichting": "Indiener van de vergunning",
"betrokkeneIdentificatie": {
"inpBsn": "<bsn-van-indiener?"
}
}
4. Bouwplan toevoegen
Voordat een bouwvergunning kan worden afgegeven kan de applicatie bepaalde documenten vereisen. Een bouwplan bijvoorbeeld. Dit bouwplan is niet zomaar een willekeurig PDF-bestand dat we in een mapje uploaden. Dat zou namelijk nogal chaotisch worden op termijn en als er veel documenten bij een Zaak komen, verdwijnt het overzicht.
LET OP: De naamgeving is VNG-iaans. De Documenten API bevat "Enkelvoudige Informatieobjecten" (lees: Documenten) die het sjabloon van een "Informatieobjecttype" (lees: Documenttype) volgen in de Catalogi API. Ik hanteer voor de leesbaarheid de naam tussen haakjes maar in API calls volg ik de API specificatie.
Het Zaaktype uit stap 1 definieert als het goed is ook Documenttype in de Catalogi API:
GET /catalogi/api/v1/zaaktype-informatieobjecttypen?zaaktype=<zaaktype-url> HTTP/1.1
Deze kan geconfigureerd zijn in de applicatie op dezelfde wijze als het Zaaktype. Of, meer dynamisch worden verkregen (denk aan: Upload hier relevante bestanden: <lijstje met mogelijke documenttypen>).
Het Document uploaden, waarbij je ook het Documenttype meegeeft.:
POST /documenten/api/v1/enkelvoudiginformatieobjecten HTTP/1.1
{
"bronorganisatie": "286130270",
"creatiedatum": "2020-01-01",
"informatieobjecttype": "/api/v1/informatieobjecttypen/<uuid>",
"titel": "Dakkapel plan",
"auteur": "Jan Janssen",
"taal": "ned",
"inhoud": "...base64-encoded..."
}
Het Document moet nu nog gekoppeld worden aan de Zaak. Dat moet middels deze call waar je de Zaak en het Document meegeeft:
POST /zaken/api/v1/zaakinformatieobjecten HTTP/1.1
{
"zaak": "<zaak-url>",
"informatieobject": "<document-url>"
}
5. Andere informatie toevoegen
De applicatie heeft waarschijnlijk nog veel meer gegevens die van belang zijn voor de Zaak. Het is niet persé nodig om alle informatie op te slaan bij de Zaak. Het criterium is grofweg dat alle informatie die na het sluiten van de Zaak nog beschikbaar moet zijn, bij de Zaak moet zijn opgeslagen.
Er zijn een 38-tal verschillende soorten gegevens die we bij de Zaak kunnen vastleggen: Wijk, Woonplaats, Wegdeel, Buurt, etc. In de praktijk zijn dit er duizenden. Veel daarvan worden nu als document toegevoegd aan de Zaak. Denk aan: Melding, Productaanvraag, Vergunning, Parkeerzone, etc.
Interesse in ander soortige objecten maken of koppelen? Dan raad ik aan om eens te kijken naar de ontwikkelingen rondom de Objecten API.
Een voorbeeld om zo'n willekeurig object uit de Objecten API te koppelen:
POST /zaken/api/v1/zaakobjecten HTTP/1.1
{
"zaak": "<zaak-url>",
"objectType": "overige",
"objectTypeOverige": "Parkeerzone",
"object": "https://objecten.demodam.nl/api/v1/<uuid>"
}
6. Zaak status zetten
Als de Zaak volledig gereed is om het proces in te gaan, dan kan de eerste (start) status te zetten.
Het Zaaktype uit stap 1 definieert als het goed is ook de Statustypen in de Catalogi API:
GET /catalogi/api/v1/statustypen?zaaktype=<zaaktype-url> HTTP/1.1
De Statustypen hebben allemaal een volgnummer. We moeten hier de status pakken met volgnummer 1. Statussen worden in volgorde van het volgnummer doorlopen. Vertakkingen zijn dus niet mogelijk, dat moet worden gedaan binnen het proces zelf.
Vervolgens zetten we de status waarmee we tevens aangeven dat we klaar zijn met de Zaak aanpassen.
POST /zaken/api/v1/statussen HTTP/1.1
{
"zaak": "<zaak-url>",
"statustype": "<statustype-url>",
"datumStatusGezet": "2021-06-07T15:00:00Z"
}
Tot slot
De Zaak is nu gestart en de eerste stap om het zaakdossier vorm te geven is gezet. Een Zaak aanmaken vergt zo'n 10 API-calls maar dan is het grondwerk ook echt gelegd. Deze calls duren bij elkaar vaak nog geen seconde.
Nabrander
Het blijft een uitdaging hoe omgegaan moet worden met applicaties die het liefst alle gegevens in eigen beheer hebben, en het vastleggen van gegevens in een Zaak. Er zijn diverse methoden om dit aan te pakken maar voor het aanmaken van zaken is het vrij duidelijk: Als het startproces is afgerond dan wordt de zaak aangemaakt. Het startproces kan een aantal stappen zijn in een formulier, een verzoek dat binnenkomt en op volledigheid is beoordeeld, of een brief die binnenkomt en is ingescant.
Disclaimer
Een deel van de informatie is terug te vinden in diverse documenten op VNG, GEMMA Online en Github. Over veel van deze informatie leg ik mijn kijk op zaken (pun intended) die niet een officieel VNG standpunt zijn.
Over de auteur
Joeri Bekker is een software ontwikkelaar in hart en nieren maar de laatste jaren vooral bezig met Common Ground projecten bij Maykin, in de rol van projectmanager. Al weer een paar jaar geleden heeft Joeri meegeholpen om RESTful API's bij VNG Realisatie te introduceren wat samenviel met de opkomst van Common Ground. In dat verlengde is Joeri aangehaakt bij het team dat de ZGW API's heeft ontwikkeld waarvoor hij ook heeft meegeholpen om de referentie implementatie ("werkende software") te realiseren op basis van de API specificaties.