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
data/lib/auto12epl.rb DELETED
@@ -1,201 +0,0 @@
1
- #!/usr/bin/ruby
2
- # Jeremy Espino MD MS
3
- # 28-JAN-2016
4
-
5
-
6
- class Float
7
- # function to round down a float to an integer value
8
- def round_down n=0
9
- n < 1 ? self.to_i.to_f : (self - 0.5 / 10**n).round(n)
10
- end
11
- end
12
-
13
- # Generates EPL code that conforms to the Auto12-A standard for specimen labeling
14
- class Auto12Epl
15
-
16
- attr_accessor :element_font
17
- attr_accessor :barcode_human_font
18
-
19
- DPI = 203
20
- LABEL_WIDTH_IN = 2.0
21
- LABEL_HEIGHT_IN = 0.5
22
-
23
- # font constants
24
- FONT_X_DOTS = [8, 10, 12, 14, 32]
25
- FONT_Y_DOTS = [12, 16, 20, 24, 24]
26
- FONT_PAD_DOTS = 2
27
-
28
- # element heights
29
- HEIGHT_MARGIN = 0.031
30
- HEIGHT_ELEMENT = 0.1
31
- HEIGHT_ELEMENT_SPACE = 0.01
32
- HEIGHT_PID = 0.1
33
- HEIGHT_BARCODE = 0.200
34
- HEIGHT_BARCODE_HUMAN = 0.050
35
-
36
- # element widths
37
- WIDTH_ELEMENT = 1.94
38
- WIDTH_BARCODE = 1.395
39
- WIDTH_BARCODE_HUMAN = 1.688
40
-
41
- # margins
42
- L_MARGIN = 0.031
43
- L_MARGIN_BARCODE = 0.25
44
-
45
- # stat locations
46
- L_MARGIN_BARCODE_W_STAT = 0.200
47
- L_MARGIN_W_STAT = 0.150
48
- STAT_WIDTH_ELEMENT = 1.78
49
- STAT_WIDTH_BARCODE = 1.150
50
- STAT_WIDTH_BARCODE_HUMAN = 1.400
51
-
52
- # constants for generated EPL code
53
- BARCODE_TYPE = '1A'
54
- BARCODE_NARROW_WIDTH = '2'
55
- BARCODE_WIDE_WIDTH = '2'
56
- BARCODE_ROTATION = '0'
57
- BARCODE_IS_HUMAN_READABLE = 'N'
58
- ASCII_HORZ_MULT = 1
59
- ASCII_VERT_MULT = 1
60
-
61
-
62
- def initialize(element_font = 1, barcode_human_font = 1)
63
- @element_font = element_font
64
- @barcode_human_font = barcode_human_font
65
- end
66
-
67
- # Calculate the number of characters that will fit in a given length
68
- def max_characters(font, length)
69
-
70
- dots_per_char = FONT_X_DOTS.at(font-1) + FONT_PAD_DOTS
71
-
72
- num_char = ( (length * DPI) / dots_per_char).round_down
73
-
74
- num_char.to_int
75
- end
76
-
77
- # Use basic truncation rule to truncate the name element i.e., if > maxCharacters cutoff and trail with +
78
- def truncate_name(last_name, first_name, middle_initial, is_stat)
79
- if is_stat
80
- name_max_characters = max_characters(@element_font, STAT_WIDTH_ELEMENT)
81
- else
82
- name_max_characters = max_characters(@element_font, WIDTH_ELEMENT)
83
- end
84
-
85
- if concatName(last_name, first_name, middle_initial).length > name_max_characters
86
- # truncate last?
87
- if last_name.length > 12
88
- last_name = last_name[0..11] + '+'
89
- end
90
-
91
- # truncate first?
92
- if concatName(last_name, first_name, middle_initial).length > name_max_characters && first_name.length > 7
93
- first_name = first_name[0..7] + '+'
94
- end
95
- end
96
-
97
- concatName(last_name, first_name, middle_initial)
98
-
99
- end
100
-
101
- def concatName(last_name, first_name, middle_initial)
102
- last_name + ', ' + first_name + (middle_initial == nil ? '' : ' ' + middle_initial)
103
- end
104
-
105
- # The main function to generate the EPL
106
- def generate_epl(last_name, first_name, middle_initial, pid, dob, age, gender, col_date_time, col_name, tests, stat, acc_num, schema_track)
107
-
108
- # format text and set margin
109
- if stat == nil
110
- name_text = truncate_name(last_name, first_name, middle_initial, false)
111
- pid_dob_age_gender_text = full_justify(pid, dob + ' ' + age + ' ' + gender, @element_font, WIDTH_ELEMENT)
112
- l_margin = L_MARGIN
113
- l_margin_barcode = L_MARGIN_BARCODE
114
- else
115
- name_text = truncate_name(last_name, first_name, middle_initial, true)
116
- pid_dob_age_gender_text = full_justify(pid, dob + ' ' + age + ' ' + gender, @element_font, STAT_WIDTH_ELEMENT)
117
- stat_element_text = pad_stat_w_space(stat)
118
- l_margin = L_MARGIN_W_STAT
119
- l_margin_barcode = L_MARGIN_BARCODE_W_STAT
120
- end
121
- barcode_human_text = "#{acc_num} * #{schema_track.gsub(/\-/i, '')}"
122
- collector_element_text = "Col: #{col_date_time} #{col_name}"
123
- tests_element_text = tests
124
-
125
- # generate EPL statements
126
- name_element = generate_ascii_element(to_dots(l_margin), to_dots(HEIGHT_MARGIN), 0, @element_font, false, name_text)
127
- pid_dob_age_gender_element = generate_ascii_element(to_dots(l_margin), to_dots(HEIGHT_MARGIN + HEIGHT_ELEMENT + HEIGHT_ELEMENT_SPACE), 0, @element_font, false, pid_dob_age_gender_text)
128
- barcode_human_element = generate_ascii_element(to_dots(l_margin_barcode), to_dots(HEIGHT_MARGIN + HEIGHT_ELEMENT + HEIGHT_ELEMENT_SPACE + HEIGHT_ELEMENT + HEIGHT_ELEMENT_SPACE + HEIGHT_BARCODE), 0, @barcode_human_font, false, barcode_human_text)
129
- collector_element = generate_ascii_element(to_dots(l_margin), to_dots(HEIGHT_MARGIN + HEIGHT_ELEMENT + HEIGHT_ELEMENT_SPACE + HEIGHT_ELEMENT + HEIGHT_ELEMENT_SPACE + HEIGHT_BARCODE + HEIGHT_BARCODE_HUMAN + HEIGHT_ELEMENT_SPACE), 0, @element_font, false, collector_element_text)
130
- tests_element = generate_ascii_element(to_dots(l_margin), to_dots(HEIGHT_MARGIN + HEIGHT_ELEMENT + HEIGHT_ELEMENT_SPACE + HEIGHT_ELEMENT + HEIGHT_ELEMENT_SPACE + HEIGHT_BARCODE + HEIGHT_BARCODE_HUMAN + HEIGHT_ELEMENT_SPACE + HEIGHT_ELEMENT + HEIGHT_ELEMENT_SPACE), 0, @element_font, false, tests_element_text)
131
- barcode_element = generate_barcode_element(to_dots(l_margin_barcode), to_dots(HEIGHT_MARGIN + HEIGHT_ELEMENT + HEIGHT_ELEMENT_SPACE + HEIGHT_ELEMENT + HEIGHT_ELEMENT_SPACE), to_dots(HEIGHT_BARCODE)-4, schema_track)
132
- stat_element = generate_ascii_element(to_dots(L_MARGIN)+FONT_Y_DOTS.at(@element_font - 1)+FONT_PAD_DOTS, to_dots(HEIGHT_MARGIN), 1, @element_font, true, stat_element_text)
133
-
134
- # combine EPL statements
135
- if stat == nil
136
- "\nN\nR216,0\nZT\nS1\n#{name_element}\n#{pid_dob_age_gender_element}\n#{barcode_element}\n#{barcode_human_element}\n#{collector_element}\n#{tests_element}\nP3\n"
137
- else
138
- "\nN\nR216,0\nZT\nS1\n#{name_element}\n#{pid_dob_age_gender_element}\n#{barcode_element}\n#{barcode_human_element}\n#{collector_element}\n#{tests_element}\n#{stat_element}\nP3\n"
139
- end
140
-
141
- end
142
-
143
- # Add spaces before and after the stat text so that black bars appear across the left edge of label
144
- def pad_stat_w_space(stat)
145
- num_char = max_characters(@element_font, LABEL_HEIGHT_IN)
146
- spaces_needed = (num_char - stat.length) / 1
147
- space = ''
148
- spaces_needed.times do
149
- space = space + ' '
150
- end
151
- space + stat + space
152
- end
153
-
154
- # Add spaces between the NPID and the dob/age/gender so that line is fully justified
155
- def full_justify(pid, dag, font, length)
156
- max_char = max_characters(font, length)
157
- spaces_needed = max_char - pid.length - dag.length
158
- space = ''
159
- spaces_needed.times do
160
- space = space + ' '
161
- end
162
- pid + space + dag
163
- end
164
-
165
- # convert inches to number of dots using DPI
166
- def to_dots(inches)
167
- (inches * DPI).round
168
- end
169
-
170
- # generate ascii EPL
171
- def generate_ascii_element(x, y, rotation, font, is_reverse, text)
172
- "A#{x.to_s},#{y.to_s},#{rotation.to_s},#{font.to_s},#{ASCII_HORZ_MULT},#{ASCII_VERT_MULT},#{is_reverse ? 'R' : 'N'},\"#{text}\""
173
- end
174
-
175
- # generate barcode EPL
176
- def generate_barcode_element(x, y, height, schema_track)
177
- schema_track = schema_track.gsub("-", "").strip
178
- "B#{x.to_s},#{y.to_s},#{BARCODE_ROTATION},#{BARCODE_TYPE},#{BARCODE_NARROW_WIDTH},#{BARCODE_WIDE_WIDTH},#{height.to_s},#{BARCODE_IS_HUMAN_READABLE},\"#{schema_track}\""
179
- end
180
-
181
- end
182
-
183
- if __FILE__ == $0
184
-
185
- auto = Auto12Epl.new
186
-
187
- puts auto.generate_epl("Banda", "Mary", "U", "Q23-HGF", "12-SEP-1997", "19y", "F", "01-JAN-2016 14:21", "byGD", "CHEM7,Ca,Mg", nil, "KCH-16-00001234", "1600001234")
188
- puts "\n"
189
- puts auto.generate_epl("Banda", "Mary", "U", "Q23-HGF", "12-SEP-1997", "19y", "F", "01-JAN-2016 14:21", "byGD", "CHEM7,Ca,Mg", "STAT CHEM", "KCH-16-00001234", "1600001234")
190
- puts "\n"
191
- puts auto.generate_epl("Bandajustrightlas", "Mary", "U", "Q23-HGF", "12-SEP-1997", "19y", "F", "01-JAN-2016 14:21", "byGD", "CHEM7,Ca,Mg", "STAT CHEM", "KCH-16-00001234", "1600001234")
192
- puts "\n"
193
- puts auto.generate_epl("Bandasuperlonglastnamethatwonfit", "Marysuperlonglastnamethatwonfit", "U", "Q23-HGF", "12-SEP-1997", "19y", "F", "01-JAN-2016 14:21", "byGD", "CHEM7,Ca,Mg", "STAT CHEM", "KCH-16-00001234", "1600001234")
194
- puts "\n"
195
- puts auto.generate_epl("Bandasuperlonglastnamethatwonfit", "Mary", "U", "Q23-HGF", "12-SEP-1997", "19y", "F", "01-JAN-2016 14:21", "byGD", "CHEM7,Ca,Mg", "STAT CHEM", "KCH-16-00001234", "1600001234")
196
- puts "\n"
197
- puts auto.generate_epl("Banda", "Marysuperlonglastnamethatwonfit", "U", "Q23-HGF", "12-SEP-1997", "19y", "F", "01-JAN-2016 14:21", "byGD", "CHEM7,Ca,Mg", "STAT CHEM", "KCH-16-00001234", "1600001234")
198
-
199
-
200
-
201
- end
@@ -1,92 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'cgi'
4
- require 'couchrest'
5
-
6
- ##
7
- # A CouchRest wrapper for the changes API.
8
- #
9
- # See: https://github.com/couchrest/couchrest
10
- class CouchBum
11
- cattr_accessor :logger
12
-
13
- def initialize(database:, protocol: 'http', host: 'localhost', port: 5984, username: nil, password: nil)
14
- @connection_string = make_connection_string(protocol, username, password, host, port, database)
15
-
16
- CouchBum.logger ||= Logger.new(STDOUT)
17
- end
18
-
19
- ##
20
- # Attaches to the Changes API and streams the updates to passed block.
21
- #
22
- # This is a blocking call that only stops when there are no more
23
- # changes to pull or is explicitly terminated by calling +choke+
24
- # within the passed block.
25
- def binge_changes(since: 0, limit: nil, include_docs: nil, &block)
26
- catch(:choke) do
27
- logger.debug("Binging #{limit} changes from '#{since}'")
28
- params = stringify_params(limit: limit, include_docs: include_docs)
29
- params = "since=#{since}&#{params}" unless since.blank?
30
-
31
- changes = couch_rest(:get, "_changes?#{params}")
32
- context = BingeContext.new(changes)
33
- changes['results'].each do |change|
34
- context.current_seq = change['seq']
35
- context.instance_exec(change, &block)
36
- end
37
- end
38
- end
39
-
40
- def couch_rest(method, route, *args, **kwargs)
41
- url = expand_route(route)
42
- CouchRest.send(method, url, *args, **kwargs)
43
- rescue CouchRest::Exception => e
44
- logger.error("Failed to communicate with CouchDB: Status: #{e.http_code} - #{e.http_body}")
45
- raise e
46
- end
47
-
48
- private
49
-
50
- # Context under which the callback passed to binge_changes is executed.
51
- class BingeContext
52
- attr_accessor :current_seq
53
-
54
- def initialize(changes)
55
- @changes = changes
56
- end
57
-
58
- def choke
59
- throw :choke
60
- end
61
-
62
- def last_seq
63
- @changes['last_seq']
64
- end
65
-
66
- def pending
67
- @changes['pending']
68
- end
69
- end
70
-
71
- def make_connection_string(protocol, username, password, host, port, database)
72
- auth = username ? "#{CGI.escape(username)}:#{CGI.escape(password)}@" : ''
73
-
74
- "#{protocol}://#{auth}#{host}:#{port}/#{database}"
75
- end
76
-
77
- def expand_route(route)
78
- route = route.gsub(%r{^/+}, '')
79
-
80
- "#{@connection_string}/#{route}"
81
- end
82
-
83
- def stringify_params(params)
84
- params.reduce('') do |str_params, entry|
85
- name, value = entry
86
- next params unless value
87
-
88
- param = "#{name}=#{value}"
89
- str_params.empty? ? param : "#{str_params}&#{param}"
90
- end
91
- end
92
- end
@@ -1,9 +0,0 @@
1
- Description:
2
- Installs the Lab engine.
3
-
4
- Example:
5
- rails generate lab:install
6
-
7
- This will create:
8
- config/initializers/rswag-ui-lab.rb
9
- swagger/lab/v1/swagger.yaml
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Lab
4
- class InstallGenerator < Rails::Generators::Base
5
- source_root File.expand_path('templates', __dir__)
6
-
7
- def copy_openapi_docs
8
- copy_file('swagger.yaml', 'swagger/lab/v1/swagger.yaml')
9
- end
10
-
11
- def copy_rswag_initializer
12
- copy_file('rswag-ui-lab.rb', 'config/initializers/rswag-ui-lab.rb')
13
- end
14
-
15
- def copy_worker
16
- copy_file('start_worker.rb', 'bin/lab/start_worker.rb')
17
- end
18
- end
19
- end
@@ -1,5 +0,0 @@
1
- require 'rswag/ui'
2
-
3
- Rswag::Ui.configure do |c|
4
- c.swagger_endpoint '/api-docs/lab/v1/swagger.yaml', 'Lab API V1 Docs'
5
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'logger_multiplexor'
4
-
5
- Rails.logger = LoggerMultiplexor.new(Rails.root.join('log/lims-push.log'), $stdout)
6
- api = Lab::Lims::Api.new
7
- worker = Lab::Lims::Worker.new(api)
8
-
9
- def with_lock(lock_file)
10
- File.open("log/#{lock_file}", File::RDWR | File::CREAT, 0o644) do |file|
11
- unless file.flock(File::LOCK_EX | File::LOCK_NB)
12
- Rails.logger.warn("Failed to start new process due to lock: #{lock_file}")
13
- exit 2
14
- end
15
-
16
- file.rewind
17
- file.puts("Process ##{Process.pid} started at #{Time.now}")
18
-
19
- yield
20
- end
21
- end
22
-
23
- case ARGV[0]&.downcase
24
- when 'push'
25
- with_lock('lims-push.lock') { worker.push_orders }
26
- when 'pull'
27
- with_lock('lims-pull.lock') { worker.pull_orders }
28
- else
29
- warn 'Error: No or invalid action specified: Valid actions are push and pull'
30
- warn 'USAGE: rails runner start_worker.rb push'
31
- exit 1
32
- end