hippo 0.0.10 → 0.0.11

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.
@@ -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
- if segment_string =~ /\AST/
55
- raw_transaction_sets << []
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 << initialize_segment(segment_string)
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 |segments|
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(:segments => segments))
101
+ Hippo::TransactionSets.const_get(transaction_set)::Base.new(separators.merge(transaction))
66
102
  end
67
103
  end
68
104
 
69
- def parse(filename)
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
@@ -74,8 +74,12 @@ module Hippo::Segments
74
74
  end
75
75
 
76
76
  def get_field(field)
77
- if field.class == Numeric || field =~ /\A#{self.class.identifier}(?:(\d+)(?:_(\d+)){0,1})\z/
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
- self.values[field.sequence]
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
@@ -86,5 +86,6 @@ module Hippo
86
86
  autoload :GS, 'hippo/segments/GS'
87
87
  autoload :GE, 'hippo/segments/GE'
88
88
  autoload :IEA, 'hippo/segments/IEA'
89
+ autoload :TA1, 'hippo/segments/TA1'
89
90
  end
90
91
  end
@@ -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
- subcomponent = component.initialize_component(self)
86
- subcomponent.populate(segments.slice!(starting_index, length))
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
- values[component.sequence] = subcomponent
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
@@ -1,3 +1,3 @@
1
1
  module Hippo
2
- VERSION = "0.0.10"
2
+ VERSION = "0.0.11"
3
3
  end
data/lib/hippo.rb CHANGED
@@ -9,6 +9,7 @@ module Hippo
9
9
  autoload :Field, 'hippo/field'
10
10
  autoload :CompositeField, 'hippo/composite_field'
11
11
  autoload :Parser, 'hippo/parser'
12
+ autoload :CodeLists, 'hippo/code_lists'
12
13
 
13
14
  DEFAULT_FIELD_SEPARATOR = '*'
14
15
  DEFAULT_COMPOSITE_SEPARATOR = ':'
@@ -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
@@ -119,6 +119,11 @@ module Hippo::TransactionSets
119
119
  :identified_by => {
120
120
  'TCS.Field7' => 'Foo2'
121
121
  }
122
+
123
+ segment Hippo::Segments::SE,
124
+ :identified_by => {
125
+ 'SE02' => 'Test'
126
+ }
122
127
  end
123
128
  end
124
129
  end
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.raw_data = ts.to_s
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
@@ -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.10
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-11-29 00:00:00.000000000 Z
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: &70133817722520 !ruby/object:Gem::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: *70133817722520
25
+ version_requirements: *70206774000140
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: rake
28
- requirement: &70133817722020 !ruby/object:Gem::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: *70133817722020
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