Skip to content

Commit 58eedcd

Browse files
authored
Updates to the data generators (#3478)
Incremental changes as a result of using these recently. See commits for the changes.
2 parents c3c510a + 81dae9b commit 58eedcd

6 files changed

Lines changed: 179 additions & 119 deletions

File tree

Lines changed: 57 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,41 @@
88
#
99
# Usage from the Rails console:
1010
#
11-
# # By default it uses existing locations in the db.
12-
# Generate::PatientImports.call
11+
# Create a cohort import of 1000 children for all the school sessions for the
12+
# org A9A5A in the local db:
13+
#
14+
# Generate::CohortImports.call(patient_count: 1000)
15+
#
16+
# You can also generate a cohort import for sessions not in the local db.
17+
#
18+
# Generate::CohortImports.call(
19+
# patient_count: 1000,
20+
# urns: ["123456", "987654"],
21+
# school_year_groups: {
22+
# "123456" => [-2, -1, 0, 1, 2, 3, 4, 5, 6],
23+
# "987654" => [9, 10, 11, 12, 13]
24+
# }
25+
# )
26+
#
27+
# You can pull out the year groups with the following:
28+
#
29+
# org = Organisation.find_by(ods_code: "A9A5A")
30+
# org.locations.school.pluck(:urn, :year_groups) .to_h
1331
#
1432
module Generate
15-
class PatientImports
16-
attr_reader :ods_code, :organisation, :programme, :urns, :patient_count
33+
class CohortImports
34+
attr_reader :ods_code,
35+
:organisation,
36+
:programme,
37+
:urns,
38+
:patient_count,
39+
:school_year_groups
1740

1841
def initialize(
1942
ods_code: "A9A5A",
2043
programme: "hpv",
2144
urns: nil,
45+
school_year_groups: nil,
2246
patient_count: 10
2347
)
2448
@organisation = Organisation.find_by(ods_code:)
@@ -30,19 +54,19 @@ def initialize(
3054
.select { it.urn.present? }
3155
.sample(3)
3256
.pluck(:urn)
57+
@school_year_groups = school_year_groups
3358
@patient_count = patient_count
59+
@nhs_numbers = Set.new
3460
end
3561

3662
def self.call(...) = new(...).call
3763

3864
def call
39-
generate
4065
write_cohort_import_csv
41-
write_class_import_csv
4266
end
4367

4468
def patients
45-
@patients = patient_count.times.map { build_patient }
69+
patient_count.times.lazy.map { build_patient }
4670
end
4771

4872
private
@@ -53,12 +77,6 @@ def cohort_import_csv_filepath
5377
)
5478
end
5579

56-
def class_import_csv_filepath(school:)
57-
Rails.root.join(
58-
"tmp/perf-test-class-import-#{school.name}-#{school.sessions.first.slug}.csv"
59-
)
60-
end
61-
6280
def write_cohort_import_csv
6381
CSV.open(cohort_import_csv_filepath, "w") do |csv|
6482
csv << %w[
@@ -105,40 +123,7 @@ def write_cohort_import_csv
105123
]
106124
end
107125
end
108-
end
109-
110-
def write_class_import_csv
111-
patients
112-
.group_by(&:school)
113-
.each do |school, school_patients|
114-
next if school.nil?
115-
116-
CSV.open(class_import_csv_filepath(school:), "w") do |csv|
117-
csv << %w[
118-
CHILD_POSTCODE
119-
CHILD_DATE_OF_BIRTH
120-
CHILD_FIRST_NAME
121-
CHILD_LAST_NAME
122-
PARENT_1_EMAIL
123-
PARENT_1_PHONE
124-
PARENT_2_EMAIL
125-
PARENT_2_PHONE
126-
]
127-
128-
school_patients.each do |patient|
129-
csv << [
130-
patient.address_postcode,
131-
patient.date_of_birth,
132-
patient.given_name,
133-
patient.family_name,
134-
patient.parents.first&.email,
135-
patient.parents.first&.phone,
136-
patient.parents.second&.email,
137-
patient.parents.second&.phone
138-
]
139-
end
140-
end
141-
end
126+
cohort_import_csv_filepath.to_s
142127
end
143128

144129
def programme_year_groups
@@ -147,28 +132,46 @@ def programme_year_groups
147132

148133
def schools_with_year_groups
149134
@schools_with_year_groups ||=
150-
organisation
151-
.locations
152-
.includes(:organisation, :sessions)
153-
.select { (it.year_groups & programme_year_groups).any? }
135+
begin
136+
locations =
137+
if school_year_groups.present?
138+
urns.map do |urn|
139+
Location.new(urn:, year_groups: school_year_groups[urn])
140+
end
141+
else
142+
organisation
143+
.locations
144+
.where(urn: urns)
145+
.includes(:organisation, :sessions)
146+
end
147+
locations.select { (it.year_groups & programme_year_groups).any? }
148+
end
154149
end
155150

156-
def build_patient(year_group: nil)
151+
def build_patient
157152
school = schools_with_year_groups.sample
158153
year_group ||= (school.year_groups & programme_year_groups).sample
154+
nhs_number = nil
155+
loop do
156+
nhs_number = Faker::NationalHealthService.british_number.gsub(" ", "")
157+
break unless nhs_number.in? @nhs_numbers
158+
end
159+
@nhs_numbers << nhs_number
159160

160161
FactoryBot
161162
.build(
162163
:patient,
163164
school:,
164-
date_of_birth: date_of_birth_for_year(year_group)
165+
organisation:,
166+
date_of_birth: date_of_birth_for_year(year_group),
167+
nhs_number:
165168
)
166169
.tap do |patient|
167170
patient.parents =
168171
FactoryBot.build_list(:parent, 2, family_name: patient.family_name)
169172
patient.parent_relationships =
170173
patient.parents.map do
171-
FactoryBot.build(:parent_relationship, parent: it)
174+
FactoryBot.build(:parent_relationship, parent: it, patient:)
172175
end
173176
end
174177
end

lib/generate/consents.rb

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ def initialize(
1212
given: 0,
1313
given_needs_triage: 0
1414
)
15+
validate_programme_and_session(programme, session) if programme
16+
1517
@organisation = organisation
1618
@programme = programme || organisation.programmes.sample
1719
@session = session
@@ -24,18 +26,34 @@ def call
2426
create_consent_with_response(:refused, @refused)
2527
create_consent_with_response(:given, @given)
2628
create_consent_given_needs_triage(@given_needs_triage)
29+
StatusUpdater.call(patient: patients)
2730
end
2831

2932
def self.call(...) = new(...).call
3033

3134
private
3235

3336
def patients
34-
(@session.presence || organisation)
35-
.patients
36-
.includes(:parents, :consents, consents: :parent)
37-
.in_programmes([programme])
38-
.select { it.consents.empty? && it.parents.any? }
37+
@patients ||=
38+
begin
39+
sessions =
40+
if @session
41+
[@session]
42+
else
43+
organisation
44+
.sessions
45+
.eager_load(:location)
46+
.merge(Location.school)
47+
.has_programme(programme)
48+
end
49+
50+
sessions.flat_map do |session|
51+
session
52+
.patients
53+
.includes(:parents, :school, :consents, consents: :parent)
54+
.select { it.consents.empty? && it.parents.any? }
55+
end
56+
end
3957
end
4058

4159
def random_patients(count)
@@ -50,12 +68,13 @@ def random_patients(count)
5068
end
5169

5270
def session_for(patient)
53-
patient
54-
.sessions
55-
.eager_load(:location)
56-
.merge(Location.school)
57-
.has_programme(programme)
58-
.sample
71+
@session ||
72+
patient
73+
.sessions
74+
.eager_load(:location)
75+
.merge(Location.school)
76+
.has_programme(programme)
77+
.sample
5978
end
6079

6180
def create_consent_with_response(response, count)
@@ -64,11 +83,13 @@ def create_consent_with_response(response, count)
6483

6584
available_patient_sessions.each do |patient, session|
6685
consent = FactoryBot.create(:consent, response, patient:, programme:)
86+
school = session.location.school? ? session.location : patient.school
6787
FactoryBot.create(
6888
:consent_form,
6989
organisation:,
7090
programmes: [programme],
7191
session:,
92+
school:,
7293
consent:,
7394
response:
7495
)
@@ -98,5 +119,15 @@ def create_consent_given_needs_triage(count)
98119
)
99120
end
100121
end
122+
123+
def validate_programme_and_session(programme, session)
124+
if session
125+
if session.programmes.exclude?(programme)
126+
raise "Session does not support programme #{programme.type}"
127+
end
128+
elsif programme.sessions.none? { it.location.school? }
129+
raise "Programme #{programme.type} does not have a school session"
130+
end
131+
end
101132
end
102133
end

0 commit comments

Comments
 (0)