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

[#1842] Modify profile template for busines users #864

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/open_inwoner/accounts/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ def __init__(self, user, *args, **kwargs):
self.fields["infix"].required = False
self.fields["last_name"].required = True

if user.is_digid_and_brp():
if user.is_digid_user_with_brp:
self.fields["first_name"].disabled = True
self.fields["infix"].disabled = True
self.fields["last_name"].disabled = True
Expand Down
11 changes: 8 additions & 3 deletions src/open_inwoner/accounts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ def get_active_notifications(self) -> str:
def require_necessary_fields(self) -> bool:
"""returns whether user needs to fill in necessary fields"""
if (
self.is_digid_and_brp()
self.is_digid_user_with_brp
and self.email
and not self.email.endswith("@example.org")
):
Expand Down Expand Up @@ -427,12 +427,17 @@ def get_plan_contact_new_count(self):
def clear_plan_contact_new_count(self):
PlanContact.objects.filter(user=self).update(notify_new=False)

def is_digid_and_brp(self) -> bool:
@property
def is_digid_user(self) -> bool:
return self.login_type == LoginTypeChoices.digid

@property
def is_digid_user_with_brp(self) -> bool:
"""
Returns whether user is logged in with digid and data has
been requested from haal centraal
"""
return self.login_type == LoginTypeChoices.digid and self.is_prepopulated
return self.is_digid_user and self.is_prepopulated


class Document(models.Model):
Expand Down
5 changes: 5 additions & 0 deletions src/open_inwoner/accounts/tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ class DigidUserFactory(UserFactory):
is_prepopulated = True


class KvKUserFactory(UserFactory):
login_type = LoginTypeChoices.eherkenning
kvk = "12345678"


class TokenFactory(factory.django.DjangoModelFactory):
class Meta:
model = "authtoken.Token"
Expand Down
11 changes: 9 additions & 2 deletions src/open_inwoner/accounts/tests/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import requests_mock
from django_webtest import WebTest
from furl import furl
from pyquery import PyQuery as PQ

from open_inwoner.configurations.models import SiteConfiguration
from open_inwoner.haalcentraal.tests.mixins import HaalCentraalMixin
Expand Down Expand Up @@ -1340,14 +1341,20 @@ def test_password_change_form_done_custom_template_is_rendered(self):

def test_password_change_button_is_rendered_with_default_login_type(self):
response = self.app.get(reverse("profile:detail"), user=self.user)
self.assertContains(response, _("Wijzig wachtwoord"))

doc = PQ(response.content)
link = doc.find("[aria-label='Wachtwoord']")[0]
self.assertTrue(doc(link).is_("a"))

def test_password_change_button_is_not_rendered_with_digid_login_type(self):
digid_user = UserFactory(
login_type=LoginTypeChoices.digid, email="[email protected]"
)
response = self.app.get(reverse("profile:detail"), user=digid_user)
self.assertNotContains(response, _("Wijzig wachtwoord"))

doc = PQ(response.content)
links = doc.find("[aria-label='Wachtwoord']")
self.assertEqual(len(links), 0)

def test_anonymous_user_is_redirected_to_login_page_if_password_change_is_accessed(
self,
Expand Down
74 changes: 61 additions & 13 deletions src/open_inwoner/accounts/tests/test_profile_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import requests_mock
from cms import api
from django_webtest import WebTest
from pyquery import PyQuery as PQ
from timeline_logger.models import TimelineLog
from webtest import Upload

Expand All @@ -28,7 +29,13 @@
from ..choices import ContactTypeChoices, LoginTypeChoices
from ..forms import BrpUserForm, UserForm
from ..models import User
from .factories import ActionFactory, DigidUserFactory, DocumentFactory, UserFactory
from .factories import (
ActionFactory,
DigidUserFactory,
DocumentFactory,
KvKUserFactory,
UserFactory,
)


@override_settings(ROOT_URLCONF="open_inwoner.cms.tests.urls")
Expand Down Expand Up @@ -60,25 +67,31 @@ def test_login_required(self):
def test_user_information_profile_page(self):
response = self.app.get(self.url, user=self.user)

self.assertContains(response, self.user.get_full_name())
self.assertContains(response, self.user.first_name)
self.assertContains(response, self.user.last_name)
self.assertContains(response, self.user.infix)
self.assertContains(response, self.user.email)
self.assertContains(response, self.user.phonenumber)
self.assertContains(response, self.user.get_address())
self.assertContains(response, self.user.street)
self.assertContains(response, self.user.housenumber)
self.assertContains(response, self.user.city)

# check business profile section not displayed
self.assertNotContains(response, "Bedrijfsgegevens")

def test_get_empty_profile_page(self):
response = self.app.get(self.url, user=self.user)

self.assertEquals(response.status_code, 200)
self.assertContains(response, _("U heeft nog geen contacten."))
self.assertContains(response, "0 acties staan open.")
self.assertContains(response, _("U heeft nog geen contacten"))
self.assertContains(response, "0 acties staan open")
self.assertNotContains(response, reverse("products:questionnaire_list"))
self.assertContains(response, _("messages, plans"))

def test_get_filled_profile_page(self):
ActionFactory(created_by=self.user)
contact = UserFactory()
self.user.user_contacts.add(contact)
category = CategoryFactory()
CategoryFactory()
QuestionnaireStepFactory(published=True)

response = self.app.get(self.url, user=self.user)
Expand All @@ -87,14 +100,13 @@ def test_get_filled_profile_page(self):
response,
f"{contact.first_name} ({contact.get_contact_type_display()})",
)
self.assertContains(response, "1 acties staan open.")
self.assertContains(response, "1 acties staan open")
self.assertContains(response, reverse("products:questionnaire_list"))

def test_only_open_actions(self):
action = ActionFactory(created_by=self.user, status=StatusChoices.closed)
ActionFactory(created_by=self.user, status=StatusChoices.closed)
response = self.app.get(self.url, user=self.user)
self.assertEquals(response.status_code, 200)
self.assertContains(response, "0 acties staan open.")
self.assertIn("0 acties staan open", response)

def test_mydata_shown_with_digid_and_brp(self):
user = UserFactory(
Expand All @@ -107,6 +119,9 @@ def test_mydata_shown_with_digid_and_brp(self):
response = self.app.get(self.url, user=user)
self.assertContains(response, _("My details"))

# check business profile section not displayed
self.assertNotContains(response, "Bedrijfsgegevens")

def test_mydata_not_shown_with_digid_and_no_brp(self):
user = UserFactory(
bsn="999993847",
Expand All @@ -122,9 +137,42 @@ def test_mydata_not_shown_without_digid(self):
response = self.app.get(self.url, user=self.user)
self.assertNotContains(response, _("My details"))

def test_business_info_kvk_user(self):
user = KvKUserFactory(
company_name="Makers and Shakers",
street="Fantasiestraat",
housenumber="42",
postcode="1789XY",
city="The good place",
)
response = self.app.get(self.url, user=user)

self.assertContains(response, "Makers and Shakers")
self.assertContains(response, "Fantasiestraat 42")
self.assertContains(response, "1789 XY The good place")

doc = PQ(response.content)

business_section = doc.find("#business-overview")[0]
self.assertEqual(business_section.text, "Bedrijfsgegevens")

# check personal overview section not displayed
personal_section = doc.find("#personal-overview")
self.assertEqual(personal_section, [])

def test_active_user_notifications_are_shown(self):
response = self.app.get(self.url, user=self.user)
self.assertContains(response, _("messages, plans"))
user = UserFactory(
bsn="999993847",
first_name="name",
last_name="surname",
is_prepopulated=False,
login_type=LoginTypeChoices.digid,
messages_notifications=True,
plans_notifications=True,
cases_notifications=False,
)
response = self.app.get(self.url, user=user)
self.assertContains(response, _("Mijn Berichten, Samenwerken"))

def test_expected_message_is_shown_when_all_notifications_disabled(self):
self.user.cases_notifications = False
Expand Down
73 changes: 48 additions & 25 deletions src/open_inwoner/accounts/views/profile.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from datetime import date, datetime
from typing import Generator, Union

from django.conf import settings
from django.contrib import messages
Expand Down Expand Up @@ -48,6 +49,23 @@ class MyProfileView(
def crumbs(self):
return [(_("Mijn profiel"), reverse("profile:detail"))]

@staticmethod
def stringify(
items: list, string_func: callable, lump: bool = False
) -> Union[Generator, str]:
"""
Create string representation(s) of `items` for display

:param string_func: the function used to stringify elements in `items`
:param lump: if `True`, `string_func` is applied to `items` collectively
:returns: a `Generator` of strings representing elements in `items`, or a
`str` representing `items` as a whole, depending on whether `lump` is
`True`
"""
if lump:
return string_func(items)
return (string_func(item) for item in items)

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
user = self.request.user
Expand All @@ -60,39 +78,44 @@ def get_context_data(self, **kwargs):

user_files = user.get_all_files()

# List of names of 'mentor' users that are a contact of me
mentor_contacts = [
c.get_full_name()
for c in user.user_contacts.filter(
contact_type=ContactTypeChoices.begeleider
)
]

# Mentor contacts + names for display
mentor_contacts = user.user_contacts.filter(
contact_type=ContactTypeChoices.begeleider
)
context["mentor_contacts"] = mentor_contacts
context["mentor_contact_names"] = self.stringify(
mentor_contacts,
string_func=lambda m: m.get_full_name,
)

# Regular contacts + names for display
contacts = user.get_active_contacts()
context["contact_names"] = self.stringify(
contacts,
string_func=lambda c: f"{c.first_name} ({c.get_contact_type_display()})",
)

# Actions
actions = (
Action.objects.visible()
.connected(self.request.user)
.filter(status=StatusChoices.open)
)
context["action_text"] = self.stringify(
actions,
string_func=lambda actions: f"{actions.count()} acties staan open",
lump=True,
)

context["next_action"] = (
Action.objects.visible()
.connected(self.request.user)
.filter(end_date__gte=today, status=StatusChoices.open)
.order_by("end_date")
.first()
)
context["files"] = user_files
context["action_text"] = _(
f"{Action.objects.visible().connected(self.request.user).filter(status=StatusChoices.open).count()} acties staan open."
)
contacts = user.get_active_contacts()
# Invited contacts
contact_names = [
f"{contact.first_name} ({contact.get_contact_type_display()})"
for contact in contacts[:3]
]

if contacts.count() > 0:
context[
"contact_text"
] = f"{', '.join(contact_names)}{'...' if contacts.count() > 3 else ''}"
else:
context["contact_text"] = _("U heeft nog geen contacten.")
context["files"] = user_files

context["questionnaire_exists"] = QuestionnaireStep.objects.filter(
published=True
Expand Down Expand Up @@ -183,7 +206,7 @@ def update_klant_api(self, user_form_data: dict):

def get_form_class(self):
user = self.request.user
if user.is_digid_and_brp():
if user.is_digid_user_with_brp:
return BrpUserForm
return super().get_form_class()

Expand Down
2 changes: 1 addition & 1 deletion src/open_inwoner/components/templatetags/dashboard_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def case_dashboard(case: dict, **kwargs) -> dict:
"value": case.get("start_date"),
},
{
"label": _("Verwachte uitslag:"),
"label": _("Beslissing op zijn laatst:"),
"value": case.get("end_date_legal"),
},
]
Expand Down
8 changes: 4 additions & 4 deletions src/open_inwoner/configurations/tests/test_show_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,17 @@ def test_default_enabled(self):
def test_when_enabled_and_user_is_logged_in(self):
response = self.app.get(self.profile_url, user=self.user)

links = response.pyquery(".personal-overview")
self.assertNotEqual(links.find(".personal-overview__actions"), [])
links = response.pyquery(".profile-section")
self.assertNotEqual(links.find("#profile-section-actions"), [])
self.assertNotEqual(links.find(f'a[href="{self.actions_list_url}"]'), [])

def test_when_disabled_and_user_is_logged_in(self):
self.profile_config.actions = False
self.profile_config.save()
response = self.app.get(self.profile_url, user=self.user)

links = response.pyquery(".personal-overview")
self.assertEqual(links.find(".personal-overview__actions"), [])
links = response.pyquery(".profile-section")
self.assertEqual(links.find("#profile-section-actions"), [])
self.assertEqual(links.find(f'a[href="{self.actions_list_url}"]'), [])

def test_action_pages_show_404_when_disabled(self):
Expand Down
2 changes: 1 addition & 1 deletion src/open_inwoner/scss/components/List/_List.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
overflow-y: auto;

.case-list,
.contactmomenten-list {
.contactmomenten-list .profile-list {
text-decoration: none;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
.personal-overview {
.profile-section {
h2,
.h2 {
margin: var(--row-height) 0 0 0;
margin: calc(var(--row-height) * 1.5) 0 0 0;
}
}

#title {
padding-bottom: var(--spacing-medium);
}
Loading
Loading