hippo 0.0.10 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +18 -1
- data/README.md +23 -6
- data/lib/hippo/code_lists/claim_adjustment_reason_codes.rb +2252 -0
- data/lib/hippo/code_lists/claim_status_category_codes.rb +376 -0
- data/lib/hippo/code_lists/claim_status_codes.rb +5456 -0
- data/lib/hippo/code_lists/remittance_advice_remark_codes.rb +6280 -0
- data/lib/hippo/code_lists/service_type_codes.rb +1299 -0
- data/lib/hippo/code_lists/taxonomy_codes.rb +9224 -0
- data/lib/hippo/code_lists.rb +10 -0
- data/lib/hippo/parser.rb +50 -8
- data/lib/hippo/segments/TA1.rb +46 -0
- data/lib/hippo/segments/base.rb +11 -3
- data/lib/hippo/segments.rb +1 -0
- data/lib/hippo/transaction_sets/HIPAA_277/L2000C.rb +10 -0
- data/lib/hippo/transaction_sets/HIPAA_277/base.rb +0 -10
- data/lib/hippo/transaction_sets/base.rb +16 -6
- data/lib/hippo/version.rb +1 -1
- data/lib/hippo.rb +1 -0
- data/samples/005010X231A1_01.edi +11 -0
- data/samples/005010X231A1_02.edi +11 -0
- data/test/test_helper.rb +5 -0
- data/test/test_parser.rb +45 -5
- data/test/test_segments_base.rb +7 -0
- metadata +16 -6
@@ -0,0 +1,10 @@
|
|
1
|
+
module Hippo
|
2
|
+
module CodeLists
|
3
|
+
autoload :ClaimAdjustmentReasonCodes, 'hippo/code_lists/claim_adjustment_reason_codes'
|
4
|
+
autoload :ClaimStatusCategoryCodes, 'hippo/code_lists/claim_status_category_codes'
|
5
|
+
autoload :ClaimStatusCodes, 'hippo/code_lists/claim_status_codes'
|
6
|
+
autoload :RemittanceAdviceRemarkCodes, 'hippo/code_lists/remittance_advice_remark_codes'
|
7
|
+
autoload :ServiceTypeCodes, 'hippo/code_lists/service_type_codes'
|
8
|
+
autoload :TaxonomyCodes, 'hippo/code_lists/taxonomy_codes'
|
9
|
+
end
|
10
|
+
end
|
data/lib/hippo/parser.rb
CHANGED
@@ -10,11 +10,22 @@ module Hippo
|
|
10
10
|
setup_separators(options)
|
11
11
|
end
|
12
12
|
|
13
|
+
def read_string(input)
|
14
|
+
@raw_data = input
|
15
|
+
remove_base_control_characters
|
16
|
+
parse_separators(@raw_data)
|
17
|
+
end
|
18
|
+
|
13
19
|
def read_file(filename)
|
14
20
|
@raw_data = File.read(filename)
|
21
|
+
remove_base_control_characters
|
15
22
|
parse_separators(@raw_data)
|
16
23
|
end
|
17
24
|
|
25
|
+
def remove_base_control_characters
|
26
|
+
@raw_data.gsub!(/[\a\e\f\n\r\t\v]/,'')
|
27
|
+
end
|
28
|
+
|
18
29
|
def initialize_segment(input)
|
19
30
|
fields = input.split(@field_separator)
|
20
31
|
|
@@ -45,31 +56,62 @@ module Hippo
|
|
45
56
|
segment
|
46
57
|
end
|
47
58
|
|
59
|
+
def find_first_segment(segments, identifier, reverse = false)
|
60
|
+
segments.reverse! if reverse
|
61
|
+
|
62
|
+
if index = segments.index{|o| o.identifier == identifier}
|
63
|
+
segments[index]
|
64
|
+
else
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
48
69
|
def populate_transaction_sets
|
49
|
-
raw_transaction_sets
|
70
|
+
raw_transaction_sets = []
|
71
|
+
segments = []
|
72
|
+
inside_transaction = false
|
50
73
|
|
51
74
|
@raw_data.split(@segment_separator).each do |segment_string|
|
52
75
|
next if segment_string.strip.empty?
|
53
76
|
|
54
|
-
|
55
|
-
|
77
|
+
segments << initialize_segment(segment_string)
|
78
|
+
end
|
79
|
+
|
80
|
+
segments.each_with_index do |segment, index|
|
81
|
+
|
82
|
+
if segment.identifier == 'ST'
|
83
|
+
raw_transaction_sets << {:segments => [],
|
84
|
+
:ISA => find_first_segment(segments[0,index + 1], 'ISA', true),
|
85
|
+
:GS => find_first_segment(segments[0,index + 1], 'GS', true),
|
86
|
+
:GE => find_first_segment(segments[index + 1,segments.length - index + 1], 'GE'),
|
87
|
+
:IEA => find_first_segment(segments[index + 1,segments.length - index + 1], 'IEA')}
|
88
|
+
|
89
|
+
inside_transaction = true
|
56
90
|
end
|
57
91
|
|
58
|
-
raw_transaction_sets.last <<
|
92
|
+
raw_transaction_sets.last[:segments] << segment if inside_transaction
|
93
|
+
|
94
|
+
inside_transaction = false if segment.identifier == 'SE'
|
59
95
|
end
|
60
96
|
|
61
|
-
raw_transaction_sets.collect do |
|
62
|
-
transaction_set_id = segments.first.ST01
|
97
|
+
raw_transaction_sets.collect do |transaction|
|
98
|
+
transaction_set_id = transaction[:segments].first.ST01
|
63
99
|
transaction_set = Hippo::TransactionSets.constants.select{|c| c.to_s.end_with?(transaction_set_id) }.first
|
64
100
|
|
65
|
-
Hippo::TransactionSets.const_get(transaction_set)::Base.new(separators.merge(
|
101
|
+
Hippo::TransactionSets.const_get(transaction_set)::Base.new(separators.merge(transaction))
|
66
102
|
end
|
67
103
|
end
|
68
104
|
|
69
|
-
def
|
105
|
+
def parse_file(filename)
|
70
106
|
read_file(filename)
|
71
107
|
populate_transaction_sets
|
72
108
|
end
|
109
|
+
alias :parse :parse_file
|
110
|
+
|
111
|
+
def parse_string(input)
|
112
|
+
read_string(input)
|
113
|
+
populate_transaction_sets
|
114
|
+
end
|
73
115
|
end
|
74
116
|
end
|
75
117
|
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Hippo::Segments
|
2
|
+
class TA1 < Base
|
3
|
+
|
4
|
+
segment_identifier 'TA1'
|
5
|
+
|
6
|
+
field :name => 'InterchangeControlNumber',
|
7
|
+
:sequence => 1,
|
8
|
+
:datatype => :string,
|
9
|
+
:minimum => 9,
|
10
|
+
:maximum => 9,
|
11
|
+
:required => true,
|
12
|
+
:data_element_number => 'I12'
|
13
|
+
|
14
|
+
field :name => 'InterchangeDate',
|
15
|
+
:sequence => 2,
|
16
|
+
:datatype => :string,
|
17
|
+
:minimum => 6,
|
18
|
+
:maximum => 6,
|
19
|
+
:required => true,
|
20
|
+
:data_element_number => 'I08'
|
21
|
+
|
22
|
+
field :name => 'InterchangeTime',
|
23
|
+
:sequence => 3,
|
24
|
+
:datatype => :string,
|
25
|
+
:minimum => 4,
|
26
|
+
:maximum => 4,
|
27
|
+
:required => true,
|
28
|
+
:data_element_number => 'I09'
|
29
|
+
|
30
|
+
field :name => 'InterchangeAcknowledgmentCode',
|
31
|
+
:sequence => 4,
|
32
|
+
:datatype => :string,
|
33
|
+
:minimum => 1,
|
34
|
+
:maximum => 1,
|
35
|
+
:required => true,
|
36
|
+
:data_element_number => 'I17'
|
37
|
+
|
38
|
+
field :name => 'InterchangeNoteCode',
|
39
|
+
:sequence => 5,
|
40
|
+
:datatype => :string,
|
41
|
+
:minimum => 3,
|
42
|
+
:maximum => 3,
|
43
|
+
:required => true,
|
44
|
+
:data_element_number => 'I18'
|
45
|
+
end
|
46
|
+
end
|
data/lib/hippo/segments/base.rb
CHANGED
@@ -74,8 +74,12 @@ module Hippo::Segments
|
|
74
74
|
end
|
75
75
|
|
76
76
|
def get_field(field)
|
77
|
-
if field
|
78
|
-
self.class.fields[$1.to_i - 1]
|
77
|
+
if field =~ /\A#{self.class.identifier}(?:(\d+)(?:_(\d+)){0,1})\z/
|
78
|
+
if $2 && self.class.fields[$1.to_i - 1].class == Array
|
79
|
+
self.class.fields[$1.to_i - 1][$2.to_i - 1]
|
80
|
+
else
|
81
|
+
self.class.fields[$1.to_i - 1]
|
82
|
+
end
|
79
83
|
else
|
80
84
|
fields = self.class.fields.flatten.select{|f| f.name == field.gsub(/_\d{1,2}\z/,'')}
|
81
85
|
|
@@ -144,7 +148,11 @@ module Hippo::Segments
|
|
144
148
|
self.values[field.sequence] = args[0]
|
145
149
|
end
|
146
150
|
else
|
147
|
-
|
151
|
+
if field.composite
|
152
|
+
self.values[field.composite_sequence][field.sequence]
|
153
|
+
else
|
154
|
+
self.values[field.sequence]
|
155
|
+
end
|
148
156
|
end
|
149
157
|
end
|
150
158
|
end
|
data/lib/hippo/segments.rb
CHANGED
@@ -37,6 +37,16 @@ module Hippo::TransactionSets
|
|
37
37
|
'TRN.TRN01' => '1'
|
38
38
|
}
|
39
39
|
|
40
|
+
#Patient Level
|
41
|
+
loop Hippo::TransactionSets::HIPAA_277::L2000D,
|
42
|
+
:name => 'Patient Level',
|
43
|
+
:minimum => 0,
|
44
|
+
:maximum => 99999,
|
45
|
+
:position => 100,
|
46
|
+
:identified_by => {
|
47
|
+
'HL.HL03' => 'PT'
|
48
|
+
}
|
49
|
+
|
40
50
|
end
|
41
51
|
end
|
42
52
|
end
|
@@ -58,16 +58,6 @@ module Hippo::TransactionSets
|
|
58
58
|
'HL.HL04' => ["0", "1"]
|
59
59
|
}
|
60
60
|
|
61
|
-
#Patient Level
|
62
|
-
loop Hippo::TransactionSets::HIPAA_277::L2000D,
|
63
|
-
:name => 'Patient Level',
|
64
|
-
:minimum => 0,
|
65
|
-
:maximum => 99999,
|
66
|
-
:position => 100,
|
67
|
-
:identified_by => {
|
68
|
-
'HL.HL03' => 'PT'
|
69
|
-
}
|
70
|
-
|
71
61
|
#Transaction Set Trailer
|
72
62
|
segment Hippo::Segments::SE,
|
73
63
|
:name => 'Transaction Set Trailer',
|
@@ -20,10 +20,14 @@ module Hippo::TransactionSets
|
|
20
20
|
alias loop add_component
|
21
21
|
end
|
22
22
|
|
23
|
-
attr_accessor :values, :parent, :sequences
|
23
|
+
attr_accessor :values, :parent, :sequences, :ISA, :GS, :GE, :IEA
|
24
24
|
|
25
25
|
def initialize(options = {})
|
26
26
|
@parent = options[:parent]
|
27
|
+
@ISA = options[:ISA]
|
28
|
+
@GS = options[:GS]
|
29
|
+
@GE = options[:GE]
|
30
|
+
@IEA = options[:IEA]
|
27
31
|
|
28
32
|
setup_separators(options)
|
29
33
|
|
@@ -67,7 +71,6 @@ module Hippo::TransactionSets
|
|
67
71
|
break unless starting_index
|
68
72
|
|
69
73
|
remaining_components = self.class.components.slice(component_index + 1, self.class.components.length - 1)
|
70
|
-
|
71
74
|
remaining_components.each do |next_component|
|
72
75
|
break if found_next_segment
|
73
76
|
length = 0
|
@@ -82,10 +85,17 @@ module Hippo::TransactionSets
|
|
82
85
|
|
83
86
|
length = segments.length - starting_index if length == 0
|
84
87
|
|
85
|
-
|
86
|
-
|
88
|
+
if component.repeating?
|
89
|
+
values[component.sequence] ||= component.initialize_component(self)
|
90
|
+
values[component.sequence].build do |subcomponent|
|
91
|
+
subcomponent.populate(segments.slice!(starting_index, length))
|
92
|
+
end
|
93
|
+
else
|
94
|
+
subcomponent = component.initialize_component(self)
|
95
|
+
subcomponent.populate(segments.slice!(starting_index, length))
|
87
96
|
|
88
|
-
|
97
|
+
values[component.sequence] = subcomponent
|
98
|
+
end
|
89
99
|
end
|
90
100
|
end
|
91
101
|
end
|
@@ -140,7 +150,7 @@ module Hippo::TransactionSets
|
|
140
150
|
if name.class == Regexp
|
141
151
|
c.options[:name] =~ name
|
142
152
|
else
|
143
|
-
c.options[:name] == name
|
153
|
+
c.options[:name] == name
|
144
154
|
end
|
145
155
|
end[sequence]
|
146
156
|
end
|
data/lib/hippo/version.rb
CHANGED
data/lib/hippo.rb
CHANGED
@@ -0,0 +1,11 @@
|
|
1
|
+
ISA*00* *00* *01*XXXXXXXXXXXXXXX*ZZ*XXXXXXXXXXXXXXX*111212*1628*^*00501*445289179*0*P*:~
|
2
|
+
TA1*346155305*111212*1553*A*000~
|
3
|
+
GS*FA*XXXXXX*XXXXXX*20111212*162832*1*X*005010X231A1~
|
4
|
+
ST*999*1001*005010X231A1~
|
5
|
+
AK1*HC*346155305*005010X222A1~
|
6
|
+
AK2*837*0005*005010X222A1~
|
7
|
+
IK5*A~
|
8
|
+
AK9*A*1*1*1~
|
9
|
+
SE*6*1001~
|
10
|
+
GE*1*1~
|
11
|
+
IEA*1*445289179~
|
@@ -0,0 +1,11 @@
|
|
1
|
+
ISA!00! !00! !01!XXXXXXXXXXXXXXX!ZZ!XXXXXXXXXXXXXXX!111212!1628!@!00501!445289179!0!P!~^
|
2
|
+
TA1!346155305!111212!1553!A!000^
|
3
|
+
GS!FA!XXXXXX!XXXXXX!20111212!162832!1!X!005010X231A1^
|
4
|
+
ST!999!1001!005010X231A1^
|
5
|
+
AK1!HC!346155305!005010X222A1^
|
6
|
+
AK2!837!0005!005010X222A1^
|
7
|
+
IK5!A^
|
8
|
+
AK9!A!1!1!1^
|
9
|
+
SE!6!1001^
|
10
|
+
GE!1!1^
|
11
|
+
IEA!1!445289179^
|
data/test/test_helper.rb
CHANGED
data/test/test_parser.rb
CHANGED
@@ -35,12 +35,52 @@ class TestParser < MiniTest::Unit::TestCase
|
|
35
35
|
|
36
36
|
#'TSS*Blah*Bar*Baz~TCS*Blah*:::CNBlah*Preset Field 7~TSS*Last Segment*Boo~TSS*Foo*SubBar~TCS*:SubBarBlah**Foo2~TSS*Last Segment*SubBarRepeater~', ts.to_s
|
37
37
|
|
38
|
-
@parser.
|
39
|
-
ts_result = @parser.populate_transaction_sets.first
|
40
|
-
|
41
|
-
puts ts.inspect
|
42
|
-
puts ts_result.inspect
|
38
|
+
ts_result = @parser.parse_string(ts.to_s).first
|
43
39
|
|
44
40
|
assert_equal ts.values.inspect, ts_result.values.inspect
|
45
41
|
end
|
42
|
+
|
43
|
+
def test_reads_separators_from_isa
|
44
|
+
@parser.parse('samples/005010X231A1_01.edi')
|
45
|
+
|
46
|
+
assert_equal '*', @parser.field_separator
|
47
|
+
assert_equal '^', @parser.repetition_separator
|
48
|
+
assert_equal ':', @parser.composite_separator
|
49
|
+
assert_equal '~', @parser.segment_separator
|
50
|
+
|
51
|
+
@parser = Hippo::Parser.new
|
52
|
+
transaction_set = @parser.parse('samples/005010X231A1_02.edi')
|
53
|
+
|
54
|
+
assert_equal '!', @parser.field_separator
|
55
|
+
assert_equal '@', @parser.repetition_separator
|
56
|
+
assert_equal '~', @parser.composite_separator
|
57
|
+
assert_equal '^', @parser.segment_separator
|
58
|
+
|
59
|
+
assert_equal transaction_set.first.ST.ST01, '999'
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_adds_enveloping_to_transaction_set
|
63
|
+
transaction_set = @parser.parse('samples/005010X231A1_01.edi').first
|
64
|
+
|
65
|
+
assert_equal '445289179', transaction_set.ISA.ISA13
|
66
|
+
assert_equal '1', transaction_set.GS.GS06
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_parses_repeating_loops
|
70
|
+
ts = Hippo::TransactionSets::Test::Base.new
|
71
|
+
ts.ST
|
72
|
+
[1,2,3,4,5].each do |i|
|
73
|
+
ts.TSS.build do |tss|
|
74
|
+
tss.Field2 = 'Bar' + i.to_s
|
75
|
+
tss.Field3 = 'Baz' + i.to_s
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
ts.TCS.Field1 = 'Blah'
|
80
|
+
ts.TSS_02.Field2 = 'Boo'
|
81
|
+
ts.SE
|
82
|
+
|
83
|
+
# ST*Test~TSS*Blah*Bar1*Baz1~TSS*Blah*Bar2*Baz2~TSS*Blah*Bar3*Baz3~TSS*Blah*Bar4*Baz4~TSS*Blah*Bar5*Baz5~TCS*Blah**Preset Field 7~TSS*Last Standalone Segment*Boo~SE**Test
|
84
|
+
assert_equal ts.values.inspect, @parser.parse_string(ts.to_s).first.values.inspect
|
85
|
+
end
|
46
86
|
end
|
data/test/test_segments_base.rb
CHANGED
@@ -95,6 +95,13 @@ class TestSegmentsBase < MiniTest::Unit::TestCase
|
|
95
95
|
seg.CompositeCommonName_2 = 'CompVal4'
|
96
96
|
|
97
97
|
assert_equal 'TCS*:::CompVal3*:::CompVal4~', seg.to_s
|
98
|
+
|
99
|
+
seg.TCS01_04 = 'CompVal5'
|
100
|
+
seg.TCS02_04 = 'CompVal6'
|
101
|
+
|
102
|
+
assert_equal 'TCS*:::CompVal5*:::CompVal6~', seg.to_s
|
103
|
+
|
104
|
+
assert_equal 'CompVal5', seg.TCS01_04
|
98
105
|
end
|
99
106
|
|
100
107
|
def test_assign_invalid_field_throws_error
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hippo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.11
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,11 +10,11 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2011-
|
13
|
+
date: 2011-12-18 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: minitest
|
17
|
-
requirement: &
|
17
|
+
requirement: &70206774000140 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: '0'
|
23
23
|
type: :development
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *70206774000140
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: rake
|
28
|
-
requirement: &
|
28
|
+
requirement: &70206773999520 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ~>
|
@@ -33,7 +33,7 @@ dependencies:
|
|
33
33
|
version: 0.9.2
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *70206773999520
|
37
37
|
description: HIPAA Transaction Set Generator/Parser
|
38
38
|
email:
|
39
39
|
- robertj@promedicalinc.com
|
@@ -50,6 +50,13 @@ files:
|
|
50
50
|
- Rakefile
|
51
51
|
- hippo.gemspec
|
52
52
|
- lib/hippo.rb
|
53
|
+
- lib/hippo/code_lists.rb
|
54
|
+
- lib/hippo/code_lists/claim_adjustment_reason_codes.rb
|
55
|
+
- lib/hippo/code_lists/claim_status_category_codes.rb
|
56
|
+
- lib/hippo/code_lists/claim_status_codes.rb
|
57
|
+
- lib/hippo/code_lists/remittance_advice_remark_codes.rb
|
58
|
+
- lib/hippo/code_lists/service_type_codes.rb
|
59
|
+
- lib/hippo/code_lists/taxonomy_codes.rb
|
53
60
|
- lib/hippo/exceptions.rb
|
54
61
|
- lib/hippo/field.rb
|
55
62
|
- lib/hippo/loop.rb
|
@@ -133,6 +140,7 @@ files:
|
|
133
140
|
- lib/hippo/segments/SV7.rb
|
134
141
|
- lib/hippo/segments/SVC.rb
|
135
142
|
- lib/hippo/segments/SVD.rb
|
143
|
+
- lib/hippo/segments/TA1.rb
|
136
144
|
- lib/hippo/segments/TOO.rb
|
137
145
|
- lib/hippo/segments/TRN.rb
|
138
146
|
- lib/hippo/segments/TS2.rb
|
@@ -239,6 +247,8 @@ files:
|
|
239
247
|
- samples/005010X221A1_tmhp_example.edi
|
240
248
|
- samples/005010X222A1_anesthesia.edi
|
241
249
|
- samples/005010X222A1_commercial_health_insurance.edi
|
250
|
+
- samples/005010X231A1_01.edi
|
251
|
+
- samples/005010X231A1_02.edi
|
242
252
|
- test/test_helper.rb
|
243
253
|
- test/test_hipaa_835.rb
|
244
254
|
- test/test_hipaa_837.rb
|