2018-02-21 16:39:17 +00:00
|
|
|
import uuid
|
2021-03-10 13:55:06 +00:00
|
|
|
from datetime import datetime
|
2018-02-21 16:39:17 +00:00
|
|
|
|
2018-03-06 12:49:46 +00:00
|
|
|
import pytest
|
2022-04-08 17:39:55 +01:00
|
|
|
from flask import current_app
|
2020-02-25 17:34:03 +00:00
|
|
|
from freezegun import freeze_time
|
2021-04-06 13:42:18 +01:00
|
|
|
from sqlalchemy.exc import SQLAlchemyError
|
2018-03-06 12:49:46 +00:00
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
from app.dao.organization_dao import (
|
|
|
|
|
dao_add_service_to_organization,
|
|
|
|
|
dao_add_user_to_organization,
|
2021-03-10 13:55:06 +00:00
|
|
|
)
|
2021-01-12 09:44:35 +00:00
|
|
|
from app.dao.services_dao import dao_archive_service
|
2023-07-10 11:06:29 -07:00
|
|
|
from app.models import AnnualBilling, Organization
|
2019-03-20 14:14:19 +00:00
|
|
|
from tests.app.db import (
|
2021-03-10 13:55:06 +00:00
|
|
|
create_annual_billing,
|
2019-03-20 14:14:19 +00:00
|
|
|
create_domain,
|
|
|
|
|
create_email_branding,
|
2021-03-10 13:55:06 +00:00
|
|
|
create_ft_billing,
|
2023-07-10 11:06:29 -07:00
|
|
|
create_organization,
|
2019-03-20 14:14:19 +00:00
|
|
|
create_service,
|
2020-02-24 17:02:25 +00:00
|
|
|
create_template,
|
2021-03-10 13:55:06 +00:00
|
|
|
create_user,
|
2019-03-20 14:14:19 +00:00
|
|
|
)
|
2018-02-08 14:54:08 +00:00
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_get_all_organizations(admin_request, notify_db_session):
|
|
|
|
|
create_organization(name='inactive org', active=False, organization_type='federal')
|
|
|
|
|
create_organization(name='active org', domains=['example.com'])
|
2018-02-08 14:54:08 +00:00
|
|
|
|
|
|
|
|
response = admin_request.get(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.get_organizations',
|
2018-02-08 14:54:08 +00:00
|
|
|
_expected_status=200
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert len(response) == 2
|
2019-09-05 16:04:14 +01:00
|
|
|
assert set(response[0].keys()) == set(response[1].keys()) == {
|
|
|
|
|
'name',
|
|
|
|
|
'id',
|
|
|
|
|
'active',
|
|
|
|
|
'count_of_live_services',
|
|
|
|
|
'domains',
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization_type',
|
2019-09-05 16:04:14 +01:00
|
|
|
}
|
2018-02-08 14:54:08 +00:00
|
|
|
assert response[0]['name'] == 'active org'
|
|
|
|
|
assert response[0]['active'] is True
|
2019-06-12 13:15:25 +01:00
|
|
|
assert response[0]['count_of_live_services'] == 0
|
2019-06-13 15:54:57 +01:00
|
|
|
assert response[0]['domains'] == ['example.com']
|
2023-07-10 11:06:29 -07:00
|
|
|
assert response[0]['organization_type'] is None
|
2018-02-08 14:54:08 +00:00
|
|
|
assert response[1]['name'] == 'inactive org'
|
|
|
|
|
assert response[1]['active'] is False
|
2019-06-12 13:15:25 +01:00
|
|
|
assert response[1]['count_of_live_services'] == 0
|
2019-06-13 15:54:57 +01:00
|
|
|
assert response[1]['domains'] == []
|
2023-07-10 11:06:29 -07:00
|
|
|
assert response[1]['organization_type'] == 'federal'
|
2018-02-08 14:54:08 +00:00
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_get_organization_by_id(admin_request, notify_db_session):
|
|
|
|
|
org = create_organization()
|
2018-02-08 14:54:08 +00:00
|
|
|
|
|
|
|
|
response = admin_request.get(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.get_organization_by_id',
|
2018-02-08 14:54:08 +00:00
|
|
|
_expected_status=200,
|
2023-07-10 11:06:29 -07:00
|
|
|
organization_id=org.id
|
2018-02-08 14:54:08 +00:00
|
|
|
)
|
|
|
|
|
|
2019-02-19 11:47:30 +00:00
|
|
|
assert set(response.keys()) == {
|
|
|
|
|
'id',
|
|
|
|
|
'name',
|
|
|
|
|
'active',
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization_type',
|
2019-02-19 11:47:30 +00:00
|
|
|
'agreement_signed',
|
|
|
|
|
'agreement_signed_at',
|
|
|
|
|
'agreement_signed_by_id',
|
|
|
|
|
'agreement_signed_version',
|
2019-06-13 16:43:34 +01:00
|
|
|
'agreement_signed_on_behalf_of_name',
|
|
|
|
|
'agreement_signed_on_behalf_of_email_address',
|
2019-02-19 11:47:30 +00:00
|
|
|
'email_branding_id',
|
2019-03-20 11:56:17 +00:00
|
|
|
'domains',
|
2019-05-10 11:47:42 +01:00
|
|
|
'request_to_go_live_notes',
|
2019-06-12 13:15:25 +01:00
|
|
|
'count_of_live_services',
|
2021-02-04 17:33:46 +00:00
|
|
|
'notes',
|
|
|
|
|
'billing_contact_names',
|
|
|
|
|
'billing_contact_email_addresses',
|
|
|
|
|
'billing_reference',
|
|
|
|
|
'purchase_order_number'
|
2019-02-19 11:47:30 +00:00
|
|
|
}
|
2018-02-08 14:54:08 +00:00
|
|
|
assert response['id'] == str(org.id)
|
|
|
|
|
assert response['name'] == 'test_org_1'
|
|
|
|
|
assert response['active'] is True
|
2023-07-10 11:06:29 -07:00
|
|
|
assert response['organization_type'] is None
|
2019-02-19 11:47:30 +00:00
|
|
|
assert response['agreement_signed'] is None
|
|
|
|
|
assert response['agreement_signed_by_id'] is None
|
|
|
|
|
assert response['agreement_signed_version'] is None
|
|
|
|
|
assert response['email_branding_id'] is None
|
2019-03-20 11:56:17 +00:00
|
|
|
assert response['domains'] == []
|
2019-05-10 11:47:42 +01:00
|
|
|
assert response['request_to_go_live_notes'] is None
|
2019-06-12 13:15:25 +01:00
|
|
|
assert response['count_of_live_services'] == 0
|
2019-06-13 16:43:34 +01:00
|
|
|
assert response['agreement_signed_on_behalf_of_name'] is None
|
|
|
|
|
assert response['agreement_signed_on_behalf_of_email_address'] is None
|
2021-02-04 17:33:46 +00:00
|
|
|
assert response['notes'] is None
|
|
|
|
|
assert response['billing_contact_names'] is None
|
|
|
|
|
assert response['billing_contact_email_addresses'] is None
|
|
|
|
|
assert response['billing_reference'] is None
|
|
|
|
|
assert response['purchase_order_number'] is None
|
2019-03-20 11:56:17 +00:00
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_get_organization_by_id_returns_domains(admin_request, notify_db_session):
|
2019-03-20 11:56:17 +00:00
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
org = create_organization(domains=[
|
2019-06-13 15:54:57 +01:00
|
|
|
'foo.gov.uk',
|
|
|
|
|
'bar.gov.uk',
|
|
|
|
|
])
|
2019-03-20 11:56:17 +00:00
|
|
|
|
|
|
|
|
response = admin_request.get(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.get_organization_by_id',
|
2019-03-20 11:56:17 +00:00
|
|
|
_expected_status=200,
|
2023-07-10 11:06:29 -07:00
|
|
|
organization_id=org.id
|
2019-03-20 11:56:17 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert set(response['domains']) == {
|
|
|
|
|
'foo.gov.uk',
|
|
|
|
|
'bar.gov.uk',
|
|
|
|
|
}
|
2018-02-08 14:54:08 +00:00
|
|
|
|
|
|
|
|
|
2019-04-04 10:13:19 +01:00
|
|
|
@pytest.mark.parametrize('domain, expected_status', (
|
|
|
|
|
('foo.gov.uk', 200),
|
|
|
|
|
('bar.gov.uk', 200),
|
|
|
|
|
('oof.gov.uk', 404),
|
2023-05-25 10:24:49 -07:00
|
|
|
('rab.gov.uk', 200),
|
2019-04-04 10:13:19 +01:00
|
|
|
(None, 400),
|
|
|
|
|
('personally.identifying.information@example.com', 400),
|
|
|
|
|
))
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_get_organization_by_domain(
|
2019-04-04 10:13:19 +01:00
|
|
|
admin_request,
|
|
|
|
|
notify_db_session,
|
|
|
|
|
domain,
|
|
|
|
|
expected_status
|
|
|
|
|
):
|
2023-07-10 11:06:29 -07:00
|
|
|
org = create_organization()
|
|
|
|
|
other_org = create_organization('Other organization')
|
2019-04-04 10:13:19 +01:00
|
|
|
create_domain('foo.gov.uk', org.id)
|
|
|
|
|
create_domain('bar.gov.uk', org.id)
|
|
|
|
|
create_domain('rab.gov.uk', other_org.id)
|
|
|
|
|
|
|
|
|
|
response = admin_request.get(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.get_organization_by_domain',
|
2019-04-04 10:13:19 +01:00
|
|
|
_expected_status=expected_status,
|
|
|
|
|
domain=domain,
|
|
|
|
|
)
|
|
|
|
|
|
2023-05-25 10:24:49 -07:00
|
|
|
if domain == 'rab.gov.uk' and expected_status == 200:
|
|
|
|
|
assert response['id'] == str(other_org.id)
|
|
|
|
|
elif expected_status == 200:
|
2019-04-04 10:13:19 +01:00
|
|
|
assert response['id'] == str(org.id)
|
|
|
|
|
else:
|
|
|
|
|
assert response['result'] == 'error'
|
|
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_post_create_organization(admin_request, notify_db_session):
|
2018-02-08 14:54:08 +00:00
|
|
|
data = {
|
2023-07-10 11:06:29 -07:00
|
|
|
'name': 'test organization',
|
2019-07-03 14:53:20 +01:00
|
|
|
'active': True,
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization_type': 'state',
|
2018-02-08 14:54:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
response = admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.create_organization',
|
2018-02-08 14:54:08 +00:00
|
|
|
_data=data,
|
|
|
|
|
_expected_status=201
|
|
|
|
|
)
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
organizations = Organization.query.all()
|
2018-02-08 14:54:08 +00:00
|
|
|
|
|
|
|
|
assert data['name'] == response['name']
|
|
|
|
|
assert data['active'] == response['active']
|
2023-07-10 11:06:29 -07:00
|
|
|
assert data['organization_type'] == response['organization_type']
|
2019-07-03 14:53:20 +01:00
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
assert len(organizations) == 1
|
2022-04-12 17:18:57 +01:00
|
|
|
# check that for non-nhs orgs, default branding is not set
|
2023-07-10 11:06:29 -07:00
|
|
|
assert organizations[0].email_branding_id is None
|
2018-02-08 14:54:08 +00:00
|
|
|
|
|
|
|
|
|
2022-04-08 17:39:55 +01:00
|
|
|
@pytest.mark.parametrize('org_type', ["nhs_central", "nhs_local", "nhs_gp"])
|
2022-09-26 16:47:57 +00:00
|
|
|
@pytest.mark.skip(reason='Update for TTS')
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_post_create_organization_sets_default_nhs_branding_for_nhs_orgs(
|
2022-04-19 12:25:11 +01:00
|
|
|
admin_request, notify_db_session, nhs_email_branding, org_type
|
2022-04-08 17:39:55 +01:00
|
|
|
):
|
|
|
|
|
data = {
|
2023-07-10 11:06:29 -07:00
|
|
|
'name': 'test organization',
|
2022-04-08 17:39:55 +01:00
|
|
|
'active': True,
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization_type': org_type,
|
2022-04-08 17:39:55 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-12 17:18:57 +01:00
|
|
|
admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.create_organization',
|
2022-04-08 17:39:55 +01:00
|
|
|
_data=data,
|
|
|
|
|
_expected_status=201
|
|
|
|
|
)
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
organizations = Organization.query.all()
|
2022-04-08 17:39:55 +01:00
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
assert len(organizations) == 1
|
|
|
|
|
assert organizations[0].email_branding_id == uuid.UUID(current_app.config['NHS_EMAIL_BRANDING_ID'])
|
2022-04-08 17:39:55 +01:00
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_post_create_organization_existing_name_raises_400(admin_request, sample_organization):
|
2023-07-10 14:21:36 -07:00
|
|
|
organization = Organization.query.all()
|
|
|
|
|
assert len(organization) == 1
|
|
|
|
|
|
2018-02-13 14:47:03 +00:00
|
|
|
data = {
|
2023-07-10 11:06:29 -07:00
|
|
|
'name': sample_organization.name,
|
2019-07-03 14:53:20 +01:00
|
|
|
'active': True,
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization_type': 'federal',
|
2018-02-13 14:47:03 +00:00
|
|
|
}
|
|
|
|
|
|
2018-02-19 14:33:44 +00:00
|
|
|
response = admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.create_organization',
|
2018-02-19 14:33:44 +00:00
|
|
|
_data=data,
|
|
|
|
|
_expected_status=400
|
|
|
|
|
)
|
2018-02-13 14:47:03 +00:00
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
organization = Organization.query.all()
|
2018-02-13 14:47:03 +00:00
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
assert len(organization) == 1
|
|
|
|
|
assert response['message'] == 'Organization name already exists'
|
2018-02-13 14:47:03 +00:00
|
|
|
|
|
|
|
|
|
2023-07-10 14:21:36 -07:00
|
|
|
def test_post_create_organization_works(admin_request, sample_organization):
|
|
|
|
|
organization = Organization.query.all()
|
|
|
|
|
assert len(organization) == 1
|
|
|
|
|
|
|
|
|
|
data = {
|
|
|
|
|
'name': "org 2",
|
|
|
|
|
'active': True,
|
|
|
|
|
'organization_type': 'federal',
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
admin_request.post(
|
|
|
|
|
'organization.create_organization',
|
|
|
|
|
_data=data,
|
|
|
|
|
_expected_status=201
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
organization = Organization.query.all()
|
|
|
|
|
|
|
|
|
|
assert len(organization) == 2
|
|
|
|
|
|
|
|
|
|
|
2019-07-03 14:53:20 +01:00
|
|
|
@pytest.mark.parametrize('data, expected_error', (
|
|
|
|
|
({
|
|
|
|
|
'active': False,
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization_type': 'federal',
|
2019-07-03 14:53:20 +01:00
|
|
|
}, 'name is a required property'),
|
|
|
|
|
({
|
|
|
|
|
'active': False,
|
|
|
|
|
'name': 'Service name',
|
2023-07-10 11:06:29 -07:00
|
|
|
}, 'organization_type is a required property'),
|
2019-07-15 16:28:54 +01:00
|
|
|
({
|
|
|
|
|
'active': False,
|
|
|
|
|
'name': 'Service name',
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization_type': 'foo',
|
2019-08-27 15:45:59 +01:00
|
|
|
}, (
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization_type foo is not one of '
|
2022-09-26 16:47:57 +00:00
|
|
|
'[federal, state, other]'
|
2019-08-27 15:45:59 +01:00
|
|
|
)),
|
2019-07-03 14:53:20 +01:00
|
|
|
))
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_post_create_organization_with_missing_data_gives_validation_error(
|
2019-07-03 14:53:20 +01:00
|
|
|
admin_request,
|
|
|
|
|
notify_db_session,
|
|
|
|
|
data,
|
|
|
|
|
expected_error,
|
|
|
|
|
):
|
2018-02-08 14:54:08 +00:00
|
|
|
response = admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.create_organization',
|
2018-02-08 14:54:08 +00:00
|
|
|
_data=data,
|
|
|
|
|
_expected_status=400
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert len(response['errors']) == 1
|
|
|
|
|
assert response['errors'][0]['error'] == 'ValidationError'
|
2019-07-03 14:53:20 +01:00
|
|
|
assert response['errors'][0]['message'] == expected_error
|
2018-02-08 14:54:08 +00:00
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_post_update_organization_updates_fields(
|
2019-02-19 11:47:30 +00:00
|
|
|
admin_request,
|
|
|
|
|
notify_db_session,
|
|
|
|
|
):
|
2023-07-10 11:06:29 -07:00
|
|
|
org = create_organization()
|
2018-02-08 14:54:08 +00:00
|
|
|
data = {
|
2023-07-10 11:06:29 -07:00
|
|
|
'name': 'new organization name',
|
2019-02-19 11:47:30 +00:00
|
|
|
'active': False,
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization_type': 'federal',
|
2018-02-08 14:54:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.update_organization',
|
2018-02-08 14:54:08 +00:00
|
|
|
_data=data,
|
2023-07-10 11:06:29 -07:00
|
|
|
organization_id=org.id,
|
2018-02-09 11:17:13 +00:00
|
|
|
_expected_status=204
|
2018-02-08 14:54:08 +00:00
|
|
|
)
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
organization = Organization.query.all()
|
2018-02-08 14:54:08 +00:00
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
assert len(organization) == 1
|
|
|
|
|
assert organization[0].id == org.id
|
|
|
|
|
assert organization[0].name == data['name']
|
|
|
|
|
assert organization[0].active == data['active']
|
|
|
|
|
assert organization[0].domains == []
|
|
|
|
|
assert organization[0].organization_type == 'federal'
|
2019-02-19 11:47:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize('domain_list', (
|
|
|
|
|
['example.com'],
|
|
|
|
|
['example.com', 'example.org', 'example.net'],
|
|
|
|
|
[],
|
|
|
|
|
))
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_post_update_organization_updates_domains(
|
2019-02-19 11:47:30 +00:00
|
|
|
admin_request,
|
|
|
|
|
notify_db_session,
|
|
|
|
|
domain_list,
|
|
|
|
|
):
|
2023-07-10 11:06:29 -07:00
|
|
|
org = create_organization(name='test_org_2')
|
2019-02-19 11:47:30 +00:00
|
|
|
data = {
|
2023-04-11 13:29:37 -07:00
|
|
|
'domains': domain_list
|
2019-02-19 11:47:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.update_organization',
|
2019-02-19 11:47:30 +00:00
|
|
|
_data=data,
|
2023-07-10 11:06:29 -07:00
|
|
|
organization_id=org.id,
|
2019-02-19 11:47:30 +00:00
|
|
|
_expected_status=204
|
|
|
|
|
)
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
organization = Organization.query.all()
|
2019-02-19 11:47:30 +00:00
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
assert len(organization) == 1
|
2019-02-19 11:47:30 +00:00
|
|
|
assert [
|
2023-07-10 11:06:29 -07:00
|
|
|
domain.domain for domain in organization[0].domains
|
2019-02-19 11:47:30 +00:00
|
|
|
] == domain_list
|
2018-02-09 11:17:13 +00:00
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_update_other_organization_attributes_doesnt_clear_domains(
|
2019-03-20 12:21:25 +00:00
|
|
|
admin_request,
|
|
|
|
|
notify_db_session,
|
|
|
|
|
):
|
2023-07-10 11:06:29 -07:00
|
|
|
org = create_organization(name='test_org_2')
|
2019-03-20 12:21:25 +00:00
|
|
|
create_domain('example.gov.uk', org.id)
|
|
|
|
|
|
|
|
|
|
admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.update_organization',
|
2023-04-11 13:29:37 -07:00
|
|
|
_data={'domains': ['example.gov.uk']},
|
2023-07-10 11:06:29 -07:00
|
|
|
organization_id=org.id,
|
2019-03-20 12:21:25 +00:00
|
|
|
_expected_status=204
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert [
|
|
|
|
|
domain.domain for domain in org.domains
|
|
|
|
|
] == [
|
|
|
|
|
'example.gov.uk'
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
2022-04-12 17:18:57 +01:00
|
|
|
@pytest.mark.parametrize('new_org_type', ["nhs_central", "nhs_local", "nhs_gp"])
|
2022-09-26 16:47:57 +00:00
|
|
|
@pytest.mark.skip(reason='Update for TTS')
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_post_update_organization_to_nhs_type_updates_branding_if_none_present(
|
2022-04-12 17:18:57 +01:00
|
|
|
admin_request,
|
2022-04-19 12:25:11 +01:00
|
|
|
nhs_email_branding,
|
2022-04-12 17:18:57 +01:00
|
|
|
notify_db_session,
|
|
|
|
|
new_org_type
|
|
|
|
|
):
|
2023-07-10 11:06:29 -07:00
|
|
|
org = create_organization(organization_type='central')
|
2022-04-12 17:18:57 +01:00
|
|
|
data = {
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization_type': new_org_type,
|
2022-04-12 17:18:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.update_organization',
|
2022-04-12 17:18:57 +01:00
|
|
|
_data=data,
|
2023-07-10 11:06:29 -07:00
|
|
|
organization_id=org.id,
|
2022-04-12 17:18:57 +01:00
|
|
|
_expected_status=204
|
|
|
|
|
)
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
organization = Organization.query.all()
|
2022-04-12 17:18:57 +01:00
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
assert len(organization) == 1
|
|
|
|
|
assert organization[0].id == org.id
|
|
|
|
|
assert organization[0].organization_type == new_org_type
|
|
|
|
|
assert organization[0].email_branding_id == uuid.UUID(current_app.config['NHS_EMAIL_BRANDING_ID'])
|
2022-04-12 17:18:57 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize('new_org_type', ["nhs_central", "nhs_local", "nhs_gp"])
|
2022-09-26 16:47:57 +00:00
|
|
|
@pytest.mark.skip(reason='Update for TTS')
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_post_update_organization_to_nhs_type_does_not_update_branding_if_default_branding_set(
|
2022-04-12 17:18:57 +01:00
|
|
|
admin_request,
|
2022-04-19 12:25:11 +01:00
|
|
|
nhs_email_branding,
|
2022-04-12 17:18:57 +01:00
|
|
|
notify_db_session,
|
|
|
|
|
new_org_type
|
|
|
|
|
):
|
|
|
|
|
current_branding = create_email_branding(
|
|
|
|
|
logo='example.png',
|
|
|
|
|
name='custom branding'
|
|
|
|
|
)
|
2023-07-10 11:06:29 -07:00
|
|
|
org = create_organization(organization_type='central', email_branding_id=current_branding.id)
|
2022-04-12 17:18:57 +01:00
|
|
|
data = {
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization_type': new_org_type,
|
2022-04-12 17:18:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.update_organization',
|
2022-04-12 17:18:57 +01:00
|
|
|
_data=data,
|
2023-07-10 11:06:29 -07:00
|
|
|
organization_id=org.id,
|
2022-04-12 17:18:57 +01:00
|
|
|
_expected_status=204
|
|
|
|
|
)
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
organization = Organization.query.all()
|
2022-04-12 17:18:57 +01:00
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
assert len(organization) == 1
|
|
|
|
|
assert organization[0].id == org.id
|
|
|
|
|
assert organization[0].organization_type == new_org_type
|
|
|
|
|
assert organization[0].email_branding_id == current_branding.id
|
2022-04-12 17:18:57 +01:00
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_update_organization_default_branding(
|
2019-03-20 14:14:19 +00:00
|
|
|
admin_request,
|
|
|
|
|
notify_db_session,
|
|
|
|
|
):
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
org = create_organization(name='Test Organization')
|
2019-03-20 14:14:19 +00:00
|
|
|
|
|
|
|
|
email_branding = create_email_branding()
|
|
|
|
|
|
|
|
|
|
assert org.email_branding is None
|
|
|
|
|
|
|
|
|
|
admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.update_organization',
|
2019-03-20 14:14:19 +00:00
|
|
|
_data={
|
|
|
|
|
'email_branding_id': str(email_branding.id),
|
|
|
|
|
},
|
2023-07-10 11:06:29 -07:00
|
|
|
organization_id=org.id,
|
2019-03-20 14:14:19 +00:00
|
|
|
_expected_status=204
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert org.email_branding == email_branding
|
|
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_post_update_organization_raises_400_on_existing_org_name(
|
|
|
|
|
admin_request, sample_organization):
|
|
|
|
|
org = create_organization()
|
2018-02-13 14:47:03 +00:00
|
|
|
data = {
|
2023-07-10 11:06:29 -07:00
|
|
|
'name': sample_organization.name,
|
2018-02-13 14:47:03 +00:00
|
|
|
'active': False
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-19 14:33:44 +00:00
|
|
|
response = admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.update_organization',
|
2018-02-19 14:33:44 +00:00
|
|
|
_data=data,
|
2023-07-10 11:06:29 -07:00
|
|
|
organization_id=org.id,
|
2018-02-19 14:33:44 +00:00
|
|
|
_expected_status=400
|
|
|
|
|
)
|
2018-02-13 14:47:03 +00:00
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
assert response['message'] == 'Organization name already exists'
|
2018-02-13 14:47:03 +00:00
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_post_update_organization_gives_404_status_if_org_does_not_exist(admin_request, notify_db_session):
|
|
|
|
|
data = {'name': 'new organization name'}
|
2018-02-09 11:17:13 +00:00
|
|
|
|
|
|
|
|
admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.update_organization',
|
2018-02-09 11:17:13 +00:00
|
|
|
_data=data,
|
2023-07-10 11:06:29 -07:00
|
|
|
organization_id='31d42ce6-3dac-45a7-95cb-94423d5ca03c',
|
2018-02-09 11:17:13 +00:00
|
|
|
_expected_status=404
|
|
|
|
|
)
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
organization = Organization.query.all()
|
2018-02-09 11:17:13 +00:00
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
assert not organization
|
2018-02-10 01:37:17 +00:00
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_post_update_organization_returns_400_if_domain_is_duplicate(admin_request, notify_db_session):
|
|
|
|
|
org = create_organization()
|
|
|
|
|
org2 = create_organization(name='Second org')
|
2019-04-10 13:23:34 +01:00
|
|
|
create_domain('same.com', org.id)
|
|
|
|
|
|
|
|
|
|
data = {'domains': ['new.com', 'same.com']}
|
|
|
|
|
|
|
|
|
|
response = admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.update_organization',
|
2019-04-10 13:23:34 +01:00
|
|
|
_data=data,
|
2023-07-10 11:06:29 -07:00
|
|
|
organization_id=org2.id,
|
2019-04-10 13:23:34 +01:00
|
|
|
_expected_status=400
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert response['message'] == 'Domain already exists'
|
|
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_post_update_organization_set_mou_doesnt_email_if_no_signed_by(
|
|
|
|
|
sample_organization,
|
2019-07-08 12:33:53 +01:00
|
|
|
admin_request,
|
|
|
|
|
mocker
|
|
|
|
|
):
|
2023-07-10 11:06:29 -07:00
|
|
|
queue_mock = mocker.patch('app.organization.rest.send_notification_to_queue')
|
2019-07-08 12:33:53 +01:00
|
|
|
|
|
|
|
|
data = {'agreement_signed': True}
|
|
|
|
|
|
|
|
|
|
admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.update_organization',
|
2019-07-08 12:33:53 +01:00
|
|
|
_data=data,
|
2023-07-10 11:06:29 -07:00
|
|
|
organization_id=sample_organization.id,
|
2019-07-08 12:33:53 +01:00
|
|
|
_expected_status=204
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert queue_mock.called is False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize('on_behalf_of_name, on_behalf_of_email_address, templates_and_recipients', [
|
|
|
|
|
(
|
|
|
|
|
None,
|
|
|
|
|
None,
|
|
|
|
|
{
|
|
|
|
|
'MOU_SIGNER_RECEIPT_TEMPLATE_ID': 'notify@digital.cabinet-office.gov.uk',
|
|
|
|
|
}
|
|
|
|
|
),
|
|
|
|
|
(
|
|
|
|
|
'Important Person',
|
|
|
|
|
'important@person.com',
|
|
|
|
|
{
|
|
|
|
|
'MOU_SIGNED_ON_BEHALF_ON_BEHALF_RECEIPT_TEMPLATE_ID': 'important@person.com',
|
|
|
|
|
'MOU_SIGNED_ON_BEHALF_SIGNER_RECEIPT_TEMPLATE_ID': 'notify@digital.cabinet-office.gov.uk',
|
|
|
|
|
}
|
|
|
|
|
),
|
|
|
|
|
])
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_post_update_organization_set_mou_emails_signed_by(
|
|
|
|
|
sample_organization,
|
2019-07-08 12:33:53 +01:00
|
|
|
admin_request,
|
|
|
|
|
mou_signed_templates,
|
|
|
|
|
mocker,
|
|
|
|
|
sample_user,
|
|
|
|
|
on_behalf_of_name,
|
|
|
|
|
on_behalf_of_email_address,
|
|
|
|
|
templates_and_recipients
|
|
|
|
|
):
|
2023-07-10 11:06:29 -07:00
|
|
|
queue_mock = mocker.patch('app.organization.rest.send_notification_to_queue')
|
|
|
|
|
sample_organization.agreement_signed_on_behalf_of_name = on_behalf_of_name
|
|
|
|
|
sample_organization.agreement_signed_on_behalf_of_email_address = on_behalf_of_email_address
|
2019-07-08 12:33:53 +01:00
|
|
|
|
|
|
|
|
admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.update_organization',
|
2019-07-08 12:33:53 +01:00
|
|
|
_data={'agreement_signed': True, 'agreement_signed_by_id': str(sample_user.id)},
|
2023-07-10 11:06:29 -07:00
|
|
|
organization_id=sample_organization.id,
|
2019-07-08 12:33:53 +01:00
|
|
|
_expected_status=204
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
notifications = [x[0][0] for x in queue_mock.call_args_list]
|
|
|
|
|
assert {n.template.name: n.to for n in notifications} == templates_and_recipients
|
|
|
|
|
|
|
|
|
|
for n in notifications:
|
|
|
|
|
# we pass in the same personalisation for all templates (though some templates don't use all fields)
|
|
|
|
|
assert n.personalisation == {
|
2023-04-11 13:29:37 -07:00
|
|
|
'mou_link': 'http://localhost:6012/agreement/agreement.pdf',
|
2023-07-10 11:06:29 -07:00
|
|
|
'org_name': 'sample organization',
|
|
|
|
|
'org_dashboard_link': 'http://localhost:6012/organizations/{}'.format(sample_organization.id),
|
2019-07-08 12:33:53 +01:00
|
|
|
'signed_by_name': 'Test User',
|
|
|
|
|
'on_behalf_of_name': on_behalf_of_name
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_post_link_service_to_organization(admin_request, sample_service):
|
2018-02-10 01:37:17 +00:00
|
|
|
data = {
|
|
|
|
|
'service_id': str(sample_service.id)
|
|
|
|
|
}
|
2023-07-10 11:06:29 -07:00
|
|
|
organization = create_organization(organization_type='federal')
|
2021-04-14 07:11:01 +01:00
|
|
|
|
2018-02-10 01:37:17 +00:00
|
|
|
admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.link_service_to_organization',
|
2018-02-10 01:37:17 +00:00
|
|
|
_data=data,
|
2023-07-10 11:06:29 -07:00
|
|
|
organization_id=organization.id,
|
2018-02-10 01:37:17 +00:00
|
|
|
_expected_status=204
|
|
|
|
|
)
|
2023-07-10 11:06:29 -07:00
|
|
|
assert len(organization.services) == 1
|
|
|
|
|
assert sample_service.organization_type == 'federal'
|
2021-04-12 13:52:40 +01:00
|
|
|
|
|
|
|
|
|
2022-04-01 10:22:07 +01:00
|
|
|
@freeze_time('2021-09-24 13:30')
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_post_link_service_to_organization_inserts_annual_billing(admin_request, sample_service):
|
2021-04-12 13:52:40 +01:00
|
|
|
data = {
|
|
|
|
|
'service_id': str(sample_service.id)
|
|
|
|
|
}
|
2023-07-10 11:06:29 -07:00
|
|
|
organization = create_organization(organization_type='federal')
|
|
|
|
|
assert len(organization.services) == 0
|
2021-04-12 13:52:40 +01:00
|
|
|
assert len(AnnualBilling.query.all()) == 0
|
|
|
|
|
admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.link_service_to_organization',
|
2021-04-12 13:52:40 +01:00
|
|
|
_data=data,
|
2023-07-10 11:06:29 -07:00
|
|
|
organization_id=organization.id,
|
2021-04-12 13:52:40 +01:00
|
|
|
_expected_status=204
|
|
|
|
|
)
|
|
|
|
|
|
2021-04-06 13:42:18 +01:00
|
|
|
annual_billing = AnnualBilling.query.all()
|
|
|
|
|
assert len(annual_billing) == 1
|
|
|
|
|
assert annual_billing[0].free_sms_fragment_limit == 150000
|
2018-02-10 01:37:17 +00:00
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_post_link_service_to_organization_rollback_service_if_annual_billing_update_fails(
|
2021-04-12 13:52:40 +01:00
|
|
|
admin_request, sample_service, mocker
|
|
|
|
|
):
|
|
|
|
|
mocker.patch('app.dao.annual_billing_dao.dao_create_or_update_annual_billing_for_year',
|
|
|
|
|
side_effect=SQLAlchemyError)
|
|
|
|
|
data = {
|
|
|
|
|
'service_id': str(sample_service.id)
|
|
|
|
|
}
|
2023-07-10 11:06:29 -07:00
|
|
|
assert not sample_service.organization_type
|
2021-04-12 13:52:40 +01:00
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
organization = create_organization(organization_type='federal')
|
|
|
|
|
assert len(organization.services) == 0
|
2021-04-12 13:52:40 +01:00
|
|
|
assert len(AnnualBilling.query.all()) == 0
|
|
|
|
|
with pytest.raises(expected_exception=SQLAlchemyError):
|
|
|
|
|
admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.link_service_to_organization',
|
2021-04-12 13:52:40 +01:00
|
|
|
_data=data,
|
2023-07-10 11:06:29 -07:00
|
|
|
organization_id=organization.id
|
2021-04-12 13:52:40 +01:00
|
|
|
)
|
2023-07-10 11:06:29 -07:00
|
|
|
assert not sample_service.organization_type
|
|
|
|
|
assert len(organization.services) == 0
|
2021-04-12 13:52:40 +01:00
|
|
|
assert len(AnnualBilling.query.all()) == 0
|
|
|
|
|
|
|
|
|
|
|
2022-04-01 10:22:07 +01:00
|
|
|
@freeze_time('2021-09-24 13:30')
|
2018-02-10 01:37:17 +00:00
|
|
|
def test_post_link_service_to_another_org(
|
2023-07-10 11:06:29 -07:00
|
|
|
admin_request, sample_service, sample_organization):
|
2018-02-10 01:37:17 +00:00
|
|
|
data = {
|
|
|
|
|
'service_id': str(sample_service.id)
|
|
|
|
|
}
|
2023-07-10 11:06:29 -07:00
|
|
|
assert len(sample_organization.services) == 0
|
|
|
|
|
assert not sample_service.organization_type
|
2018-02-10 01:37:17 +00:00
|
|
|
admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.link_service_to_organization',
|
2018-02-10 01:37:17 +00:00
|
|
|
_data=data,
|
2023-07-10 11:06:29 -07:00
|
|
|
organization_id=sample_organization.id,
|
2018-02-10 01:37:17 +00:00
|
|
|
_expected_status=204
|
|
|
|
|
)
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
assert len(sample_organization.services) == 1
|
|
|
|
|
assert not sample_service.organization_type
|
2018-02-10 01:37:17 +00:00
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
new_org = create_organization(organization_type='federal')
|
2018-02-10 01:37:17 +00:00
|
|
|
admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.link_service_to_organization',
|
2018-02-10 01:37:17 +00:00
|
|
|
_data=data,
|
2023-07-10 11:06:29 -07:00
|
|
|
organization_id=new_org.id,
|
2018-02-10 01:37:17 +00:00
|
|
|
_expected_status=204
|
|
|
|
|
)
|
2023-07-10 11:06:29 -07:00
|
|
|
assert not sample_organization.services
|
2018-02-10 01:37:17 +00:00
|
|
|
assert len(new_org.services) == 1
|
2023-07-10 11:06:29 -07:00
|
|
|
assert sample_service.organization_type == 'federal'
|
2021-04-06 13:42:18 +01:00
|
|
|
annual_billing = AnnualBilling.query.all()
|
|
|
|
|
assert len(annual_billing) == 1
|
|
|
|
|
assert annual_billing[0].free_sms_fragment_limit == 150000
|
2018-02-10 01:37:17 +00:00
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_post_link_service_to_organization_nonexistent_organization(
|
2018-02-10 01:37:17 +00:00
|
|
|
admin_request, sample_service, fake_uuid):
|
|
|
|
|
data = {
|
|
|
|
|
'service_id': str(sample_service.id)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.link_service_to_organization',
|
2018-02-10 01:37:17 +00:00
|
|
|
_data=data,
|
2023-07-10 11:06:29 -07:00
|
|
|
organization_id=fake_uuid,
|
2018-02-10 01:37:17 +00:00
|
|
|
_expected_status=404
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_post_link_service_to_organization_nonexistent_service(
|
|
|
|
|
admin_request, sample_organization, fake_uuid):
|
2018-02-10 01:37:17 +00:00
|
|
|
data = {
|
|
|
|
|
'service_id': fake_uuid
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.link_service_to_organization',
|
2018-02-10 01:37:17 +00:00
|
|
|
_data=data,
|
2023-07-10 11:06:29 -07:00
|
|
|
organization_id=str(sample_organization.id),
|
2018-02-10 01:37:17 +00:00
|
|
|
_expected_status=404
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_post_link_service_to_organization_missing_payload(
|
|
|
|
|
admin_request, sample_organization, fake_uuid):
|
2018-02-10 01:37:17 +00:00
|
|
|
admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.link_service_to_organization',
|
|
|
|
|
organization_id=str(sample_organization.id),
|
2018-02-10 01:37:17 +00:00
|
|
|
_expected_status=400
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_rest_get_organization_services(
|
|
|
|
|
admin_request, sample_organization, sample_service):
|
|
|
|
|
dao_add_service_to_organization(sample_service, sample_organization.id)
|
2018-02-10 01:37:17 +00:00
|
|
|
response = admin_request.get(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.get_organization_services',
|
|
|
|
|
organization_id=str(sample_organization.id),
|
2018-02-10 01:37:17 +00:00
|
|
|
_expected_status=200
|
|
|
|
|
)
|
|
|
|
|
|
2018-02-13 09:28:48 +00:00
|
|
|
assert response == [sample_service.serialize_for_org_dashboard()]
|
|
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_rest_get_organization_services_is_ordered_by_name(
|
|
|
|
|
admin_request, sample_organization, sample_service):
|
2018-02-13 09:28:48 +00:00
|
|
|
service_2 = create_service(service_name='service 2')
|
|
|
|
|
service_1 = create_service(service_name='service 1')
|
2023-07-10 11:06:29 -07:00
|
|
|
dao_add_service_to_organization(service_1, sample_organization.id)
|
|
|
|
|
dao_add_service_to_organization(service_2, sample_organization.id)
|
|
|
|
|
dao_add_service_to_organization(sample_service, sample_organization.id)
|
2018-02-13 09:28:48 +00:00
|
|
|
|
|
|
|
|
response = admin_request.get(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.get_organization_services',
|
|
|
|
|
organization_id=str(sample_organization.id),
|
2018-02-13 09:28:48 +00:00
|
|
|
_expected_status=200
|
|
|
|
|
)
|
|
|
|
|
|
2018-02-10 01:37:17 +00:00
|
|
|
assert response[0]['name'] == sample_service.name
|
2018-02-13 09:28:48 +00:00
|
|
|
assert response[1]['name'] == service_1.name
|
|
|
|
|
assert response[2]['name'] == service_2.name
|
|
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_rest_get_organization_services_inactive_services_at_end(
|
|
|
|
|
admin_request, sample_organization):
|
2018-02-13 09:28:48 +00:00
|
|
|
inactive_service = create_service(service_name='inactive service', active=False)
|
|
|
|
|
service = create_service()
|
|
|
|
|
inactive_service_1 = create_service(service_name='inactive service 1', active=False)
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
dao_add_service_to_organization(inactive_service, sample_organization.id)
|
|
|
|
|
dao_add_service_to_organization(service, sample_organization.id)
|
|
|
|
|
dao_add_service_to_organization(inactive_service_1, sample_organization.id)
|
2018-02-13 09:28:48 +00:00
|
|
|
|
|
|
|
|
response = admin_request.get(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.get_organization_services',
|
|
|
|
|
organization_id=str(sample_organization.id),
|
2018-02-13 09:28:48 +00:00
|
|
|
_expected_status=200
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert response[0]['name'] == service.name
|
|
|
|
|
assert response[1]['name'] == inactive_service.name
|
|
|
|
|
assert response[2]['name'] == inactive_service_1.name
|
2018-02-21 16:39:17 +00:00
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_add_user_to_organization_returns_added_user(admin_request, sample_organization, sample_user):
|
2018-02-21 16:39:17 +00:00
|
|
|
response = admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.add_user_to_organization',
|
|
|
|
|
organization_id=str(sample_organization.id),
|
2018-02-21 16:39:17 +00:00
|
|
|
user_id=str(sample_user.id),
|
|
|
|
|
_expected_status=200
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert response['data']['id'] == str(sample_user.id)
|
2023-07-10 11:06:29 -07:00
|
|
|
assert len(response['data']['organizations']) == 1
|
|
|
|
|
assert response['data']['organizations'][0] == str(sample_organization.id)
|
2018-02-21 16:39:17 +00:00
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_add_user_to_organization_returns_404_if_user_does_not_exist(admin_request, sample_organization):
|
2018-02-21 16:39:17 +00:00
|
|
|
admin_request.post(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.add_user_to_organization',
|
|
|
|
|
organization_id=str(sample_organization.id),
|
2018-02-21 16:39:17 +00:00
|
|
|
user_id=str(uuid.uuid4()),
|
|
|
|
|
_expected_status=404
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_remove_user_from_organization(admin_request, sample_organization, sample_user):
|
|
|
|
|
dao_add_user_to_organization(organization_id=sample_organization.id, user_id=sample_user.id)
|
2022-01-05 13:30:52 +00:00
|
|
|
|
|
|
|
|
admin_request.delete(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.remove_user_from_organization',
|
|
|
|
|
organization_id=sample_organization.id,
|
2022-01-05 13:30:52 +00:00
|
|
|
user_id=sample_user.id
|
|
|
|
|
)
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
assert sample_organization.users == []
|
2022-01-05 13:30:52 +00:00
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_remove_user_from_organization_when_user_is_not_an_org_member(admin_request, sample_organization, sample_user):
|
2022-01-05 13:30:52 +00:00
|
|
|
resp = admin_request.delete(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.remove_user_from_organization',
|
|
|
|
|
organization_id=sample_organization.id,
|
2022-01-05 13:30:52 +00:00
|
|
|
user_id=sample_user.id,
|
|
|
|
|
_expected_status=404
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert resp == {
|
|
|
|
|
'result': 'error',
|
|
|
|
|
'message': 'User not found'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_get_organization_users_returns_users_for_organization(admin_request, sample_organization):
|
2018-02-21 16:39:17 +00:00
|
|
|
first = create_user(email='first@invited.com')
|
|
|
|
|
second = create_user(email='another@invited.com')
|
2023-07-10 11:06:29 -07:00
|
|
|
dao_add_user_to_organization(organization_id=sample_organization.id, user_id=first.id)
|
|
|
|
|
dao_add_user_to_organization(organization_id=sample_organization.id, user_id=second.id)
|
2018-02-21 16:39:17 +00:00
|
|
|
|
|
|
|
|
response = admin_request.get(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.get_organization_users',
|
|
|
|
|
organization_id=sample_organization.id,
|
2018-02-21 16:39:17 +00:00
|
|
|
_expected_status=200
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assert len(response['data']) == 2
|
|
|
|
|
assert response['data'][0]['id'] == str(first.id)
|
2020-02-24 17:02:25 +00:00
|
|
|
|
|
|
|
|
|
2023-06-14 13:19:11 -07:00
|
|
|
@freeze_time('2019-12-24 13:30')
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_get_organization_services_usage(admin_request, notify_db_session):
|
|
|
|
|
org = create_organization(name='Organization without live services')
|
2020-02-24 17:02:25 +00:00
|
|
|
service = create_service()
|
|
|
|
|
template = create_template(service=service)
|
2023-07-10 11:06:29 -07:00
|
|
|
dao_add_service_to_organization(service=service, organization_id=org.id)
|
2020-02-25 17:47:03 +00:00
|
|
|
create_annual_billing(service_id=service.id, free_sms_fragment_limit=10, financial_year_start=2019)
|
2022-11-21 11:49:59 -05:00
|
|
|
create_ft_billing(local_date=datetime.utcnow().date(), template=template, billable_unit=19, rate=0.060,
|
2020-02-25 17:47:03 +00:00
|
|
|
notifications_sent=19)
|
2020-02-24 17:02:25 +00:00
|
|
|
response = admin_request.get(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.get_organization_services_usage',
|
|
|
|
|
organization_id=org.id,
|
2020-02-25 17:34:03 +00:00
|
|
|
**{"year": 2019}
|
2020-02-24 17:02:25 +00:00
|
|
|
)
|
|
|
|
|
assert len(response) == 1
|
2020-02-25 17:34:03 +00:00
|
|
|
assert len(response['services']) == 1
|
2020-02-25 17:47:03 +00:00
|
|
|
service_usage = response['services'][0]
|
|
|
|
|
assert service_usage['service_id'] == str(service.id)
|
|
|
|
|
assert service_usage['service_name'] == service.name
|
|
|
|
|
assert service_usage['chargeable_billable_sms'] == 9.0
|
|
|
|
|
assert service_usage['emails_sent'] == 0
|
|
|
|
|
assert service_usage['free_sms_limit'] == 10
|
|
|
|
|
assert service_usage['sms_billable_units'] == 19
|
Fix calculating remaining free allowance for SMS
The way it was done before, the remainder was incorrect in the
billing report and in the org usage query - it was the sms remainder
left at the start of the report period, not at the end of that period.
This became apparent when we tried to show sms_remainder on the org
usage report, where start date is always the start of the financial year.
We saw that sms sent by services did not reduce their free allowance
remainder according to the report. As a result of this, we had to
temporarily remove of sms_remainder column from the report, until
we fix the bug - it has been fixed now, yay!
I think the bug has snuck in partially because our fixtures for testing
this part of the code are quite complex, so it was
harder to see that numbers don't add up. I have added comments
to the tests to try and make it a bit clearer why the results are
as they are.
I also added comments to the code, and renamed some variables,
to make it easier to understand, as there are quite a few
moving parts in it - subqueries and the like.
I also renamed the fetch_sms_free_allowance_remainder method to
fetch_sms_free_allowance_remainder_until_date so it is clearer
what it does.
2021-12-09 17:50:03 +00:00
|
|
|
assert service_usage['sms_remainder'] == 0
|
2020-02-25 17:47:03 +00:00
|
|
|
assert service_usage['sms_cost'] == 0.54
|
2020-02-25 17:34:03 +00:00
|
|
|
|
|
|
|
|
|
2021-01-12 09:44:35 +00:00
|
|
|
@freeze_time('2020-02-24 13:30')
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_get_organization_services_usage_sort_active_first(admin_request, notify_db_session):
|
|
|
|
|
org = create_organization(name='Organization without live services')
|
2021-01-12 09:44:35 +00:00
|
|
|
service = create_service(service_name='live service')
|
|
|
|
|
archived_service = create_service(service_name='archived_service')
|
|
|
|
|
template = create_template(service=service)
|
2023-07-10 11:06:29 -07:00
|
|
|
dao_add_service_to_organization(service=service, organization_id=org.id)
|
|
|
|
|
dao_add_service_to_organization(service=archived_service, organization_id=org.id)
|
2021-01-12 09:44:35 +00:00
|
|
|
create_annual_billing(service_id=service.id, free_sms_fragment_limit=10, financial_year_start=2019)
|
2022-11-21 11:49:59 -05:00
|
|
|
create_ft_billing(local_date=datetime.utcnow().date(), template=template, billable_unit=19, rate=0.060,
|
2021-01-12 09:44:35 +00:00
|
|
|
notifications_sent=19)
|
|
|
|
|
response = admin_request.get(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.get_organization_services_usage',
|
|
|
|
|
organization_id=org.id,
|
2021-01-12 09:44:35 +00:00
|
|
|
**{"year": 2019}
|
|
|
|
|
)
|
|
|
|
|
assert len(response) == 1
|
|
|
|
|
assert len(response['services']) == 2
|
|
|
|
|
first_service = response['services'][0]
|
|
|
|
|
assert first_service['service_id'] == str(archived_service.id)
|
|
|
|
|
assert first_service['service_name'] == archived_service.name
|
|
|
|
|
assert first_service['active'] is True
|
|
|
|
|
last_service = response['services'][1]
|
|
|
|
|
assert last_service['service_id'] == str(service.id)
|
|
|
|
|
assert last_service['service_name'] == service.name
|
|
|
|
|
assert last_service['active'] is True
|
|
|
|
|
|
|
|
|
|
dao_archive_service(service_id=archived_service.id)
|
|
|
|
|
response_after_archive = admin_request.get(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.get_organization_services_usage',
|
|
|
|
|
organization_id=org.id,
|
2021-01-12 09:44:35 +00:00
|
|
|
**{"year": 2019}
|
|
|
|
|
)
|
|
|
|
|
first_service = response_after_archive['services'][0]
|
|
|
|
|
assert first_service['service_id'] == str(service.id)
|
|
|
|
|
assert first_service['service_name'] == service.name
|
|
|
|
|
assert first_service['active'] is True
|
|
|
|
|
last_service = response_after_archive['services'][1]
|
|
|
|
|
assert last_service['service_id'] == str(archived_service.id)
|
|
|
|
|
assert last_service['service_name'] == archived_service.name
|
|
|
|
|
assert last_service['active'] is False
|
|
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_get_organization_services_usage_returns_400_if_year_is_invalid(admin_request):
|
2020-02-25 17:34:03 +00:00
|
|
|
response = admin_request.get(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.get_organization_services_usage',
|
|
|
|
|
organization_id=uuid.uuid4(),
|
2020-02-26 17:38:20 +00:00
|
|
|
**{"year": 'not-a-valid-year'},
|
|
|
|
|
_expected_status=400
|
|
|
|
|
)
|
|
|
|
|
assert response['message'] == 'No valid year provided'
|
|
|
|
|
|
|
|
|
|
|
2023-07-10 11:06:29 -07:00
|
|
|
def test_get_organization_services_usage_returns_400_if_year_is_empty(admin_request):
|
2020-02-26 17:38:20 +00:00
|
|
|
response = admin_request.get(
|
2023-07-10 11:06:29 -07:00
|
|
|
'organization.get_organization_services_usage',
|
|
|
|
|
organization_id=uuid.uuid4(),
|
2020-02-25 17:34:03 +00:00
|
|
|
_expected_status=400
|
|
|
|
|
)
|
|
|
|
|
assert response['message'] == 'No valid year provided'
|