From 06227ab3f2ebdf3f90aedb84349cf9ad93724ea8 Mon Sep 17 00:00:00 2001 From: Paul Schilling Date: Wed, 11 Oct 2023 15:38:19 +0200 Subject: [PATCH] [#1799] Create cms plugin for mijn aanvragen --- src/open_inwoner/cms/cases/cms_plugins.py | 42 ++++ .../cms/cases/tests/test_plugin_cases.py | 34 +++ src/open_inwoner/cms/products/cms_plugins.py | 8 +- src/open_inwoner/cms/utils/plugin_mixins.py | 10 +- src/open_inwoner/conf/base.py | 1 + src/open_inwoner/openzaak/tests/mixins.py | 202 ++++++++++++++++++ .../templates/cms/cases/cases_plugin.html | 31 +++ 7 files changed, 325 insertions(+), 3 deletions(-) create mode 100644 src/open_inwoner/cms/cases/cms_plugins.py create mode 100644 src/open_inwoner/cms/cases/tests/test_plugin_cases.py create mode 100644 src/open_inwoner/openzaak/tests/mixins.py create mode 100644 src/open_inwoner/templates/cms/cases/cases_plugin.html diff --git a/src/open_inwoner/cms/cases/cms_plugins.py b/src/open_inwoner/cms/cases/cms_plugins.py new file mode 100644 index 0000000000..1d18eb40ab --- /dev/null +++ b/src/open_inwoner/cms/cases/cms_plugins.py @@ -0,0 +1,42 @@ +from django.utils.translation import ugettext_lazy as _ + +from cms.plugin_base import CMSPluginBase +from cms.plugin_pool import plugin_pool + +# TODO: import `preprocess_data` after merge of PR 804 +from open_inwoner.openzaak.cases import fetch_cases +from open_inwoner.openzaak.formapi import fetch_open_submissions + +from ..utils.plugin_mixins import CMSActiveAppMixin + + +# TODO: refactor after merge of PR 804 +@plugin_pool.register_plugin +class CasesPlugin(CMSActiveAppMixin, CMSPluginBase): + module = _("Openzaak") + name = _("Cases Plugin") + render_template = "cms/cases/cases_plugin.html" + app_hook = "CasesApphook" + cache = False + + limit = 4 + + def render(self, context, instance, placeholder): + request = context["request"] + + raw_cases = [ + case for case in fetch_cases(request.user.bsn) if not case.einddatum + ] + # TODO + # preprocessed_cases = preprocess_data(raw_cases) + + subs = fetch_open_submissions(request.user.bsn) + + # replce raw_cases with preprocessed_cases + all_cases = raw_cases + subs + + # processed_cases = [case.preprocess_data() for case in all_cases] + + context["cases"] = all_cases[: self.limit] + + return context diff --git a/src/open_inwoner/cms/cases/tests/test_plugin_cases.py b/src/open_inwoner/cms/cases/tests/test_plugin_cases.py new file mode 100644 index 0000000000..acda5f4a52 --- /dev/null +++ b/src/open_inwoner/cms/cases/tests/test_plugin_cases.py @@ -0,0 +1,34 @@ +from unittest.mock import patch + +from django.test import TestCase, override_settings + +import requests_mock + +from open_inwoner.openzaak.tests.mixins import ZakenTestMixin +from open_inwoner.utils.test import ClearCachesMixin + +from ...tests import cms_tools +from ..cms_apps import CasesApphook +from ..cms_plugins import CasesPlugin + + +@requests_mock.Mocker() +@patch.object(CasesPlugin, "limit", 2) +@override_settings(ROOT_URLCONF="open_inwoner.cms.tests.urls") +class CasesPluginTest(ZakenTestMixin, ClearCachesMixin, TestCase): + @classmethod + def setUpTestData(cls): + super().setUpTestData() + cms_tools.create_apphook_page(CasesApphook) + + def test_cms_plugin_cases_are_rendered(self, m): + self._setUpMocks(m) + + html, context = cms_tools.render_plugin(CasesPlugin, user=self.user) + + cases = context["cases"] + + self.assertEqual(len(cases), 2) + + self.assertEqual(cases[0].omschrijving, "Coffee zaak 1") + self.assertEqual(cases[1].omschrijving, "Coffee zaak 2") diff --git a/src/open_inwoner/cms/products/cms_plugins.py b/src/open_inwoner/cms/products/cms_plugins.py index 9b423f0aa1..83685d6198 100644 --- a/src/open_inwoner/cms/products/cms_plugins.py +++ b/src/open_inwoner/cms/products/cms_plugins.py @@ -3,6 +3,7 @@ from cms.plugin_base import CMSPluginBase from cms.plugin_pool import plugin_pool +from open_inwoner.openzaak.cases import fetch_cases from open_inwoner.pdc.forms import ProductFinderForm from open_inwoner.pdc.models import Category, ProductCondition, ProductLocation from open_inwoner.questionnaire.models import QuestionnaireStep @@ -14,7 +15,8 @@ class CategoriesPlugin(CMSActiveAppMixin, CMSPluginBase): module = _("PDC") name = _("Categories Plugin") - render_template = "cms/products/categories_plugin.html" + # render_template = "cms/products/categories_plugin.html" + render_template = "cms/cases/cases_plugin.html" app_hook = "ProductsApphook" cache = False @@ -40,6 +42,10 @@ def render(self, context, instance, placeholder): context["categories"] = categories + # from cms.models import Page + # pages = Page.objects.published().all() + # import pdb;pdb.set_trace() + return context diff --git a/src/open_inwoner/cms/utils/plugin_mixins.py b/src/open_inwoner/cms/utils/plugin_mixins.py index 608e1a524b..20788e368b 100644 --- a/src/open_inwoner/cms/utils/plugin_mixins.py +++ b/src/open_inwoner/cms/utils/plugin_mixins.py @@ -1,12 +1,18 @@ from cms.models import Page -from cms.plugin_base import CMSPluginBase class CMSActiveAppMixin: + """ + Render only plugins for active CMS apps + """ + app_hook = None @property - def render_plugin(self): + def render_plugin(self) -> bool: + """ + Return `True` if plugin should be rendered, `False` otherwise + """ if self.app_hook is None: raise ValueError(f"Apphook for plugin '{self.name}' is not defined") diff --git a/src/open_inwoner/conf/base.py b/src/open_inwoner/conf/base.py index 17fadf7c0c..925a5988d5 100644 --- a/src/open_inwoner/conf/base.py +++ b/src/open_inwoner/conf/base.py @@ -535,6 +535,7 @@ "content": { "plugins": [ # "TextPlugin", + "CasesPlugin", "PicturePlugin", "VideoPlayerPlugin", "CategoriesPlugin", diff --git a/src/open_inwoner/openzaak/tests/mixins.py b/src/open_inwoner/openzaak/tests/mixins.py new file mode 100644 index 0000000000..e6e26e17b0 --- /dev/null +++ b/src/open_inwoner/openzaak/tests/mixins.py @@ -0,0 +1,202 @@ +from furl import furl +from zgw_consumers.api_models.constants import VertrouwelijkheidsAanduidingen +from zgw_consumers.constants import APITypes +from zgw_consumers.test import generate_oas_component, mock_service_oas_get + +from open_inwoner.accounts.choices import LoginTypeChoices +from open_inwoner.accounts.tests.factories import UserFactory +from open_inwoner.openzaak.models import OpenZaakConfig +from open_inwoner.openzaak.tests.factories import ServiceFactory +from open_inwoner.openzaak.tests.shared import CATALOGI_ROOT, ZAKEN_ROOT +from open_inwoner.utils.test import paginated_response + + +class ZakenTestMixin: + """ + Set up data required by tests that interact with the Zaken API: + - digid user + - services (zaken, catalogi) + - zaken, zaak types, status types + - request mocks + + Note: the inheriting class must be decorated with requests_mock.Mocker() to make + the call to _setUpMocks work + """ + + @classmethod + def setUpTestData(cls): + super().setUpTestData() + + cls.user = UserFactory( + login_type=LoginTypeChoices.digid, bsn="900222086", email="johm@smith.nl" + ) + # services + cls.zaak_service = ServiceFactory(api_root=ZAKEN_ROOT, api_type=APITypes.zrc) + cls.catalogi_service = ServiceFactory( + api_root=CATALOGI_ROOT, api_type=APITypes.ztc + ) + # openzaak config + cls.config = OpenZaakConfig.get_solo() + cls.config.zaak_service = cls.zaak_service + cls.config.catalogi_service = cls.catalogi_service + cls.config.zaak_max_confidentiality = ( + VertrouwelijkheidsAanduidingen.beperkt_openbaar + ) + cls.config.save() + + cls.zaaktype = generate_oas_component( + "ztc", + "schemas/ZaakType", + url=f"{CATALOGI_ROOT}zaaktypen/53340e34-7581-4b04-884f", + omschrijving="Coffee zaaktype", + catalogus=f"{CATALOGI_ROOT}catalogussen/1b643db-81bb-d71bd5a2317a", + vertrouwelijkheidaanduiding=VertrouwelijkheidsAanduidingen.openbaar, + indicatieInternOfExtern="extern", + ) + cls.zaak_type_intern = generate_oas_component( + "ztc", + "schemas/ZaakType", + url=f"{CATALOGI_ROOT}zaaktypen/53340e34-75a1-4b04-1234", + omschrijving="Intern zaaktype", + catalogus=f"{CATALOGI_ROOT}catalogussen/1b643db-81bb-d71bd5a2317a", + vertrouwelijkheidaanduiding=VertrouwelijkheidsAanduidingen.openbaar, + indicatieInternOfExtern="intern", + ) + cls.status_type1 = generate_oas_component( + "ztc", + "schemas/StatusType", + url=f"{CATALOGI_ROOT}statustypen/e3798107-ab27-4c3c-977d-777yu878km09", + zaaktype=cls.zaaktype["url"], + omschrijving="Initial request", + volgnummer=1, + isEindstatus=False, + ) + cls.status_type2 = generate_oas_component( + "ztc", + "schemas/StatusType", + url=f"{CATALOGI_ROOT}statustypen/e3798107-ab27-4c3c-977d-744516671fe4", + zaaktype=cls.zaaktype["url"], + omschrijving="Finish", + volgnummer=2, + isEindstatus=True, + ) + # open + cls.zaak1 = generate_oas_component( + "zrc", + "schemas/Zaak", + url=f"{ZAKEN_ROOT}zaken/d8bbdeb7-770f-4ca9-b1ea-77b4730bf67d", + uuid="d8bbdeb7-770f-4ca9-b1ea-77b4730bf67d", + zaaktype=cls.zaaktype["url"], + identificatie="ZAAK-2022-0000000001", + omschrijving="Coffee zaak 1", + startdatum="2022-01-02", + einddatum=None, + status=f"{ZAKEN_ROOT}statussen/3da89990-c7fc-476a-ad13-c9023450083c", + vertrouwelijkheidaanduiding=VertrouwelijkheidsAanduidingen.openbaar, + ) + cls.status1 = generate_oas_component( + "zrc", + "schemas/Status", + url=cls.zaak1["status"], + zaak=cls.zaak1["url"], + statustype=cls.status_type1["url"], + datumStatusGezet="2021-01-12", + statustoelichting="", + ) + cls.zaak2 = generate_oas_component( + "zrc", + "schemas/Zaak", + url=f"{ZAKEN_ROOT}zaken/e4d469b9-6666-4bdd-bf42-b53445298102", + uuid="e4d469b9-6666-4bdd-bf42-b53445298102", + zaaktype=cls.zaaktype["url"], + identificatie="ZAAK-2022-0008800002", + omschrijving="Coffee zaak 2", + startdatum="2022-01-12", + einddatum=None, + status=f"{ZAKEN_ROOT}statussen/3da81560-c7fc-476a-ad13-beu760sle929", + vertrouwelijkheidaanduiding=VertrouwelijkheidsAanduidingen.openbaar, + ) + cls.status2 = generate_oas_component( + "zrc", + "schemas/Status", + url=cls.zaak2["status"], + zaak=cls.zaak2["url"], + statustype=cls.status_type1["url"], + datumStatusGezet="2021-03-12", + statustoelichting="", + ) + # closed + cls.zaak3 = generate_oas_component( + "zrc", + "schemas/Zaak", + url=f"{ZAKEN_ROOT}zaken/6f8de38f-85ea-42d3-978c-845a033335a7", + uuid="6f8de38f-85ea-42d3-978c-845a033335a7", + zaaktype=cls.zaaktype["url"], + identificatie="ZAAK-2022-0001000003", + omschrijving="Coffee zaak closed", + startdatum="2021-07-26", + einddatum="2022-01-16", + status=f"{ZAKEN_ROOT}statussen/98659876-bbb3-476a-ad13-n3nvcght758js", + vertrouwelijkheidaanduiding=VertrouwelijkheidsAanduidingen.openbaar, + ) + cls.status3 = generate_oas_component( + "zrc", + "schemas/Status", + url=cls.zaak3["status"], + zaak=cls.zaak3["url"], + statustype=cls.status_type2["url"], + datumStatusGezet="2021-03-15", + statustoelichting="", + ) + # not visible + cls.zaak_intern = generate_oas_component( + "zrc", + "schemas/Zaak", + url=f"{ZAKEN_ROOT}zaken/d8bbdeb7-770f-4ca9-b1ea-77b4ee0bf67d", + uuid="d8bbdeb7-770f-4ca9-b1ea-77b4730bf67d", + zaaktype=cls.zaak_type_intern["url"], + identificatie="ZAAK-2022-0000000009", + omschrijving="Intern zaak", + startdatum="2022-01-02", + einddatum=None, + status=f"{ZAKEN_ROOT}statussen/3da89990-c7fc-476a-ad13-c90234500333", + vertrouwelijkheidaanduiding=VertrouwelijkheidsAanduidingen.openbaar, + ) + cls.status_intern = generate_oas_component( + "zrc", + "schemas/Status", + url=cls.zaak_intern["status"], + zaak=cls.zaak_intern["url"], + statustype=cls.status_type1["url"], + datumStatusGezet="2021-01-12", + statustoelichting="", + ) + + def _setUpMocks(self, m): + mock_service_oas_get(m, ZAKEN_ROOT, "zrc") + mock_service_oas_get(m, CATALOGI_ROOT, "ztc") + m.get( + furl(f"{ZAKEN_ROOT}zaken") + .add( + { + "rol__betrokkeneIdentificatie__natuurlijkPersoon__inpBsn": self.user.bsn, + "maximaleVertrouwelijkheidaanduiding": VertrouwelijkheidsAanduidingen.beperkt_openbaar, + } + ) + .url, + json=paginated_response( + [self.zaak1, self.zaak2, self.zaak3, self.zaak_intern] + ), + ) + for resource in [ + self.zaaktype, + self.status_type1, + self.status_type2, + self.status1, + self.status2, + self.status3, + self.zaak_intern, + self.status_intern, + self.zaak_type_intern, + ]: + m.get(resource["url"], json=resource) diff --git a/src/open_inwoner/templates/cms/cases/cases_plugin.html b/src/open_inwoner/templates/cms/cases/cases_plugin.html new file mode 100644 index 0000000000..6544e0cd79 --- /dev/null +++ b/src/open_inwoner/templates/cms/cases/cases_plugin.html @@ -0,0 +1,31 @@ +{% load i18n anchor_menu_tags grid_tags icon_tags list_tags pagination_tags utils %} + +
+ {% anchor_menu anchors desktop=True %} +
+ +

{{ page_title }} ({{ paginator.count }})

+{% render_grid %} + + {% for case in cases %} +
+
+

{{ title }}

+

{{ description }}

+ +
+
{% trans "Einddatum" %}:
+
{{ case }}
+
{% trans "Created by" %}:
+
{{ object }}
+
+ + + + {% icon icon="arrow_forward" icon_position="after" primary=True outlined=True %} + + +
+ + {% endfor %} +{% endrender_grid %}