Skip to content

Commit 9f34b19

Browse files
authored
Merge pull request #1173 from NHSDigital/12455-fix-role-change-caching
Fix stale role cache after UserAssignment change
2 parents 06a0adf + 73ae96f commit 9f34b19

2 files changed

Lines changed: 97 additions & 7 deletions

File tree

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
from datetime import datetime, timezone
2+
from zoneinfo import ZoneInfo
3+
4+
import pytest
5+
from django.urls import reverse
6+
from playwright.sync_api import expect
7+
8+
from manage_breast_screening.auth.models import Role
9+
from manage_breast_screening.clinics.models import Clinic
10+
from manage_breast_screening.clinics.tests.factories import ClinicFactory
11+
from manage_breast_screening.participants.models.appointment import (
12+
AppointmentStatusNames,
13+
)
14+
from manage_breast_screening.participants.tests.factories import AppointmentFactory
15+
16+
from ..system_test_setup import SystemTestCase
17+
18+
19+
class TestRoleChangePermissions(SystemTestCase):
20+
@pytest.fixture(autouse=True)
21+
def before(self):
22+
today = datetime.now(timezone.utc).replace(hour=9, minute=0)
23+
self.clinic_start_time = today
24+
25+
def test_changing_role_to_clinical_grants_ability_to_start_appointments(self):
26+
self.given_i_am_logged_in_as_an_administrative_user()
27+
self.and_a_clinic_exists_that_is_run_by_my_provider()
28+
self.and_there_are_appointments()
29+
self.and_i_am_on_the_clinic_show_page()
30+
31+
self.then_the_scheduled_appointment_row_has_a_check_in_button()
32+
self.then_the_checked_in_appointment_row_has_no_start_appointment_button()
33+
34+
self.when_my_role_is_changed_to_clinical()
35+
self.and_i_am_on_the_clinic_show_page()
36+
37+
self.then_the_checked_in_appointment_row_has_a_start_appointment_button()
38+
39+
def and_a_clinic_exists_that_is_run_by_my_provider(self):
40+
user_assignment = self.current_user.assignments.first()
41+
self.clinic = ClinicFactory(
42+
starts_at=self.clinic_start_time,
43+
setting__provider=user_assignment.provider,
44+
risk_type=Clinic.RiskType.ROUTINE_RISK,
45+
)
46+
47+
def and_there_are_appointments(self):
48+
tzinfo = ZoneInfo("Europe/London")
49+
AppointmentFactory(
50+
clinic_slot__clinic=self.clinic,
51+
starts_at=datetime.now().replace(hour=9, minute=0, tzinfo=tzinfo),
52+
current_status=AppointmentStatusNames.SCHEDULED,
53+
first_name="Janet",
54+
last_name="Scheduled",
55+
)
56+
AppointmentFactory(
57+
clinic_slot__clinic=self.clinic,
58+
starts_at=datetime.now().replace(hour=9, minute=15, tzinfo=tzinfo),
59+
current_status=AppointmentStatusNames.CHECKED_IN,
60+
first_name="Janet",
61+
last_name="CheckedIn",
62+
)
63+
64+
def and_i_am_on_the_clinic_show_page(self):
65+
self.page.goto(
66+
self.live_server_url
67+
+ reverse("clinics:show_clinic", kwargs={"pk": self.clinic.pk})
68+
)
69+
70+
def _appointment_row(self, last_name):
71+
return self.page.locator(".nhsuk-table__row").filter(has_text=last_name)
72+
73+
def then_the_scheduled_appointment_row_has_a_check_in_button(self):
74+
row = self._appointment_row("Scheduled")
75+
expect(row.get_by_text("Check in")).to_be_visible()
76+
77+
def then_the_checked_in_appointment_row_has_no_start_appointment_button(self):
78+
row = self._appointment_row("CheckedIn")
79+
expect(row.get_by_text("Start appointment")).to_be_hidden()
80+
81+
def when_my_role_is_changed_to_clinical(self):
82+
assignment = self.current_user.assignments.first()
83+
assignment.roles = [Role.CLINICAL]
84+
assignment.save()
85+
86+
def then_the_checked_in_appointment_row_has_a_start_appointment_button(self):
87+
row = self._appointment_row("CheckedIn")
88+
expect(row.get_by_text("Start appointment")).to_be_visible()

manage_breast_screening/users/models.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from dataclasses import dataclass
2-
from functools import cache
2+
from functools import cached_property
33

44
import rules
55
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
@@ -38,13 +38,15 @@ class User(AbstractBaseUser):
3838
USERNAME_FIELD = "nhs_uid"
3939
REQUIRED_FIELDS = []
4040

41-
@cache
42-
def has_role(self, role):
41+
@cached_property
42+
def _current_provider_roles(self):
4343
if not self.current_provider:
44-
return False
45-
return self.assignments.filter(
46-
provider_id=self.current_provider, roles__contains=[role]
47-
).exists()
44+
return []
45+
assignment = self.assignments.filter(provider=self.current_provider).first()
46+
return assignment.roles if assignment else []
47+
48+
def has_role(self, role):
49+
return role in self._current_provider_roles
4850

4951
@property
5052
def current_provider(self):

0 commit comments

Comments
 (0)