Skip to content

Commit

Permalink
Merge pull request #1404 from maykinmedia/tasks/2758-expand-openklant…
Browse files Browse the repository at this point in the history
…2-resources

[#2758] Add the KlantContact and related resources to the openklant2 client
  • Loading branch information
alextreme authored Oct 3, 2024
2 parents f081910 + 37d3c3a commit cdaab0d
Show file tree
Hide file tree
Showing 81 changed files with 27,311 additions and 102 deletions.
34 changes: 34 additions & 0 deletions src/openklant2/_resources/actor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import uuid
from typing import cast

from ape_pie import APIClient

from openklant2._resources.base import ResourceMixin
from openklant2.types.pagination import PaginatedResponseBody
from openklant2.types.resources.actor import Actor, ActorListParams, CreateActorData


class ActorResource(ResourceMixin):
http_client: APIClient
base_path: str = "/actoren"

def create(
self,
*,
data: CreateActorData,
) -> Actor:
response = self._post(self.base_path, data=data)
return cast(Actor, self.process_response(response))

def retrieve(self, /, uuid: str | uuid.UUID) -> Actor:
response = self._get(f"{self.base_path}/{str(uuid)}")
return cast(Actor, self.process_response(response))

def list(
self, *, params: ActorListParams | None = None
) -> PaginatedResponseBody[Actor]:
response = self._get(f"{self.base_path}", params=params)
return cast(
PaginatedResponseBody[Actor],
self.process_response(response),
)
62 changes: 61 additions & 1 deletion src/openklant2/_resources/base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
import json
from typing import Any, Dict, List, Mapping, MutableMapping, TypeGuard, Union
import logging
from typing import (
Any,
Callable,
Dict,
Generator,
List,
Mapping,
MutableMapping,
Optional,
ParamSpec,
TypeGuard,
TypeVar,
Union,
cast,
)

import pydantic
import requests
Expand All @@ -19,6 +34,9 @@
ErrorResponseBodyValidator,
ValidationErrorResponseBodyValidator,
)
from openklant2.types.pagination import PaginatedResponseBody

logger = logging.getLogger(__name__)

ResourceResponse = MutableMapping[str, Any]

Expand All @@ -27,6 +45,9 @@
JSONValue = Union[JSONPrimitive, "JSONObject", List["JSONValue"]]
JSONObject = Dict[str, JSONValue]

P = ParamSpec("P")
T = TypeVar("T")


class ResourceMixin:
http_client: APIClient
Expand Down Expand Up @@ -95,6 +116,35 @@ def _process_params(params: Mapping | None) -> None | Mapping:

return transposed_params

def _paginator(
self,
paginated_data: PaginatedResponseBody[T],
max_requests: Optional[int] = None,
) -> Generator[T, Any, None]:
def row_iterator(
_data: PaginatedResponseBody[T], num_requests=0
) -> Generator[T, Any, None]:
for result in _data["results"]:
yield cast(T, result)

if next_url := _data.get("next"):
if max_requests and num_requests >= max_requests:
logger.info(
"Number of requests while retrieving paginated results reached "
"maximum of %s requests, returning results",
max_requests,
)
return

response = self.http_client.get(next_url)
num_requests += 1
response.raise_for_status()
data = response.json()

yield from row_iterator(data, num_requests)

return row_iterator(paginated_data)

def _get(
self,
path: str,
Expand Down Expand Up @@ -172,3 +222,13 @@ def _options(
headers=headers,
params=self._process_params(params),
)

def _make_list_iter(
self, f: Callable[P, PaginatedResponseBody[T]]
) -> Callable[P, Generator[T, Any, Any]]:
"""Create a fully paginated iterator for the resource list() method."""

def inner(*args: P.args, **kwargs: P.kwargs) -> Generator[T, Any, None]:
return self._paginator(f(*args, **kwargs))

return inner
36 changes: 36 additions & 0 deletions src/openklant2/_resources/betrokkene.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import uuid
from typing import cast

from ape_pie import APIClient

from openklant2._resources.base import ResourceMixin
from openklant2.types.pagination import PaginatedResponseBody
from openklant2.types.resources.betrokkene import Betrokkene, BetrokkeneCreateData


class BetrokkeneResource(ResourceMixin):
http_client: APIClient
base_path: str = "/betrokkenen"

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.list_iter = self._make_list_iter(self.list)

def create(
self,
*,
data: BetrokkeneCreateData,
) -> Betrokkene:
response = self._post(self.base_path, data=data)
return cast(Betrokkene, self.process_response(response))

def retrieve(self, /, uuid: str | uuid.UUID) -> Betrokkene:
response = self._get(f"{self.base_path}/{str(uuid)}")
return cast(Betrokkene, self.process_response(response))

def list(self) -> PaginatedResponseBody[Betrokkene]:
response = self._get(f"{self.base_path}")
return cast(
PaginatedResponseBody[Betrokkene],
self.process_response(response),
)
36 changes: 36 additions & 0 deletions src/openklant2/_resources/interne_taak.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import uuid
from typing import cast

from ape_pie import APIClient

from openklant2._resources.base import ResourceMixin
from openklant2.types.pagination import PaginatedResponseBody
from openklant2.types.resources.interne_taak import CreateInterneTaakData, InterneTaak


class InterneTaakResource(ResourceMixin):
http_client: APIClient
base_path: str = "/internetaken"

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.list_iter = self._make_list_iter(self.list)

def create(
self,
*,
data: CreateInterneTaakData,
) -> InterneTaak:
response = self._post(self.base_path, data=data)
return cast(InterneTaak, self.process_response(response))

def retrieve(self, /, uuid: str | uuid.UUID) -> InterneTaak:
response = self._get(f"{self.base_path}/{str(uuid)}")
return cast(InterneTaak, self.process_response(response))

def list(self) -> PaginatedResponseBody[InterneTaak]:
response = self._get(f"{self.base_path}")
return cast(
PaginatedResponseBody[InterneTaak],
self.process_response(response),
)
49 changes: 49 additions & 0 deletions src/openklant2/_resources/klant_contact.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import uuid
from typing import cast

from ape_pie import APIClient

from openklant2._resources.base import ResourceMixin
from openklant2.types.pagination import PaginatedResponseBody
from openklant2.types.resources.klant_contact import (
CreateKlantContactData,
KlantContact,
ListKlantContactParams,
RetrieveKlantContactParams,
)


class KlantContactResource(ResourceMixin):
http_client: APIClient
base_path: str = "/klantcontacten"

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.list_iter = self._make_list_iter(self.list)

def create(
self,
*,
data: CreateKlantContactData,
) -> KlantContact:
response = self._post(self.base_path, data=data)
return cast(KlantContact, self.process_response(response))

def retrieve(
self,
/,
uuid: str | uuid.UUID,
*,
params: RetrieveKlantContactParams | None = None,
) -> KlantContact:
response = self._get(f"{self.base_path}/{str(uuid)}", params=params)
return cast(KlantContact, self.process_response(response))

def list(
self, *, params: ListKlantContactParams | None = None
) -> PaginatedResponseBody[KlantContact]:
response = self._get(f"{self.base_path}", params=params)
return cast(
PaginatedResponseBody[KlantContact],
self.process_response(response),
)
38 changes: 38 additions & 0 deletions src/openklant2/_resources/onderwerp_object.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import uuid
from typing import cast

from ape_pie import APIClient

from openklant2._resources.base import ResourceMixin
from openklant2.types.pagination import PaginatedResponseBody
from openklant2.types.resources.onderwerp_object import (
CreateOnderwerpObjectData,
OnderwerpObject,
OnderwerpobjectIdentificatorListParams,
)


class OnderwerpObjectResource(ResourceMixin):
http_client: APIClient
base_path: str = "/onderwerpobjecten"

def create(
self,
*,
data: CreateOnderwerpObjectData,
) -> OnderwerpObject:
response = self._post(self.base_path, data=data)
return cast(OnderwerpObject, self.process_response(response))

def retrieve(self, /, uuid: str | uuid.UUID) -> OnderwerpObject:
response = self._get(f"{self.base_path}/{str(uuid)}")
return cast(OnderwerpObject, self.process_response(response))

def list(
self, *, params: OnderwerpobjectIdentificatorListParams | None = None
) -> PaginatedResponseBody[OnderwerpObject]:
response = self._get(f"{self.base_path}", params=params)
return cast(
PaginatedResponseBody[OnderwerpObject],
self.process_response(response),
)
10 changes: 10 additions & 0 deletions src/openklant2/client.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
from ape_pie import APIClient

from openklant2._resources.actor import ActorResource
from openklant2._resources.betrokkene import BetrokkeneResource
from openklant2._resources.digitaal_adres import DigitaalAdresResource
from openklant2._resources.interne_taak import InterneTaakResource
from openklant2._resources.klant_contact import KlantContactResource
from openklant2._resources.onderwerp_object import OnderwerpObjectResource
from openklant2._resources.partij import PartijResource
from openklant2._resources.partij_identificator import PartijIdentificatorResource

Expand All @@ -18,3 +23,8 @@ def __init__(self, token: str, api_root: str):
self.partij = PartijResource(self.http_client)
self.partij_identificator = PartijIdentificatorResource(self.http_client)
self.digitaal_adres = DigitaalAdresResource(self.http_client)
self.klant_contact = KlantContactResource(self.http_client)
self.onderwerp_object = OnderwerpObjectResource(self.http_client)
self.actor = ActorResource(self.http_client)
self.interne_taak = InterneTaakResource(self.http_client)
self.betrokkene = BetrokkeneResource(self.http_client)
29 changes: 29 additions & 0 deletions src/openklant2/factories/actor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import factory
import factory.fuzzy

from openklant2.factories.common import IdentificationNumber
from openklant2.factories.helpers import validator
from openklant2.types.resources.actor import CreateActorDataValidator


class ActorIdentificatorFactory(factory.Factory):
class Meta:
model = dict

objectId = IdentificationNumber()
codeObjecttype = factory.Faker("word")
codeRegister = factory.Faker("word")
codeSoortObjectId = factory.Faker("word")


@validator(CreateActorDataValidator)
class CreateActorDataFactory(factory.Factory):
class Meta:
model = dict

naam = factory.Faker("name")
soortActor = factory.fuzzy.FuzzyChoice(
["medewerker", "geautomatiseerde_actor", "organisatorische_eenheid"]
)
indicatieActief = True
actoridentificator = factory.SubFactory(ActorIdentificatorFactory)
35 changes: 35 additions & 0 deletions src/openklant2/factories/betrokkene.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import factory
import factory.faker
import factory.fuzzy

from openklant2.factories.common import ForeignKeyRef
from openklant2.factories.helpers import FuzzyLiteral, validator
from openklant2.types.resources.betrokkene import (
BetrokkeneCreateDataValidator,
BetrokkeneRol,
)


class ContactnaamFactory(factory.Factory):
class Meta:
model = dict

voorletters = factory.Faker("prefix")
voornaam = factory.Faker("first_name")
voorvoegselAchternaam = factory.Faker("prefix")
achternaam = factory.Faker("last_name")


@validator(BetrokkeneCreateDataValidator)
class BetrokkeneCreateDataFactory(factory.Factory):
class Meta:
model = dict

wasPartij = factory.SubFactory(ForeignKeyRef)
hadKlantcontact = factory.SubFactory(ForeignKeyRef)
bezoekadres = None
correspondentieadres = None
contactnaam = factory.SubFactory(ContactnaamFactory)
rol = FuzzyLiteral(BetrokkeneRol)
organisatienaam = factory.Faker("company")
initiator = factory.fuzzy.FuzzyChoice((True, False))
3 changes: 3 additions & 0 deletions src/openklant2/factories/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ class Meta:
model = dict

uuid = factory.Faker("uuid4")


IdentificationNumber = lambda: factory.LazyAttributeSequence(lambda o, n: f"{n+1:010d}")
Loading

0 comments on commit cdaab0d

Please sign in to comment.