Skip to content

Commit a132559

Browse files
committed
✨ [#500] Implement Referentielijsten integration for Klantcontact
1 parent 1500393 commit a132559

File tree

20 files changed

+503
-2
lines changed

20 files changed

+503
-2
lines changed

bin/docker_start.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ until pg_isready; do
2121
done
2222

2323
>&2 echo "Database is up."
24-
24+
>&2 echo "Waiting 10 seconds for PostgreSQL initialization to complete..."
25+
sleep 10
2526
# Set defaults for OTEL
2627
export OTEL_SERVICE_NAME="${OTEL_SERVICE_NAME:-openklant}"
2728

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
services:
2+
referentielijsten-redis:
3+
image: redis:7
4+
command: ["redis-server", "--appendonly", "yes"]
5+
networks:
6+
- referentielijsten-dev
7+
8+
referentielijsten-db:
9+
image: postgres:${PG_VERSION:-14}
10+
environment:
11+
- POSTGRES_HOST_AUTH_METHOD=trust
12+
- POSTGRES_USER=referentielijsten
13+
- POSTGRES_DB=referentielijsten
14+
volumes:
15+
- ./docker-init-referentielijsten-db/:/docker-entrypoint-initdb.d
16+
- referentielijsten-db:/var/lib/postgresql/data
17+
networks:
18+
- referentielijsten-dev
19+
20+
referentielijsten-web.local:
21+
image: maykinmedia/referentielijsten-api:${REFERENTIELIJSTEN_VERSION:-latest}
22+
environment: &referentielijsten_web_env
23+
- DJANGO_SETTINGS_MODULE=referentielijsten.conf.docker
24+
- SECRET_KEY=${SECRET_KEY:-7&3f^bo1(-5($bre4iv-!nt%1xr!b54b&y7+97j5f&ndm_e=lz}
25+
- ALLOWED_HOSTS=referentielijsten-web.local,localhost
26+
- DB_NAME=referentielijsten
27+
- DB_USER=referentielijsten
28+
- DB_HOST=referentielijsten-db
29+
- DISABLE_2FA=true
30+
- IS_HTTPS=no
31+
- CACHE_DEFAULT=referentielijsten-redis:6379/0
32+
- CACHE_AXES=referentielijsten-redis:6379/0
33+
- SUBPATH=${SUBPATH:-/}
34+
- DJANGO_SUPERUSER_PASSWORD=admin
35+
ports:
36+
- 8004:8000
37+
volumes: &referentielijsten_web_volumes
38+
# mount fixtures dir to automatically populate the DB
39+
- ./fixtures/:/app/fixtures
40+
- media:/app/media # Shared media volume to get access to saved OAS files
41+
- private-media:/app/private-media
42+
depends_on:
43+
- referentielijsten-db
44+
- referentielijsten-redis
45+
networks:
46+
- referentielijsten-dev
47+
48+
volumes:
49+
referentielijsten-db:
50+
media:
51+
private-media:
52+
53+
networks:
54+
referentielijsten-dev:
55+
name: referentielijsten-dev
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
CREATE USER referentielijsten;
2+
CREATE DATABASE referentielijsten;
3+
GRANT ALL PRIVILEGES ON DATABASE referentielijsten TO referentielijsten;
4+
-- On Postgres 15+, connect to the database and grant schema permissions.
5+
-- GRANT USAGE, CREATE ON SCHEMA public TO referentielijsten;
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
[
2+
{
3+
"model": "api.tabel",
4+
"pk": 1,
5+
"fields": {
6+
"code": "TEST",
7+
"naam": "Test Tabel",
8+
"einddatum_geldigheid": null,
9+
"beheerder_naam": "Mary",
10+
"beheerder_email": "[email protected]",
11+
"beheerder_afdeling": "",
12+
"beheerder_organisatie": ""
13+
}
14+
},
15+
{
16+
"model": "api.item",
17+
"pk": 1,
18+
"fields": {
19+
"tabel": 1,
20+
"code": "ITEM001",
21+
"naam": "Test Item 1",
22+
"begindatum_geldigheid": "2025-10-27T15:09:23Z",
23+
"einddatum_geldigheid": null,
24+
"aanvullende_gegevens": null
25+
}
26+
},
27+
{
28+
"model": "api.item",
29+
"pk": 2,
30+
"fields": {
31+
"tabel": 1,
32+
"code": "ITEM002",
33+
"naam": "Test Item 2",
34+
"begindatum_geldigheid": "2025-10-27T15:09:07Z",
35+
"einddatum_geldigheid": "2026-10-27T15:09:08Z",
36+
"aanvullende_gegevens": null
37+
}
38+
}
39+
]

migration/cassettes/test_digitaal_adres.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,4 @@ interactions:
3535
status:
3636
code: 200
3737
message: OK
38-
version: 1
38+
version: 1

src/openklant/components/klantinteracties/api/serializers/klantcontacten.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
)
1919
from openklant.components.klantinteracties.api.validators import (
2020
FKUniqueTogetherValidator,
21+
KanaalValidator,
2122
betrokkene_exists,
2223
bijlage_exists,
2324
klantcontact_exists,
@@ -306,6 +307,12 @@ class KlantcontactSerializer(serializers.HyperlinkedModelSerializer):
306307
"had_betrokkenen.digitale_adressen": f"{SERIALIZER_PATH}.digitaal_adres.DigitaalAdresSerializer",
307308
}
308309

310+
kanaal = serializers.CharField(
311+
max_length=50,
312+
help_text=_("Communicatiekanaal dat bij het klantcontact werd gebruikt."),
313+
validators=[KanaalValidator()],
314+
)
315+
309316
class Meta:
310317
model = Klantcontact
311318
fields = (

src/openklant/components/klantinteracties/api/validators.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
from django.core.exceptions import ValidationError
12
from django.core.validators import EmailValidator
23
from django.db import models
34
from django.utils.translation import gettext_lazy as _
45

6+
import structlog
57
from rest_framework import serializers
68
from rest_framework.validators import UniqueTogetherValidator, qs_filter
9+
from zgw_consumers.client import build_client
710

811
from openklant.components.klantinteracties.constants import SoortDigitaalAdres
912
from openklant.components.klantinteracties.models.actoren import Actor
@@ -25,7 +28,11 @@
2528
PartijIdentificator,
2629
)
2730
from openklant.components.klantinteracties.models.rekeningnummers import Rekeningnummer
31+
from openklant.config.models import ReferentielijstenConfig
2832
from openklant.utils.validators import validate_phone_number
33+
from referentielijsten_client.client import ReferentielijstenClient
34+
35+
logger = structlog.get_logger(__name__)
2936

3037

3138
class FKUniqueTogetherValidator(UniqueTogetherValidator):
@@ -180,3 +187,28 @@ def __call__(self, soort_digitaal_adres: SoortDigitaalAdres, value: str):
180187
validate_phone_number(value)
181188
case _:
182189
return
190+
191+
192+
class KanaalValidator:
193+
def __call__(self, value: str):
194+
config = ReferentielijstenConfig.get_solo()
195+
if not config.enabled:
196+
return value
197+
198+
if not config.service:
199+
logger.warning("missing_referentielijsten_service")
200+
return value
201+
202+
client = build_client(
203+
service=config.service,
204+
client_factory=ReferentielijstenClient,
205+
)
206+
kanalen_data = client.get_cached_items_by_tabel_code(config.tabel_code)
207+
kanalen = [item["code"] for item in kanalen_data if "code" in item]
208+
209+
if value not in kanalen:
210+
raise ValidationError(
211+
f"'{value}' is not a valid kanaal. Allowed values: {', '.join(kanalen)}"
212+
)
213+
214+
return value

src/openklant/conf/base.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"openklant.components.token",
2626
"openklant.components.klantinteracties",
2727
"openklant.components.contactgegevens",
28+
"openklant.config",
2829
# Django libraries
2930
"localflavor",
3031
]

src/openklant/config/__init__.py

Whitespace-only changes.

src/openklant/config/admin.py

Whitespace-only changes.

0 commit comments

Comments
 (0)