his_emr_api_lab 0.0.5.pre.p1 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/services/lab/labelling_service/order_label.rb +20 -2
- data/app/services/lab/lims/migrator.rb +4 -2
- data/app/services/lab/lims/order_dto.rb +8 -2
- data/app/services/lab/lims/utils.rb +2 -0
- data/app/services/lab/lims/worker.rb +3 -1
- data/app/services/lab/orders_search_service.rb +26 -16
- data/lib/generators/lab/install/templates/swagger.yaml +32 -0
- data/lib/lab/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1820c47a6689d070b7e2d7c15e2fbcea3d66468141865a4aba4f52cc394a5146
|
4
|
+
data.tar.gz: 49d92b0a38610d40274555b8fc130834137c2bfd8a278697ceada745cecf8fc2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f7ba1de5785aaa82cb6471639b7edb8ab59a4972cd289bf9886a1f89c460e17d202479b92460377a66fb55998d45a2ad50f4cc5c48d5fafb04e972bf66802bf5
|
7
|
+
data.tar.gz: 932735ff44518d81045456b6c80fde5e488e6971e4bee9180e7943012bd0db5d809d2af38b30da736d858aebf09b3dd8a926c82d23d93224d3451a528e7b2740
|
@@ -27,7 +27,7 @@ module Lab
|
|
27
27
|
'',
|
28
28
|
drawer,
|
29
29
|
'',
|
30
|
-
|
30
|
+
tests,
|
31
31
|
reason_for_test,
|
32
32
|
order.accession_number,
|
33
33
|
order.accession_number)
|
@@ -36,7 +36,7 @@ module Lab
|
|
36
36
|
def reason_for_test
|
37
37
|
return 'Unknown' unless order.reason_for_test
|
38
38
|
|
39
|
-
|
39
|
+
short_concept_name(order.reason_for_test.value_coded) || 'Unknown'
|
40
40
|
end
|
41
41
|
|
42
42
|
def patient
|
@@ -73,6 +73,24 @@ module Lab
|
|
73
73
|
ConceptName.find_by_concept_id(order.concept_id)&.name || 'Unknown'
|
74
74
|
end
|
75
75
|
|
76
|
+
def tests
|
77
|
+
tests = order.tests.map do |test|
|
78
|
+
name = short_concept_name(test.value_coded) || 'Unknown'
|
79
|
+
|
80
|
+
next 'VL' if name.match?(/Viral load/i)
|
81
|
+
|
82
|
+
name.size > 7 ? name[0..6] : name
|
83
|
+
end
|
84
|
+
|
85
|
+
tests.join(', ')
|
86
|
+
end
|
87
|
+
|
88
|
+
def short_concept_name(concept_id)
|
89
|
+
ConceptName.where(concept_id: concept_id)
|
90
|
+
.min_by { |concept| concept.name.size }
|
91
|
+
&.name
|
92
|
+
end
|
93
|
+
|
76
94
|
def unknown_concept
|
77
95
|
ConceptName.find_by_name('Unknown')
|
78
96
|
end
|
@@ -142,9 +142,10 @@ module Lab
|
|
142
142
|
MIGRATION_REJECTIONS_CSV_PATH = LIMS_LOG_PATH.join('migration-rejections.csv')
|
143
143
|
|
144
144
|
def self.export_rejections(rejections)
|
145
|
-
headers = ['Accession number', 'NHID', 'First name', 'Last name', 'Reason']
|
145
|
+
headers = ['doc_id', 'Accession number', 'NHID', 'First name', 'Last name', 'Reason']
|
146
146
|
rows = (rejections || []).map do |rejection|
|
147
147
|
[
|
148
|
+
rejection.order[:_id],
|
148
149
|
rejection.order[:tracking_number],
|
149
150
|
rejection.order[:patient][:id],
|
150
151
|
rejection.order[:patient][:first_name],
|
@@ -159,9 +160,10 @@ module Lab
|
|
159
160
|
MIGRATION_FAILURES_CSV_PATH = LIMS_LOG_PATH.join('migration-failures.csv')
|
160
161
|
|
161
162
|
def self.export_failures
|
162
|
-
headers = ['Accession number', 'NHID', 'Reason', 'Difference']
|
163
|
+
headers = ['doc_id', 'Accession number', 'NHID', 'Reason', 'Difference']
|
163
164
|
rows = Lab::LimsFailedImport.all.map do |failure|
|
164
165
|
[
|
166
|
+
failure.lims_id,
|
165
167
|
failure.tracking_number,
|
166
168
|
failure.patient_nhid,
|
167
169
|
failure.reason,
|
@@ -30,9 +30,9 @@ module Lab
|
|
30
30
|
|
31
31
|
# Translates a LIMS specimen name to an OpenMRS concept_id
|
32
32
|
def specimen_type_id
|
33
|
-
lims_specimen_name = self['sample_type']
|
33
|
+
lims_specimen_name = self['sample_type']&.strip&.downcase
|
34
34
|
|
35
|
-
if %w[specimen_not_collected not_assigned].include?(lims_specimen_name)
|
35
|
+
if %w[specimen_not_collected not_assigned not_specified].include?(lims_specimen_name)
|
36
36
|
return ConceptName.select(:concept_id).find_by_name!('Unknown').concept_id
|
37
37
|
end
|
38
38
|
|
@@ -53,6 +53,8 @@ module Lab
|
|
53
53
|
|
54
54
|
# Extract requesting clinician name from LIMS
|
55
55
|
def requesting_clinician
|
56
|
+
return 'Unknown' unless self['who_order_test']
|
57
|
+
|
56
58
|
# TODO: Extend requesting clinician to an obs tree having extra parameters
|
57
59
|
# like phone number and ID to closely match the lims user.
|
58
60
|
first_name = self['who_order_test']['first_name'] || ''
|
@@ -67,6 +69,10 @@ module Lab
|
|
67
69
|
end
|
68
70
|
|
69
71
|
def start_date
|
72
|
+
if self['date_created'].blank?
|
73
|
+
raise LimsException, 'Order missing created date'
|
74
|
+
end
|
75
|
+
|
70
76
|
Utils.parse_date(self['date_created'])
|
71
77
|
end
|
72
78
|
|
@@ -66,6 +66,8 @@ module Lab
|
|
66
66
|
Date.strptime(str_date, '%d-%m-%Y').strftime('%Y-%m-%d')
|
67
67
|
elsif str_date.match?(/(\d{4}\d{2}\d{2})\d+/)
|
68
68
|
Date.strptime(str_date, '%Y%m%d').strftime('%Y-%m-%d')
|
69
|
+
elsif str_date.match?(%r{\d{2}/\d{2}/\d{4}})
|
70
|
+
str_date.to_date.to_s
|
69
71
|
else
|
70
72
|
Rails.logger.warn("Invalid date: #{str_date}")
|
71
73
|
parse_date(fallback_date)
|
@@ -28,7 +28,9 @@ module Lab
|
|
28
28
|
fout.write("Worker ##{Process.pid} started at #{Time.now}")
|
29
29
|
worker = new(Api.new)
|
30
30
|
worker.pull_orders
|
31
|
-
|
31
|
+
# TODO: Verify that names being pushed to LIMS are of the correct format (ie matching
|
32
|
+
# LIMS naming conventions). Enable pushing when that is done
|
33
|
+
# worker.push_orders
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
@@ -5,44 +5,54 @@ module Lab
|
|
5
5
|
module OrdersSearchService
|
6
6
|
class << self
|
7
7
|
def find_orders(filters)
|
8
|
-
|
9
|
-
status = filters.delete(:status)
|
8
|
+
extra_filters = pop_filters(filters, :date, :end_date, :status)
|
10
9
|
|
11
10
|
orders = Lab::LabOrder.prefetch_relationships
|
12
11
|
.where(filters)
|
13
12
|
.order(start_date: :desc)
|
14
13
|
|
15
|
-
orders =
|
16
|
-
orders =
|
14
|
+
orders = filter_orders_by_status(orders, pop_filters(extra_filters, :status))
|
15
|
+
orders = filter_orders_by_date(orders, extra_filters)
|
17
16
|
|
18
17
|
orders.map { |order| Lab::LabOrderSerializer.serialize_order(order) }
|
19
18
|
end
|
20
19
|
|
21
|
-
def filter_orders_by_date(orders, date)
|
22
|
-
|
23
|
-
|
20
|
+
def filter_orders_by_date(orders, date: nil, end_date: nil)
|
21
|
+
date = date&.to_date
|
22
|
+
end_date = end_date&.to_date
|
24
23
|
|
25
|
-
|
26
|
-
|
27
|
-
when 'ordered' then orders.where(concept_id: unknown_concept_id)
|
28
|
-
when 'drawn' then orders.where.not(concept_id: unknown_concept_id)
|
24
|
+
if date && end_date
|
25
|
+
return orders.where('start_date BETWEEN ? AND ?', date, end_date + 1.day)
|
29
26
|
end
|
30
|
-
end
|
31
27
|
|
32
|
-
|
33
|
-
|
28
|
+
if date
|
29
|
+
return orders.where('start_date BETWEEN ? AND ?', date, date + 1.day)
|
30
|
+
end
|
31
|
+
|
32
|
+
return orders.where('start_date < ?', end_date + 1.day) if end_date
|
33
|
+
|
34
|
+
orders
|
34
35
|
end
|
35
36
|
|
36
|
-
def filter_orders_by_status(orders, status)
|
37
|
-
case status
|
37
|
+
def filter_orders_by_status(orders, status: nil)
|
38
|
+
case status&.downcase
|
38
39
|
when 'ordered' then orders.where(concept_id: unknown_concept_id)
|
39
40
|
when 'drawn' then orders.where.not(concept_id: unknown_concept_id)
|
41
|
+
else orders
|
40
42
|
end
|
41
43
|
end
|
42
44
|
|
43
45
|
def unknown_concept_id
|
44
46
|
ConceptName.find_by_name!('Unknown').concept_id
|
45
47
|
end
|
48
|
+
|
49
|
+
def pop_filters(params, *filters)
|
50
|
+
filters.each_with_object({}) do |filter, popped_params|
|
51
|
+
next unless params.key?(filter)
|
52
|
+
|
53
|
+
popped_params[filter.to_sym] = params.delete(filter)
|
54
|
+
end
|
55
|
+
end
|
46
56
|
end
|
47
57
|
end
|
48
58
|
end
|
@@ -175,6 +175,12 @@ paths:
|
|
175
175
|
description: 'Filter by sample status: ordered, drawn'
|
176
176
|
schema:
|
177
177
|
type: string
|
178
|
+
- name: end_date
|
179
|
+
in: query
|
180
|
+
required: false
|
181
|
+
description: Select all results before this date
|
182
|
+
schema:
|
183
|
+
type: date
|
178
184
|
responses:
|
179
185
|
'200':
|
180
186
|
description: Success
|
@@ -396,6 +402,32 @@ paths:
|
|
396
402
|
responses:
|
397
403
|
'204':
|
398
404
|
description: No Content
|
405
|
+
"/api/v1/lab/reasons_for_test":
|
406
|
+
get:
|
407
|
+
summary: Reasons for test
|
408
|
+
description: Retrieve default reasons for test concept set
|
409
|
+
tags:
|
410
|
+
- Concepts
|
411
|
+
security:
|
412
|
+
- api_key: []
|
413
|
+
responses:
|
414
|
+
'200':
|
415
|
+
description: Success
|
416
|
+
content:
|
417
|
+
application/json:
|
418
|
+
schema:
|
419
|
+
type: array
|
420
|
+
items:
|
421
|
+
type: object
|
422
|
+
properties:
|
423
|
+
concept_id:
|
424
|
+
type: integer
|
425
|
+
name:
|
426
|
+
type: string
|
427
|
+
example: Routine
|
428
|
+
required:
|
429
|
+
- concept_id
|
430
|
+
- name
|
399
431
|
"/api/v1/lab/tests/{test_id}/results":
|
400
432
|
post:
|
401
433
|
summary: Add results to order
|
data/lib/lab/version.rb
CHANGED
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.10
|
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-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: couchrest
|
@@ -304,9 +304,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
304
304
|
version: '0'
|
305
305
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
306
306
|
requirements:
|
307
|
-
- - "
|
307
|
+
- - ">="
|
308
308
|
- !ruby/object:Gem::Version
|
309
|
-
version:
|
309
|
+
version: '0'
|
310
310
|
requirements: []
|
311
311
|
rubygems_version: 3.0.8
|
312
312
|
signing_key:
|