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.
- checksums.yaml +7 -0
- data/README.md +265 -0
- data/lib/dzero/segments/01_patient.rb +27 -0
- data/lib/dzero/segments/02_pharmacy_provider.rb +12 -0
- data/lib/dzero/segments/03_prescriber.rb +22 -0
- data/lib/dzero/segments/04_insurance.rb +29 -0
- data/lib/dzero/segments/05_coord_of_benefits.rb +27 -0
- data/lib/dzero/segments/06_workers_comp.rb +30 -0
- data/lib/dzero/segments/07_claim.rb +52 -0
- data/lib/dzero/segments/08_dur_pps.rb +17 -0
- data/lib/dzero/segments/09_coupon.rb +13 -0
- data/lib/dzero/segments/10_compound.rb +20 -0
- data/lib/dzero/segments/11_pricing.rb +26 -0
- data/lib/dzero/segments/12_prior_auth.rb +23 -0
- data/lib/dzero/segments/13_clinical.rb +19 -0
- data/lib/dzero/segments/14_additional_documentation.rb +25 -0
- data/lib/dzero/segments/15_facility.rb +16 -0
- data/lib/dzero/segments/16_narrative.rb +11 -0
- data/lib/dzero/segments/20_response_message.rb +11 -0
- data/lib/dzero/segments/21_response_status.rb +26 -0
- data/lib/dzero/segments/22_response_claim.rb +19 -0
- data/lib/dzero/segments/23_response_pricing.rb +55 -0
- data/lib/dzero/segments/24_response_dur_pps.rb +20 -0
- data/lib/dzero/segments/25_response_insurance.rb +18 -0
- data/lib/dzero/segments/26_response_prior_auth.rb +18 -0
- data/lib/dzero/segments/27_response_insurance_additional_documentation.rb +17 -0
- data/lib/dzero/segments/28_response_coord_of_benefits.rb +22 -0
- data/lib/dzero/segments/29_response_patient.rb +13 -0
- data/lib/dzero/segments/base.rb +128 -0
- data/lib/dzero/segments/concerns/parser.rb +18 -0
- data/lib/dzero/segments/concerns/serializer.rb +20 -0
- data/lib/dzero/test_support.rb +5 -0
- data/lib/dzero/transmissions/base.rb +47 -0
- data/lib/dzero/transmissions/concerns/parser.rb +23 -0
- data/lib/dzero/transmissions/concerns/segments_methods.rb +76 -0
- data/lib/dzero/transmissions/concerns/serializer.rb +11 -0
- data/lib/dzero/transmissions/groups/base.rb +59 -0
- data/lib/dzero/transmissions/groups/transaction_group.rb +3 -0
- data/lib/dzero/transmissions/groups/transmission_group.rb +11 -0
- data/lib/dzero/transmissions/request.rb +19 -0
- data/lib/dzero/transmissions/response.rb +17 -0
- data/lib/dzero/utils/fixed_width.rb +19 -0
- data/lib/dzero/utils/rejection_codes.rb +297 -0
- data/lib/dzero/utils/validator.rb +61 -0
- data/lib/dzero/version.rb +3 -0
- data/lib/dzero.rb +28 -0
- 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,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,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
|