Skip to content

Commit d438b61

Browse files
committed
[#4267] Add catalogus endpoint, allow to filter against catalogus in the IOT endoint
1 parent 0083434 commit d438b61

11 files changed

+404
-37
lines changed

docker/open-zaak/fixtures/open_zaak_fixtures.json

+25-4
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"model": "catalogi.catalogus",
2222
"pk": 1,
2323
"fields": {
24-
"_etag": "f324f0578ac42cf6f2a7f68df8819d29",
24+
"_etag": "3b954569daa5871216ebb13dbf11eb9e",
2525
"naam": "Test catalog",
2626
"uuid": "bd58635c-793e-446d-a7e0-460d7b04829d",
2727
"domein": "TEST",
@@ -64,9 +64,9 @@
6464
"model": "catalogi.informatieobjecttype",
6565
"pk": 1,
6666
"fields": {
67-
"_etag": "89c597c58e42b804148e6867c3480ed1",
67+
"_etag": "bfa6b74c27efa9845576bf1d54281820",
6868
"datum_begin_geldigheid": "2024-03-19",
69-
"datum_einde_geldigheid": null,
69+
"datum_einde_geldigheid": "2024-07-10",
7070
"concept": false,
7171
"uuid": "7a474713-0833-402a-8441-e467c08ac55b",
7272
"omschrijving": "PDF Informatieobjecttype",
@@ -108,7 +108,7 @@
108108
"fields": {
109109
"_etag": "cf350f1b55d7eb0ccd17cceb88c1c6c8",
110110
"datum_begin_geldigheid": "2024-03-19",
111-
"datum_einde_geldigheid": null,
111+
"datum_einde_geldigheid": "2024-07-10",
112112
"concept": false,
113113
"uuid": "531f6c1a-97f7-478c-85f0-67d2f23661c7",
114114
"omschrijving": "Attachment Informatieobjecttype",
@@ -123,6 +123,27 @@
123123
"catalogus": 1
124124
}
125125
},
126+
{
127+
"model": "catalogi.informatieobjecttype",
128+
"pk": 4,
129+
"fields": {
130+
"_etag": "35fb6a08e82a1195076f698c3ac1725c",
131+
"datum_begin_geldigheid": "2024-07-11",
132+
"datum_einde_geldigheid": null,
133+
"concept": false,
134+
"uuid": "29b63e5c-3835-4f68-8fad-f2aea9ae6b71",
135+
"omschrijving": "PDF Informatieobjecttype",
136+
"informatieobjectcategorie": "Test category",
137+
"trefwoord": "[]",
138+
"vertrouwelijkheidaanduiding": "openbaar",
139+
"omschrijving_generiek_informatieobjecttype": "",
140+
"omschrijving_generiek_definitie": "",
141+
"omschrijving_generiek_herkomst": "",
142+
"omschrijving_generiek_hierarchie": "",
143+
"omschrijving_generiek_opmerking": "",
144+
"catalogus": 1
145+
}
146+
},
126147
{
127148
"model": "catalogi.zaaktypeinformatieobjecttype",
128149
"pk": 1,

src/openforms/contrib/zgw/clients/catalogi.py

+11-2
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,17 @@ def get_all_catalogi(self) -> list[dict]:
3131
all_data = pagination_helper(self, data)
3232
return list(all_data)
3333

34-
def get_all_informatieobjecttypen(self) -> list[dict]:
35-
response = self.get("informatieobjecttypen")
34+
def get_all_informatieobjecttypen(
35+
self, *, catalogus: str | None = None
36+
) -> list[dict]:
37+
"""List all informatieobjecttypen.
38+
39+
:arg catalogus: the catalogus URL the informatieobjecttypen should belong to.
40+
"""
41+
params = {}
42+
if catalogus is not None:
43+
params["catalogus"] = catalogus
44+
response = self.get("informatieobjecttypen", params=params)
3645
response.raise_for_status()
3746
data = response.json()
3847
all_data = pagination_helper(self, data)

src/openforms/registrations/api/filters.py

+32-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from ..registry import register
1515

1616

17-
class ListInformatieObjectTypenQueryParamsSerializer(serializers.Serializer):
17+
class APIGroupQueryParamsSerializer(serializers.Serializer):
1818
zgw_api_group = PrimaryKeyRelatedAsChoicesField(
1919
queryset=ZGWApiGroupConfig.objects.all(),
2020
help_text=_(
@@ -77,3 +77,34 @@ def get_ztc_client(self) -> CatalogiClient | None:
7777
]
7878
if service := objects_api_group.catalogi_service:
7979
return build_client(service, client_factory=CatalogiClient)
80+
81+
82+
class ListInformatieObjectTypenQueryParamsSerializer(APIGroupQueryParamsSerializer):
83+
catalogus_domein = serializers.CharField(
84+
label=_("catalogus domein"),
85+
help_text=_(
86+
"Filter informatieobjecttypen against this catalogus domein."
87+
"If provided, the RSIN should also be present."
88+
),
89+
required=False,
90+
)
91+
92+
catalogus_rsin = serializers.CharField(
93+
label=_("catalogus RSIN"),
94+
help_text=_(
95+
"Filter informatieobjecttypen against this catalogus RSIN."
96+
"If provided, the RSIN should also be present."
97+
),
98+
required=False,
99+
)
100+
101+
def validate(self, attrs: dict[str, Any]) -> dict[str, Any]:
102+
attrs = super().validate(attrs)
103+
if ("catalogus_domein" in attrs) ^ ("catalogus_rsin" in attrs):
104+
raise serializers.ValidationError(
105+
_(
106+
"'catalogus_domein' and 'catalogus_rsin' should be provided together."
107+
)
108+
)
109+
110+
return attrs

src/openforms/registrations/api/serializers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class Meta:
5050
class CatalogusDomainSerializer(APIModelSerializer):
5151
class Meta:
5252
model = Catalogus
53-
fields = ("domein",)
53+
fields = ("domein", "rsin")
5454

5555

5656
class InformatieObjectTypeChoiceSerializer(serializers.Serializer):

src/openforms/registrations/api/urls.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
from django.urls import include, path
22

3-
from .views import AllAttributesListView, InformatieObjectTypenListView, PluginListView
3+
from .views import (
4+
AllAttributesListView,
5+
CatalogusListView,
6+
InformatieObjectTypenListView,
7+
PluginListView,
8+
)
49

510
urlpatterns = [
611
path("plugins", PluginListView.as_view(), name="registrations-plugin-list"),
@@ -9,6 +14,11 @@
914
AllAttributesListView.as_view(),
1015
name="registrations-attribute-list",
1116
),
17+
path(
18+
"catalogus",
19+
CatalogusListView.as_view(),
20+
name="catalogus-list",
21+
),
1222
path(
1323
"informatieobjecttypen",
1424
InformatieObjectTypenListView.as_view(),

src/openforms/registrations/api/views.py

+81-9
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@
1010

1111
from ..constants import RegistrationAttribute
1212
from ..registry import register
13-
from .filters import ListInformatieObjectTypenQueryParamsSerializer
13+
from .filters import (
14+
APIGroupQueryParamsSerializer,
15+
ListInformatieObjectTypenQueryParamsSerializer,
16+
)
1417
from .serializers import (
18+
CatalogusDomainSerializer,
1519
ChoiceWrapper,
1620
InformatieObjectTypeChoiceSerializer,
1721
RegistrationAttributeSerializer,
@@ -56,6 +60,35 @@ def get_objects(self):
5660
return [ChoiceWrapper(choice) for choice in choices]
5761

5862

63+
@extend_schema_view(
64+
get=extend_schema(
65+
summary=_("List available Catalogus"),
66+
parameters=[APIGroupQueryParamsSerializer],
67+
),
68+
)
69+
class CatalogusListView(ListMixin, APIView):
70+
"""
71+
List the available Catalogus based on the provided API group.
72+
"""
73+
74+
authentication_classes = (authentication.SessionAuthentication,)
75+
permission_classes = (permissions.IsAdminUser,)
76+
serializer_class = CatalogusDomainSerializer
77+
78+
def get_objects(self):
79+
filter_serializer = APIGroupQueryParamsSerializer(
80+
data=self.request.query_params
81+
)
82+
filter_serializer.is_valid(raise_exception=True)
83+
84+
client = filter_serializer.get_ztc_client()
85+
if not client:
86+
return []
87+
88+
catalogus_data = client.get_all_catalogi()
89+
return factory(Catalogus, catalogus_data)
90+
91+
5992
@extend_schema_view(
6093
get=extend_schema(
6194
summary=_("List available InformatieObjectTypen"),
@@ -65,6 +98,10 @@ def get_objects(self):
6598
class InformatieObjectTypenListView(ListMixin, APIView):
6699
"""
67100
List the available InformatieObjectTypen based on the configured registration backend and ZGW APIs services.
101+
102+
Each InformatieObjectType is uniquely identified by its 'omschrijving', 'catalogus',
103+
and beginning and end date. If multiple same InformatieObjectTypen exist for different dates,
104+
only one entry is returned.
68105
"""
69106

70107
authentication_classes = (authentication.SessionAuthentication,)
@@ -86,13 +123,48 @@ def get_objects(self):
86123
catalogus["url"]: catalogus for catalogus in catalogus_data
87124
}
88125

89-
iotypen_data = client.get_all_informatieobjecttypen()
90-
iotypen = [
91-
{
92-
"informatieobjecttype": factory(InformatieObjectType, iotype),
93-
"catalogus": factory(Catalogus, catalogus_mapping[iotype["catalogus"]]),
94-
}
95-
for iotype in iotypen_data
96-
]
126+
if "catalogus_domein" in filter_serializer.validated_data:
127+
domein = filter_serializer.validated_data["catalogus_domein"]
128+
# `catalogus_rsin` is guaranteed to be present if `catalogus_domein` is:
129+
rsin = filter_serializer.validated_data["catalogus_rsin"]
130+
131+
matching_catalogus: str | None = next(
132+
(
133+
catalogus["url"]
134+
for catalogus in catalogus_data
135+
if catalogus["domein"] == domein and catalogus["rsin"] == rsin
136+
),
137+
None,
138+
)
139+
140+
if matching_catalogus is None:
141+
return []
142+
143+
iotypen_data = client.get_all_informatieobjecttypen(
144+
catalogus=matching_catalogus
145+
)
146+
else:
147+
iotypen_data = client.get_all_informatieobjecttypen()
148+
149+
iotypen = []
150+
151+
for iotype in iotypen_data:
152+
# fmt: off
153+
exists = any(
154+
existing_iotype["informatieobjecttype"].omschrijving == iotype["omschrijving"]
155+
and existing_iotype["informatieobjecttype"].catalogus == iotype["catalogus"]
156+
for existing_iotype in iotypen
157+
)
158+
# fmt: on
159+
160+
if not exists:
161+
iotypen.append(
162+
{
163+
"informatieobjecttype": factory(InformatieObjectType, iotype),
164+
"catalogus": factory(
165+
Catalogus, catalogus_mapping[iotype["catalogus"]]
166+
),
167+
}
168+
)
97169

98170
return iotypen
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
interactions:
2+
- request:
3+
body: null
4+
headers:
5+
Accept:
6+
- '*/*'
7+
Accept-Encoding:
8+
- gzip, deflate, br
9+
Authorization:
10+
- Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0ZXN0X2NsaWVudF9pZCIsImlhdCI6MTcyMDQ2MDQwNCwiY2xpZW50X2lkIjoidGVzdF9jbGllbnRfaWQiLCJ1c2VyX2lkIjoiIiwidXNlcl9yZXByZXNlbnRhdGlvbiI6IiJ9.gLx2nHgFUz7fAr9NSbLbT25FqSp97siXMARqdkbcaeU
11+
Connection:
12+
- keep-alive
13+
User-Agent:
14+
- python-requests/2.32.2
15+
method: GET
16+
uri: http://localhost:8003/catalogi/api/v1/catalogussen
17+
response:
18+
body:
19+
string: '{"count":1,"next":null,"previous":null,"results":[{"url":"http://localhost:8003/catalogi/api/v1/catalogussen/bd58635c-793e-446d-a7e0-460d7b04829d","domein":"TEST","rsin":"000000000","contactpersoonBeheerNaam":"Test
20+
name","contactpersoonBeheerTelefoonnummer":"","contactpersoonBeheerEmailadres":"","zaaktypen":["http://localhost:8003/catalogi/api/v1/zaaktypen/1f41885e-23fc-4462-bbc8-80be4ae484dc","http://localhost:8003/catalogi/api/v1/zaaktypen/119dbe23-cbf2-4759-80e5-29bb28b3d95f"],"besluittypen":[],"informatieobjecttypen":["http://localhost:8003/catalogi/api/v1/informatieobjecttypen/7a474713-0833-402a-8441-e467c08ac55b","http://localhost:8003/catalogi/api/v1/informatieobjecttypen/b2d83b94-9b9b-4e80-a82f-73ff993c62f3","http://localhost:8003/catalogi/api/v1/informatieobjecttypen/531f6c1a-97f7-478c-85f0-67d2f23661c7"],"naam":"Test
21+
catalog","versie":"","begindatumVersie":null}]}'
22+
headers:
23+
API-version:
24+
- 1.3.1
25+
Allow:
26+
- GET, POST, HEAD, OPTIONS
27+
Content-Length:
28+
- '886'
29+
Content-Type:
30+
- application/json
31+
Cross-Origin-Opener-Policy:
32+
- same-origin
33+
Referrer-Policy:
34+
- same-origin
35+
Vary:
36+
- Accept, origin
37+
X-Content-Type-Options:
38+
- nosniff
39+
X-Frame-Options:
40+
- DENY
41+
status:
42+
code: 200
43+
message: OK
44+
version: 1

0 commit comments

Comments
 (0)