hippo 0.0.10 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -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