Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#2862] Integrate OpenKlant2 service with detail views #1490

Merged
merged 2 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 35 additions & 26 deletions src/open_inwoner/accounts/views/contactmoments.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,18 +91,18 @@ class KlantContactMomentBaseView(
CommonPageMixin, BaseBreadcrumbMixin, KlantContactMomentAccessMixin, TemplateView
):
def get_service(self, service_type: KlantenServiceType) -> VragenService | None:
if service_type == KlantenServiceType.OPENKLANT2:
try:
return OpenKlant2Service()
except ImproperlyConfigured:
logger.error("OpenKlant2 configuration missing")
if service_type == KlantenServiceType.ESUITE:
try:
return eSuiteVragenService()
except ImproperlyConfigured:
logger.error("eSuiteVragenService configuration missing")
elif service_type == KlantenServiceType.OPENKLANT2:
try:
return OpenKlant2Service()
except ImproperlyConfigured:
logger.error("OpenKlant2 configuration missing")
except RuntimeError:
logger.error("Failed to build OpenKlant2Service")
logger.error("Failed to build eSuiteVragenService")

def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
Expand Down Expand Up @@ -146,24 +146,24 @@ def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)

questions = []
if esuite_service := self.get_service(service_type=KlantenServiceType.ESUITE):
if ok2_service := self.get_service(service_type=KlantenServiceType.OPENKLANT2):
questions.extend(
esuite_service.list_questions(
fetch_params=self.get_fetch_params(esuite_service),
ok2_service.list_questions(
self.get_fetch_params(ok2_service),
user=self.request.user,
)
)
if ok2_service := self.get_service(service_type=KlantenServiceType.OPENKLANT2):
if esuite_service := self.get_service(service_type=KlantenServiceType.ESUITE):
questions.extend(
ok2_service.list_questions(
self.get_fetch_params(ok2_service),
esuite_service.list_questions(
fetch_params=self.get_fetch_params(esuite_service),
user=self.request.user,
)
)
questions.sort(key=lambda q: q["registered_date"], reverse=True)
ctx["contactmomenten"] = questions
ctx["questions"] = questions

paginator_dict = self.paginate_with_context(ctx["contactmomenten"])
paginator_dict = self.paginate_with_context(ctx["questions"])
ctx.update(paginator_dict)

return ctx
Expand All @@ -187,25 +187,28 @@ def get_anchors(self) -> list:

def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
service = self.get_service(service_type=KlantenServiceType.ESUITE)

kcm, zaak = service.retrieve_question(
if KlantenServiceType.ESUITE.value in self.request.path:
service = self.get_service(service_type=KlantenServiceType.ESUITE)
elif KlantenServiceType.OPENKLANT2.value in self.request.path:
service = self.get_service(service_type=KlantenServiceType.OPENKLANT2)

question, zaak = service.retrieve_question(
self.get_fetch_params(service), kwargs["kcm_uuid"], user=self.request.user
)
if not kcm:
if not question:
raise Http404()

QuestionValidator.validate_python(kcm)
QuestionValidator.validate_python(question)

local_kcm, created = KlantContactMomentAnswer.objects.get_or_create( # noqa
user=self.request.user, contactmoment_url=kcm["case_detail_url"]
user=self.request.user, contactmoment_url=question["api_source_url"]
)
if not local_kcm.is_seen:
local_kcm.is_seen = True
local_kcm.save()

contactmoment = kcm
ctx["contactmoment"] = contactmoment
ctx["question"] = question
ctx["zaak"] = zaak.zaak if zaak else None
case_url = (
reverse(
Expand All @@ -221,19 +224,19 @@ def get_context_data(self, **kwargs):
ctx["metrics"] = [
{
"label": _("Status: "),
"value": contactmoment["status"],
"value": question["status"].capitalize(),
},
{
"label": _("Ingediend op: "),
"value": contactmoment["registered_date"],
"value": question["registered_date"],
},
{
"label": _("Vraag nummer: "),
"value": contactmoment["identification"],
"value": question["identification"],
},
{
"label": _("Contact gehad via: "),
"value": contactmoment["channel"],
"value": question["channel"].capitalize(),
},
]
origin = self.request.headers.get("Referer")
Expand Down Expand Up @@ -284,5 +287,11 @@ def get(self, request, *args, **kwargs):
raise Http404

return HttpResponseRedirect(
reverse("cases:contactmoment_detail", kwargs={"kcm_uuid": kcm.uuid})
reverse(
"cases:contactmoment_detail",
kwargs={
"api_service": KlantenServiceType.ESUITE.value,
"kcm_uuid": kcm.uuid,
},
)
)
2 changes: 1 addition & 1 deletion src/open_inwoner/cms/cases/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
name="contactmoment_list",
),
path(
"contactmomenten/<str:kcm_uuid>/",
"contactmomenten/<str:api_service>/<str:kcm_uuid>/",
KlantContactMomentDetailView.as_view(),
name="contactmoment_detail",
),
Expand Down
91 changes: 53 additions & 38 deletions src/open_inwoner/cms/cases/views/status.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@
import logging
from collections import defaultdict
from datetime import datetime
from typing import Iterable, Protocol

from django.conf import settings
from django.contrib import messages
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
from django.core.exceptions import (
ImproperlyConfigured,
ObjectDoesNotExist,
PermissionDenied,
)
from django.http import (
Http404,
HttpRequest,
Expand All @@ -20,19 +25,21 @@
from django.views.generic import FormView, TemplateView

from django_htmx.http import HttpResponseClientRedirect
from glom import glom
from mail_editor.helpers import find_template
from view_breadcrumbs import BaseBreadcrumbMixin
from zgw_consumers.api_models.constants import RolOmschrijving

from open_inwoner.accounts.models import User
from open_inwoner.mail.service import send_contact_confirmation_mail
from open_inwoner.openklant.constants import KlantenServiceType
from open_inwoner.openklant.models import OpenKlantConfig
from open_inwoner.openklant.services import eSuiteKlantenService, eSuiteVragenService
from open_inwoner.openklant.wrap import (
contactmoment_has_new_answer,
get_fetch_parameters,
get_kcm_answer_mapping,
from open_inwoner.openklant.services import (
OpenKlant2Service,
Question,
eSuiteKlantenService,
eSuiteVragenService,
)
from open_inwoner.openklant.wrap import get_fetch_parameters
from open_inwoner.openzaak.api_models import Status, StatusType, Zaak
from open_inwoner.openzaak.clients import CatalogiClient, ZakenClient
from open_inwoner.openzaak.documents import (
Expand Down Expand Up @@ -67,6 +74,15 @@ class SimpleFile:
created: datetime | None = None


class VragenService(Protocol):
def list_questions_for_zaak(
self,
zaak: Zaak,
user: User | None = None,
) -> Iterable[Question]: # noqa: E704
...


class OuterCaseDetailView(
OuterCaseAccessMixin, CommonPageMixin, BaseBreadcrumbMixin, TemplateView
):
Expand Down Expand Up @@ -110,6 +126,20 @@ class InnerCaseDetailView(
contact_form_class = CaseContactForm
case: Zaak | None = None

def get_service(self, service_type: KlantenServiceType) -> VragenService | None:
if service_type == KlantenServiceType.OPENKLANT2:
try:
return OpenKlant2Service()
except ImproperlyConfigured:
logger.error("OpenKlant2 configuration missing")
if service_type == KlantenServiceType.ESUITE:
try:
return eSuiteVragenService()
except ImproperlyConfigured:
logger.error("eSuiteVragenService configuration missing")
except RuntimeError:
logger.error("Failed to build eSuiteVragenService")

def store_statustype_mapping(self, zaaktype_identificatie):
# Filter on ZaakType identificatie to avoid eSuite situation where one statustype
# is linked to multiple zaaktypes
Expand Down Expand Up @@ -151,7 +181,6 @@ def get_context_data(self, **kwargs):
self.log_access_case_detail(self.case)

openzaak_config = OpenZaakConfig.get_solo()
openklant_config = OpenKlantConfig.get_solo()

api_group = ZGWApiGroupConfig.objects.get(pk=self.kwargs["api_group_id"])
zaken_client = api_group.zaken_client
Expand All @@ -162,38 +191,24 @@ def get_context_data(self, **kwargs):
self.store_statustype_mapping(self.case.zaaktype.identificatie)
self.store_resulttype_mapping(self.case.zaaktype.identificatie)

# questions/E-suite contactmomenten
try:
service = eSuiteVragenService(config=openklant_config)
except RuntimeError:
logger.error("Failed to build eSuiteVragenService")
objectcontactmomenten = []
else:
objectcontactmomenten = service.retrieve_objectcontactmomenten_for_zaak(
self.case
)

questions = []
for ocm in objectcontactmomenten:
question = getattr(ocm, "contactmoment", None)
if question:
questions.append(question)
questions.sort(key=lambda q: q.registratiedatum, reverse=True)

kcm_answer_mapping = get_kcm_answer_mapping(questions, self.request.user)
for question in questions:
question.new_answer_available = contactmoment_has_new_answer(
question, kcm_answer_mapping
if ok2_service := self.get_service(
service_type=KlantenServiceType.OPENKLANT2
):
questions.extend(
ok2_service.list_questions_for_zaak(
self.case, user=self.request.user
)
)

# filter questions
openklant_config = OpenKlantConfig.get_solo()
if exclude_range := openklant_config.exclude_contactmoment_kanalen:
questions = [
item
for item in questions
if glom(item, "kanaal") not in exclude_range
]
if esuite_service := self.get_service(
service_type=KlantenServiceType.ESUITE
):
questions.extend(
esuite_service.list_questions_for_zaak(
self.case, user=self.request.user
)
)
questions.sort(key=lambda q: q["registered_date"], reverse=True)

statustypen = []
catalogi_client = api_group.catalogi_client
Expand Down
Loading
Loading