Skip to content

Commit

Permalink
[#1437 #1457] Enhanced contact-form to create/update Klant, or fallba…
Browse files Browse the repository at this point in the history
…ck to appending contact info
  • Loading branch information
Bart van der Schoor committed Jun 8, 2023
1 parent ba9e76c commit 6bac99d
Show file tree
Hide file tree
Showing 7 changed files with 315 additions and 33 deletions.
35 changes: 31 additions & 4 deletions src/open_inwoner/openklant/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from django.forms import Form
from django.utils.translation import gettext_lazy as _

from open_inwoner.accounts.models import User
from open_inwoner.openklant.models import ContactFormSubject, OpenKlantConfig
from open_inwoner.utils.validators import validate_phone_number

Expand Down Expand Up @@ -44,21 +45,47 @@ class ContactForm(Form):
required=True,
)

def __init__(self, *args, **kwargs):
user: User

def __init__(self, user, *args, **kwargs):
super().__init__(*args, **kwargs)
self.user = user

config = OpenKlantConfig.get_solo()
self.fields["subject"].queryset = config.contactformsubject_set.order_by(
"subject"
)

if self.user.is_authenticated:
del self.fields["first_name"]
del self.fields["last_name"]
del self.fields["infix"]
if self.user.email:
del self.fields["email"]
if self.user.phonenumber:
del self.fields["phonenumber"]

def clean(self, *args, **kwargs):
cleaned_data = super().clean(*args, **kwargs)

email = cleaned_data["email"]
phonenumber = cleaned_data["phonenumber"]
email = cleaned_data.get("email", "")
phonenumber = cleaned_data.get("phonenumber", "")

if not email and not phonenumber:
if ("email" in self.fields and not email) and (
"phonenumber" in self.fields and not phonenumber
):
msg = _("Vul een e-mailadres of telefoonnummer in.")
self.add_error("email", msg)
self.add_error("phonenumber", msg)

if self.user.is_authenticated:
if not email and self.user.get_contact_email():
cleaned_data["email"] = self.user.get_contact_email()
if not phonenumber and self.user.phonenumber:
cleaned_data["phonenumber"] = self.user.phonenumber

cleaned_data["first_name"] = self.user.first_name
cleaned_data["infix"] = self.user.infix
cleaned_data["last_name"] = self.user.last_name

return cleaned_data
8 changes: 8 additions & 0 deletions src/open_inwoner/openklant/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
from zgw_consumers.constants import APITypes


class OpenKlantConfigManager(models.Manager):
def get_queryset(self):
qs = super().get_queryset()
return qs.select_related("klanten_service", "contactmomenten_service")


class OpenKlantConfig(SingletonModel):
"""
Global configuration and defaults for Klant & Contactmomenten APIs
Expand Down Expand Up @@ -67,6 +73,8 @@ class OpenKlantConfig(SingletonModel):
"register_employee_id",
)

objects = OpenKlantConfigManager()

class Meta:
verbose_name = _("Open Klant configuration")

Expand Down
27 changes: 26 additions & 1 deletion src/open_inwoner/openklant/tests/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def __init__(self):

self.matchers = []

def install_mocks_anon(self, m) -> "MockAPICreateData":
def install_mocks_anon_with_klant(self, m) -> "MockAPICreateData":
self.setUpOASMocks(m)

self.matchers = [
Expand All @@ -141,6 +141,19 @@ def install_mocks_anon(self, m) -> "MockAPICreateData":
]
return self

def install_mocks_anon_without_klant(self, m) -> "MockAPICreateData":
self.setUpOASMocks(m)

self.matchers = [
m.post(f"{KLANTEN_ROOT}klanten", json=self.klant, status_code=500),
m.post(
f"{CONTACTMOMENTEN_ROOT}contactmomenten",
json=self.contactmoment,
status_code=201,
),
]
return self

def install_mocks_digid(self, m) -> "MockAPICreateData":
self.setUpOASMocks(m)

Expand All @@ -161,3 +174,15 @@ def install_mocks_digid(self, m) -> "MockAPICreateData":
),
]
return self

def install_mocks_digid_no_Klant(self, m) -> "MockAPICreateData":
self.setUpOASMocks(m)

self.matchers = [
m.post(
f"{CONTACTMOMENTEN_ROOT}contactmomenten",
json=self.contactmoment,
status_code=201,
),
]
return self
146 changes: 133 additions & 13 deletions src/open_inwoner/openklant/tests/test_contactform.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import inspect

from django.contrib import messages
from django.core import mail
from django.urls import reverse
Expand All @@ -6,16 +8,23 @@
import requests_mock
from django_webtest import WebTest

from open_inwoner.accounts.tests.factories import DigidUserFactory
from open_inwoner.openklant.models import ContactFormSubject, OpenKlantConfig
from open_inwoner.accounts.tests.factories import UserFactory
from open_inwoner.openklant.models import OpenKlantConfig
from open_inwoner.openklant.tests.data import MockAPICreateData
from open_inwoner.openklant.tests.factories import ContactFormSubjectFactory
from open_inwoner.openzaak.tests.factories import ServiceFactory
from open_inwoner.utils.test import ClearCachesMixin, DisableRequestLogMixin
from open_inwoner.utils.tests.helpers import AssertFormMixin, AssertTimelineLogMixin


@requests_mock.Mocker()
class ContactFormTestCase(ClearCachesMixin, DisableRequestLogMixin, WebTest):
class ContactFormTestCase(
ClearCachesMixin,
AssertTimelineLogMixin,
AssertFormMixin,
DisableRequestLogMixin,
WebTest,
):
@classmethod
def setUpTestData(cls):
super().setUpTestData()
Expand Down Expand Up @@ -68,14 +77,26 @@ def test_no_form_shown_if_not_has_configuration(self, m):
self.assertContains(response, _("Contact formulier niet geconfigureerd."))
self.assertEqual(0, len(response.pyquery("#contactmoment-form")))

def test_form_requires_either_email_or_phonenumber(self, m):
def test_anon_form_requires_either_email_or_phonenumber(self, m):
config = OpenKlantConfig.get_solo()
config.register_email = "example@example.com"
config.save()
subject = ContactFormSubjectFactory(config=config)

response = self.app.get(self.url)
form = response.forms["contactmoment-form"]
self.assertFormExactFields(
form,
(
"subject",
"first_name",
"infix",
"last_name",
"email",
"phonenumber",
"question",
),
)
form["subject"].select(text=subject.subject)
form["first_name"] = "Foo"
form["last_name"] = "Bar"
Expand All @@ -88,6 +109,28 @@ def test_form_requires_either_email_or_phonenumber(self, m):
response.context["errors"], [_("Vul een e-mailadres of telefoonnummer in.")]
)

def test_regular_auth_form_fills_email_and_phonenumber(self, m):
config = OpenKlantConfig.get_solo()
config.register_email = "example@example.com"
config.save()
subject = ContactFormSubjectFactory(config=config)

user = UserFactory()

response = self.app.get(self.url, user=user)
form = response.forms["contactmoment-form"]
self.assertFormExactFields(
form,
(
"subject",
"question",
),
)
form["subject"].select(text=subject.subject)
form["question"] = "hey!\n\nwaddup?"

response = form.submit(status=302)

def test_submit_and_register_via_email(self, m):
config = OpenKlantConfig.get_solo()
config.register_email = "example@example.com"
Expand Down Expand Up @@ -123,7 +166,9 @@ def test_submit_and_register_via_email(self, m):
self.assertIn("0612345678", email.body)
self.assertIn("hey!\n\nwaddup?", email.body)

def test_submit_and_register_anon_via_api(self, m):
self.assertTimelineLog("registered contactmoment by email")

def test_submit_and_register_anon_via_api_with_klant(self, m):
MockAPICreateData.setUpServices()

config = OpenKlantConfig.get_solo()
Expand All @@ -134,9 +179,9 @@ def test_submit_and_register_anon_via_api(self, m):
config.save()

data = MockAPICreateData()
data.install_mocks_anon(m)
data.install_mocks_anon_with_klant(m)

subject = ContactFormSubjectFactory(config=config, subject="Vraag")
subject = ContactFormSubjectFactory(config=config, subject="Aanvraag document")

response = self.app.get(self.url)
form = response.forms["contactmoment-form"]
Expand Down Expand Up @@ -178,7 +223,7 @@ def test_submit_and_register_anon_via_api(self, m):
{
"medewerkerIdentificatie": {"identificatie": "FooVonBar"},
"bronorganisatie": "123456789",
"tekst": f"Vraag\n\nhey!\n\nwaddup?",
"tekst": f"Aanvraag document\n\nhey!\n\nwaddup?",
"type": "Melding",
"kanaal": "Internet",
},
Expand All @@ -191,8 +236,10 @@ def test_submit_and_register_anon_via_api(self, m):
"klant": "https://klanten.nl/api/v1/klant/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
},
)
self.assertTimelineLog("created klant for anonymous user")
self.assertTimelineLog("registered contactmoment by API")

def test_submit_and_register_bsn_user_via_api(self, m):
def test_submit_and_register_anon_via_api_without_klant(self, m):
MockAPICreateData.setUpServices()

config = OpenKlantConfig.get_solo()
Expand All @@ -203,11 +250,11 @@ def test_submit_and_register_bsn_user_via_api(self, m):
config.save()

data = MockAPICreateData()
data.install_mocks_digid(m)
data.install_mocks_anon_without_klant(m)

subject = ContactFormSubjectFactory(config=config, subject="Vraag")
subject = ContactFormSubjectFactory(config=config, subject="Aanvraag document")

response = self.app.get(self.url, user=data.user)
response = self.app.get(self.url)
form = response.forms["contactmoment-form"]
form["subject"].select(text=subject.subject)
form["first_name"] = "Foo"
Expand All @@ -226,6 +273,76 @@ def test_submit_and_register_bsn_user_via_api(self, m):

self.assertEqual(len(mail.outbox), 0)

for m in data.matchers:
self.assertTrue(m.called_once, str(m))

contactmoment_create_data = data.matchers[1].request_history[0].json()

text = inspect.cleandoc(
"""
Aanvraag document
hey!
waddup?
Naam: Foo de Bar
Email: foo@example.com
Telefoonnummer: 0612345678
"""
)

self.assertEqual(
contactmoment_create_data,
{
"medewerkerIdentificatie": {"identificatie": "FooVonBar"},
"bronorganisatie": "123456789",
"tekst": text,
"type": "Melding",
"kanaal": "Internet",
},
)
self.assertTimelineLog(
"could not retrieve or create klant for user, appended info to message"
)
self.assertTimelineLog("registered contactmoment by API")

def test_submit_and_register_bsn_user_via_api(self, m):
MockAPICreateData.setUpServices()

config = OpenKlantConfig.get_solo()
config.register_contact_moment = True
config.register_bronorganisatie_rsin = "123456789"
config.register_type = "Melding"
config.register_employee_id = "FooVonBar"
config.save()

data = MockAPICreateData()
data.install_mocks_digid(m)

subject = ContactFormSubjectFactory(config=config, subject="Aanvraag document")

response = self.app.get(self.url, user=data.user)
form = response.forms["contactmoment-form"]
self.assertFormExactFields(
form,
(
"subject",
"question",
),
)
form["subject"].select(text=subject.subject)
form["question"] = "hey!\n\nwaddup?"

response = form.submit().follow()

msgs = list(response.context["messages"])
self.assertEqual(len(msgs), 1)
self.assertEqual(str(msgs[0]), _("Vraag verstuurd!"))
self.assertEqual(msgs[0].level, messages.SUCCESS)

self.assertEqual(len(mail.outbox), 0)

for m in data.matchers:
self.assertTrue(m.called_once, str(m))

Expand All @@ -235,7 +352,7 @@ def test_submit_and_register_bsn_user_via_api(self, m):
{
"medewerkerIdentificatie": {"identificatie": "FooVonBar"},
"bronorganisatie": "123456789",
"tekst": f"Vraag\n\nhey!\n\nwaddup?",
"tekst": f"Aanvraag document\n\nhey!\n\nwaddup?",
"type": "Melding",
"kanaal": "Internet",
},
Expand All @@ -248,3 +365,6 @@ def test_submit_and_register_bsn_user_via_api(self, m):
"klant": "https://klanten.nl/api/v1/klant/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
},
)

self.assertTimelineLog("retrieved klant for BSN-user")
self.assertTimelineLog("registered contactmoment by API")
Loading

0 comments on commit 6bac99d

Please sign in to comment.