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

Release/1.12.2 #906

Closed
wants to merge 8 commits into from
9 changes: 8 additions & 1 deletion src/open_inwoner/cms/cases/views/status.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class InnerCaseDetailView(
template_name = "pages/cases/status_inner.html"
form_class = CaseUploadForm
contact_form_class = CaseContactForm
case: Zaak = None
case: Optional[Zaak] = None

def __init__(self):
self.statustype_config_mapping = {
Expand Down Expand Up @@ -279,6 +279,13 @@ def is_file_upload_enabled_for_statustype(self) -> bool:
enabled_for_status_type = self.statustype_config_mapping[
self.case.status.statustype.url
].document_upload_enabled
except AttributeError:
logger.info(
"Could not retrieve status type for case {case}; "
"the status has not been resolved to a ZGW model object.".format(
case=self.case
)
)
except KeyError:
logger.info(
"Could not retrieve status type config for url {url}".format(
Expand Down
5 changes: 4 additions & 1 deletion src/open_inwoner/contrib/kvk/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ def _build_request_kwargs(self) -> dict:

return request_kwargs

def _request(self, endpoint: str, params: dict) -> list:
def _request(self, endpoint: str, params: dict) -> dict:
if not self.config or not self.config.api_root:
return {}

url = self._build_url(endpoint, params=params)
request_kwargs = self._build_request_kwargs()

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Generated by Django 3.2.20 on 2023-12-04 12:53

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("kvk", "0001_initial"),
]

operations = [
migrations.AlterField(
model_name="kvkconfig",
name="api_root",
field=models.URLField(
help_text="The root of the API (e.g. https://api.kvk.nl/api/v1)",
max_length=128,
verbose_name="API root",
),
),
]
1 change: 0 additions & 1 deletion src/open_inwoner/contrib/kvk/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ class KvKConfig(SingletonModel):
api_root = models.URLField(
verbose_name=_("API root"),
max_length=128,
blank=True,
help_text=_("The root of the API (e.g. https://api.kvk.nl/api/v1)"),
)
api_key = models.CharField(
Expand Down
23 changes: 23 additions & 0 deletions src/open_inwoner/contrib/kvk/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,29 @@ def test_search_by_kvk_extra_params(self):
},
)

def test_no_search_without_config(self):
config = None
kvk_client = KvKClient(config)

company = kvk_client.search(kvk="69599084")

self.assertEqual(company, {})

def test_no_search_with_empty_api_root(self):
"""Sentry 343407"""

config = KvKConfig(
api_root="",
api_key="12345",
client_certificate=CLIENT_CERT,
server_certificate=SERVER_CERT,
)
kvk_client = KvKClient(config)

company = kvk_client.search(kvk="69599084")

self.assertEqual(company, {})

#
# requests interface
#
Expand Down
1 change: 1 addition & 0 deletions src/open_inwoner/openzaak/api_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ def process_data(self) -> dict:
"current_status": status_translate.from_glom(
self, "status.statustype.omschrijving", default=""
),
"zaaktype_config": getattr(self, "zaaktype_config", None),
"statustype_config": getattr(self, "statustype_config", None),
"case_type": "Zaak",
}
Expand Down
23 changes: 20 additions & 3 deletions src/open_inwoner/openzaak/cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from .api_models import Resultaat, Rol, Status, Zaak, ZaakInformatieObject
from .catalog import fetch_single_case_type, fetch_single_status_type
from .clients import build_client
from .models import OpenZaakConfig, ZaakTypeStatusTypeConfig
from .models import OpenZaakConfig, ZaakTypeConfig, ZaakTypeStatusTypeConfig
from .utils import is_zaak_visible

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -403,6 +403,21 @@ def resolve_status_type(case: Zaak) -> None:
case.status.statustype = fetch_single_status_type(statustype_url)


def add_zaak_type_config(case: Zaak) -> None:
"""
Add `ZaakTypeConfig` corresponding to the zaaktype type url of the case

Note: must be called after `resolve_zaak_type` since we're using the `uuid` and
`identificatie` from `case.zaaktype`
"""
try:
case.zaaktype_config = ZaakTypeConfig.objects.filter_case_type(
case.zaaktype
).get()
except ZaakTypeConfig.DoesNotExist:
pass


def add_status_type_config(case: Zaak) -> None:
"""
Add `ZaakTypeStatusTypeConfig` corresponding to the status type url of the case
Expand All @@ -412,9 +427,10 @@ def add_status_type_config(case: Zaak) -> None:
"""
try:
case.statustype_config = ZaakTypeStatusTypeConfig.objects.get(
statustype_url=case.status.statustype.url
zaaktype_config=case.zaaktype_config,
statustype_url=case.status.statustype.url,
)
except ZaakTypeStatusTypeConfig.DoesNotExist:
except (AttributeError, ZaakTypeStatusTypeConfig.DoesNotExist):
pass


Expand All @@ -433,6 +449,7 @@ def preprocess_data(cases: list[Zaak]) -> list[Zaak]:
for case in cases:
resolve_status(case)
resolve_status_type(case)
add_zaak_type_config(case)
add_status_type_config(case)

cases.sort(key=lambda case: case.startdatum, reverse=True)
Expand Down
4 changes: 2 additions & 2 deletions src/open_inwoner/openzaak/notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,8 @@ def _handle_status_notification(notification: Notification, case: Zaak, inform_u
status.statustype = status_type

# check the ZaakTypeConfig
ztc = get_zaak_type_config(case.zaaktype)
if oz_config.skip_notification_statustype_informeren:
ztc = get_zaak_type_config(case.zaaktype)
if not ztc:
log_system_action(
f"ignored {r} notification: 'skip_notification_statustype_informeren' is True but cannot retrieve case_type configuration '{case.zaaktype.identificatie}' for case {case.url}",
Expand All @@ -321,7 +321,7 @@ def _handle_status_notification(notification: Notification, case: Zaak, inform_u

try:
statustype_config = ZaakTypeStatusTypeConfig.objects.get(
statustype_url=statustype_url
zaaktype_config=ztc, statustype_url=statustype_url
)
except ZaakTypeStatusTypeConfig.DoesNotExist:
pass
Expand Down
33 changes: 32 additions & 1 deletion src/open_inwoner/openzaak/tests/test_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
from ..constants import StatusIndicators
from ..models import OpenZaakConfig
from .factories import (
CatalogusConfigFactory,
ServiceFactory,
StatusTranslationFactory,
ZaakTypeConfigFactory,
ZaakTypeStatusTypeConfigFactory,
)
from .mocks import ESuiteData
Expand Down Expand Up @@ -163,6 +165,7 @@ def setUpTestData(cls):
"schemas/ZaakType",
url=f"{CATALOGI_ROOT}zaaktypen/53340e34-7581-4b04-884f",
omschrijving="Coffee zaaktype",
identificatie="ZAAK-2022-0000000001",
catalogus=f"{CATALOGI_ROOT}catalogussen/1b643db-81bb-d71bd5a2317a",
vertrouwelijkheidaanduiding=VertrouwelijkheidsAanduidingen.openbaar,
indicatieInternOfExtern="extern",
Expand Down Expand Up @@ -195,8 +198,16 @@ def setUpTestData(cls):
isEindstatus=True,
)

cls.catalogus_config = CatalogusConfigFactory.create(
url=cls.zaaktype["catalogus"]
)
cls.zaaktype_config1 = ZaakTypeConfigFactory.create(
urls=[cls.zaaktype["url"]],
identificatie=cls.zaaktype["identificatie"],
catalogus=cls.catalogus_config,
)
cls.zt_statustype_config1 = ZaakTypeStatusTypeConfigFactory.create(
zaaktype_config__identificatie="ZAAK-2022-0000000001",
zaaktype_config=cls.zaaktype_config1,
statustype_url=cls.status_type1["url"],
status_indicator=StatusIndicators.warning,
status_indicator_text="U moet documenten toevoegen",
Expand Down Expand Up @@ -376,6 +387,19 @@ def _setUpMocks(self, m):
def test_list_cases(self, m):
self._setUpMocks(m)

# Added for https://taiga.maykinmedia.nl/project/open-inwoner/task/1904
# In eSuite it is possible to reuse a StatusType for multiple ZaakTypen, which
# led to errors when retrieving the ZaakTypeStatusTypeConfig. This duplicate
# config is added to verify that that issue was solved
ZaakTypeStatusTypeConfigFactory.create(
statustype_url=self.status_type1["url"],
status_indicator=StatusIndicators.warning,
status_indicator_text="U moet documenten toevoegen",
description="Lorem ipsum dolor sit amet",
call_to_action_url="https://example.com",
call_to_action_text="duplicate",
)

response = self.app.get(
self.inner_url, user=self.user, headers={"HX-Request": "true"}
)
Expand All @@ -390,6 +414,7 @@ def test_list_cases(self, m):
"identification": self.zaak2["identificatie"],
"description": self.zaaktype["omschrijving"],
"current_status": self.status_type1["omschrijving"],
"zaaktype_config": self.zaaktype_config1,
"statustype_config": self.zt_statustype_config1,
"case_type": "Zaak",
},
Expand All @@ -400,6 +425,7 @@ def test_list_cases(self, m):
"identification": self.zaak1["identificatie"],
"description": self.zaaktype["omschrijving"],
"current_status": self.status_type1["omschrijving"],
"zaaktype_config": self.zaaktype_config1,
"statustype_config": self.zt_statustype_config1,
"case_type": "Zaak",
},
Expand All @@ -410,6 +436,7 @@ def test_list_cases(self, m):
"identification": self.zaak3["identificatie"],
"description": self.zaaktype["omschrijving"],
"current_status": self.status_type2["omschrijving"],
"zaaktype_config": self.zaaktype_config1,
"statustype_config": None,
"case_type": "Zaak",
},
Expand Down Expand Up @@ -470,6 +497,7 @@ def test_list_cases_for_eherkenning_user(self, m):
"identification": self.zaak_eherkenning2["identificatie"],
"description": self.zaaktype["omschrijving"],
"current_status": self.status_type1["omschrijving"],
"zaaktype_config": self.zaaktype_config1,
"statustype_config": self.zt_statustype_config1,
"case_type": "Zaak",
},
Expand All @@ -482,6 +510,7 @@ def test_list_cases_for_eherkenning_user(self, m):
"identification": self.zaak_eherkenning1["identificatie"],
"description": self.zaaktype["omschrijving"],
"current_status": self.status_type1["omschrijving"],
"zaaktype_config": self.zaaktype_config1,
"statustype_config": self.zt_statustype_config1,
"case_type": "Zaak",
},
Expand Down Expand Up @@ -631,6 +660,7 @@ def test_list_cases_paginated(self, m):
"identification": self.zaak2["identificatie"],
"description": self.zaaktype["omschrijving"],
"current_status": self.status_type1["omschrijving"],
"zaaktype_config": self.zaaktype_config1,
"statustype_config": self.zt_statustype_config1,
"case_type": "Zaak",
},
Expand All @@ -655,6 +685,7 @@ def test_list_cases_paginated(self, m):
"identification": self.zaak1["identificatie"],
"description": self.zaaktype["omschrijving"],
"current_status": self.status_type1["omschrijving"],
"zaaktype_config": self.zaaktype_config1,
"statustype_config": self.zt_statustype_config1,
"case_type": "Zaak",
},
Expand Down
33 changes: 32 additions & 1 deletion src/open_inwoner/openzaak/tests/test_notification_zaak_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,24 @@ def test_status_handle_zaken_notification(self, m, mock_handle: Mock):
"""
data = MockAPIData().install_mocks(m)

# Added for https://taiga.maykinmedia.nl/project/open-inwoner/task/1904
# In eSuite it is possible to reuse a StatusType for multiple ZaakTypen, which
# led to errors when retrieving the ZaakTypeStatusTypeConfig. This duplicate
# config is added to verify that that issue was solved
ztc = ZaakTypeConfigFactory.create(
catalogus__url=data.zaak_type["catalogus"],
identificatie=data.zaak_type["identificatie"],
)
ZaakTypeStatusTypeConfigFactory.create(
omschrijving=data.status_type_final["omschrijving"],
statustype_url=data.status_type_final["url"],
)
ZaakTypeStatusTypeConfigFactory.create(
zaaktype_config=ztc,
omschrijving=data.status_type_final["omschrijving"],
statustype_url=data.status_type_final["url"],
)

handle_zaken_notification(data.status_notification)

mock_handle.assert_called_once()
Expand Down Expand Up @@ -299,12 +317,25 @@ def test_status_handle_notification_when_skip_informeren_is_set_and_zaaktypeconf

data = MockAPIData().install_mocks(m)

ZaakTypeConfigFactory.create(
ztc = ZaakTypeConfigFactory.create(
catalogus__url=data.zaak_type["catalogus"],
identificatie=data.zaak_type["identificatie"],
# set this to notify
notify_status_changes=True,
)
# Added for https://taiga.maykinmedia.nl/project/open-inwoner/task/1904
# In eSuite it is possible to reuse a StatusType for multiple ZaakTypen, which
# led to errors when retrieving the ZaakTypeStatusTypeConfig. This duplicate
# config is added to verify that that issue was solved
ZaakTypeStatusTypeConfigFactory.create(
omschrijving=data.status_type_final["omschrijving"],
statustype_url=data.status_type_final["url"],
)
ZaakTypeStatusTypeConfigFactory.create(
zaaktype_config=ztc,
omschrijving=data.status_type_final["omschrijving"],
statustype_url=data.status_type_final["url"],
)

handle_zaken_notification(data.status_notification)

Expand Down
4 changes: 4 additions & 0 deletions src/open_inwoner/openzaak/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ def test_is_zaak_visible(self):
zaak.vertrouwelijkheidaanduiding = VertrouwelijkheidsAanduidingen.geheim
self.assertFalse(is_zaak_visible(zaak))

with self.subTest("invisible when zaaktype not properly resolved"):
zaak.zaaktype = None
self.assertFalse(is_zaak_visible(zaak))

def test_get_role_name_display(self):
with self.subTest("natuurlijk_persoon > all fields"):
role = generate_rol(
Expand Down
2 changes: 1 addition & 1 deletion src/open_inwoner/openzaak/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def is_zaak_visible(zaak: Zaak) -> bool:
if isinstance(zaak.zaaktype, str):
raise ValueError("expected zaak.zaaktype to be resolved from url to model")

if zaak.zaaktype.indicatie_intern_of_extern != "extern":
if not zaak.zaaktype or zaak.zaaktype.indicatie_intern_of_extern != "extern":
return False

return is_object_visible(zaak, config.zaak_max_confidentiality)
Expand Down
2 changes: 2 additions & 0 deletions src/open_inwoner/openzaak/zgw_imports.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ def import_statustype_configs_for_type(
# load urls and update/create records
for statustype_url, using_zaak_types in info_queue.items():
status_type = fetch_single_status_type(statustype_url)
if not status_type: # Statustype isn't available anymore?
continue

zaaktype_statustype = info_map.get(status_type.url)
if zaaktype_statustype:
Expand Down
17 changes: 13 additions & 4 deletions src/open_inwoner/scss/components/Card/Card.scss
Original file line number Diff line number Diff line change
Expand Up @@ -262,17 +262,26 @@
}

/// On a stretched card, the one and only link after a list should be placed on above the bottom border.
&--stretch &__body {
padding-bottom: 0;
&-- stretch &__body {
padding-bottom: var(--card-spacing);

@media (min-width: 768px) {
padding-bottom: 0;
}
}

&--stretch &__body .list:last-of-type {
padding-bottom: calc(var(--font-size-body) + var(--card-spacing) + 1em);
}

&--stretch .list + .link:first-of-type:last-of-type {
&--stretch .list + .link:first-of-type:last-of-type,
&--stretch .profile__link > .link:first-of-type:last-of-type {
bottom: var(--card-spacing);
position: absolute;
position: static;

@media (min-width: 768px) {
position: absolute;
}
}
}

Expand Down
Loading
Loading