his_emr_api_lab 1.1.21 → 1.1.22

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. metadata +3 -82
  3. data/MIT-LICENSE +0 -20
  4. data/README.md +0 -71
  5. data/Rakefile +0 -32
  6. data/app/controllers/lab/application_controller.rb +0 -6
  7. data/app/controllers/lab/labels_controller.rb +0 -17
  8. data/app/controllers/lab/orders_controller.rb +0 -38
  9. data/app/controllers/lab/reasons_for_test_controller.rb +0 -9
  10. data/app/controllers/lab/results_controller.rb +0 -19
  11. data/app/controllers/lab/specimen_types_controller.rb +0 -15
  12. data/app/controllers/lab/test_result_indicators_controller.rb +0 -9
  13. data/app/controllers/lab/test_types_controller.rb +0 -15
  14. data/app/controllers/lab/tests_controller.rb +0 -26
  15. data/app/jobs/lab/application_job.rb +0 -4
  16. data/app/jobs/lab/push_order_job.rb +0 -12
  17. data/app/jobs/lab/update_patient_orders_job.rb +0 -32
  18. data/app/jobs/lab/void_order_job.rb +0 -17
  19. data/app/mailers/lab/application_mailer.rb +0 -6
  20. data/app/models/lab/application_record.rb +0 -5
  21. data/app/models/lab/lab_accession_number_counter.rb +0 -13
  22. data/app/models/lab/lab_encounter.rb +0 -7
  23. data/app/models/lab/lab_order.rb +0 -58
  24. data/app/models/lab/lab_result.rb +0 -31
  25. data/app/models/lab/lab_test.rb +0 -19
  26. data/app/models/lab/lims_failed_import.rb +0 -4
  27. data/app/models/lab/lims_order_mapping.rb +0 -10
  28. data/app/serializers/lab/lab_order_serializer.rb +0 -55
  29. data/app/serializers/lab/result_serializer.rb +0 -36
  30. data/app/serializers/lab/test_serializer.rb +0 -29
  31. data/app/services/lab/accession_number_service.rb +0 -77
  32. data/app/services/lab/concepts_service.rb +0 -82
  33. data/app/services/lab/labelling_service/order_label.rb +0 -106
  34. data/app/services/lab/lims/api/blackhole_api.rb +0 -21
  35. data/app/services/lab/lims/api/couchdb_api.rb +0 -53
  36. data/app/services/lab/lims/api/mysql_api.rb +0 -316
  37. data/app/services/lab/lims/api/rest_api.rb +0 -416
  38. data/app/services/lab/lims/api/ws_api.rb +0 -121
  39. data/app/services/lab/lims/api_factory.rb +0 -19
  40. data/app/services/lab/lims/config.rb +0 -100
  41. data/app/services/lab/lims/exceptions.rb +0 -11
  42. data/app/services/lab/lims/migrator.rb +0 -216
  43. data/app/services/lab/lims/order_dto.rb +0 -105
  44. data/app/services/lab/lims/order_serializer.rb +0 -244
  45. data/app/services/lab/lims/pull_worker.rb +0 -289
  46. data/app/services/lab/lims/push_worker.rb +0 -149
  47. data/app/services/lab/lims/utils.rb +0 -91
  48. data/app/services/lab/lims/worker.rb +0 -86
  49. data/app/services/lab/metadata.rb +0 -24
  50. data/app/services/lab/orders_search_service.rb +0 -66
  51. data/app/services/lab/orders_service.rb +0 -212
  52. data/app/services/lab/results_service.rb +0 -147
  53. data/app/services/lab/tests_service.rb +0 -93
  54. data/config/routes.rb +0 -17
  55. data/db/migrate/20210126092910_create_lab_lab_accession_number_counters.rb +0 -12
  56. data/db/migrate/20210310115457_create_lab_lims_order_mappings.rb +0 -15
  57. data/db/migrate/20210323080140_change_lims_id_to_string_in_lims_order_mapping.rb +0 -15
  58. data/db/migrate/20210326195504_add_order_revision_to_lims_order_mapping.rb +0 -5
  59. data/db/migrate/20210407071728_create_lab_lims_failed_imports.rb +0 -19
  60. data/db/migrate/20210610095024_fix_numeric_results_value_type.rb +0 -20
  61. data/db/migrate/20210807111531_add_default_to_lims_order_mapping.rb +0 -7
  62. data/lib/auto12epl.rb +0 -201
  63. data/lib/couch_bum/couch_bum.rb +0 -92
  64. data/lib/generators/lab/install/USAGE +0 -9
  65. data/lib/generators/lab/install/install_generator.rb +0 -19
  66. data/lib/generators/lab/install/templates/rswag-ui-lab.rb +0 -5
  67. data/lib/generators/lab/install/templates/start_worker.rb +0 -32
  68. data/lib/generators/lab/install/templates/swagger.yaml +0 -714
  69. data/lib/his_emr_api_lab.rb +0 -5
  70. data/lib/lab/engine.rb +0 -15
  71. data/lib/lab/version.rb +0 -5
  72. data/lib/logger_multiplexor.rb +0 -38
  73. data/lib/tasks/lab_tasks.rake +0 -25
  74. data/lib/tasks/loaders/data/reasons-for-test.csv +0 -7
  75. data/lib/tasks/loaders/data/test-measures.csv +0 -225
  76. data/lib/tasks/loaders/data/tests.csv +0 -161
  77. data/lib/tasks/loaders/loader_mixin.rb +0 -53
  78. data/lib/tasks/loaders/metadata_loader.rb +0 -26
  79. data/lib/tasks/loaders/reasons_for_test_loader.rb +0 -23
  80. data/lib/tasks/loaders/specimens_loader.rb +0 -65
  81. data/lib/tasks/loaders/test_result_indicators_loader.rb +0 -54
@@ -1,216 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'csv'
4
- require 'parallel'
5
-
6
- require 'couch_bum/couch_bum'
7
- require 'logger_multiplexor'
8
-
9
- require 'concept'
10
- require 'concept_name'
11
- require 'drug_order'
12
- require 'encounter'
13
- require 'encounter_type'
14
- require 'observation'
15
- require 'order'
16
- require 'order_type'
17
- require 'patient'
18
- require 'patient_identifier'
19
- require 'patient_identifier_type'
20
- require 'person'
21
- require 'person_name'
22
- require 'program'
23
- require 'user'
24
-
25
- require 'lab/lab_encounter'
26
- require 'lab/lab_order'
27
- require 'lab/lab_result'
28
- require 'lab/lab_test'
29
- require 'lab/lims_order_mapping'
30
- require 'lab/lims_failed_import'
31
-
32
- require_relative './api/couchdb_api'
33
- require_relative './config'
34
- require_relative './pull_worker'
35
- require_relative './utils'
36
-
37
- require_relative '../orders_service'
38
- require_relative '../results_service'
39
- require_relative '../tests_service'
40
- require_relative '../../../serializers/lab/lab_order_serializer'
41
- require_relative '../../../serializers/lab/result_serializer'
42
- require_relative '../../../serializers/lab/test_serializer'
43
-
44
- require_relative 'order_dto'
45
- require_relative 'utils'
46
-
47
- module Lab
48
- module Lims
49
- ##
50
- # Tools for performing a bulk import of data from LIMS' databases to local OpenMRS database.
51
- #
52
- # Migration sources supported:
53
- # - MySQL
54
- # - CouchDB
55
- #
56
- # The sources above can be changed by setting the environment various MIGRATION_SOURCE to
57
- # either mysql or couchdb.
58
- module Migrator
59
- MAX_THREADS = ENV.fetch('MIGRATION_WORKERS', 6).to_i
60
-
61
- ##
62
- # A Lab::Lims::Api object that supports crawling of a LIMS CouchDB instance.
63
- class CouchDbMigratorApi < Lab::Lims::Api::CouchDbApi
64
- def initialize(*args, processes: 1, on_merge_processes: nil, **kwargs)
65
- super(*args, **kwargs)
66
-
67
- @processes = processes
68
- @on_merge_processes = on_merge_processes
69
- end
70
-
71
- def consume_orders(from: nil, **_kwargs)
72
- limit = 25_000
73
-
74
- loop do
75
- on_merge_processes = ->(_item, index, _result) { @on_merge_processes&.call(from + index) }
76
- processes = @processes > 1 ? @processes : 0
77
-
78
- orders = read_orders(from, limit)
79
- break if orders.empty?
80
-
81
- Parallel.each(orders, in_processes: processes, finish: on_merge_processes) do |row|
82
- next unless row['doc']['type']&.casecmp?('Order')
83
-
84
- User.current = Utils.lab_user
85
- yield OrderDTO.new(row['doc']), OpenStruct.new(last_seq: (from || 0) + limit, current_seq: from)
86
- end
87
-
88
- from += orders.size
89
- end
90
- end
91
-
92
- private
93
-
94
- def read_orders(from, batch_size)
95
- start_key_param = from ? "&skip=#{from}" : ''
96
- url = "_all_docs?include_docs=true&limit=#{batch_size}#{start_key_param}"
97
-
98
- Rails.logger.debug("#{CouchDbMigratorApi}: Pulling orders from LIMS CouchDB: #{url}")
99
- response = bum.couch_rest :get, url
100
-
101
- response['rows']
102
- end
103
- end
104
-
105
- ##
106
- # Extends the PullWorker to provide pause/resume capabilities.
107
- #
108
- # Migrations can be take a long time to complete, in cases where something
109
- # went wrong you wouldn't to start all over. This worker thus saves
110
- # progress and allows for the process to continue from whether it stopped.
111
- class MigrationWorker < PullWorker
112
- LOG_FILE_PATH = Utils::LIMS_LOG_PATH.join('migration-last-id.dat')
113
-
114
- attr_reader :rejections
115
-
116
- def initialize(api_class)
117
- api = api_class.new(processes: MAX_THREADS, on_merge_processes: method(:save_seq))
118
- super(api)
119
- end
120
-
121
- def last_seq
122
- return 0 unless File.exist?(LOG_FILE_PATH)
123
-
124
- File.open(LOG_FILE_PATH, File::RDONLY) do |file|
125
- last_seq = file.read&.strip
126
- return last_seq.blank? ? nil : last_seq&.to_i
127
- end
128
- end
129
-
130
- private
131
-
132
- def save_seq(last_seq)
133
- File.open(LOG_FILE_PATH, File::WRONLY | File::CREAT, 0o644) do |file|
134
- Rails.logger.debug("Process ##{Parallel.worker_number}: Saving last seq: #{last_seq}")
135
- file.flock(File::LOCK_EX)
136
- file.write(last_seq.to_s)
137
- file.flush
138
- end
139
- end
140
-
141
- def order_rejected(order_dto, reason)
142
- @rejections ||= []
143
-
144
- @rejections << OpenStruct.new(order: order_dto, reason: reason)
145
- end
146
- end
147
-
148
- def self.save_csv(filename, rows:, headers: nil)
149
- CSV.open(filename, File::WRONLY | File::CREAT) do |csv|
150
- csv << headers if headers
151
- rows.each { |row| csv << row }
152
- end
153
- end
154
-
155
- # NOTE: LIMS_LOG_PATH below is defined in worker.rb
156
- MIGRATION_REJECTIONS_CSV_PATH = Utils::LIMS_LOG_PATH.join('migration-rejections.csv')
157
-
158
- def self.export_rejections(rejections)
159
- headers = ['doc_id', 'Accession number', 'NHID', 'First name', 'Last name', 'Reason']
160
- rows = (rejections || []).map do |rejection|
161
- [
162
- rejection.order[:_id],
163
- rejection.order[:tracking_number],
164
- rejection.order[:patient][:id],
165
- rejection.order[:patient][:first_name],
166
- rejection.order[:patient][:last_name],
167
- rejection.reason
168
- ]
169
- end
170
-
171
- save_csv(MIGRATION_REJECTIONS_CSV_PATH, headers: headers, rows: rows)
172
- end
173
-
174
- MIGRATION_FAILURES_CSV_PATH = Utils::LIMS_LOG_PATH.join('migration-failures.csv')
175
-
176
- def self.export_failures
177
- headers = ['doc_id', 'Accession number', 'NHID', 'Reason', 'Difference']
178
- rows = Lab::LimsFailedImport.all.map do |failure|
179
- [
180
- failure.lims_id,
181
- failure.tracking_number,
182
- failure.patient_nhid,
183
- failure.reason,
184
- failure.diff
185
- ]
186
- end
187
-
188
- save_csv(MIGRATION_FAILURES_CSV_PATH, headers: headers, rows: rows)
189
- end
190
-
191
- MIGRATION_LOG_PATH = Utils::LIMS_LOG_PATH.join('migration.log')
192
-
193
- def self.start_migration
194
- Dir.mkdir(Utils::LIMS_LOG_PATH) unless File.exist?(Utils::LIMS_LOG_PATH)
195
-
196
- logger = LoggerMultiplexor.new(Logger.new($stdout), MIGRATION_LOG_PATH)
197
- logger.level = :debug
198
- Rails.logger = logger
199
- ActiveRecord::Base.logger = logger
200
- # CouchBum.logger = logger
201
-
202
- api_class = case ENV.fetch('MIGRATION_SOURCE', 'couchdb').downcase
203
- when 'couchdb' then CouchDbMigratorApi
204
- when 'mysql' then Api::MysqlApi
205
- else raise "Invalid MIGRATION_SOURCE: #{ENV['MIGRATION_SOURCE']}"
206
- end
207
-
208
- worker = MigrationWorker.new(api_class)
209
- worker.pull_orders(batch_size: 10_000)
210
- ensure
211
- worker && export_rejections(worker.rejections)
212
- export_failures
213
- end
214
- end
215
- end
216
- end
@@ -1,105 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative './exceptions'
4
-
5
- module Lab
6
- module Lims
7
- ##
8
- # LIMS' Data Transfer Object for orders
9
- class OrderDTO < ActiveSupport::HashWithIndifferentAccess
10
- include Utils
11
-
12
- ##
13
- # Unpacks a LIMS order into an object that OrdersService can handle
14
- def to_order_service_params(patient_id:)
15
- ActiveSupport::HashWithIndifferentAccess.new(
16
- program_id: lab_program.program_id,
17
- accession_number: self['tracking_number'],
18
- patient_id: patient_id,
19
- specimen: { concept_id: specimen_type_id },
20
- tests: self['tests']&.map { |test| { concept_id: test_type_id(test) } },
21
- requesting_clinician: requesting_clinician,
22
- date: start_date,
23
- target_lab: facility_name(self['receiving_facility']),
24
- order_location: facility_name(self['sending_facility']),
25
- reason_for_test_id: reason_for_test
26
- )
27
- end
28
-
29
- private
30
-
31
- # Translates a LIMS specimen name to an OpenMRS concept_id
32
- def specimen_type_id
33
- lims_specimen_name = self['sample_type']&.strip&.downcase
34
-
35
- if lims_specimen_name.nil? || %w[specimen_not_collected not_assigned not_specified].include?(lims_specimen_name)
36
- return ConceptName.select(:concept_id).find_by_name!('Unknown').concept_id
37
- end
38
-
39
- concept = Utils.find_concept_by_name(lims_specimen_name)
40
- return concept.concept_id if concept
41
-
42
- raise UnknownSpecimenType, "Unknown specimen name: #{lims_specimen_name}"
43
- end
44
-
45
- # Translates a LIMS test type name to an OpenMRS concept_id
46
- def test_type_id(lims_test_name)
47
- lims_test_name = Utils.translate_test_name(lims_test_name)
48
- concept = Utils.find_concept_by_name(lims_test_name)
49
- return concept.concept_id if concept
50
-
51
- raise UnknownTestType, "Unknown test type: #{lims_test_name}"
52
- end
53
-
54
- # Extract requesting clinician name from LIMS
55
- def requesting_clinician
56
- return 'Unknown' unless self['who_order_test']
57
-
58
- # TODO: Extend requesting clinician to an obs tree having extra parameters
59
- # like phone number and ID to closely match the lims user.
60
- first_name = self['who_order_test']['first_name'] || ''
61
- last_name = self['who_order_test']['last_name'] || ''
62
-
63
- if first_name.blank? && last_name.blank?
64
- logger.warn('Missing requesting clinician name')
65
- return ''
66
- end
67
-
68
- "#{first_name} #{last_name}"
69
- end
70
-
71
- def start_date
72
- raise LimsException, 'Order missing created date' if self['date_created'].blank?
73
-
74
- Utils.parse_date(self['date_created'])
75
- end
76
-
77
- # Parses a LIMS facility name
78
- def facility_name(lims_target_lab)
79
- return 'Unknown' if lims_target_lab == 'not_assigned'
80
-
81
- lims_target_lab
82
- end
83
-
84
- # Translates a LIMS sample priority to a concept_id
85
- def reason_for_test
86
- return nil unless self['priority']
87
-
88
- name = case self['priority']
89
- when %r{Reapet / Missing}i then 'Repeat / Missing'
90
- else self['priority']
91
- end
92
-
93
- ConceptName.find_by_name!(name).concept_id
94
- end
95
-
96
- def lab_program
97
- Program.find_by_name!(Lab::Metadata::LAB_PROGRAM_NAME)
98
- end
99
-
100
- def unknown_concept
101
- ConceptName.find_by_name!('Unknown')
102
- end
103
- end
104
- end
105
- end
@@ -1,244 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative './config'
4
- require_relative './order_dto'
5
- require_relative './utils'
6
-
7
- module Lab
8
- module Lims
9
- ##
10
- # Serializes a LabOrder into a LIMS OrderDTO.
11
- module OrderSerializer
12
- class << self
13
- include Utils
14
-
15
- def serialize_order(order)
16
- serialized_order = Lims::Utils.structify(Lab::LabOrderSerializer.serialize_order(order))
17
-
18
- Lims::OrderDTO.new(
19
- _id: Lab::LimsOrderMapping.find_by(order: order)&.lims_id || serialized_order.accession_number,
20
- tracking_number: serialized_order.accession_number,
21
- sending_facility: current_facility_name,
22
- receiving_facility: serialized_order.target_lab,
23
- tests: serialized_order.tests.map { |test| format_test_name(test.name) },
24
- patient: format_patient(serialized_order.patient_id),
25
- order_location: format_order_location(serialized_order.encounter_id),
26
- sample_type: format_sample_type(serialized_order.specimen.name),
27
- sample_status: format_sample_status(serialized_order.specimen.name),
28
- sample_statuses: format_sample_status_trail(order),
29
- test_statuses: format_test_status_trail(order),
30
- who_order_test: format_orderer(order),
31
- districy: current_district, # yes districy [sic]...
32
- priority: format_sample_priority(serialized_order.reason_for_test.name),
33
- date_created: serialized_order.order_date,
34
- test_results: format_test_results(serialized_order),
35
- type: 'Order'
36
- )
37
- end
38
-
39
- private
40
-
41
- def format_order_location(encounter_id)
42
- location_id = Encounter.select(:location_id).where(encounter_id: encounter_id)
43
- location = Location.select(:name)
44
- .where(location_id: location_id)
45
- .first
46
-
47
- location&.name
48
- end
49
-
50
- # Format patient into a structure that LIMS expects
51
- def format_patient(patient_id)
52
- person = Person.find(patient_id)
53
- name = PersonName.find_by_person_id(patient_id)
54
- national_id = PatientIdentifier.joins(:type)
55
- .merge(PatientIdentifierType.where(name: 'National ID'))
56
- .where(patient_id: patient_id)
57
- .first
58
- phone_number = PersonAttribute.joins(:type)
59
- .merge(PersonAttributeType.where(name: 'Cell phone Number'))
60
- .where(person_id: patient_id)
61
- .first
62
-
63
- {
64
- first_name: name&.given_name,
65
- last_name: name&.family_name,
66
- id: national_id&.identifier,
67
- arv_number: find_arv_number(patient_id),
68
- art_regimen: find_current_regimen(patient_id),
69
- art_start_date: find_art_start_date(patient_id),
70
- phone_number: phone_number&.value || 'Unknown',
71
- gender: person.gender,
72
- email: nil
73
- }
74
- end
75
-
76
- def find_current_regimen(patient_id)
77
- regimen_data = ActiveRecord::Base.connection.select_one <<~SQL
78
- SELECT patient_current_regimen(#{patient_id}, current_date()) regimen
79
- SQL
80
- return nil if regimen_data.blank?
81
-
82
- regimen_data['regimen']
83
- end
84
-
85
- def find_arv_number(patient_id)
86
- PatientIdentifier.joins(:type)
87
- .merge(PatientIdentifierType.where(name: 'ARV Number'))
88
- .where(patient_id: patient_id)
89
- .first&.identifier
90
- end
91
-
92
- def find_art_start_date(patient_id)
93
- start_date = ActiveRecord::Base.connection.select_one <<~SQL
94
- SELECT date_antiretrovirals_started(#{patient_id}, current_date()) AS earliest_date
95
- SQL
96
- return nil if start_date.blank?
97
-
98
- start_date['earliest_date']
99
- end
100
-
101
- def format_sample_type(name)
102
- return 'not_specified' if name.casecmp?('Unknown')
103
-
104
- return 'CSF' if name.casecmp?('Cerebrospinal Fluid')
105
-
106
- name.titleize
107
- end
108
-
109
- def format_sample_status(name)
110
- name.casecmp?('Unknown') ? 'specimen_not_collected' : 'specimen_collected'
111
- end
112
-
113
- def format_sample_status_trail(order)
114
- return [] if order.concept_id == ConceptName.find_by_name!('Unknown').concept_id
115
-
116
- user = User.find(order.discontinued_by || order.creator)
117
- drawn_by = PersonName.find_by_person_id(user.user_id)
118
- drawn_date = order.discontinued_date || order.start_date
119
-
120
- [
121
- drawn_date.strftime('%Y%m%d%H%M%S') => {
122
- 'status' => 'Drawn',
123
- 'updated_by' => {
124
- 'first_name' => drawn_by&.given_name || user.username,
125
- 'last_name' => drawn_by&.family_name,
126
- 'phone_number' => nil,
127
- 'id' => user.username
128
- }
129
- }
130
- ]
131
- end
132
-
133
- def format_test_status_trail(order)
134
- tests = order.voided.zero? ? order.tests : Lab::LabOrderSerializer.voided_tests(order)
135
-
136
- tests.each_with_object({}) do |test, trail|
137
- test_name = format_test_name(ConceptName.find_by_concept_id!(test.value_coded).name)
138
-
139
- current_test_trail = trail[test_name] = {}
140
-
141
- current_test_trail[test.obs_datetime.strftime('%Y%m%d%H%M%S')] = {
142
- status: 'Drawn',
143
- updated_by: find_user(test.creator)
144
- }
145
-
146
- unless test.voided.zero?
147
- current_test_trail[test.date_voided.strftime('%Y%m%d%H%M%S')] = {
148
- status: 'Voided',
149
- updated_by: find_user(test.voided_by)
150
- }
151
- end
152
-
153
- next unless test.result
154
-
155
- current_test_trail[test.obs_datetime.strftime('%Y%m%d%H%M%S')] = {
156
- status: 'Verified',
157
- updated_by: find_user(test.result.creator)
158
- }
159
- end
160
- end
161
-
162
- def format_orderer(order)
163
- find_user(order.creator)
164
- end
165
-
166
- def format_test_results(order)
167
- order.tests&.each_with_object({}) do |test, results|
168
- next if test.result.nil? || test.result.empty?
169
-
170
- test_creator = User.find(Observation.find(test.result.first.id).creator)
171
- test_creator_name = PersonName.find_by_person_id(test_creator.person_id)
172
-
173
- results[format_test_name(test.name)] = {
174
- results: test.result.each_with_object({}) do |measure, measures|
175
- measures[format_test_name(measure.indicator.name)] = {
176
- result_value: "#{measure.value_modifier}#{measure.value}"
177
- }
178
- end,
179
- result_date: test.result.first&.date,
180
- result_entered_by: {
181
- first_name: test_creator_name&.given_name,
182
- last_name: test_creator_name&.family_name,
183
- id: test_creator.username
184
- }
185
- }
186
- end
187
- end
188
-
189
- def format_test_name(test_name)
190
- return 'Viral Load' if test_name.casecmp?('HIV Viral load')
191
-
192
- return 'TB' if test_name.casecmp?('TB Program')
193
-
194
- test_name.titleize
195
- end
196
-
197
- def format_sample_priority(priority)
198
- return 'Routine' if priority&.casecmp?('Medical examination, routine')
199
-
200
- priority&.titleize
201
- end
202
-
203
- def current_health_center
204
- health_center = Location.current_health_center
205
- raise 'Current health center not set' unless health_center
206
-
207
- health_center
208
- end
209
-
210
- def current_district
211
- district = current_health_center.city_village\
212
- || current_health_center.parent&.name\
213
- || GlobalProperty.find_by_property('current_health_center_district')&.property_value
214
-
215
- return district if district
216
-
217
- GlobalProperty.create(property: 'current_health_center_district',
218
- property_value: Lims::Config.application['district'],
219
- uuid: SecureRandom.uuid)
220
-
221
- Config.application['district']
222
- end
223
-
224
- def current_facility_name
225
- current_health_center.name
226
- end
227
-
228
- def find_user(user_id)
229
- user = User.find(user_id)
230
- person_name = PersonName.find_by(person_id: user.person_id)
231
- phone_number = PersonAttribute.find_by(type: PersonAttributeType.where(name: 'Cell phone number'),
232
- person_id: user.person_id)
233
-
234
- {
235
- first_name: person_name&.given_name,
236
- last_name: person_name&.family_name,
237
- phone_number: phone_number&.value,
238
- id: user.username
239
- }
240
- end
241
- end
242
- end
243
- end
244
- end