emr_ohsp_interface 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6d9929d6c572d68a83032faf3e7bcd30beb07c2ad9a6c5936f0da9b4e54e4377
|
4
|
+
data.tar.gz: a7df28d9f471cfaddecd76174698a83ee8b64172a8bc68ef91ec0751a2535ca4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e74d315683453b6853ecd523abed43953a29a8f7d34d948c11d3a382b0a3fb258c72945fecb685a34328d14ea5990127f61607723fcde62221621f0087f6f389
|
7
|
+
data.tar.gz: 702c61725fc4db911ab0d51c9cf55bd2bc3414daa5720bc2dd3c3cdfd0e5e57943d4e062bd01ee73aea148f485aaacdb9b262890e3f0b16394cb6783a29ad84e
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class EmrOhspInterface::EmrLimsInterfaceController < ::ApplicationController
|
4
|
+
def create
|
5
|
+
# lab_details = params.require %i[lab_details]
|
6
|
+
# render json: "#{lab_details[0]['firstname']}"
|
7
|
+
# render json:
|
8
|
+
order_params_list, clinician_id = params.require %i[lab_details clinician_id]
|
9
|
+
|
10
|
+
render json: service.create_lab_order(order_params_list, clinician_id)
|
11
|
+
end
|
12
|
+
|
13
|
+
def index
|
14
|
+
render json: service.get_lims_test_results(params[:id],params[:patient_id])
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_user_info()
|
18
|
+
render json: service.get_user_details(params[:id])
|
19
|
+
end
|
20
|
+
|
21
|
+
def service
|
22
|
+
EmrOhspInterface::EmrLimsInterfaceService
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,405 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'emr_ohsp_interface/version'
|
4
|
+
module EmrOhspInterface
|
5
|
+
module EmrLimsInterfaceService
|
6
|
+
class << self
|
7
|
+
require 'csv'
|
8
|
+
require 'rest-client'
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@mysql_connection_pool = {}
|
12
|
+
end
|
13
|
+
######################################### start creation of lab test in lims #####################################################
|
14
|
+
def settings
|
15
|
+
file = File.read(Rails.root.join('db', 'lims_metadata', 'lims_map.json'))
|
16
|
+
JSON.parse(file)
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_patient_number
|
20
|
+
query "SELECT COUNT(*) as 'patient_identify' FROM patients; "
|
21
|
+
end
|
22
|
+
|
23
|
+
def check_patient_number(patient_id)
|
24
|
+
patient_number = ''
|
25
|
+
get_patient_id = query "SELECT patient_number FROM patients WHERE `external_patient_number` ='#{patient_id}'; "
|
26
|
+
|
27
|
+
get_patient_id.each do |x|
|
28
|
+
patient_number = x['patient_number']
|
29
|
+
end
|
30
|
+
|
31
|
+
patient_number
|
32
|
+
end
|
33
|
+
|
34
|
+
def filterpatient_number(data)
|
35
|
+
patient_number = 0
|
36
|
+
data.each do |x|
|
37
|
+
patient_number = x['patient_identify']
|
38
|
+
end
|
39
|
+
patient_number
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_patient_dentifier(patient_id)
|
43
|
+
patient_dentifier =PatientIdentifier.where('patient_id= ? AND identifier_type = ?', patient_id,3)[0]
|
44
|
+
patient_dentifier[:identifier]
|
45
|
+
end
|
46
|
+
def create_lab_order(lab_details, clinician_id)
|
47
|
+
external_patient_number = get_patient_dentifier(lab_details[0][:patient_id])
|
48
|
+
patient_number = check_patient_number(external_patient_number)
|
49
|
+
time = Time.new
|
50
|
+
date = time.strftime('%Y-%m-%d %H:%M:%S')
|
51
|
+
lab_details.map do |order_params|
|
52
|
+
if patient_number.blank?
|
53
|
+
patient_number = filterpatient_number(get_patient_number) + 1
|
54
|
+
|
55
|
+
person_data = Person.where('person_id= ?', order_params[:patient_id])[0]
|
56
|
+
address_data = PersonAddress.where('person_id= ?', order_params[:patient_id])[0]
|
57
|
+
name_data = PersonName.where('person_id= ?', order_params[:patient_id])[0]
|
58
|
+
|
59
|
+
gender = person_data[:gender].match(/f/i) ? 1 : (person_data[:gender].match(/m/i) ? 0 : 2)
|
60
|
+
create_patient(
|
61
|
+
name_data[:given_name],
|
62
|
+
name_data[:family_name],
|
63
|
+
clinician_id[0][:requesting_clinician_id],
|
64
|
+
address_data[:address1],
|
65
|
+
gender,
|
66
|
+
person_data[:birthdate],
|
67
|
+
person_data[:birthdate_estimated],
|
68
|
+
external_patient_number,
|
69
|
+
patient_number,
|
70
|
+
date
|
71
|
+
)
|
72
|
+
end
|
73
|
+
create_visit(patient_number, date)
|
74
|
+
create_specimens(
|
75
|
+
clinician_id[0][:requesting_clinician_id],
|
76
|
+
order_params[:specimen][:name],
|
77
|
+
order_params[:accession_number]
|
78
|
+
)
|
79
|
+
specimen_id = get_specimen_id
|
80
|
+
create_unsync_orders(date, specimen_id)
|
81
|
+
|
82
|
+
create_test(specimen_id, order_params[:requesting_clinician], order_params[:tests][0][:name])
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def create_patient(
|
87
|
+
firstname, surname,
|
88
|
+
user_id, address,
|
89
|
+
gender, dob,
|
90
|
+
dob_estimated, external_patient_number,
|
91
|
+
patient_number, date
|
92
|
+
)
|
93
|
+
query(
|
94
|
+
"INSERT INTO `patients` (`name`, `first_name_code`, `last_name_code`, `created_by`, `address`, `gender`, `patient_number`, `dob`, `dob_estimated`, `external_patient_number`, `created_at`, `updated_at`)
|
95
|
+
VALUES ('#{firstname} #{surname}', SOUNDEX('#{firstname}'), SOUNDEX('#{surname}'), #{user_id}, '#{address}',#{gender},'#{patient_number}', '#{dob}', '#{dob_estimated}', '#{external_patient_number}', '#{date}', '#{date}')"
|
96
|
+
)
|
97
|
+
end
|
98
|
+
|
99
|
+
def create_visit(patient_number, date)
|
100
|
+
query "INSERT INTO `visits` (`patient_id`, `visit_type`, `ward_or_location`, `created_at`, `updated_at`)
|
101
|
+
VALUES ('#{patient_number}', 'Out Patient', 'EM OPD', '#{date}', '#{date}')"
|
102
|
+
end
|
103
|
+
|
104
|
+
def create_specimens(user_id, specimen_type, tracking_number)
|
105
|
+
specimen_type_id = settings['lims_specimen_map'][specimen_type.to_s]
|
106
|
+
accession_number = new_accession_number
|
107
|
+
# prepare_next_tracking_number()
|
108
|
+
# tracking_number = create_local_tracking_number()
|
109
|
+
query(" INSERT INTO `specimens` (`specimen_type_id`, `accepted_by`, `priority`, `accession_number`, `tracking_number`)
|
110
|
+
VALUES ('#{specimen_type_id}', '#{user_id}', 'Stat', '#{accession_number}', '#{tracking_number}')")
|
111
|
+
end
|
112
|
+
|
113
|
+
def create_unsync_orders(date, specimen_id)
|
114
|
+
query(" INSERT INTO `unsync_orders` (`specimen_id`, `data_not_synced`, `data_level`, `sync_status`, `updated_by_name`, `updated_by_id`, `created_at`, `updated_at`)
|
115
|
+
VALUES ('#{specimen_id}', 'new order', 'specimen', 'not-synced', 'kBLIS Administrator', '1', '#{date}', '#{date}')")
|
116
|
+
end
|
117
|
+
|
118
|
+
def create_test(specimen_id, requested_by, test_type)
|
119
|
+
visit_id = get_visit_id
|
120
|
+
test_type_id = settings['lims_test_type_map'][test_type.to_s]
|
121
|
+
query("INSERT INTO `tests` (`visit_id`, `test_type_id`, `specimen_id`, `test_status_id`, `not_done_reasons`, `person_talked_to_for_not_done`, `created_by`, `requested_by`)
|
122
|
+
VALUES ('#{visit_id}', '#{test_type_id}', '#{specimen_id}', '2', '0', '0', 1, '#{requested_by}')")
|
123
|
+
end
|
124
|
+
|
125
|
+
def new_accession_number
|
126
|
+
# Generate the next accession number for specimen registration
|
127
|
+
@mutex = Mutex.new if @mutex.blank?
|
128
|
+
@mutex.lock
|
129
|
+
max_acc_num = 0
|
130
|
+
return_value = nil
|
131
|
+
sentinel = 99_999_999
|
132
|
+
|
133
|
+
settings = YAML.load_file("#{Rails.root}/config/application.yml")[Rails.env]
|
134
|
+
code = settings['facility_code']
|
135
|
+
year = Date.today.year.to_s[2..3]
|
136
|
+
|
137
|
+
record = get_last_accession_number
|
138
|
+
|
139
|
+
unless record.blank?
|
140
|
+
max_acc_num = record[5..20].match(/\d+/)[0].to_i # first 5 chars are for facility code and 2 digit year
|
141
|
+
end
|
142
|
+
|
143
|
+
if max_acc_num < sentinel
|
144
|
+
max_acc_num += 1
|
145
|
+
else
|
146
|
+
max_acc_num = 1
|
147
|
+
end
|
148
|
+
|
149
|
+
max_acc_num = max_acc_num.to_s.rjust(8, '0')
|
150
|
+
return_value = "#{code}#{year}#{max_acc_num}"
|
151
|
+
@mutex.unlock
|
152
|
+
|
153
|
+
return_value
|
154
|
+
end
|
155
|
+
|
156
|
+
def get_last_accession_number
|
157
|
+
data = query('SELECT * FROM specimens WHERE accession_number IS NOT NULL ORDER BY id DESC LIMIT 1')
|
158
|
+
data.each do |x|
|
159
|
+
return last_accession_number = x['accession_number']
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def get_specimen_id
|
164
|
+
data = query('SELECT * FROM specimens WHERE accession_number IS NOT NULL ORDER BY id DESC LIMIT 1')
|
165
|
+
data.each do |x|
|
166
|
+
return specimen_id = x['id']
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def get_visit_id
|
171
|
+
data = query('SELECT * FROM visits WHERE id IS NOT NULL ORDER BY id DESC LIMIT 1')
|
172
|
+
data.each do |x|
|
173
|
+
return specimen_id = x['id']
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def prepare_next_tracking_number
|
178
|
+
file = JSON.parse(File.read("#{Rails.root}/public/tracker.json"))
|
179
|
+
todate = Time.now.strftime('%Y%m%d')
|
180
|
+
|
181
|
+
counter = file[todate]
|
182
|
+
counter = counter.to_i + 1
|
183
|
+
fi = {}
|
184
|
+
fi[todate] = counter
|
185
|
+
File.open("#{Rails.root}/public/tracker.json", 'w') do |f|
|
186
|
+
f.write(fi.to_json)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
###### lims tracking number ###############
|
191
|
+
def create_local_tracking_number
|
192
|
+
configs = YAML.load_file "#{Rails.root}/config/application.yml"
|
193
|
+
site_code = configs['facility_code']
|
194
|
+
file = JSON.parse(File.read("#{Rails.root}/public/tracker.json"))
|
195
|
+
todate = Time.now.strftime('%Y%m%d')
|
196
|
+
year = Time.now.strftime('%Y%m%d').to_s.slice(2..3)
|
197
|
+
month = Time.now.strftime('%m')
|
198
|
+
day = Time.now.strftime('%d')
|
199
|
+
|
200
|
+
key = file.keys
|
201
|
+
|
202
|
+
if todate > key[0]
|
203
|
+
|
204
|
+
fi = {}
|
205
|
+
fi[todate] = 1
|
206
|
+
File.open("#{Rails.root}/public/tracker.json", 'w') do |f|
|
207
|
+
f.write(fi.to_json)
|
208
|
+
end
|
209
|
+
|
210
|
+
value = '001'
|
211
|
+
tracking_number = "X#{site_code}#{year}#{get_month(month)}#{get_day(day)}#{value}"
|
212
|
+
|
213
|
+
else
|
214
|
+
counter = file[todate]
|
215
|
+
|
216
|
+
value = if counter.to_s.length == 1
|
217
|
+
'00' + counter.to_s
|
218
|
+
elsif counter.to_s.length == 2
|
219
|
+
'0' + counter.to_s
|
220
|
+
else
|
221
|
+
begin
|
222
|
+
counter.to_s
|
223
|
+
rescue StandardError
|
224
|
+
'001'
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
tracking_number = "X#{site_code}#{year}#{get_month(month)}#{get_day(day)}#{value}"
|
229
|
+
|
230
|
+
end
|
231
|
+
tracking_number
|
232
|
+
end
|
233
|
+
|
234
|
+
def get_month(month)
|
235
|
+
case month
|
236
|
+
|
237
|
+
when '01'
|
238
|
+
'1'
|
239
|
+
when '02'
|
240
|
+
'2'
|
241
|
+
when '03'
|
242
|
+
'3'
|
243
|
+
when '04'
|
244
|
+
'4'
|
245
|
+
when '05'
|
246
|
+
'5'
|
247
|
+
when '06'
|
248
|
+
'6'
|
249
|
+
when '07'
|
250
|
+
'7'
|
251
|
+
when '08'
|
252
|
+
'8'
|
253
|
+
when '09'
|
254
|
+
'9'
|
255
|
+
when '10'
|
256
|
+
'A'
|
257
|
+
when '11'
|
258
|
+
'B'
|
259
|
+
when '12'
|
260
|
+
'C'
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
def get_day(day)
|
265
|
+
case day
|
266
|
+
|
267
|
+
when '01'
|
268
|
+
'1'
|
269
|
+
when '02'
|
270
|
+
'2'
|
271
|
+
when '03'
|
272
|
+
'3'
|
273
|
+
when '04'
|
274
|
+
'4'
|
275
|
+
when '05'
|
276
|
+
'5'
|
277
|
+
when '06'
|
278
|
+
'6'
|
279
|
+
when '07'
|
280
|
+
'7'
|
281
|
+
when '08'
|
282
|
+
'8'
|
283
|
+
when '09'
|
284
|
+
'9'
|
285
|
+
when '10'
|
286
|
+
'A'
|
287
|
+
when '11'
|
288
|
+
'B'
|
289
|
+
when '12'
|
290
|
+
'C'
|
291
|
+
when '13'
|
292
|
+
'E'
|
293
|
+
when '14'
|
294
|
+
'F'
|
295
|
+
when '15'
|
296
|
+
'G'
|
297
|
+
when '16'
|
298
|
+
'H'
|
299
|
+
when '17'
|
300
|
+
'Y'
|
301
|
+
when '18'
|
302
|
+
'J'
|
303
|
+
when '19'
|
304
|
+
'K'
|
305
|
+
when '20'
|
306
|
+
'Z'
|
307
|
+
when '21'
|
308
|
+
'M'
|
309
|
+
when '22'
|
310
|
+
'N'
|
311
|
+
when '23'
|
312
|
+
'O'
|
313
|
+
when '24'
|
314
|
+
'P'
|
315
|
+
when '25'
|
316
|
+
'Q'
|
317
|
+
when '26'
|
318
|
+
'R'
|
319
|
+
when '27'
|
320
|
+
'S'
|
321
|
+
when '28'
|
322
|
+
'T'
|
323
|
+
when '29'
|
324
|
+
'V'
|
325
|
+
when '30'
|
326
|
+
'W'
|
327
|
+
when '31'
|
328
|
+
'X'
|
329
|
+
end
|
330
|
+
end
|
331
|
+
############################################# end creation of lab test in lims #####################################################
|
332
|
+
|
333
|
+
############## get results from lims ###############
|
334
|
+
|
335
|
+
def get_lims_test_results(tracking_number,patient_id)
|
336
|
+
external_patient_number = get_patient_dentifier(patient_id)
|
337
|
+
data = query("
|
338
|
+
SELECT
|
339
|
+
visits.ward_or_location, specimens.accession_number,
|
340
|
+
tests.created_by, tests.verified_by,
|
341
|
+
tests.time_completed,tests.requested_by,tests.interpretation,
|
342
|
+
tests.time_created as tests_time_created,
|
343
|
+
test_types.name as test_types_name,
|
344
|
+
test_categories.name as test_categories_name,
|
345
|
+
tests.time_verified as tests_time_verified,
|
346
|
+
users.name as users_name,
|
347
|
+
specimen_types.name as specimen_types_name,
|
348
|
+
specimen_statuses.name as specimen_statuses_name,
|
349
|
+
test_results.result as test_results_result,
|
350
|
+
test_results.device_name as test_results_device_name,
|
351
|
+
measures.name as measures_name,
|
352
|
+
measures.unit as measures_unit,
|
353
|
+
measure_ranges.range_lower as measure_ranges_range_lower,
|
354
|
+
measure_ranges.range_upper as measure_ranges_range_upper
|
355
|
+
FROM iblis.patients
|
356
|
+
inner join iblis.visits on `visits`.`patient_id` = `patients`.`patient_number`
|
357
|
+
inner join iblis.tests on `tests`.`visit_id` = `visits`.`id`
|
358
|
+
inner join iblis.test_types on `test_types`.`id` = `tests`.`test_type_id`
|
359
|
+
inner join iblis.test_categories on `test_categories`.`id` = `test_types`.`test_category_id`
|
360
|
+
inner join iblis.users on `users`.`id` = `tests`.`tested_by`
|
361
|
+
inner join iblis.specimens on `specimens`.`id` = `tests`.`specimen_id`
|
362
|
+
inner join iblis.specimen_types on `specimen_types`.`id` = `specimens`.`specimen_type_id`
|
363
|
+
inner join iblis.specimen_statuses on `specimen_statuses`.`id` = `specimens`.`specimen_status_id`
|
364
|
+
right join iblis.test_results on `test_results`.`test_id` = `tests`.`id`
|
365
|
+
right join iblis.measures on `measures`.`id` = `test_results`.`measure_id`
|
366
|
+
right join iblis.measure_ranges on `measure_ranges`.`measure_id` = `measures`.`id`
|
367
|
+
where `patients`.`deleted_at` is null and `specimens`.`tracking_number` = '#{tracking_number}' and `patients`.`external_patient_number` = '#{external_patient_number}' and `measure_ranges`.`deleted_at`
|
368
|
+
is null group by(`measure_ranges`.`measure_id`) order by time_completed asc ;
|
369
|
+
")
|
370
|
+
data
|
371
|
+
end
|
372
|
+
def get_user_details(user_id)
|
373
|
+
data = query("SELECT * FROM iblis.users where id = #{user_id};")
|
374
|
+
data
|
375
|
+
end
|
376
|
+
############################################# start connection to lims database ######################################################
|
377
|
+
def query(sql)
|
378
|
+
Rails.logger.debug(sql.to_s)
|
379
|
+
result = mysql.query(sql)
|
380
|
+
end
|
381
|
+
|
382
|
+
def mysql
|
383
|
+
# self.initialize
|
384
|
+
return mysql_connection if mysql_connection
|
385
|
+
|
386
|
+
connection = Mysql2::Client.new(host: settings['headers']['host'],
|
387
|
+
username: settings['headers']['username'],
|
388
|
+
password: settings['headers']['password'],
|
389
|
+
port: settings['headers']['port'],
|
390
|
+
database: settings['headers']['database'],
|
391
|
+
reconnect: true)
|
392
|
+
self.mysql_connection = connection
|
393
|
+
end
|
394
|
+
|
395
|
+
def mysql_connection=(connection)
|
396
|
+
@mysql_connection_pool = connection
|
397
|
+
end
|
398
|
+
|
399
|
+
def mysql_connection
|
400
|
+
@mysql_connection_pool
|
401
|
+
end
|
402
|
+
############################################# end connection to lims database ######################################################
|
403
|
+
end
|
404
|
+
end
|
405
|
+
end
|
data/config/routes.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
EmrOhspInterface::Engine.routes.draw do
|
2
|
-
resources :
|
2
|
+
resources :emr_lims_interface, path: 'api/v1/emr_lims_interface'
|
3
|
+
get '/get_lims_user', to: 'emr_lims_interface#get_user_info'
|
3
4
|
get '/get_weeks', to: 'emr_ohsp_interface#weeks_generator'
|
4
5
|
get '/get_months', to: 'emr_ohsp_interface#months_generator'
|
5
6
|
get '/generate_weekly_idsr_report', to: 'emr_ohsp_interface#generate_weekly_idsr_report'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: emr_ohsp_interface
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
- Justin Manda
|
7
|
+
- Justin Manda and Petros Kayange
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-11-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -74,7 +74,7 @@ dependencies:
|
|
74
74
|
version: '0'
|
75
75
|
description:
|
76
76
|
email:
|
77
|
-
- justinmandah@gmail.com
|
77
|
+
- justinmandah@gmail.com, kayangepetros@gmail.com
|
78
78
|
executables: []
|
79
79
|
extensions: []
|
80
80
|
extra_rdoc_files: []
|
@@ -86,11 +86,13 @@ files:
|
|
86
86
|
- app/assets/javascripts/emr_ohsp_interface/application.js
|
87
87
|
- app/assets/stylesheets/emr_ohsp_interface/application.css
|
88
88
|
- app/controllers/emr_ohsp_interface/application_controller.rb
|
89
|
+
- app/controllers/emr_ohsp_interface/emr_lims_interface_controller.rb
|
89
90
|
- app/controllers/emr_ohsp_interface/emr_ohsp_interface_controller.rb
|
90
91
|
- app/helpers/emr_ohsp_interface/application_helper.rb
|
91
92
|
- app/jobs/emr_ohsp_interface/application_job.rb
|
92
93
|
- app/mailers/emr_ohsp_interface/application_mailer.rb
|
93
94
|
- app/models/emr_ohsp_interface/application_record.rb
|
95
|
+
- app/services/emr_ohsp_interface/emr_lims_interface_service.rb
|
94
96
|
- app/services/emr_ohsp_interface/emr_ohsp_interface_service.rb
|
95
97
|
- app/views/layouts/emr_ohsp_interface/application.html.erb
|
96
98
|
- config/routes.rb
|
@@ -121,6 +123,6 @@ requirements: []
|
|
121
123
|
rubygems_version: 3.0.8
|
122
124
|
signing_key:
|
123
125
|
specification_version: 4
|
124
|
-
summary: This in a gem that facilitates interfacing of EMR
|
125
|
-
Platform
|
126
|
+
summary: This in a gem that facilitates interfacing of EMR, One Health Surveillance
|
127
|
+
Platform and Lims
|
126
128
|
test_files: []
|