Skip to content

Commit 35a4208

Browse files
authored
Merge pull request #809 from NHSDigital/split-models
Split models
2 parents 4e36973 + 0498e12 commit 35a4208

File tree

61 files changed

+676
-401
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+676
-401
lines changed
Lines changed: 0 additions & 312 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,9 @@
11
import os
2-
import random
32
import urllib.parse
4-
from datetime import date
53
from enum import StrEnum
6-
from typing import NamedTuple
74

8-
import nhs_number
9-
import requests
10-
from attr import dataclass
115
from faker import Faker
126

13-
from mavis.test.utils import (
14-
get_date_of_birth_for_year_group,
15-
normalize_postcode,
16-
normalize_whitespace,
17-
)
18-
197
faker = Faker("en_GB")
208

219

@@ -426,170 +414,6 @@ def headers(self) -> str:
426414
}
427415

428416

429-
class Clinic(NamedTuple):
430-
name: str
431-
432-
def __str__(self) -> str:
433-
return self.name
434-
435-
def to_onboarding(self) -> dict:
436-
return {"name": self.name}
437-
438-
@classmethod
439-
def generate(cls) -> "Clinic":
440-
return cls(
441-
name=faker.company(),
442-
)
443-
444-
445-
class School(NamedTuple):
446-
name: str
447-
urn: str
448-
site: str
449-
450-
def __str__(self) -> str:
451-
return self.name
452-
453-
@property
454-
def urn_and_site(self) -> str:
455-
if self.site:
456-
return self.urn + self.site
457-
return self.urn
458-
459-
def to_onboarding(self) -> str:
460-
return self.urn_and_site
461-
462-
@classmethod
463-
def get_from_testing_api(
464-
cls, base_url: str, year_groups: dict[str, int]
465-
) -> "dict[str, list[School]]":
466-
def _get_schools_with_year_group(year_group: int) -> list[School]:
467-
url = urllib.parse.urljoin(base_url, "api/testing/locations")
468-
params = {
469-
"type": "school",
470-
"status": "open",
471-
"is_attached_to_team": "false",
472-
"gias_year_groups[]": [str(year_group)],
473-
}
474-
475-
response = requests.get(url, params=params, timeout=30)
476-
response.raise_for_status()
477-
478-
data = response.json()
479-
schools_data = random.choices(data, k=2)
480-
481-
return [
482-
School(
483-
name=normalize_whitespace(school_data["name"]),
484-
urn=school_data["urn"],
485-
site=school_data["site"],
486-
)
487-
for school_data in schools_data
488-
]
489-
490-
return {
491-
programme.group: _get_schools_with_year_group(year_groups[programme.group])
492-
for programme in Programme
493-
}
494-
495-
496-
class Organisation(NamedTuple):
497-
ods_code: str
498-
499-
def to_onboarding(self) -> dict:
500-
return {
501-
"ods_code": self.ods_code,
502-
}
503-
504-
@classmethod
505-
def generate(cls) -> "Organisation":
506-
return cls(
507-
ods_code=faker.bothify("?###?", letters="ABCDEFGHIJKLMNOPQRSTUVWXYZ"),
508-
)
509-
510-
511-
class Subteam(NamedTuple):
512-
key: str
513-
name: str
514-
email: str
515-
phone: str
516-
517-
def __str__(self) -> str:
518-
return self.name
519-
520-
def to_onboarding(self) -> dict:
521-
return {self.key: {"name": self.name, "email": self.email, "phone": self.phone}}
522-
523-
@classmethod
524-
def generate(cls) -> "Subteam":
525-
return cls(
526-
key="team",
527-
name=f"{faker.company()} est. {random.randint(1600, 2025)}",
528-
email=faker.email(),
529-
phone=faker.cellphone_number(),
530-
)
531-
532-
533-
class Team(NamedTuple):
534-
name: str
535-
workgroup: str
536-
careplus_venue_code: str
537-
email: str
538-
phone: str
539-
540-
def __str__(self) -> str:
541-
return f"{self.name}"
542-
543-
def to_onboarding(self) -> dict:
544-
return {
545-
"name": self.name,
546-
"workgroup": self.workgroup,
547-
"email": self.email,
548-
"phone": self.phone,
549-
"careplus_venue_code": self.careplus_venue_code,
550-
"privacy_notice_url": "https://example.com/privacy",
551-
"privacy_policy_url": "https://example.com/privacy",
552-
"type": "poc_only",
553-
}
554-
555-
@classmethod
556-
def generate(cls, subteam: Subteam, organisation: Organisation) -> "Team":
557-
return cls(
558-
name=subteam.name,
559-
workgroup=organisation.ods_code,
560-
careplus_venue_code=organisation.ods_code,
561-
email=subteam.email,
562-
phone=subteam.phone,
563-
)
564-
565-
566-
class User(NamedTuple):
567-
username: str
568-
password: str
569-
role: str
570-
571-
def __str__(self) -> str:
572-
return self.username
573-
574-
def to_onboarding(self) -> dict:
575-
return {
576-
"email": self.username,
577-
"password": self.password,
578-
"given_name": self.role,
579-
"family_name": self.role,
580-
"fallback_role": self.role,
581-
}
582-
583-
@classmethod
584-
def generate(cls, role: str) -> "User":
585-
email = faker.email()
586-
return cls(
587-
username=email,
588-
password=email,
589-
role=role,
590-
)
591-
592-
593417
class Relationship(StrEnum):
594418
DAD = "Dad"
595419
MUM = "Mum"
@@ -606,75 +430,6 @@ def generate_name(self) -> str:
606430
return faker.name_nonbinary()
607431

608432

609-
class Parent(NamedTuple):
610-
full_name: str
611-
relationship: Relationship
612-
email_address: str
613-
614-
@property
615-
def name_and_relationship(self) -> str:
616-
return f"{self.full_name} ({self.relationship})"
617-
618-
@classmethod
619-
def get(cls, relationship: Relationship) -> "Parent":
620-
return cls(
621-
full_name=relationship.generate_name,
622-
relationship=relationship,
623-
email_address=faker.email(),
624-
)
625-
626-
627-
class Child(NamedTuple):
628-
first_name: str
629-
last_name: str
630-
nhs_number: str
631-
address: tuple[str, str, str, str]
632-
date_of_birth: date
633-
year_group: int
634-
parents: tuple[Parent, Parent]
635-
636-
def __str__(self) -> str:
637-
return f"{self.last_name}, {self.first_name}"
638-
639-
@property
640-
def name(self) -> tuple[str, str]:
641-
return self.first_name, self.last_name
642-
643-
@classmethod
644-
def generate(cls, year_group: int) -> "Child":
645-
return cls(
646-
first_name=faker.first_name(),
647-
last_name=faker.last_name().upper(),
648-
nhs_number=nhs_number.generate(
649-
for_region=nhs_number.REGION_SYNTHETIC,
650-
)[0],
651-
address=(
652-
faker.secondary_address(),
653-
faker.street_name(),
654-
faker.city(),
655-
normalize_postcode(faker.postcode()),
656-
),
657-
date_of_birth=get_date_of_birth_for_year_group(year_group),
658-
year_group=year_group,
659-
parents=(Parent.get(Relationship.DAD), Parent.get(Relationship.MUM)),
660-
)
661-
662-
@classmethod
663-
def generate_children_for_year_group(cls, n: int, year_group: int) -> list["Child"]:
664-
return [cls.generate(year_group) for _ in range(n)]
665-
666-
@classmethod
667-
def generate_children_in_year_group_for_each_programme_group(
668-
cls, n: int, year_group_dict: dict[str, int]
669-
) -> dict[str, list["Child"]]:
670-
return {
671-
programme.group: cls.generate_children_for_year_group(
672-
n, year_group_dict[programme.group]
673-
)
674-
for programme in Programme
675-
}
676-
677-
678433
class ImmsEndpoints(StrEnum):
679434
AUTH = "/oauth2/token"
680435
CREATE = "/immunisation-fhir-api/FHIR/R4/Immunization"
@@ -689,70 +444,3 @@ def to_url(self) -> str:
689444
os.getenv("IMMS_BASE_URL", "PROVIDEURL"),
690445
self.value,
691446
)
692-
693-
694-
@dataclass
695-
class VaccinationRecord:
696-
child: Child
697-
programme: Programme
698-
batch_name: str
699-
consent_option: ConsentOption = ConsentOption.INJECTION
700-
delivery_site: DeliverySite = DeliverySite.LEFT_ARM_UPPER
701-
702-
703-
@dataclass
704-
class Onboarding:
705-
organisation: Organisation
706-
team: Team
707-
subteam: Subteam
708-
users: dict[str, User]
709-
clinics: list[Clinic]
710-
schools: dict[str, list[School]]
711-
programmes: str
712-
713-
@classmethod
714-
def get_onboarding_data_for_tests(
715-
cls, base_url: str, year_groups: dict[str, int], programmes: str
716-
) -> "Onboarding":
717-
subteam = Subteam.generate()
718-
organisation = Organisation.generate()
719-
team = Team.generate(subteam, organisation)
720-
users = {
721-
role: User.generate(role)
722-
for role in (
723-
"nurse",
724-
"medical_secretary",
725-
"superuser",
726-
"prescriber",
727-
"healthcare_assistant",
728-
)
729-
}
730-
clinics = [Clinic.generate()]
731-
schools = School.get_from_testing_api(base_url, year_groups)
732-
733-
return cls(
734-
organisation=organisation,
735-
team=team,
736-
subteam=subteam,
737-
users=users,
738-
clinics=clinics,
739-
schools=schools,
740-
programmes=programmes,
741-
)
742-
743-
def to_dict(self) -> dict[str, object]:
744-
return {
745-
"clinics": {self.subteam.key: [it.to_onboarding() for it in self.clinics]},
746-
"team": self.team.to_onboarding(),
747-
"organisation": self.organisation.to_onboarding(),
748-
"programmes": self.programmes,
749-
"schools": {
750-
self.subteam.key: [
751-
school.to_onboarding()
752-
for schools_list in self.schools.values()
753-
for school in schools_list
754-
],
755-
},
756-
"subteams": self.subteam.to_onboarding(),
757-
"users": [it.to_onboarding() for it in self.users.values()],
758-
}

mavis/test/data/__init__.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,14 @@
77
import pandas as pd
88
from faker import Faker
99

10-
from mavis.test.models import Child, Clinic, Organisation, Programme, School, User
10+
from mavis.test.constants import Programme
11+
from mavis.test.data_models import (
12+
Child,
13+
Clinic,
14+
Organisation,
15+
School,
16+
User,
17+
)
1118
from mavis.test.utils import (
1219
get_current_datetime_compact,
1320
get_current_time_hms_format,

mavis/test/data/pds.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77

88
from dateutil.relativedelta import relativedelta
99

10-
from mavis.test.models import Child, Parent, Relationship
10+
from mavis.test.constants import Relationship
11+
from mavis.test.data_models import Child, Parent
1112
from mavis.test.utils import get_todays_date
1213

1314

0 commit comments

Comments
 (0)