yahl7 0.1.0 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +47 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +27 -0
- data/.github/dependabot.yml +7 -0
- data/CHANGELOG.md +64 -0
- data/CODE_OF_CONDUCT.md +74 -25
- data/CONTRIBUTING.md +47 -0
- data/README.md +19 -3
- data/lib/yahl7/v2/{segment_field_names.rb → alias_field_names.rb} +14 -7
- data/lib/yahl7/v2/alias_person_name.rb +65 -0
- data/lib/yahl7/v2/data_type/cnn.rb +29 -0
- data/lib/yahl7/v2/data_type/dt.rb +28 -0
- data/lib/yahl7/v2/data_type/ft.rb +26 -0
- data/lib/yahl7/v2/data_type/ndl.rb +30 -0
- data/lib/yahl7/v2/data_type/ts.rb +24 -0
- data/lib/yahl7/v2/data_type/xad.rb +31 -0
- data/lib/yahl7/v2/data_type/xpn.rb +40 -0
- data/lib/yahl7/v2/data_type/xtn.rb +29 -0
- data/lib/yahl7/v2/data_type.rb +20 -0
- data/lib/yahl7/v2/date_time.rb +1 -1
- data/lib/yahl7/v2/error/invalid_format_error.rb +12 -0
- data/lib/yahl7/v2/message/adt.rb +2 -0
- data/lib/yahl7/v2/message/oru.rb +1 -0
- data/lib/yahl7/v2/message.rb +10 -0
- data/lib/yahl7/v2/segment/al1.rb +21 -0
- data/lib/yahl7/v2/segment/dg1.rb +36 -0
- data/lib/yahl7/v2/segment/evn.rb +23 -0
- data/lib/yahl7/v2/segment/in1.rb +68 -0
- data/lib/yahl7/v2/segment/msh.rb +4 -2
- data/lib/yahl7/v2/segment/nte.rb +3 -2
- data/lib/yahl7/v2/segment/obr.rb +13 -12
- data/lib/yahl7/v2/segment/obx.rb +11 -5
- data/lib/yahl7/v2/segment/orc.rb +8 -7
- data/lib/yahl7/v2/segment/pd1.rb +36 -0
- data/lib/yahl7/v2/segment/pid.rb +11 -10
- data/lib/yahl7/v2/segment/pv1.rb +7 -6
- data/lib/yahl7/v2.rb +6 -1
- data/lib/yahl7/version.rb +1 -1
- metadata +23 -3
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module YAHL7
|
4
|
+
module V2
|
5
|
+
# This module can be included into a class of a data type that includes the
|
6
|
+
# name components in order to add an `#assemble_name_family_first` method
|
7
|
+
# and an `#assemble_name_given_first` method.
|
8
|
+
module AliasPersonName
|
9
|
+
# This is the method the builds the "bare" name (i.e., without prefixes
|
10
|
+
# and/or suffixes) with the family name first.
|
11
|
+
def bare_name_family_first
|
12
|
+
buf = family_name.nil? || family_name == '' ? '' : "#{family_name}, "
|
13
|
+
buf += "#{given_name} " unless given_name.nil? || given_name == ''
|
14
|
+
buf += middle_name unless middle_name.nil? || middle_name == ''
|
15
|
+
|
16
|
+
buf.strip
|
17
|
+
end
|
18
|
+
|
19
|
+
# This is the method the builds the "bare" name (i.e., without prefixes
|
20
|
+
# and/or suffixes) with the given name first.
|
21
|
+
def bare_name_given_first
|
22
|
+
[given_name, middle_name, family_name]
|
23
|
+
.reject { |p| p.nil? || p == '' }
|
24
|
+
.join(' ')
|
25
|
+
end
|
26
|
+
|
27
|
+
# This is the method that builds the full name (i.e., with prefixes and/or
|
28
|
+
# suffixes) with the family name first.
|
29
|
+
def assemble_name_family_first
|
30
|
+
buf = prefix.nil? || prefix == '' ? '' : "#{prefix} "
|
31
|
+
buf += bare_name_family_first
|
32
|
+
|
33
|
+
s = suffixes
|
34
|
+
buf += ", #{s}" unless s == ''
|
35
|
+
|
36
|
+
buf
|
37
|
+
end
|
38
|
+
|
39
|
+
# We have two locations for suffix information on a name:
|
40
|
+
#
|
41
|
+
# 1. The suffix, which is meant to house information like Jr, II, etc.
|
42
|
+
# 2. The degree, which is meant to house information like MD, PhD, etc.
|
43
|
+
#
|
44
|
+
# This method is used to combine those into a single value to make name
|
45
|
+
# assembly easier.
|
46
|
+
def suffixes
|
47
|
+
[suffix, degree]
|
48
|
+
.reject { |p| p.nil? || p == '' }
|
49
|
+
.join(', ')
|
50
|
+
end
|
51
|
+
|
52
|
+
# This is the method that builds the full name (i.e., with prefixes and/or
|
53
|
+
# suffixes) with the given name first.
|
54
|
+
def assemble_name_given_first
|
55
|
+
buf = prefix.nil? || prefix == '' ? '' : "#{prefix} "
|
56
|
+
buf += bare_name_given_first
|
57
|
+
|
58
|
+
s = suffixes
|
59
|
+
buf += ", #{s}" unless s == ''
|
60
|
+
|
61
|
+
buf
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
module YAHL7
|
6
|
+
module V2
|
7
|
+
class DataType
|
8
|
+
# This is the HL7 data type for a composite name and ID number.
|
9
|
+
class CNN < YAHL7::V2::DataType
|
10
|
+
include YAHL7::V2::AliasPersonName
|
11
|
+
include YAHL7::V2::AliasFieldNames
|
12
|
+
|
13
|
+
define_field_names({
|
14
|
+
id_number: 0,
|
15
|
+
family_name: 1,
|
16
|
+
given_name: 2,
|
17
|
+
middle_name: 3,
|
18
|
+
suffix: 4,
|
19
|
+
prefix: 5,
|
20
|
+
degree: 6,
|
21
|
+
source_table: 7,
|
22
|
+
assigning_authority_namespace_id: 8,
|
23
|
+
assigning_authority_universal_id: 9,
|
24
|
+
assigning_authority_universal_id_type: 10
|
25
|
+
})
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
module YAHL7
|
6
|
+
module V2
|
7
|
+
class DataType
|
8
|
+
# This is the HL7 data type for a single date. This should be in the
|
9
|
+
# format of YYYY[MM[DD]]
|
10
|
+
class DT < YAHL7::V2::DataType
|
11
|
+
def date
|
12
|
+
@date ||= parse_date
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def parse_date
|
18
|
+
case @value.length
|
19
|
+
when 4 then Date.parse("#{@value}0101")
|
20
|
+
when 6 then Date.parse("#{@value}01")
|
21
|
+
when 8 then Date.parse(@value)
|
22
|
+
else raise YAHL7::V2::Error::InvalidFormatError, 'Unknown date format'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
module YAHL7
|
6
|
+
module V2
|
7
|
+
class DataType
|
8
|
+
# This is the HL7 data type for formatted text
|
9
|
+
class FT < YAHL7::V2::DataType
|
10
|
+
def formatted
|
11
|
+
@formatted ||= parse_value
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def parse_value
|
17
|
+
value.is_a?(Array) ? value.map { |v| parse_body(v) }.join("\n") : parse_body(value)
|
18
|
+
end
|
19
|
+
|
20
|
+
def parse_body(body)
|
21
|
+
YAHL7::V2::Formatter.format(body)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
require_relative 'ts'
|
6
|
+
|
7
|
+
module YAHL7
|
8
|
+
module V2
|
9
|
+
class DataType
|
10
|
+
# This is the HL7 data type for a name with a date and location.
|
11
|
+
class NDL < YAHL7::V2::DataType
|
12
|
+
include YAHL7::V2::AliasFieldNames
|
13
|
+
|
14
|
+
define_field_names({
|
15
|
+
name: { index: 0, class: YAHL7::V2::DataType::CNN },
|
16
|
+
start_datetime: { index: 1, class: YAHL7::V2::DataType::TS },
|
17
|
+
end_datetime: { index: 2, class: YAHL7::V2::DataType::TS },
|
18
|
+
point_of_care: 3,
|
19
|
+
room: 4,
|
20
|
+
bed: 5,
|
21
|
+
facility: 6,
|
22
|
+
location_status: 7,
|
23
|
+
patient_location_type: 8,
|
24
|
+
building: 9,
|
25
|
+
floor: 10
|
26
|
+
})
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
module YAHL7
|
6
|
+
module V2
|
7
|
+
class DataType
|
8
|
+
# This is the HL7 data type for a timestamp with a format of
|
9
|
+
# YYYY[MM[DD[HH[MM[SS[.S[S[S[S]]]]]]]]][+/-ZZZZ]
|
10
|
+
class TS < YAHL7::V2::DataType
|
11
|
+
def timestamp
|
12
|
+
@timestamp ||= parse_timestamp
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def parse_timestamp
|
18
|
+
timestamp = @value.is_a?(Array) ? @value.first : @value
|
19
|
+
YAHL7::V2::DateTime.parse(timestamp)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
module YAHL7
|
6
|
+
module V2
|
7
|
+
class DataType
|
8
|
+
# This is the HL7 data type for an extended address.
|
9
|
+
class XAD < YAHL7::V2::DataType
|
10
|
+
include YAHL7::V2::AliasFieldNames
|
11
|
+
|
12
|
+
define_field_names({
|
13
|
+
street_address: 0,
|
14
|
+
other_designation: 1,
|
15
|
+
city: 2,
|
16
|
+
state: 3,
|
17
|
+
zip: 4,
|
18
|
+
country: 5,
|
19
|
+
address_type: 6,
|
20
|
+
other_geographic_designation: 7,
|
21
|
+
county_code: 8,
|
22
|
+
census_tract: 9,
|
23
|
+
address_representation_code: 10,
|
24
|
+
address_validity_range: 11,
|
25
|
+
effective_date: { index: 12, class: YAHL7::V2::DataType::TS },
|
26
|
+
expiration_date: { index: 13, class: YAHL7::V2::DataType::TS }
|
27
|
+
})
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
module YAHL7
|
6
|
+
module V2
|
7
|
+
class DataType
|
8
|
+
# This is the HL7 data type for an extended person name. This is the data
|
9
|
+
# type used for patient names, etc.
|
10
|
+
class XPN < YAHL7::V2::DataType
|
11
|
+
include YAHL7::V2::AliasPersonName
|
12
|
+
include YAHL7::V2::AliasFieldNames
|
13
|
+
|
14
|
+
define_field_names({
|
15
|
+
family_name: 0,
|
16
|
+
given_name: 1,
|
17
|
+
middle_name: 2,
|
18
|
+
suffix: 3,
|
19
|
+
prefix: 4,
|
20
|
+
degree: 5,
|
21
|
+
name_type_code: 6,
|
22
|
+
name_representation_code: 7,
|
23
|
+
name_context: 8,
|
24
|
+
name_validity_range: 9,
|
25
|
+
name_assembly_order: 10,
|
26
|
+
effective_date: 11,
|
27
|
+
expiration_date: 12,
|
28
|
+
professional_suffix: 13
|
29
|
+
})
|
30
|
+
|
31
|
+
def full_name
|
32
|
+
case name_assembly_order&.downcase
|
33
|
+
when 'f' then assemble_name_family_first
|
34
|
+
else assemble_name_given_first
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
module YAHL7
|
6
|
+
module V2
|
7
|
+
class DataType
|
8
|
+
# This is the HL7 data type for an extended telephone number.
|
9
|
+
class XTN < YAHL7::V2::DataType
|
10
|
+
include YAHL7::V2::AliasFieldNames
|
11
|
+
|
12
|
+
define_field_names({
|
13
|
+
telephone_number: 0,
|
14
|
+
telephone_use_code: 1,
|
15
|
+
telephone_equipment_type: 2,
|
16
|
+
email_address: 3,
|
17
|
+
country_code: 4,
|
18
|
+
area_city_code: 5,
|
19
|
+
local_number: 6,
|
20
|
+
extension: 7,
|
21
|
+
any_text: 8,
|
22
|
+
extension_prefix: 9,
|
23
|
+
speed_dial_code: 10,
|
24
|
+
unformatted_telephone_number: 11
|
25
|
+
})
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Dir[File.join(__dir__, 'data_type', '*.rb')].sort.each { |f| require f }
|
4
|
+
|
5
|
+
module YAHL7
|
6
|
+
module V2
|
7
|
+
# This is the base data type class for custom HL7 data types.
|
8
|
+
class DataType
|
9
|
+
attr_accessor :value
|
10
|
+
|
11
|
+
def initialize(value)
|
12
|
+
@value = value
|
13
|
+
end
|
14
|
+
|
15
|
+
def [](index)
|
16
|
+
value[index]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/yahl7/v2/date_time.rb
CHANGED
@@ -21,7 +21,7 @@ module YAHL7
|
|
21
21
|
timezone = parts[1]
|
22
22
|
|
23
23
|
format = timestamp_format(timestamp)
|
24
|
-
raise 'Unknown timestamp format' if format.nil?
|
24
|
+
raise YAHL7::V2::Error::InvalidFormatError, 'Unknown timestamp format' if format.nil?
|
25
25
|
|
26
26
|
format += '%z' unless timezone.nil?
|
27
27
|
::DateTime.strptime(value, format)
|
data/lib/yahl7/v2/message/adt.rb
CHANGED
data/lib/yahl7/v2/message/oru.rb
CHANGED
data/lib/yahl7/v2/message.rb
CHANGED
@@ -17,6 +17,10 @@ module YAHL7
|
|
17
17
|
.map { |s| Segment.parse(s, parse_options) }
|
18
18
|
end
|
19
19
|
|
20
|
+
def to_s
|
21
|
+
@to_s ||= segments.join(parse_options.segment_sep)
|
22
|
+
end
|
23
|
+
|
20
24
|
def [](index)
|
21
25
|
case index
|
22
26
|
when Integer then segments[index]
|
@@ -41,9 +45,15 @@ module YAHL7
|
|
41
45
|
# information, as this method simply finds the type code and then hands it
|
42
46
|
# off to `get_message_class` to find the class to use.
|
43
47
|
def self.message_type(body, parse_options = nil)
|
48
|
+
return self if body.length < 8
|
49
|
+
|
44
50
|
parse_options ||= ParseOptions.from_body(body)
|
45
51
|
head = body.split(parse_options.segment_sep)[0]
|
52
|
+
return self if head.nil?
|
53
|
+
|
46
54
|
type = head.split(parse_options.repetition_sep)[8]
|
55
|
+
return self if type.nil?
|
56
|
+
|
47
57
|
code = type.split(parse_options.component_sep)[0]
|
48
58
|
get_message_class(code)
|
49
59
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module YAHL7
|
4
|
+
module V2
|
5
|
+
class Segment
|
6
|
+
# AL1 segments contain patient allergy information.
|
7
|
+
class AL1 < YAHL7::V2::Segment
|
8
|
+
include YAHL7::V2::AliasFieldNames
|
9
|
+
|
10
|
+
define_field_names({
|
11
|
+
set_id: 1,
|
12
|
+
allergen_type_code: 2,
|
13
|
+
allergen_code: 3,
|
14
|
+
allergen_severity_code: 4,
|
15
|
+
allergen_reaction_code: 5,
|
16
|
+
identification_date: { index: 6, class: YAHL7::V2::DataType::DT }
|
17
|
+
})
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module YAHL7
|
4
|
+
module V2
|
5
|
+
class Segment
|
6
|
+
# DG1 segments contain patient diagnosis information.
|
7
|
+
class DG1 < YAHL7::V2::Segment
|
8
|
+
include YAHL7::V2::AliasFieldNames
|
9
|
+
|
10
|
+
define_field_names({
|
11
|
+
set_id: 1,
|
12
|
+
diagnosis_code_method: 2,
|
13
|
+
diagnosis_code: 3,
|
14
|
+
diagnosis_description: 4,
|
15
|
+
diagnosis_datetime: { index: 5, class: YAHL7::V2::DataType::TS },
|
16
|
+
diagnosis_type: 6,
|
17
|
+
major_diagnosis_category: 7,
|
18
|
+
diagnostic_related_group: 8,
|
19
|
+
drg_approval_indicator: 9,
|
20
|
+
drg_grouper_review_code: 10,
|
21
|
+
outlier_type: 11,
|
22
|
+
outlier_days: 12,
|
23
|
+
outlier_cost: 13,
|
24
|
+
grouper_version_and_type: 14,
|
25
|
+
diagnostic_priority: 15,
|
26
|
+
diagnosing_clinician: 16,
|
27
|
+
diagnosis_classification: 17,
|
28
|
+
confidential_indicator: 18,
|
29
|
+
attestation_datetime: { index: 19, class: YAHL7::V2::DataType::TS },
|
30
|
+
diagnosis_identifier: 20,
|
31
|
+
diagnosis_action_code: 21
|
32
|
+
})
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|