Skip to content

Commit

Permalink
Merge pull request #937 from maykinmedia/feature/2002-case-notificati…
Browse files Browse the repository at this point in the history
…ons-for-companies

✨ [#2002] Implement Zaken notifications for companies
  • Loading branch information
alextreme authored Jan 9, 2024
2 parents e2f4b64 + fe16158 commit ca8f7ab
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 8 deletions.
53 changes: 46 additions & 7 deletions src/open_inwoner/openzaak/notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,16 +419,55 @@ def get_np_initiator_bsns_from_roles(roles: List[Rol]) -> List[str]:
return list(ret)


def get_nnp_initiator_nnp_id_from_roles(roles: List[Rol]) -> List[str]:
"""
iterate over Rollen and for all non-natural-person initiators return their nnpId
"""
ret = set()

for role in roles:
if role.omschrijving_generiek not in (
RolOmschrijving.initiator,
RolOmschrijving.medeinitiator,
):
continue
if role.betrokkene_type != RolTypes.niet_natuurlijk_persoon:
continue
if not role.betrokkene_identificatie:
continue
nnp_id = role.betrokkene_identificatie.get("inn_nnp_id")
if not nnp_id:
continue
ret.add(nnp_id)

return list(ret)


def get_emailable_initiator_users_from_roles(roles: List[Rol]) -> List[User]:
"""
iterate over Rollen and return User objects for all natural-person initiators we can notify
"""
users = []

bsn_list = get_np_initiator_bsns_from_roles(roles)
if not bsn_list:
return []
users = list(
User.objects.filter(
bsn__in=bsn_list, is_active=True, cases_notifications=True
).having_usable_email()
)
if bsn_list:
users += list(
User.objects.filter(
bsn__in=bsn_list, is_active=True, cases_notifications=True
).having_usable_email()
)

nnp_id_list = get_nnp_initiator_nnp_id_from_roles(roles)
if nnp_id_list:
config = OpenZaakConfig.get_solo()
if config.fetch_eherkenning_zaken_with_rsin:
id_filter = {"rsin__in": nnp_id_list}
else:
id_filter = {"kvk__in": nnp_id_list}
users += list(
User.objects.filter(
is_active=True, cases_notifications=True, **id_filter
).having_usable_email()
)

return users
62 changes: 61 additions & 1 deletion src/open_inwoner/openzaak/tests/test_notification_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
from zgw_consumers.constants import APITypes
from zgw_consumers.test import generate_oas_component, mock_service_oas_get

from open_inwoner.accounts.tests.factories import DigidUserFactory
from open_inwoner.accounts.tests.factories import (
DigidUserFactory,
eHerkenningUserFactory,
)
from open_inwoner.openzaak.tests.factories import (
NotificationFactory,
ServiceFactory,
Expand Down Expand Up @@ -54,6 +57,11 @@ def __init__(self):
bsn="100000001",
email="[email protected]",
)
self.eherkenning_user_initiator = eHerkenningUserFactory(
kvk="12345678",
rsin="000000000",
email="[email protected]",
)
self.zaak_type = generate_oas_component(
"ztc",
"schemas/ZaakType",
Expand Down Expand Up @@ -93,6 +101,15 @@ def __init__(self):
resultaat=f"{ZAKEN_ROOT}resultaten/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
vertrouwelijkheidaanduiding=VertrouwelijkheidsAanduidingen.openbaar,
)
self.zaak2 = generate_oas_component(
"zrc",
"schemas/Zaak",
url=f"{ZAKEN_ROOT}zaken/bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
zaaktype=self.zaak_type["url"],
status=f"{ZAKEN_ROOT}statussen/aaaaaaaa-aaaa-aaaa-aaaa-222222222222",
resultaat=f"{ZAKEN_ROOT}resultaten/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
vertrouwelijkheidaanduiding=VertrouwelijkheidsAanduidingen.openbaar,
)
self.status_initial = generate_oas_component(
"zrc",
"schemas/Status",
Expand Down Expand Up @@ -123,6 +140,13 @@ def __init__(self):
informatieobject=self.informatie_object["url"],
zaak=self.zaak["url"],
)
self.zaak_informatie_object2 = generate_oas_component(
"zrc",
"schemas/ZaakInformatieObject",
url=f"{ZAKEN_ROOT}zaakinformatieobjecten/aaaaaaaa-0002-aaaa-aaaa-aaaaaaaaaaaa",
informatieobject=self.informatie_object["url"],
zaak=self.zaak2["url"],
)

self.role_initiator = generate_oas_component(
"zrc",
Expand All @@ -134,8 +158,32 @@ def __init__(self):
"inpBsn": self.user_initiator.bsn,
},
)
self.eherkenning_role_initiator = generate_oas_component(
"zrc",
"schemas/Rol",
url=f"{ZAKEN_ROOT}rollen/aaaaaaaa-0002-aaaa-aaaa-aaaaaaaaaaaa",
omschrijvingGeneriek=RolOmschrijving.initiator,
betrokkeneType=RolTypes.niet_natuurlijk_persoon,
betrokkeneIdentificatie={
"innNnpId": self.eherkenning_user_initiator.kvk,
},
)
self.eherkenning_role_initiator2 = generate_oas_component(
"zrc",
"schemas/Rol",
url=f"{ZAKEN_ROOT}rollen/aaaaaaaa-0003-aaaa-aaaa-aaaaaaaaaaaa",
omschrijvingGeneriek=RolOmschrijving.initiator,
betrokkeneType=RolTypes.niet_natuurlijk_persoon,
betrokkeneIdentificatie={
"innNnpId": self.eherkenning_user_initiator.rsin,
},
)

self.case_roles = [self.role_initiator]
self.eherkenning_case_roles = [
self.eherkenning_role_initiator,
self.eherkenning_role_initiator2,
]
self.status_history = [self.status_initial, self.status_final]

self.status_notification = NotificationFactory(
Expand All @@ -150,6 +198,12 @@ def __init__(self):
resource_url=self.zaak_informatie_object["url"],
hoofd_object=self.zaak["url"],
)
self.zio_notification2 = NotificationFactory(
resource="zaakinformatieobject",
actie="create",
resource_url=self.zaak_informatie_object2["url"],
hoofd_object=self.zaak2["url"],
)

def setUpOASMocks(self, m):
mock_service_oas_get(m, ZAKEN_ROOT, "zrc")
Expand All @@ -171,6 +225,10 @@ def install_mocks(self, m, *, res404: Optional[List[str]] = None) -> "MockAPIDat
f"{ZAKEN_ROOT}rollen?zaak={self.zaak['url']}",
json=paginated_response(self.case_roles),
)
m.get(
f"{ZAKEN_ROOT}rollen?zaak={self.zaak2['url']}",
json=paginated_response(self.eherkenning_case_roles),
)

if "status_history" in res404:
m.get(f"{ZAKEN_ROOT}statussen?zaak={self.zaak['url']}", status_code=404)
Expand All @@ -182,6 +240,7 @@ def install_mocks(self, m, *, res404: Optional[List[str]] = None) -> "MockAPIDat

for resource_attr in [
"zaak",
"zaak2",
"zaak_type",
"status_initial",
"status_final",
Expand All @@ -190,6 +249,7 @@ def install_mocks(self, m, *, res404: Optional[List[str]] = None) -> "MockAPIDat
"status_type_final",
"informatie_object",
"zaak_informatie_object",
"zaak_informatie_object2",
]:
resource = getattr(self, resource_attr)
if resource_attr in res404:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,48 @@ def test_zio_handle_zaken_notification(self, m, mock_handle: Mock):
level=logging.INFO,
)

def test_zio_handle_zaken_notification_niet_natuurlijk_persoon_initiator(
self, m, mock_handle: Mock
):
"""
happy-flow from valid data calls the (mocked) handle_zaakinformatieobject() for
niet natuurlijk persoon initiator
"""
data = MockAPIData().install_mocks(m)

ZaakTypeInformatieObjectTypeConfigFactory.from_case_type_info_object_dicts(
data.zaak_type, data.informatie_object, document_notification_enabled=True
)

config = OpenZaakConfig.get_solo()
for fetch_eherkenning_zaken_with_rsin in [True, False]:
with self.subTest(
fetch_eherkenning_zaken_with_rsin=fetch_eherkenning_zaken_with_rsin
):
mock_handle.reset_mock()
self.clearTimelineLogs()

config.fetch_eherkenning_zaken_with_rsin = (
fetch_eherkenning_zaken_with_rsin
)
config.save()

handle_zaken_notification(data.zio_notification2)

mock_handle.assert_called_once()

# check call arguments
args = mock_handle.call_args.args
self.assertEqual(args[0], data.eherkenning_user_initiator)
self.assertEqual(args[1].url, data.zaak2["url"])
self.assertEqual(args[2].url, data.zaak_informatie_object2["url"])

self.assertTimelineLog(
"accepted zaakinformatieobject notification: attempt informing users ",
lookup=Lookups.startswith,
level=logging.INFO,
)

# start of generic checks

def test_zio_bails_when_bad_notification_channel(self, m, mock_handle: Mock):
Expand Down

0 comments on commit ca8f7ab

Please sign in to comment.