@@ -12,84 +12,120 @@ def call = create_vaccinations
1212
1313 def self . call ( ...) = new ( ...) . call
1414
15+ class NotEnoughAvailablePatients < StandardError
16+ end
17+
18+ class SessionHasNoDates < StandardError
19+ end
20+
21+ class NoSessionsWithDates < StandardError
22+ end
23+
24+ class NoSessionsWithPatients < StandardError
25+ end
26+
1527 private
1628
1729 attr_reader :config , :team , :programme , :session , :administered
1830
1931 def create_vaccinations
20- attendance_records = [ ]
21- vaccination_records = [ ]
22-
23- sessions . each do |session |
24- location = session . location
25-
26- random_patients_for ( session :) . each do |patient |
27- unless AttendanceRecord . exists? ( patient :, location :)
28- attendance_records << FactoryBot . build (
29- :attendance_record ,
30- :present ,
31- patient :,
32- session :
33- )
34- end
35-
36- location_name = location . name if session . clinic?
37-
38- vaccination_records << FactoryBot . build (
39- :vaccination_record ,
40- :administered ,
41- patient :,
42- programme :,
43- team :,
44- performed_by :,
45- session :,
46- vaccine :,
47- batch :,
48- location_name :
49- )
50- end
32+ attendances = [ ]
33+ vaccinations = [ ]
34+
35+ check_sessions_have_enough_patients
36+
37+ each_random_patient_ready_for_vaccination (
38+ administered
39+ ) do |session , patient |
40+ attendance , vaccination =
41+ create_administered_vaccination ( session , patient )
42+
43+ attendances << attendance if attendance . present?
44+ vaccinations << vaccination
5145 end
5246
53- AttendanceRecord . import! ( attendance_records )
54- imported_ids = VaccinationRecord . import! ( vaccination_records ) . ids
47+ AttendanceRecord . import! ( attendances )
48+ imported_ids = VaccinationRecord . import! ( vaccinations ) . ids
5549 SyncPatientTeamJob . perform_later ( VaccinationRecord , imported_ids )
5650
57- StatusUpdater . call ( patient : vaccination_records . map ( &:patient ) )
51+ StatusUpdater . call ( patient : vaccinations . map ( &:patient ) )
5852 end
5953
60- def random_patients_for ( session :)
61- if administered &.positive?
62- patients_for ( session :)
63- . sample ( administered )
64- . tap do |selected |
65- if selected . size < administered
66- info =
67- "#{ selected . size } (patient_locations) < #{ administered } (administered)"
68- raise "Not enough patients to generate vaccinations: #{ info } "
69- end
70- end
71- else
72- patients_for ( session :)
54+ def check_sessions_have_enough_patients
55+ available_patients = sessions . sum { patients_for ( session : it ) . count }
56+ if available_patients < administered
57+ info =
58+ "#{ available_patients } (available patients) < #{ administered } (administered)"
59+ raise NotEnoughAvailablePatients , info
7360 end
7461 end
7562
63+ def each_random_patient_ready_for_vaccination ( count )
64+ count . times do
65+ session = sessions . sample
66+ patients = patients_for ( session :)
67+
68+ patient = patients . sample
69+
70+ yield session , patient
71+
72+ patients . delete ( patient )
73+ sessions . delete ( session ) if patients . empty?
74+ end
75+ end
76+
77+ def create_administered_vaccination ( session , patient )
78+ location = session . location
79+
80+ attendance = nil
81+
82+ unless AttendanceRecord . exists? ( patient :, location :)
83+ attendance =
84+ FactoryBot . build ( :attendance_record , :present , patient :, session :)
85+ end
86+
87+ location_name = location . name if session . clinic?
88+
89+ vaccination =
90+ FactoryBot . build (
91+ :vaccination_record ,
92+ :administered ,
93+ patient :,
94+ programme :,
95+ team :,
96+ performed_by :,
97+ session :,
98+ vaccine :,
99+ batch :,
100+ location_name :
101+ )
102+
103+ [ attendance , vaccination ]
104+ end
105+
76106 def sessions
77107 @sessions ||=
78108 if session
109+ raise SessionHasNoDates , session . id if session . dates . empty?
79110 [ session ]
80111 else
81- team . sessions . includes (
82- :location ,
83- :session_programme_year_groups ,
84- :team_location
85- )
112+ team
113+ . sessions
114+ . where . not ( dates : [ ] )
115+ . tap { raise NoSessionsWithDates if it . empty? }
116+ . includes ( :location , :session_programme_year_groups , :team_location )
117+ . select { patients_for ( session : it ) . any? }
118+ . tap { raise NoSessionsWithPatients if it . empty? }
86119 end
87120 end
88121
89122 def patients_for ( session :)
123+ @patients_for ||= { }
124+ return @patients_for [ session . id ] if @patients_for . key? ( session . id )
125+
90126 academic_year = session . academic_year
91127
92- session
128+ @patients_for [ session . id ] = session
93129 . patients
94130 . includes_statuses
95131 . appear_in_programmes ( [ programme ] , academic_year :)
0 commit comments