his_emr_api_lab 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/lab/labels_controller.rb +15 -0
- data/app/controllers/lab/orders_controller.rb +2 -1
- data/app/models/lab/lab_order.rb +5 -1
- data/app/models/lab/lab_result.rb +10 -0
- data/app/models/lab/lab_test.rb +5 -0
- data/app/services/lab/labelling_service/order_label.rb +85 -0
- data/app/services/lab/lims/api.rb +7 -0
- data/app/services/lab/lims/exceptions.rb +11 -0
- data/app/services/lab/lims/migrator.rb +206 -0
- data/app/services/lab/lims/order_dto.rb +41 -122
- data/app/services/lab/lims/order_serializer.rb +28 -2
- data/app/services/lab/lims/utils.rb +45 -1
- data/app/services/lab/lims/worker.rb +227 -38
- data/app/services/lab/metadata.rb +1 -1
- data/app/services/lab/orders_service.rb +9 -8
- data/app/services/lab/results_service.rb +38 -6
- data/config/routes.rb +2 -0
- data/lib/auto12epl.rb +201 -0
- data/lib/couch_bum/couch_bum.rb +11 -1
- data/lib/lab/version.rb +1 -1
- data/lib/tasks/loaders/data/tests.csv +21 -0
- metadata +21 -2
@@ -27,7 +27,7 @@ module Lab
|
|
27
27
|
# },
|
28
28
|
# program_id: { type: :integer, required: false },
|
29
29
|
# patient_id: { type: :integer, required: false }
|
30
|
-
#
|
30
|
+
# specimen: { type: :object, properties: { concept_id: :integer }, required: %i[concept_id] },
|
31
31
|
# test_type_ids: {
|
32
32
|
# type: :array,
|
33
33
|
# items: {
|
@@ -71,11 +71,15 @@ module Lab
|
|
71
71
|
end
|
72
72
|
|
73
73
|
order = Lab::LabOrder.find(order_id)
|
74
|
-
unless order.concept_id == unknown_concept_id
|
74
|
+
unless order.concept_id == unknown_concept_id || params[:force_update]&.to_s&.casecmp?('true')
|
75
75
|
raise ::UnprocessableEntityError
|
76
76
|
end
|
77
77
|
|
78
|
-
order.update!(concept_id: specimen_id
|
78
|
+
order.update!(concept_id: specimen_id,
|
79
|
+
discontinued: true,
|
80
|
+
discontinued_by: User.current.user_id,
|
81
|
+
discontinued_date: params[:date]&.to_date || Date.today,
|
82
|
+
discontinued_reason_non_coded: 'Sample drawn/updated')
|
79
83
|
Lab::LabOrderSerializer.serialize_order(order)
|
80
84
|
end
|
81
85
|
|
@@ -87,10 +91,7 @@ module Lab
|
|
87
91
|
order.reason_for_test&.void(reason)
|
88
92
|
order.target_lab&.void(reason)
|
89
93
|
|
90
|
-
order.tests.each
|
91
|
-
test.result&.void(reason)
|
92
|
-
test.void(reason)
|
93
|
-
end
|
94
|
+
order.tests.each { |test| test.void(reason) }
|
94
95
|
|
95
96
|
order.void(reason)
|
96
97
|
end
|
@@ -119,7 +120,7 @@ module Lab
|
|
119
120
|
program_id: program_id,
|
120
121
|
type: EncounterType.find_by_name!(Lab::Metadata::ENCOUNTER_TYPE_NAME),
|
121
122
|
encounter_datetime: order_params[:date] || Date.today,
|
122
|
-
provider_id: order_params[:provider_id] || User.current
|
123
|
+
provider_id: order_params[:provider_id] || User.current.person.person_id
|
123
124
|
)
|
124
125
|
end
|
125
126
|
|
@@ -3,14 +3,26 @@
|
|
3
3
|
module Lab
|
4
4
|
module ResultsService
|
5
5
|
class << self
|
6
|
+
##
|
7
|
+
# Attach results to a test
|
8
|
+
#
|
9
|
+
# Params:
|
10
|
+
# test_id: The tests id (maps to obs_id of the test's observation in OpenMRS)
|
11
|
+
# params: A hash comprising the following fields
|
12
|
+
# - encounter_id: Encounter to create result under (can be ommitted but provider_id has to specified)
|
13
|
+
# - provider_id: Specify a provider for an encounter the result is going to be created under
|
14
|
+
# - date: Retrospective date when the result was received (can be ommitted, defaults to today)
|
15
|
+
# - measures: An array of measures. A measure is an object of the following structure
|
16
|
+
# - indicator: An object that has a concept_id field (concept_id of the indicator)
|
17
|
+
# - value_type: An enum that's limited to 'numeric', 'boolean', 'text', and 'coded'
|
6
18
|
def create_results(test_id, params)
|
7
19
|
ActiveRecord::Base.transaction do
|
8
20
|
test = Lab::LabTest.find(test_id)
|
9
21
|
encounter = find_encounter(test, encounter_id: params[:encounter_id],
|
10
|
-
date: params[:date],
|
22
|
+
date: params[:date]&.to_date,
|
11
23
|
provider_id: params[:provider_id])
|
12
24
|
|
13
|
-
results_obs = create_results_obs(encounter, test, params[:date])
|
25
|
+
results_obs = create_results_obs(encounter, test, params[:date], params[:comments])
|
14
26
|
params[:measures].map { |measure| add_measure_to_results(results_obs, measure, params[:date]) }
|
15
27
|
|
16
28
|
Lab::ResultSerializer.serialize(results_obs)
|
@@ -32,23 +44,41 @@ module Lab
|
|
32
44
|
end
|
33
45
|
|
34
46
|
# Creates the parent observation for results to which the different measures are attached
|
35
|
-
def create_results_obs(encounter, test, date)
|
47
|
+
def create_results_obs(encounter, test, date, comments = nil)
|
48
|
+
void_existing_results_obs(encounter, test)
|
49
|
+
|
36
50
|
Lab::LabResult.create!(
|
37
51
|
person_id: encounter.patient_id,
|
38
52
|
encounter_id: encounter.encounter_id,
|
39
|
-
concept_id:
|
53
|
+
concept_id: test_result_concept.concept_id,
|
40
54
|
order_id: test.order_id,
|
41
55
|
obs_group_id: test.obs_id,
|
42
|
-
obs_datetime: date&.to_datetime || DateTime.now
|
56
|
+
obs_datetime: date&.to_datetime || DateTime.now,
|
57
|
+
comments: comments
|
43
58
|
)
|
44
59
|
end
|
45
60
|
|
61
|
+
def void_existing_results_obs(encounter, test)
|
62
|
+
result = Lab::LabResult.find_by(person_id: encounter.patient_id,
|
63
|
+
concept_id: test_result_concept.concept_id,
|
64
|
+
obs_group_id: test.obs_id)
|
65
|
+
return unless result
|
66
|
+
|
67
|
+
result.measures.map { |child_obs| child_obs.void("Updated/overwritten by #{User.current.username}") }
|
68
|
+
result.void("Updated/overwritten by #{User.current.username}")
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_result_concept
|
72
|
+
ConceptName.find_by_name!(Lab::Metadata::TEST_RESULT_CONCEPT_NAME)
|
73
|
+
end
|
74
|
+
|
46
75
|
def add_measure_to_results(results_obs, params, date)
|
47
76
|
validate_measure_params(params)
|
48
77
|
|
49
78
|
Observation.create!(
|
50
79
|
person_id: results_obs.person_id,
|
51
80
|
encounter_id: results_obs.encounter_id,
|
81
|
+
order_id: results_obs.order_id,
|
52
82
|
concept_id: params[:indicator][:concept_id],
|
53
83
|
obs_group_id: results_obs.obs_id,
|
54
84
|
obs_datetime: date&.to_datetime || DateTime.now,
|
@@ -57,7 +87,9 @@ module Lab
|
|
57
87
|
end
|
58
88
|
|
59
89
|
def validate_measure_params(params)
|
60
|
-
|
90
|
+
if params[:value].blank?
|
91
|
+
raise InvalidParameterError, 'measures.value is required'
|
92
|
+
end
|
61
93
|
|
62
94
|
if params[:indicator]&.[](:concept_id).blank?
|
63
95
|
raise InvalidParameterError, 'measures.indicator.concept_id is required'
|
data/config/routes.rb
CHANGED
@@ -6,6 +6,8 @@ Lab::Engine.routes.draw do
|
|
6
6
|
resources :results, only: %i[index create destroy]
|
7
7
|
end
|
8
8
|
|
9
|
+
get 'api/v1/lab/labels/order', to: 'labels#print_order_label'
|
10
|
+
|
9
11
|
# Metadata
|
10
12
|
# TODO: Move the following to namespace /concepts
|
11
13
|
resources :specimen_types, only: %i[index], path: 'api/v1/lab/specimen_types'
|
data/lib/auto12epl.rb
ADDED
@@ -0,0 +1,201 @@
|
|
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
|
data/lib/couch_bum/couch_bum.rb
CHANGED
@@ -8,8 +8,12 @@ require 'couchrest'
|
|
8
8
|
#
|
9
9
|
# See: https://github.com/couchrest/couchrest
|
10
10
|
class CouchBum
|
11
|
+
cattr_accessor :logger
|
12
|
+
|
11
13
|
def initialize(database:, protocol: 'http', host: 'localhost', port: 5984, username: nil, password: nil)
|
12
14
|
@connection_string = make_connection_string(protocol, username, password, host, port, database)
|
15
|
+
|
16
|
+
CouchBum.logger ||= Logger.new(STDOUT)
|
13
17
|
end
|
14
18
|
|
15
19
|
##
|
@@ -29,7 +33,13 @@ class CouchBum
|
|
29
33
|
end
|
30
34
|
|
31
35
|
def couch_rest(method, route, *args, **kwargs)
|
32
|
-
|
36
|
+
url = expand_route(route)
|
37
|
+
|
38
|
+
logger.debug("CouchBum: Executing #{method} #{url}")
|
39
|
+
CouchRest.send(method, url, *args, **kwargs)
|
40
|
+
rescue CouchRest::Exception => e
|
41
|
+
logger.error("Failed to communicate with CouchDB: Status: #{e.http_code} - #{e.http_body}")
|
42
|
+
raise e
|
33
43
|
end
|
34
44
|
|
35
45
|
private
|
data/lib/lab/version.rb
CHANGED
@@ -35,6 +35,7 @@ Blood,"Liver Function Tests","2019-11-19 14:05:31"
|
|
35
35
|
Blood,"Renal Function Test","2019-11-19 14:05:31"
|
36
36
|
Blood,Lipogram,"2019-11-19 14:05:31"
|
37
37
|
Blood,FBC,"2019-11-19 14:05:31"
|
38
|
+
Blood,"FBS","2021-04-11 00:00:00"
|
38
39
|
Blood,Electrolytes,"2019-11-19 14:05:31"
|
39
40
|
Blood,Enzymes,"2019-11-19 14:05:31"
|
40
41
|
Blood,Glucose,"2019-11-19 14:05:31"
|
@@ -42,6 +43,22 @@ Blood,"Prothrombin Time","2019-11-19 14:05:31"
|
|
42
43
|
Blood,APTT,"2019-11-19 14:05:31"
|
43
44
|
Blood,INR,"2019-11-19 14:05:31"
|
44
45
|
Blood,ESR,"2019-11-19 14:05:31"
|
46
|
+
Blood,"D/Coombs","2021-04-11 00:00:00"
|
47
|
+
Blood,"creat","2021-04-11 00:00:00"
|
48
|
+
Blood,"Widal","2021-04-11 00:00:00"
|
49
|
+
Blood,"AAFB (3rd)","2021-04-11 00:00:00"
|
50
|
+
Blood,"Urine micro","2021-04-11 00:00:00"
|
51
|
+
Blood,"AAFB (1st)","2021-04-11 00:00:00"
|
52
|
+
Blood,ASOT,"2021-04-11 00:00:00"
|
53
|
+
Blood,"Blood C/S","2021-04-11 00:00:00"
|
54
|
+
Blood,"Cryptococcal Ag","2021-04-11 00:00:00"
|
55
|
+
Blood,"I/Ink","2021-04-11 00:00:00"
|
56
|
+
Blood,"Prot& Sugar","2021-04-11 00:00:00"
|
57
|
+
Blood,C_S,"2021-04-11 00:00:00"
|
58
|
+
Blood,hep,"2021-04-11 00:00:00"
|
59
|
+
Blood,"Cryptococcal Antigen","2021-04-11 00:00:00"
|
60
|
+
Blood,Resistance,"2021-04-11 00:00:00"
|
61
|
+
Blood,Sickle,"2021-04-11 00:00:00"
|
45
62
|
Blood,"Sickling Test","2019-11-19 14:05:31"
|
46
63
|
Blood,"Manual Differential & Cell Morphology","2019-11-19 14:05:31"
|
47
64
|
Blood,"Pancreatic Function Test","2019-11-19 14:05:31"
|
@@ -69,8 +86,12 @@ Blood,HbA1c,"2019-11-19 14:05:31"
|
|
69
86
|
Blood,Microalbumin,"2019-11-19 14:05:31"
|
70
87
|
Blood,Microprotein,"2019-11-19 14:05:31"
|
71
88
|
Blood,"Von Willebrand Factor","2019-11-19 14:05:31"
|
89
|
+
Blood,"HIV_viral_load","2021-04-13 00:00:00"
|
90
|
+
Blood,"Viral laod","2021-04-11 00:00:00"
|
72
91
|
Blood,"Viral Load","2019-11-19 14:05:31"
|
73
92
|
Blood,"Urine Lam","2019-11-19 14:05:31"
|
93
|
+
Blood,"Protein and Sugar","2021-04-16"
|
94
|
+
Blood,"White cell count","2021-04-16"
|
74
95
|
Blood,Urea,"2019-11-19 14:05:31"
|
75
96
|
Blood,Creatinine,"2019-11-19 14:05:31"
|
76
97
|
Blood,ALT,"2019-11-19 14:05:31"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: his_emr_api_lab
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Elizabeth Glaser Pediatric Foundation Malawi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-04-
|
11
|
+
date: 2021-04-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: couchrest
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 2.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: parallel
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.20.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.20.1
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rails
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -211,6 +225,7 @@ files:
|
|
211
225
|
- README.md
|
212
226
|
- Rakefile
|
213
227
|
- app/controllers/lab/application_controller.rb
|
228
|
+
- app/controllers/lab/labels_controller.rb
|
214
229
|
- app/controllers/lab/orders_controller.rb
|
215
230
|
- app/controllers/lab/reasons_for_test_controller.rb
|
216
231
|
- app/controllers/lab/results_controller.rb
|
@@ -233,8 +248,11 @@ files:
|
|
233
248
|
- app/serializers/lab/test_serializer.rb
|
234
249
|
- app/services/lab/accession_number_service.rb
|
235
250
|
- app/services/lab/concepts_service.rb
|
251
|
+
- app/services/lab/labelling_service/order_label.rb
|
236
252
|
- app/services/lab/lims/api.rb
|
237
253
|
- app/services/lab/lims/config.rb
|
254
|
+
- app/services/lab/lims/exceptions.rb
|
255
|
+
- app/services/lab/lims/migrator.rb
|
238
256
|
- app/services/lab/lims/order_dto.rb
|
239
257
|
- app/services/lab/lims/order_serializer.rb
|
240
258
|
- app/services/lab/lims/utils.rb
|
@@ -250,6 +268,7 @@ files:
|
|
250
268
|
- db/migrate/20210323080140_change_lims_id_to_string_in_lims_order_mapping.rb
|
251
269
|
- db/migrate/20210326195504_add_order_revision_to_lims_order_mapping.rb
|
252
270
|
- db/migrate/20210407071728_create_lab_lims_failed_imports.rb
|
271
|
+
- lib/auto12epl.rb
|
253
272
|
- lib/couch_bum/couch_bum.rb
|
254
273
|
- lib/generators/lab/install/USAGE
|
255
274
|
- lib/generators/lab/install/install_generator.rb
|