diff --git a/src/openapi.yaml b/src/openapi.yaml index 733e98b40a..0df897a580 100644 --- a/src/openapi.yaml +++ b/src/openapi.yaml @@ -3715,6 +3715,44 @@ paths: $ref: '#/components/headers/X-Is-Form-Designer' Content-Language: $ref: '#/components/headers/Content-Language' + /api/v2/referentielijst-tabellen/{service_slug}: + get: + operationId: referentielijst_tabellen_list + description: |- + Return a list of available (JSON) tabellen in a given Referentielijsten service configured in the backend. + + Note that this endpoint is **EXPERIMENTAL**. + summary: List tabellen for a Referentielijsten service + parameters: + - in: path + name: service_slug + schema: + type: string + pattern: ^[-a-zA-Z0-9_]+$ + required: true + tags: + - referentielijst-tabellen + security: + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ReferentielijstTabellen' + description: '' + headers: + X-Session-Expires-In: + $ref: '#/components/headers/X-Session-Expires-In' + X-CSRFToken: + $ref: '#/components/headers/X-CSRFToken' + X-Is-Form-Designer: + $ref: '#/components/headers/X-Is-Form-Designer' + Content-Language: + $ref: '#/components/headers/Content-Language' + x-experimental: true /api/v2/registration/attributes: get: operationId: registration_attributes_list @@ -9657,6 +9695,30 @@ components: required: - name - slug + ReferentielijstTabellen: + type: object + properties: + code: + type: string + description: The unique code that identifies the table. + naam: + type: string + description: The name of the table. + einddatumGeldigheid: + type: string + format: date-time + writeOnly: true + description: The timestamp on which the tabel expires. + isGeldig: + type: boolean + readOnly: true + description: Indicates whether or not the table is expired. + required: + - code + - einddatumGeldigheid + - isGeldig + - naam + x-experimental: true RegistrationAttribute: type: object properties: diff --git a/src/openforms/api/urls.py b/src/openforms/api/urls.py index 286d637ea8..9ba9b8337e 100644 --- a/src/openforms/api/urls.py +++ b/src/openforms/api/urls.py @@ -10,6 +10,9 @@ from rest_framework_nested.routers import NestedSimpleRouter from openforms.config.api.viewsets import ThemeViewSet +from openforms.contrib.referentielijsten.api.viewsets import ( + ReferentielijstenTabellenViewSet, +) from openforms.forms.api.public_api.viewsets import CategoryViewSet from openforms.forms.api.viewsets import ( FormDefinitionViewSet, @@ -60,6 +63,13 @@ # services router.register("services", ServiceViewSet) +# referentielijsten +router.register( + "referentielijst-tabellen", + ReferentielijstenTabellenViewSet, + basename="referentielijst-tabellen", +) + # service fetch configurations router.register("service-fetch-configurations", ServiceFetchConfigurationViewSet) diff --git a/src/openforms/contrib/referentielijsten/api/__init__.py b/src/openforms/contrib/referentielijsten/api/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/openforms/contrib/referentielijsten/api/serializers.py b/src/openforms/contrib/referentielijsten/api/serializers.py new file mode 100644 index 0000000000..208518d9a1 --- /dev/null +++ b/src/openforms/contrib/referentielijsten/api/serializers.py @@ -0,0 +1,29 @@ +from datetime import datetime + +from django.utils.translation import gettext_lazy as _ + +from rest_framework import serializers + +from openforms.api.utils import mark_experimental + + +@mark_experimental +class ReferentielijstTabellenSerializer(serializers.Serializer): + code = serializers.CharField( + help_text=_("The unique code that identifies the table.") + ) + naam = serializers.CharField(help_text=_("The name of the table.")) + einddatumGeldigheid = serializers.DateTimeField( + help_text=_("The timestamp on which the tabel expires."), write_only=True + ) + + is_geldig = serializers.SerializerMethodField( + help_text=_("Indicates whether or not the table is expired.") + ) + + def get_is_geldig(self, attrs: dict) -> bool: + if einddatum := attrs.get("einddatumGeldigheid"): + parsed_datetime = datetime.fromisoformat(einddatum) + if parsed_datetime < datetime.now(tz=parsed_datetime.tzinfo): + return False + return True diff --git a/src/openforms/contrib/referentielijsten/api/viewsets.py b/src/openforms/contrib/referentielijsten/api/viewsets.py new file mode 100644 index 0000000000..b4f2994910 --- /dev/null +++ b/src/openforms/contrib/referentielijsten/api/viewsets.py @@ -0,0 +1,55 @@ +from django.shortcuts import get_object_or_404 +from django.utils.translation import gettext_lazy as _ + +from drf_spectacular.utils import extend_schema, extend_schema_view +from requests.exceptions import RequestException +from rest_framework import authentication, permissions, serializers, status, viewsets +from rest_framework.decorators import action +from rest_framework.response import Response +from zgw_consumers.client import build_client +from zgw_consumers.models import Service + +from openforms.api.utils import mark_experimental + +from ..client import ReferentielijstenClient +from .serializers import ReferentielijstTabellenSerializer + + +@extend_schema_view( + get=extend_schema( + summary=_("List tabellen for a Referentielijsten service"), + description=_( + "Return a list of available (JSON) tabellen in a given Referentielijsten service configured " + "in the backend.\n\n" + "Note that this endpoint is **EXPERIMENTAL**." + ), + responses={ + 200: ReferentielijstTabellenSerializer(many=True), + }, + ) +) +@mark_experimental +class ReferentielijstenTabellenViewSet(viewsets.ViewSet): + """ + List tabellen for a given Referentielijst service + """ + + authentication_classes = (authentication.SessionAuthentication,) + permission_classes = (permissions.IsAdminUser,) + serializer_class = ReferentielijstTabellenSerializer + + @action(detail=False, methods=["get"], url_path="(?P[-a-zA-Z0-9_]+)") + def get(self, request, service_slug: str | None = None): + service = get_object_or_404(Service, slug=service_slug) + try: + with build_client( + service, client_factory=ReferentielijstenClient + ) as client: + result = client.get_tabellen() + except RequestException: + result = [] + + assert issubclass(self.serializer_class, serializers.Serializer) + serializer = self.serializer_class(data=result, many=True) + serializer.is_valid() + return Response(serializer.data, status=status.HTTP_200_OK) diff --git a/src/openforms/contrib/referentielijsten/client.py b/src/openforms/contrib/referentielijsten/client.py index edf492bc87..12b8bc6d51 100644 --- a/src/openforms/contrib/referentielijsten/client.py +++ b/src/openforms/contrib/referentielijsten/client.py @@ -17,7 +17,28 @@ class TabelItem(TypedDict): aanvullendeGegevens: Any +class Beheerder(TypedDict): + naam: str + email: str + afdeling: str + organisatie: str + + +class Tabel(TypedDict): + code: str + naam: str + beheerder: Beheerder + einddatumGeldigheid: str | None # ISO 8601 datetime string + + class ReferentielijstenClient(APIClient): + def get_tabellen(self) -> list[Tabel]: + response = self.get("tabellen", timeout=10) + response.raise_for_status() + data = response.json() + all_data = list(pagination_helper(self, data)) + return all_data + def get_items_for_tabel(self, code: str) -> list[TabelItem]: response = self.get("items", params={"tabel__code": code}, timeout=10) response.raise_for_status() diff --git a/src/openforms/js/components/formio_builder/WebformBuilder.js b/src/openforms/js/components/formio_builder/WebformBuilder.js index 0c290c1dbf..3cd1b1b55e 100644 --- a/src/openforms/js/components/formio_builder/WebformBuilder.js +++ b/src/openforms/js/components/formio_builder/WebformBuilder.js @@ -24,7 +24,7 @@ import { getRegistrationAttributes, getValidatorPlugins, } from './plugins'; -import {getServices} from './referentielijsten'; +import {getReferentielijstenTabellen, getServices} from './referentielijsten'; let _supportedLanguages = undefined; const getSupportedLanguages = () => { @@ -169,6 +169,7 @@ class WebformBuilder extends WebformBuilderFormio { getValidatorPlugins={getValidatorPlugins} getRegistrationAttributes={getRegistrationAttributes} getServices={getServices} + getReferentielijstenTabellen={getReferentielijstenTabellen} getPrefillPlugins={getPrefillPlugins} getPrefillAttributes={getPrefillAttributes} getFileTypes={async () => FILE_TYPES} diff --git a/src/openforms/js/components/formio_builder/referentielijsten.js b/src/openforms/js/components/formio_builder/referentielijsten.js index fecb76c251..b9a4bab578 100644 --- a/src/openforms/js/components/formio_builder/referentielijsten.js +++ b/src/openforms/js/components/formio_builder/referentielijsten.js @@ -4,3 +4,8 @@ export const getServices = async type => { const resp = await get(`/api/v2/services?type=${encodeURIComponent(type)}`); return resp.data; }; + +export const getReferentielijstenTabellen = async service => { + const resp = await get(`/api/v2/referentielijst-tabellen/${service}`); + return resp.data; +};