dzero 0.1.1

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.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +265 -0
  3. data/lib/dzero/segments/01_patient.rb +27 -0
  4. data/lib/dzero/segments/02_pharmacy_provider.rb +12 -0
  5. data/lib/dzero/segments/03_prescriber.rb +22 -0
  6. data/lib/dzero/segments/04_insurance.rb +29 -0
  7. data/lib/dzero/segments/05_coord_of_benefits.rb +27 -0
  8. data/lib/dzero/segments/06_workers_comp.rb +30 -0
  9. data/lib/dzero/segments/07_claim.rb +52 -0
  10. data/lib/dzero/segments/08_dur_pps.rb +17 -0
  11. data/lib/dzero/segments/09_coupon.rb +13 -0
  12. data/lib/dzero/segments/10_compound.rb +20 -0
  13. data/lib/dzero/segments/11_pricing.rb +26 -0
  14. data/lib/dzero/segments/12_prior_auth.rb +23 -0
  15. data/lib/dzero/segments/13_clinical.rb +19 -0
  16. data/lib/dzero/segments/14_additional_documentation.rb +25 -0
  17. data/lib/dzero/segments/15_facility.rb +16 -0
  18. data/lib/dzero/segments/16_narrative.rb +11 -0
  19. data/lib/dzero/segments/20_response_message.rb +11 -0
  20. data/lib/dzero/segments/21_response_status.rb +26 -0
  21. data/lib/dzero/segments/22_response_claim.rb +19 -0
  22. data/lib/dzero/segments/23_response_pricing.rb +55 -0
  23. data/lib/dzero/segments/24_response_dur_pps.rb +20 -0
  24. data/lib/dzero/segments/25_response_insurance.rb +18 -0
  25. data/lib/dzero/segments/26_response_prior_auth.rb +18 -0
  26. data/lib/dzero/segments/27_response_insurance_additional_documentation.rb +17 -0
  27. data/lib/dzero/segments/28_response_coord_of_benefits.rb +22 -0
  28. data/lib/dzero/segments/29_response_patient.rb +13 -0
  29. data/lib/dzero/segments/base.rb +128 -0
  30. data/lib/dzero/segments/concerns/parser.rb +18 -0
  31. data/lib/dzero/segments/concerns/serializer.rb +20 -0
  32. data/lib/dzero/test_support.rb +5 -0
  33. data/lib/dzero/transmissions/base.rb +47 -0
  34. data/lib/dzero/transmissions/concerns/parser.rb +23 -0
  35. data/lib/dzero/transmissions/concerns/segments_methods.rb +76 -0
  36. data/lib/dzero/transmissions/concerns/serializer.rb +11 -0
  37. data/lib/dzero/transmissions/groups/base.rb +59 -0
  38. data/lib/dzero/transmissions/groups/transaction_group.rb +3 -0
  39. data/lib/dzero/transmissions/groups/transmission_group.rb +11 -0
  40. data/lib/dzero/transmissions/request.rb +19 -0
  41. data/lib/dzero/transmissions/response.rb +17 -0
  42. data/lib/dzero/utils/fixed_width.rb +19 -0
  43. data/lib/dzero/utils/rejection_codes.rb +297 -0
  44. data/lib/dzero/utils/validator.rb +61 -0
  45. data/lib/dzero/version.rb +3 -0
  46. data/lib/dzero.rb +28 -0
  47. metadata +186 -0
@@ -0,0 +1,26 @@
1
+ module DZero::Segments
2
+ class ResponseStatus < Base
3
+ Base.register_segment(self, identifier: '21')
4
+
5
+ def self.field_id_to_symbol
6
+ super.merge({
7
+ 'AN' => :response_status,
8
+ 'F3' => :authorization_number,
9
+ 'FA' => :reject_count,
10
+ 'FB' => :reject_code,
11
+ '4F' => :reject_field_occurrence_indicator,
12
+ '5F' => :approved_message_code_count,
13
+ '6F' => :approved_message_code,
14
+ 'UF' => :additional_message_information_count,
15
+ 'UH' => :additional_message_information_qualifier,
16
+ 'FQ' => :additional_message_information,
17
+ 'UG' => :additional_message_information_continuity,
18
+ '7F' => :help_desk_phone_number_qualifier,
19
+ '8F' => :help_desk_phone_number,
20
+ 'K5' => :transaction_reference_number,
21
+ 'A7' => :internal_control_number,
22
+ 'MA' => :url,
23
+ })
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,19 @@
1
+ module DZero::Segments
2
+ class ResponseClaim < Base
3
+ Base.register_segment(self, identifier: '22')
4
+
5
+ def self.field_id_to_symbol
6
+ super.merge({
7
+ 'EM' => :prescription_reference_number_qualifier,
8
+ 'D2' => :prescription_reference_number,
9
+ '9F' => :preferred_product_count,
10
+ 'AP' => :preferred_product_id_qualifier,
11
+ 'AR' => :preferred_product_id,
12
+ 'AS' => :preferred_product_incentive,
13
+ 'AT' => :preferred_product_cost_share_incentive,
14
+ 'AU' => :preferred_product_description,
15
+ 'N4' => :medicade_icn,
16
+ })
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,55 @@
1
+ module DZero::Segments
2
+ class ResponsePricing < Base
3
+ Base.register_segment(self, identifier: '23')
4
+
5
+ def self.field_id_to_symbol
6
+ super.merge({
7
+ 'F5' => :gross_amount_due, # :patient_pay_amount
8
+ 'F6' => :ingredient_cost_paid,
9
+ 'F7' => :dispensing_fee_paid,
10
+ 'AV' => :tax_exempt_indicator,
11
+ 'AW' => :flat_sales_tax_amount_paid,
12
+ 'AX' => :percentage_sales_tax_amount_paid,
13
+ 'AY' => :percentage_sales_tax_rate_paid,
14
+ 'AZ' => :percentage_sales_tax_basis_paid,
15
+ 'FL' => :incentive_amount_paid,
16
+ 'J1' => :professional_service_fee_paid,
17
+ 'J2' => :other_amount_paid_count,
18
+ 'J3' => :other_amount_paid_qualifier,
19
+ 'J4' => :other_amount_paid,
20
+ 'J5' => :other_payer_amount_recognized,
21
+ 'F9' => :total_amount_paid,
22
+ 'FM' => :basis_of_reimbursement_determination,
23
+ 'FN' => :amount_attributed_to_sales_tax,
24
+ 'FC' => :accumulated_deductible_amount,
25
+ 'FD' => :remaining_deductible_amount,
26
+ 'FE' => :remaining_benefit_amount,
27
+ 'FH' => :amount_applied_to_periodic_deductible,
28
+ 'FI' => :amount_of_copay,
29
+ 'FK' => :amount_exceeding_periodic_benefit_maximum,
30
+ 'HH' => :basis_of_calculation_dispensing_fee,
31
+ 'HJ' => :basis_of_calculation_copay,
32
+ 'HK' => :basis_of_calculation_flat_sales_tax,
33
+ 'HM' => :basis_of_calculation_percentage_sales_tax,
34
+ 'NZ' => :amount_attributed_to_processor_fee,
35
+ 'EQ' => :patient_sales_tax_amount,
36
+ '2Y' => :plan_sales_tax_amount,
37
+ '4U' => :amount_of_coinsurance,
38
+ '4V' => :basis_of_calculation_coinsurance,
39
+ 'MU' => :benefit_stage_count,
40
+ 'MV' => :benefit_stage_qualifier,
41
+ 'MW' => :benefit_stage_amount,
42
+ 'G3' => :estimated_generic_savings,
43
+ 'UC' => :spending_account_amount_remaining,
44
+ 'UD' => :health_plan_funded_assistance_amount,
45
+ 'UJ' => :amount_attributed_to_provider_network_selection,
46
+ 'UK' => :amount_attributed_to_product_selection_brand_drug,
47
+ 'UM' => :amount_attributed_to_product_selection_non_preferred_formulary_selection,
48
+ 'UN' => :amount_attributed_to_product_selection_brand_non_preferred_formulary_selection,
49
+ 'UP' => :amount_attributed_to_coverage_gap,
50
+ 'U8' => :ingredient_cost_contracted_reimbursable_amount,
51
+ 'U9' => :dispensing_fee_contracted_reimbursable_amount,
52
+ })
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,20 @@
1
+ module DZero::Segments
2
+ class ResponseDurPps < Base
3
+ Base.register_segment(self, identifier: '24')
4
+
5
+ def self.field_id_to_symbol
6
+ super.merge({
7
+ 'J6' => :dur_pps_response_code_counter,
8
+ 'E4' => :reason_for_service_code,
9
+ 'FS' => :clinical_significance_code,
10
+ 'FT' => :other_pharmacy_indicator,
11
+ 'FV' => :quantity_of_previous_fill,
12
+ 'FU' => :previous_date_of_fill,
13
+ 'FW' => :database_indicator,
14
+ 'FX' => :other_prescriber_indicator,
15
+ 'FY' => :dur_free_text_message,
16
+ 'NS' => :dur_additional_text,
17
+ })
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ module DZero::Segments
2
+ class ResponseInsurance < Base
3
+ Base.register_segment(self, identifier: '25')
4
+
5
+ def self.field_id_to_symbol
6
+ super.merge({
7
+ 'C1' => :group_id,
8
+ 'FO' => :plan_id,
9
+ '2F' => :network_reimbursement_id,
10
+ 'J7' => :payer_id_qualifier,
11
+ 'J8' => :payer_id,
12
+ 'N5' => :medicaid_id_number,
13
+ 'N6' => :medicaid_agency_number,
14
+ 'C2' => :cardholder_id,
15
+ })
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ module DZero::Segments
2
+ class ResponsePriorAuth < Base
3
+ Base.register_segment(self, identifier: '26')
4
+
5
+ def self.field_id_to_symbol
6
+ super.merge({
7
+ 'PR' => :prior_authorization_processed_date,
8
+ 'PS' => :prior_authorization_effective_date,
9
+ 'PT' => :prior_authorization_expiration_date,
10
+ 'RA' => :prior_authorization_quantity,
11
+ 'RB' => :prior_authorization_dollars_authorized,
12
+ 'PW' => :prior_authorization_number_of_refills_authorized,
13
+ 'PX' => :prior_authorization_quantity_accumulated,
14
+ 'PY' => :prior_authorization_number_assigned,
15
+ })
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ module DZero::Segments
2
+ class ResponseInsuranceAdditionalDocumentation < Base
3
+ Base.register_segment(self, identifier: '27')
4
+
5
+ def self.field_id_to_symbol
6
+ super.merge({
7
+ 'UR' => :medicare_part_d_coverage_code,
8
+ 'UQ' => :cms_low_income_cost_sharing_lics_level,
9
+ 'U1' => :contract_number,
10
+ 'FF' => :formulary_id,
11
+ 'U6' => :benefit_id,
12
+ 'US' => :next_medicare_part_d_effective_date,
13
+ 'UT' => :next_medicare_part_d_termination_date,
14
+ })
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,22 @@
1
+ module DZero::Segments
2
+ class ResponseCoordOfBenefits < Base
3
+ Base.register_segment(self, identifier: '28')
4
+
5
+ def self.field_id_to_symbol
6
+ super.merge({
7
+ 'NT' => :other_payer_id_count,
8
+ '5C' => :other_payer_coverage_type,
9
+ '6C' => :other_payer_id_qualifier,
10
+ '7C' => :other_payer_id,
11
+ 'MH' => :other_payer_processor_control_number,
12
+ 'NU' => :other_payer_cardholder_id,
13
+ 'MJ' => :other_payer_group_id,
14
+ 'UV' => :other_payer_person_code,
15
+ 'UB' => :other_payer_help_desk_phone_number,
16
+ 'UW' => :other_payer_patient_relationship_code,
17
+ 'UX' => :other_payer_benefit_effective_date,
18
+ 'UY' => :other_payer_benefit_termination_date,
19
+ })
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,13 @@
1
+ module DZero::Segments
2
+ class ResponsePatient < Base
3
+ Base.register_segment(self, identifier: '29')
4
+
5
+ def self.field_id_to_symbol
6
+ super.merge({
7
+ 'CA' => :patient_first_name,
8
+ 'CB' => :patient_last_name,
9
+ 'C4' => :date_of_birth,
10
+ })
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,128 @@
1
+ require_relative './concerns/parser.rb'
2
+ require_relative './concerns/serializer.rb'
3
+
4
+ module DZero::Segments
5
+ class Base
6
+ include Concerns::Parser
7
+ include Concerns::Serializer
8
+
9
+ class << self
10
+ attr_accessor :segment_id_to_symbol
11
+ attr_accessor :segment_id_to_klass
12
+ attr_accessor :segment_identifier
13
+ attr_accessor :symbol
14
+
15
+ def register_segment(klass, identifier:)
16
+ klass.segment_identifier = identifier
17
+
18
+ self.segment_id_to_klass[identifier] = klass
19
+ self.segment_id_to_symbol[identifier] = klass.symbol
20
+ end
21
+
22
+ def field_id_to_symbol
23
+ { 'AM' => :segment_identification }
24
+ end
25
+
26
+ def get_field_by_symbol(sym)
27
+ field_id_to_symbol.invert[sym]
28
+ end
29
+
30
+ def get_symbol_by_field(sym)
31
+ field_id_to_symbol[sym]
32
+ end
33
+
34
+ def get_klass_by_symbol(sym)
35
+ identifier = segment_id_to_symbol.invert[sym]
36
+ get_klass_by_identifier(identifier)
37
+ end
38
+
39
+ def get_klass_by_identifier(identifier)
40
+ segment_id_to_klass[identifier] || self
41
+ end
42
+
43
+ def build(initial_hash = {})
44
+ given_identifier = initial_hash[get_field_by_symbol(:segment_identification)]
45
+ segment_klass = segment_id_to_klass[given_identifier]
46
+ if segment_klass
47
+ segment_klass.new(initial_hash)
48
+ else
49
+ self.new(initial_hash)
50
+ end
51
+ end
52
+ end
53
+
54
+ self.segment_id_to_symbol = {}
55
+ self.segment_id_to_klass = {}
56
+ self.segment_identifier = nil
57
+
58
+ def self.inherited(klass)
59
+ super
60
+ klass.symbol = klass.name.demodulize.underscore.to_sym
61
+ klass.segment_id_to_symbol = segment_id_to_symbol
62
+ klass.segment_id_to_klass = segment_id_to_klass
63
+ end
64
+
65
+ def initialize(initial_hash = {})
66
+ @hash = {}
67
+
68
+ unless self.class.segment_identifier.nil?
69
+ self[:segment_identification] = self.class.segment_identifier
70
+ end
71
+
72
+ self.merge(initial_hash)
73
+ end
74
+
75
+ attr_reader :hash
76
+
77
+ def [](key)
78
+ if key.is_a?(Symbol)
79
+ key = self.class.get_field_by_symbol(key)
80
+ end
81
+
82
+ @hash[key]
83
+ end
84
+
85
+ def []=(key, value)
86
+ if key.is_a?(Symbol)
87
+ key = self.class.get_field_by_symbol(key)
88
+ end
89
+
90
+ @hash[key] = value
91
+ end
92
+
93
+ def merge(hash = {})
94
+ hash.each do |key, value|
95
+ self[key] = value
96
+ end
97
+
98
+ self
99
+ end
100
+ end
101
+ end
102
+
103
+ require_relative './01_patient.rb'
104
+ require_relative './02_pharmacy_provider.rb'
105
+ require_relative './03_prescriber.rb'
106
+ require_relative './04_insurance.rb'
107
+ require_relative './05_coord_of_benefits.rb'
108
+ require_relative './06_workers_comp.rb'
109
+ require_relative './07_claim.rb'
110
+ require_relative './08_dur_pps.rb'
111
+ require_relative './09_coupon.rb'
112
+ require_relative './10_compound.rb'
113
+ require_relative './11_pricing.rb'
114
+ require_relative './12_prior_auth.rb'
115
+ require_relative './13_clinical.rb'
116
+ require_relative './14_additional_documentation.rb'
117
+ require_relative './15_facility.rb'
118
+ require_relative './16_narrative.rb'
119
+ require_relative './20_response_message.rb'
120
+ require_relative './21_response_status.rb'
121
+ require_relative './22_response_claim.rb'
122
+ require_relative './23_response_pricing.rb'
123
+ require_relative './24_response_dur_pps.rb'
124
+ require_relative './25_response_insurance.rb'
125
+ require_relative './26_response_prior_auth.rb'
126
+ require_relative './27_response_insurance_additional_documentation.rb'
127
+ require_relative './28_response_coord_of_benefits.rb'
128
+ require_relative './29_response_patient.rb'
@@ -0,0 +1,18 @@
1
+ module DZero::Segments::Concerns
2
+ module Parser
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ # parses from a string
9
+ # @param [String] source
10
+ def parse(source)
11
+ elements = source.split(/[\x1C\x1E\x3\x1D]/).delete_if(&:empty?)
12
+ segment_hash = Hash[elements.map {|e| [e[0..1], e[2..-1]]}]
13
+
14
+ self.build(segment_hash)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,20 @@
1
+ module DZero::Segments::Concerns
2
+ module Serializer
3
+ # Serializes instance to string
4
+ # @return [String]
5
+ def to_s
6
+ string = hash.to_a.map(&:join).join("\x1c")
7
+ string = "\x1C" + string + "\x1E"
8
+ end
9
+
10
+ # Returns a hash
11
+ # @return [Hash]
12
+ def to_json(options = {})
13
+ hash.inject({}) do |memo, (key, value)|
14
+ readable_key = self.class.get_symbol_by_field(key) if options[:readable] == true
15
+ memo[readable_key || key] = value
16
+ memo
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ module DZero
2
+ module TestSupport
3
+ FACTORY_PATH = File.expand_path("../../spec/factories", __dir__)
4
+ end
5
+ end
@@ -0,0 +1,47 @@
1
+ require_relative './concerns/parser.rb'
2
+ require_relative './concerns/serializer.rb'
3
+ require_relative './concerns/segments_methods.rb'
4
+
5
+ module DZero::Transmissions
6
+ class Base
7
+ include Concerns::SegmentsMethods
8
+ include Concerns::Serializer
9
+
10
+ class << self
11
+ include Concerns::Parser
12
+
13
+ def header_schema
14
+ raise NotImplementedError
15
+ end
16
+ end
17
+
18
+ def initialize(
19
+ header: {},
20
+ transmission_group: Groups::TransmissionGroup.new,
21
+ transaction_groups: [],
22
+ segments: []
23
+ )
24
+ @header = header
25
+ @transmission_group = transmission_group
26
+ @transaction_groups = transaction_groups
27
+
28
+ unless segments.empty?
29
+ sort_segments(segments)
30
+ end
31
+ end
32
+
33
+ attr_reader :header, :transmission_group, :transaction_groups
34
+
35
+ def to_s
36
+ string = ::DZero::Utils::FixedWidth.to_fixed_width(header.slice(*self.class.header_schema.keys), self.class.header_schema)
37
+ string += ::DZero::Constants::SEGMENT_SEPARATOR
38
+ string += transmission_group.to_s
39
+ string += transaction_groups.map(&:to_s).join
40
+ string
41
+ end
42
+ end
43
+ end
44
+
45
+ require_relative './groups/base.rb'
46
+ require_relative './request.rb'
47
+ require_relative './response.rb'
@@ -0,0 +1,23 @@
1
+ module DZero::Transmissions::Concerns
2
+ module Parser
3
+ def parse(string)
4
+ string = string.dup
5
+ header_length = header_schema.values.reduce(0, :+)
6
+ header = ::DZero::Utils::FixedWidth.parse_fixed_width(header_schema, string.slice!(0..header_length))
7
+
8
+ raw_transaction_groups = string.split(::DZero::Constants::GROUP_SEPARATOR)
9
+ raw_transmission_group = raw_transaction_groups.shift
10
+
11
+ transmission_group = ::DZero::Transmissions::Groups::TransmissionGroup.parse(raw_transmission_group)
12
+ transaction_groups = raw_transaction_groups.map do |raw_transaction_group|
13
+ ::DZero::Transmissions::Groups::TransactionGroup.parse(raw_transaction_group)
14
+ end
15
+
16
+ new(
17
+ header: header,
18
+ transmission_group: transmission_group,
19
+ transaction_groups: transaction_groups
20
+ )
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,76 @@
1
+ module DZero::Transmissions::Concerns
2
+ module SegmentsMethods
3
+ TRANSMISSION_LEVEL_SEGMENTS = [
4
+ :patient,
5
+ :insurance,
6
+ :response_message,
7
+ :response_insurance,
8
+ :response_patient,
9
+ ]
10
+
11
+ TRANSACTION_LEVEL_SEGMENTS = [
12
+ :pharmacy_provider,
13
+ :prescriber,
14
+ :coord_of_benefits,
15
+ :workers_comp,
16
+ :claim,
17
+ :dur_pps,
18
+ :coupon,
19
+ :compound,
20
+ :pricing,
21
+ :prior_auth,
22
+ :clinical,
23
+ :additional_documentation,
24
+ :facility,
25
+ :narrative,
26
+ :response_status,
27
+ :response_claim,
28
+ :response_pricing,
29
+ :response_dur_pps,
30
+ :response_prior_auth,
31
+ :response_additional_documentation,
32
+ :response_coord_of_benefits
33
+ ]
34
+
35
+ def self.included(base)
36
+ ::DZero::Segments::Base.segment_id_to_symbol.each do |segment_identifier, segment_name_sym|
37
+ segment_klass = ::DZero::Segments::Base.get_klass_by_identifier(segment_identifier)
38
+ base.send(:define_method, "#{segment_name_sym}_segment") do
39
+ get_segment(segment_klass)
40
+ end
41
+ end
42
+ end
43
+
44
+ def get_segment(segment_klass)
45
+ self.transmission_group.segments.detect { |s| s.is_a?(segment_klass) } ||
46
+ self.transaction_groups.first.segments.detect { |s| s.is_a?(segment_klass) } ||
47
+ begin
48
+ segment = segment_klass.new({})
49
+ self.segments << segment
50
+ segment
51
+ end
52
+ end
53
+
54
+ def sort_segments(segments)
55
+ segments.each do |segment|
56
+ segment_sym = segment.class.symbol
57
+ if TRANSMISSION_LEVEL_SEGMENTS.include?(segment_sym)
58
+ transmission_group.segments << segment
59
+ else
60
+ if transaction_groups.empty?
61
+ transaction_groups << ::DZero::Transmissions::Groups::TransactionGroup.new({ segments: [] })
62
+ end
63
+
64
+ transaction_groups.first.segments << segment
65
+ end
66
+ end
67
+ end
68
+
69
+ def segments
70
+ all = []
71
+ all += transmission_group.segments
72
+ all += transaction_groups.map(&:segments).flatten
73
+ all.compact
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,11 @@
1
+ module DZero::Transmissions::Concerns
2
+ module Serializer
3
+ def to_json(options = {})
4
+ {
5
+ header: header,
6
+ transmission_group: transmission_group.to_json(options),
7
+ transaction_groups: transaction_groups.map { |group| group.to_json(options) }
8
+ }
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,59 @@
1
+ module DZero::Transmissions::Groups
2
+ class Base
3
+ class << self
4
+ def parse(string)
5
+ segments = string.split(::DZero::Constants::SEGMENT_SEPARATOR).map do |raw_segment|
6
+ next if raw_segment.strip == ""
7
+ ::DZero::Segments::Base.parse(raw_segment)
8
+ end
9
+
10
+ new(
11
+ segments: segments
12
+ )
13
+ end
14
+ end
15
+
16
+ def initialize(segments: [])
17
+ @segments = segments
18
+ end
19
+
20
+ attr_reader :segments
21
+
22
+ def to_s
23
+ string = ::DZero::Constants::GROUP_SEPARATOR
24
+ string += ::DZero::Constants::SEGMENT_SEPARATOR
25
+ string += @segments.map(&:to_s).join
26
+ # remove the trailing segment separator, if any
27
+ string.chomp!(::DZero::Constants::SEGMENT_SEPARATOR)
28
+ string
29
+ end
30
+
31
+ def to_json(options = {})
32
+ if options[:key_group_by_segment_sym] == true
33
+ segments.compact.inject({}) { |memo, segment| memo.merge(segment.class.symbol => segment.to_json(options)) }
34
+ else
35
+ {
36
+ segments: segments.map { |segment| segment.to_json(options) }
37
+ }
38
+ end
39
+ end
40
+
41
+ def get_segment(segment_klass)
42
+ self.segments.detect { |s| s.is_a?(segment_klass) } || begin
43
+ segment = segment_klass.new({})
44
+ self.segments << segment
45
+ segment
46
+ end
47
+ end
48
+
49
+ ::DZero::Segments::Base.segment_id_to_symbol.each do |segment_identifier, segment_name_sym|
50
+ segment_klass = ::DZero::Segments::Base.get_klass_by_identifier(segment_identifier)
51
+ self.send(:define_method, "#{segment_name_sym}_segment") do
52
+ get_segment(segment_klass)
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ require_relative './transaction_group.rb'
59
+ require_relative './transmission_group.rb'
@@ -0,0 +1,3 @@
1
+ module DZero::Transmissions::Groups
2
+ class TransactionGroup < Base; end
3
+ end
@@ -0,0 +1,11 @@
1
+ module DZero::Transmissions::Groups
2
+ class TransmissionGroup < Base
3
+ # transmission level segments are not preceeded by a group separator
4
+ def to_s
5
+ string = @segments.map(&:to_s).join
6
+ # remove the trailing segment separator, if any
7
+ string.chomp!(::DZero::Constants::SEGMENT_SEPARATOR)
8
+ string
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ module DZero::Transmissions
2
+ class Request < Base
3
+ class << self
4
+ def header_schema
5
+ {
6
+ bin_number: 6,
7
+ version: 2,
8
+ transaction_code: 2,
9
+ processor_control_number: 10,
10
+ transaction_count: 1,
11
+ service_provider_id_qualifier: 2,
12
+ service_provider_id: 15,
13
+ date_of_service: 8,
14
+ software: 10
15
+ }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ module DZero::Transmissions
2
+ class Response < Base
3
+ class << self
4
+ def header_schema
5
+ {
6
+ version: 2,
7
+ transaction_code: 2,
8
+ transaction_count: 1,
9
+ header_response_status: 1,
10
+ service_provider_id_qualifier: 2,
11
+ service_provider_id: 15,
12
+ date_of_service: 8,
13
+ }
14
+ end
15
+ end
16
+ end
17
+ end