diff --git a/app/__init__.py b/app/__init__.py index 436fae237..d79d7cd93 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -46,6 +46,7 @@ from app.extensions import ( statsd_client, zendesk_client, ) +from app.models.organisation import Organisation from app.models.service import Service from app.models.user import AnonymousUser from app.navigation import ( @@ -502,7 +503,7 @@ def load_organisation_before_request(): if org_id: try: - _request_ctx_stack.top.organisation = organisations_client.get_organisation(org_id) + _request_ctx_stack.top.organisation = Organisation.from_id(org_id) except HTTPError as exc: # if org id isn't real, then 404 rather than 500ing later because we expect org to be set if exc.status_code == 404: diff --git a/app/main/views/organisations.py b/app/main/views/organisations.py index 4c7fc391f..58c8e3b48 100644 --- a/app/main/views/organisations.py +++ b/app/main/views/organisations.py @@ -70,17 +70,13 @@ def add_organisation(): @login_required @user_has_permissions() def organisation_dashboard(org_id): - organisation_services = [ - service for service in organisations_client.get_organisation_services(org_id) - if service['active'] and not service['restricted'] - ] - for service in organisation_services: + for service in current_organisation.live_services: has_permission = current_user.has_permission_for_service(service['id'], 'view_activity') service.update({'has_permission_to_view': has_permission}) return render_template( 'views/organisations/organisation/index.html', - organisation_services=organisation_services + organisation_services=current_organisation.live_services ) @@ -88,12 +84,10 @@ def organisation_dashboard(org_id): @login_required @user_is_platform_admin def organisation_trial_mode_services(org_id): - organisation_services = organisations_client.get_organisation_services(org_id) - return render_template( 'views/organisations/organisation/trial-mode-services.html', search_form=SearchByNameForm(), - services=[service for service in organisation_services if not service['active'] or service['restricted']] + services=current_organisation.trial_services ) @@ -101,18 +95,10 @@ def organisation_trial_mode_services(org_id): @login_required @user_has_permissions() def manage_org_users(org_id): - users = sorted( - user_api_client.get_users_for_organisation(org_id=org_id) + [ - invite for invite in org_invite_api_client.get_invites_for_organisation(org_id=org_id) - if invite.status != 'accepted' - ], - key=lambda user: user.email_address, - ) - return render_template( 'views/organisations/organisation/users/index.html', - users=users, - show_search_box=(len(users) > 7), + users=current_organisation.team_members, + show_search_box=(len(current_organisation.team_members) > 7), form=SearchUsersForm(), ) @@ -199,16 +185,16 @@ def organisation_settings(org_id): email_branding = 'GOV.UK' - if current_organisation['email_branding_id']: + if current_organisation.email_branding_id: email_branding = email_branding_client.get_email_branding( - current_organisation['email_branding_id'] + current_organisation.email_branding_id )['email_branding']['name'] letter_branding = None - if current_organisation['letter_branding_id']: + if current_organisation.letter_branding_id: letter_branding = letter_branding_client.get_letter_branding( - current_organisation['letter_branding_id'] + current_organisation.letter_branding_id )['name'] return render_template( @@ -225,7 +211,7 @@ def edit_organisation_name(org_id): form = RenameOrganisationForm() if request.method == 'GET': - form.name.data = current_organisation.get('name') + form.name.data = current_organisation.name if form.validate_on_submit(): unique_name = organisations_client.is_organisation_name_unique(org_id, form.name.data) @@ -248,12 +234,12 @@ def edit_organisation_name(org_id): def edit_organisation_type(org_id): form = OrganisationOrganisationTypeForm( - organisation_type=current_organisation['organisation_type'] + organisation_type=current_organisation.organisation_type ) if form.validate_on_submit(): organisations_client.update_organisation( - current_organisation['id'], + current_organisation.id, organisation_type=form.organisation_type.data, ) return redirect(url_for('.organisation_settings', org_id=org_id)) @@ -275,12 +261,12 @@ def edit_organisation_crown_status(org_id): True: 'crown', False: 'non-crown', None: 'unknown', - }.get(current_organisation['crown']) + }.get(current_organisation.crown) ) if form.validate_on_submit(): organisations_client.update_organisation( - current_organisation['id'], + current_organisation.id, crown={ 'crown': True, 'non-crown': False, @@ -306,12 +292,12 @@ def edit_organisation_agreement(org_id): True: 'yes', False: 'no', None: 'unknown', - }.get(current_organisation['agreement_signed']) + }.get(current_organisation.agreement_signed) ) if form.validate_on_submit(): organisations_client.update_organisation( - current_organisation['id'], + current_organisation.id, agreement_signed={ 'yes': True, 'no': False, @@ -336,7 +322,7 @@ def edit_organisation_email_branding(org_id): form = SetEmailBranding( all_branding_options=get_branding_as_value_and_label(email_branding), - current_branding=current_organisation['email_branding_id'], + current_branding=current_organisation.email_branding_id, ) if form.validate_on_submit(): @@ -385,7 +371,7 @@ def edit_organisation_letter_branding(org_id): form = SetLetterBranding( all_branding_options=get_branding_as_value_and_label(letter_branding), - current_branding=current_organisation['letter_branding_id'], + current_branding=current_organisation.letter_branding_id, ) if form.validate_on_submit(): @@ -442,7 +428,7 @@ def edit_organisation_domains(org_id): ) return redirect(url_for('.organisation_settings', org_id=org_id)) - form.populate(current_organisation.get('domains', [])) + form.populate(current_organisation.domains) return render_template( 'views/organisations/organisation/settings/edit-domains.html', @@ -463,7 +449,7 @@ def confirm_edit_organisation_name(org_id): if form.validate_on_submit(): try: organisations_client.update_organisation_name( - current_organisation['id'], + current_organisation.id, name=session['organisation_name_change'], ) except HTTPError as e: diff --git a/app/main/views/service_settings.py b/app/main/views/service_settings.py index 95a72cfe8..6089cfa8e 100644 --- a/app/main/views/service_settings.py +++ b/app/main/views/service_settings.py @@ -911,16 +911,16 @@ def request_letter_branding(service_id): @user_is_platform_admin def link_service_to_organisation(service_id): - organisations = organisations_client.get_organisations() - current_organisation = organisations_client.get_service_organisation(service_id).get('id', None) + all_organisations = organisations_client.get_organisations() + current_linked_organisation = organisations_client.get_service_organisation(service_id).get('id', None) form = LinkOrganisationsForm( - choices=convert_dictionary_to_wtforms_choices_format(organisations, 'id', 'name'), - organisations=current_organisation + choices=convert_dictionary_to_wtforms_choices_format(all_organisations, 'id', 'name'), + organisations=current_linked_organisation ) if form.validate_on_submit(): - if form.organisations.data != current_organisation: + if form.organisations.data != current_linked_organisation: organisations_client.update_service_organisation( service_id, form.organisations.data @@ -929,7 +929,7 @@ def link_service_to_organisation(service_id): return render_template( 'views/service-settings/link-service-to-organisation.html', - has_organisations=organisations, + has_organisations=all_organisations, form=form, ) diff --git a/app/models/organisation.py b/app/models/organisation.py index 1335a08e1..df54ec53f 100644 --- a/app/models/organisation.py +++ b/app/models/organisation.py @@ -1,6 +1,8 @@ from flask import Markup, abort +from werkzeug.utils import cached_property from app.models import JSONModel +from app.notify_client.organisations_api_client import organisations_client class Organisation(JSONModel): @@ -21,6 +23,10 @@ class Organisation(JSONModel): 'request_to_go_live_notes', } + @classmethod + def from_id(cls, org_id): + return cls(organisations_client.get_organisation(org_id)) + def __init__(self, _dict): super().__init__(_dict) @@ -111,3 +117,34 @@ class Organisation(JSONModel): if self.crown is None: abort(404) return self.crown + + @cached_property + def services(self): + return organisations_client.get_organisation_services(self.id) + + @property + def live_services(self): + return [s for s in self.services if s['active'] and not s['restricted']] + + @property + def trial_services(self): + return [s for s in self.services if not s['active'] or s['restricted']] + + @cached_property + def active_users(self): + # need to put this here to prevent cyclical import + from app.notify_client.user_api_client import user_api_client + return user_api_client.get_users_for_organisation(org_id=self.id) + + @cached_property + def invited_users(self): + # need to put this here to prevent cyclical import + from app.notify_client.org_invite_api_client import org_invite_api_client + return org_invite_api_client.get_invites_for_organisation(org_id=self.id) + + @cached_property + def team_members(self): + return sorted( + self.active_users + [i for i in self.invited_users if i.status != 'accepted'], + key=lambda user: user.email_address, + ) diff --git a/tests/app/main/views/organisations/test_organisation.py b/tests/app/main/views/organisations/test_organisation.py index 261dfb8ff..e3c2964c6 100644 --- a/tests/app/main/views/organisations/test_organisation.py +++ b/tests/app/main/views/organisations/test_organisation.py @@ -118,7 +118,7 @@ def test_organisation_services_shows_live_services_only( assert services[1].find('a')['href'] == url_for('main.service_dashboard', service_id=SERVICE_ONE_ID) -def test_organisation_trial_mode_services_shows_all_services( +def test_organisation_trial_mode_services_shows_all_non_live_services( client_request, platform_admin_user, mock_get_organisation, @@ -130,7 +130,7 @@ def test_organisation_trial_mode_services_shows_all_services( return_value=[ service_json(id_='1', name='1', restricted=False, active=True), # live service_json(id_='2', name='2', restricted=True, active=True), # trial - service_json(id_='3', name='3', restricted=True, active=False), # archived + service_json(id_='3', name='3', restricted=False, active=False), # archived ] )