Skip to content

Commit

Permalink
[#2638] Use Mixin to update klanten API when user is created
Browse files Browse the repository at this point in the history
  • Loading branch information
pi-sigma committed Aug 13, 2024
1 parent 50490bf commit 1992d6a
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 121 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,17 @@ <h3 class="utrecht-heading-3">{% trans "Notification preferences" %}</h3>
<p class="choice-list__p">{% trans "E-mailnotificaties wanneer er actie nodig is voor een zaak (kan niet uitgeschakeld worden)" %}</p>
</div>

{# Choice of zaken notification channel #}
<h3 class="utrecht-heading-4">{% trans "How do you want to receive notifications about cases?" %}</h3>
{% choice_radio_multiple form.case_notification_channel %}
<div class="radios radios--spaced">
{% with form.case_notification_channel as field %}
{% for choice in field.field.choices %}
<div class="radio-group radio-group--stacked choice-list-multiple__item">
{% choice_radio_stacked choice=choice name=field.name data=field.value index=forloop.counter initial=field.form.initial icon_class=choice.1|get_icon_class %}
</div>
{% endfor %}
{% endwith %}
</div>

{% form_actions primary_icon='east' primary_text="Voltooi registratie" fullwidth=True %}
</form>
Expand Down
4 changes: 4 additions & 0 deletions src/open_inwoner/accounts/tests/test_profile_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,10 @@ def test_disabling_notification_is_saved(self, mock_page_display):
self.assertTrue(self.user.cases_notifications)
self.assertFalse(self.user.messages_notifications)
self.assertTrue(self.user.plans_notifications)
self.assertEqual(
self.user.case_notification_channel,
NotificationChannelChoice.digital_and_post,
)

def test_cases_notifications_is_accessible_when_digid_user(self, mock_page_display):
self.user.login_type = LoginTypeChoices.digid
Expand Down
30 changes: 0 additions & 30 deletions src/open_inwoner/accounts/views/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
from digid_eherkenning.views.base import get_redirect_url
from digid_eherkenning.views.digid import DigiDAssertionConsumerServiceView
from digid_eherkenning.views.eherkenning import eHerkenningAssertionConsumerServiceView
from onelogin.saml2.utils import OneLogin_Saml2_ValidationError

from digid_eherkenning_oidc_generics.views import (
eHerkenningOIDCAuthenticationCallbackView,
Expand All @@ -27,7 +26,6 @@
from eherkenning.mock.views.eherkenning import (
eHerkenningAssertionConsumerServiceMockView,
)
from open_inwoner.openklant.clients import build_klanten_client
from open_inwoner.openklant.models import OpenKlantConfig
from open_inwoner.openzaak.models import OpenZaakConfig
from open_inwoner.utils.views import LogMixin
Expand Down Expand Up @@ -109,34 +107,6 @@ def get_success_url(self):


class CustomDigiDAssertionConsumerServiceView(DigiDAssertionConsumerServiceView):
def get(self, request):
errors = []
user = auth.authenticate(
request=request,
digid=True,
saml_art=request.GET.get("SAMLart"),
errors=errors,
)
if user is None:
error_code = getattr(errors[0], "code", "") if errors else ""
error_type = (
"cancelled"
if error_code == OneLogin_Saml2_ValidationError.STATUS_CODE_AUTHNFAILED
else "default"
)
messages.error(request, self.error_messages[error_type])
login_url = self.get_login_url(error_type=error_type)
return HttpResponseRedirect(login_url)

if (client := build_klanten_client()) and (
klant := client.create_klant(user_bsn=user.bsn)
):
logger.info("Created klant %s for new user %s", klant, user)

auth.login(request, user)

return HttpResponseRedirect(self.get_success_url())

def get_login_url(self, **kwargs):
invite_url = self.request.session.get("invite_url")
next_url = self.request.GET.get("RelayState")
Expand Down
22 changes: 22 additions & 0 deletions src/open_inwoner/accounts/views/mixins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import logging

from open_inwoner.openklant.clients import build_klanten_client
from open_inwoner.openklant.wrap import get_fetch_parameters

logger = logging.getLogger(__name__)


class KlantenAPIMixin:
def patch_klant(self, update_data: dict):
if update_data and (client := build_klanten_client()):
klant = client.retrieve_klant(**get_fetch_parameters(self.request))
if not klant:
logger.error("Failed to retrieve klant for user %s", self.request.user)
return

self.log_system_action("retrieved klant for user", user=self.request.user)
client.partial_update_klant(klant, update_data)
self.log_system_action(
f"patched klant from user profile edit with fields: {', '.join(sorted(update_data.keys()))}",
user=self.request.user,
)
65 changes: 20 additions & 45 deletions src/open_inwoner/accounts/views/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,14 @@
from open_inwoner.haalcentraal.utils import fetch_brp
from open_inwoner.laposta.forms import NewsletterSubscriptionForm
from open_inwoner.laposta.models import LapostaConfig
from open_inwoner.openklant.clients import build_klanten_client
from open_inwoner.openklant.wrap import get_fetch_parameters
from open_inwoner.plans.models import Plan
from open_inwoner.qmatic.client import NoServiceConfigured, QmaticClient
from open_inwoner.questionnaire.models import QuestionnaireStep
from open_inwoner.utils.views import CommonPageMixin, LogMixin

from ..forms import BrpUserForm, CategoriesForm, UserForm, UserNotificationsForm
from ..models import Action, User
from .mixins import KlantenAPIMixin

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -202,6 +201,7 @@ class EditProfileView(
LogMixin,
LoginRequiredMixin,
CommonPageMixin,
KlantenAPIMixin,
BaseBreadcrumbMixin,
UpdateView,
):
Expand All @@ -223,17 +223,13 @@ def get_object(self):
def form_valid(self, form):
form.save()

self.update_klant_api({k: form.cleaned_data[k] for k in form.changed_data})
self.update_klant({k: form.cleaned_data[k] for k in form.changed_data})

messages.success(self.request, _("Uw wijzigingen zijn opgeslagen"))
self.log_change(self.get_object(), _("profile was modified"))
return HttpResponseRedirect(self.get_success_url())

def update_klant_api(self, user_form_data: dict):
user: User = self.request.user
if not user.bsn and not user.kvk:
return

def update_klant(self, user_form_data: dict):
field_mapping = {
"emailadres": "email",
"telefoonnummer": "phonenumber",
Expand All @@ -243,20 +239,7 @@ def update_klant_api(self, user_form_data: dict):
for api_name, local_name in field_mapping.items()
if user_form_data.get(local_name)
}
if update_data:
if client := build_klanten_client():
klant = client.retrieve_klant(**get_fetch_parameters(self.request))

if klant:
self.log_system_action(
"retrieved klant for user", user=self.request.user
)
client.partial_update_klant(klant, update_data)
if klant:
self.log_system_action(
f"patched klant from user profile edit with fields: {', '.join(sorted(update_data.keys()))}",
user=self.request.user,
)
self.patch_klant(update_data)

def get_form_class(self):
user = self.request.user
Expand Down Expand Up @@ -319,7 +302,12 @@ def get_brp_data(self):


class MyNotificationsView(
LogMixin, LoginRequiredMixin, CommonPageMixin, BaseBreadcrumbMixin, UpdateView
LogMixin,
LoginRequiredMixin,
CommonPageMixin,
KlantenAPIMixin,
BaseBreadcrumbMixin,
UpdateView,
):
template_name = "pages/profile/notifications.html"
model = User
Expand All @@ -344,34 +332,21 @@ def get_form_kwargs(self):
def form_valid(self, form):
form.save()

self.update_klant_api({k: form.cleaned_data[k] for k in form.changed_data})
self.update_klant(
user_form_data={k: form.cleaned_data[k] for k in form.changed_data}
)

messages.success(self.request, _("Uw wijzigingen zijn opgeslagen"))
self.log_change(self.object, _("users notifications were modified"))
return HttpResponseRedirect(self.get_success_url())

def update_klant_api(self, user_form_data: dict):
user: User = self.request.user
if not user.bsn and not user.kvk:
return

update_data = {}
def update_klant(self, user_form_data: dict):
if notification_channel := user_form_data.get("case_notification_channel"):
update_data = {
"toestemmingZaakNotificatiesAlleenDigitaal": notification_channel
== NotificationChannelChoice.digital_only
}

if update_data and (client := build_klanten_client()):
klant = client.retrieve_klant(**get_fetch_parameters(self.request))
if not klant:
return

self.log_system_action("retrieved klant for user", user=self.request.user)
client.partial_update_klant(klant, update_data)
self.log_system_action(
f"patched klant from user profile edit with fields: {', '.join(sorted(update_data.keys()))}",
user=self.request.user,
self.patch_klant(
update_data={
"toestemmingZaakNotificatiesAlleenDigitaal": notification_channel
== NotificationChannelChoice.digital_only
}
)


Expand Down
40 changes: 15 additions & 25 deletions src/open_inwoner/accounts/views/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
OpenIDConnectEHerkenningConfig,
)
from open_inwoner.accounts.choices import NotificationChannelChoice
from open_inwoner.openklant.clients import build_klanten_client
from open_inwoner.openklant.wrap import get_fetch_parameters
from open_inwoner.accounts.views.mixins import KlantenAPIMixin
from open_inwoner.utils.hash import generate_email_from_string
from open_inwoner.utils.views import CommonPageMixin, LogMixin

Expand Down Expand Up @@ -138,7 +137,13 @@ def get(self, request, *args, **kwargs):
return super().get(self, request, *args, **kwargs)


class NecessaryFieldsUserView(LogMixin, LoginRequiredMixin, InviteMixin, UpdateView):
class NecessaryFieldsUserView(
LogMixin,
LoginRequiredMixin,
KlantenAPIMixin,
InviteMixin,
UpdateView,
):
model = User
form_class = NecessaryUserForm
template_name = "accounts/registration_necessary.html"
Expand All @@ -163,7 +168,7 @@ def get_form_kwargs(self):
def form_valid(self, form):
user = form.save()

self.update_klant_api({k: form.cleaned_data[k] for k in form.changed_data})
self.update_klant({k: form.cleaned_data[k] for k in form.changed_data})

invite = form.cleaned_data["invite"]
if invite:
Expand All @@ -187,28 +192,13 @@ def get_initial(self):

return initial

def update_klant_api(self, user_form_data: dict):
user: User = self.request.user
if not user.bsn and not user.kvk:
return

update_data = {}
def update_klant(self, user_form_data: dict):
if notification_channel := user_form_data.get("case_notification_channel"):
update_data = {
"toestemmingZaakNotificatiesAlleenDigitaal": notification_channel
== NotificationChannelChoice.digital_only
}

if update_data and (client := build_klanten_client()):
klant = client.retrieve_klant(**get_fetch_parameters(self.request))
if not klant:
return

self.log_system_action("retrieved klant for user", user=self.request.user)
client.partial_update_klant(klant, update_data)
self.log_system_action(
f"patched klant from user profile edit with fields: {', '.join(sorted(update_data.keys()))}",
user=self.request.user,
self.patch_klant(
update_data={
"toestemmingZaakNotificatiesAlleenDigitaal": notification_channel
== NotificationChannelChoice.digital_only
}
)


Expand Down
28 changes: 28 additions & 0 deletions src/open_inwoner/accounts/views/signals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import logging

from django.db.models.signals import post_save
from django.dispatch import receiver

from open_inwoner.accounts.models import User
from open_inwoner.openklant.clients import build_klanten_client

logger = logging.getLogger(__name__)


@receiver(post_save, sender=User)
def create_klant_for_new_user(
sender: type, instance: User, created: bool, **kwargs
) -> None:
if not created:
return

user = instance

if (client := build_klanten_client()) and (
klant := client.create_klant(user_bsn=user.bsn)
):
logger.info("Created klant %s for new user %s", klant, user)
elif klant:
logger.warning("Failed to create klanten client for new user %s", user)
else:
logger.error("Failed to create klant for new user %s", user)
30 changes: 11 additions & 19 deletions src/open_inwoner/components/templatetags/form_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,29 +266,21 @@ def choice_radio(choice, **kwargs):
@register.inclusion_tag("components/Form/ChoiceRadioStacked.html")
def choice_radio_stacked(choice, **kwargs):
"""
Displaying a radio input that is rendered from a choice field.
Usage:
{% choice_radio form.radio_field %}
Display radio input rendered from a choice field.
Variables:
+ choice: The choice that needs to be rendered.
"""
return {**kwargs, "choice": choice}


@register.inclusion_tag(WIDGET_TEMPLATES["RADIO"])
def choice_radio_multiple(field, **kwargs):
"""
Display multiple radio inputs that are rendered from a choice field.
Args:
choice: the choice to be rendered
name: the name of the form field
data: the value of a form field field
index: the index of a for-loop when looping over choices
initial: the initial value of the field
icon_class: the icon to be displayed at the top of the
radio stack
Usage:
{% choice_radio_multiple form.radio_field %}
Variables:
+ field: The field that needs to be rendered.
{% choice_radio_stacked choice=choice name=field.name ... icon_class=choice.1|get_icon_class %}
"""
return {**kwargs, "field": field}
return {**kwargs, "choice": choice}


@register.inclusion_tag("components/Form/Input.html")
Expand Down
2 changes: 1 addition & 1 deletion src/open_inwoner/openklant/api_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class Klant(ZGWModel):
achternaam: str = ""
telefoonnummer: str = ""
emailadres: str = ""
toestemmingZaakNotificatiesAlleenDigitaal: bool = False
toestemmingZaakNotificatiesAlleenDigitaal: bool | None = None

def get_name_display(self):
return " ".join(
Expand Down

0 comments on commit 1992d6a

Please sign in to comment.