change_health 2.2.0 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +76 -21
- data/README.md +143 -53
- data/lib/change_health/connection.rb +4 -3
- data/lib/change_health/models/claim/submission/address.rb +13 -0
- data/lib/change_health/models/claim/submission/drug_identification.rb +12 -0
- data/lib/change_health/models/claim/submission/service_line.rb +2 -2
- data/lib/change_health/models/claim/submission/subscriber.rb +1 -0
- data/lib/change_health/models/model.rb +44 -16
- data/lib/change_health/request/report.rb +33 -12
- data/lib/change_health/request/submission.rb +23 -2
- data/lib/change_health/response/claim/report/report_277_claim.rb +40 -0
- data/lib/change_health/response/claim/report/report_277_data.rb +84 -0
- data/lib/change_health/response/claim/report/report_277_info_claim_status.rb +16 -0
- data/lib/change_health/response/claim/report/report_835_claim.rb +17 -0
- data/lib/change_health/response/claim/report/report_835_data.rb +116 -0
- data/lib/change_health/response/claim/report/report_835_service_adjustment.rb +15 -0
- data/lib/change_health/response/claim/report/report_835_service_line.rb +13 -0
- data/lib/change_health/response/claim/report/report_claim.rb +16 -0
- data/lib/change_health/{models → response}/error.rb +8 -7
- data/lib/change_health/response/response_data.rb +3 -3
- data/lib/change_health/version.rb +1 -1
- data/lib/change_health.rb +14 -4
- metadata +13 -3
@@ -1,7 +1,7 @@
|
|
1
1
|
module ChangeHealth
|
2
2
|
module Models
|
3
3
|
DATE_FORMAT = '%Y%m%d'
|
4
|
-
DATE_FORMATTER =
|
4
|
+
DATE_FORMATTER = lambda { |d|
|
5
5
|
begin
|
6
6
|
d = Date.parse(d) if d.is_a?(String)
|
7
7
|
rescue ArgumentError
|
@@ -12,37 +12,65 @@ module ChangeHealth
|
|
12
12
|
d
|
13
13
|
}
|
14
14
|
|
15
|
-
PARSE_DATE =
|
15
|
+
PARSE_DATE = lambda { |d|
|
16
16
|
begin
|
17
17
|
d = Date.strptime(d, ChangeHealth::Models::DATE_FORMAT)
|
18
|
-
rescue
|
18
|
+
rescue StandardError
|
19
19
|
end
|
20
20
|
|
21
21
|
d
|
22
22
|
}
|
23
23
|
|
24
|
-
|
24
|
+
POSTAL_CODE_FORMATTER = lambda { |postal_code|
|
25
|
+
begin
|
26
|
+
formatted_postal_code = postal_code&.to_s&.tr('-', '')
|
27
|
+
rescue StandardError
|
28
|
+
end
|
29
|
+
formatted_postal_code || postal_code
|
30
|
+
}
|
31
|
+
|
32
|
+
CONTROL_NUMBER = -> { '%09d' % rand(1_000_000_000) }
|
25
33
|
|
26
34
|
class Model < Hashie::Trash
|
27
35
|
def to_h
|
28
|
-
|
36
|
+
self.class.hashify(self)
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.hashify(model)
|
40
|
+
model.map do |key, value|
|
41
|
+
formatted_value = case value
|
42
|
+
when Hash
|
43
|
+
hashify(model[key])
|
44
|
+
when Array
|
45
|
+
value.map do |element|
|
46
|
+
if element.is_a?(Hash)
|
47
|
+
hashify(element)
|
48
|
+
else # if it's an array of arrays, can't handle it
|
49
|
+
format_value(key, element)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
else
|
53
|
+
format_value(key, value)
|
54
|
+
end
|
55
|
+
[key, formatted_value]
|
56
|
+
end.to_h
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.format_value(key, value)
|
60
|
+
return nil if value == ''
|
29
61
|
|
30
|
-
|
31
|
-
|
32
|
-
result[key] = ChangeHealth::Models::DATE_FORMATTER.call(result[key])
|
33
|
-
end
|
34
|
-
result[key] = nil if value == ""
|
35
|
-
end
|
62
|
+
return ChangeHealth::Models::DATE_FORMATTER.call(value) if key.to_s.downcase.include?('date')
|
63
|
+
return ChangeHealth::Models::POSTAL_CODE_FORMATTER.call(value) if key.to_s.downcase.include?('postalcode')
|
36
64
|
|
37
|
-
|
65
|
+
value
|
38
66
|
end
|
39
67
|
|
40
|
-
def as_json(
|
41
|
-
|
68
|
+
def as_json(_args = {})
|
69
|
+
to_h
|
42
70
|
end
|
43
71
|
|
44
|
-
def to_json
|
45
|
-
|
72
|
+
def to_json(*_args)
|
73
|
+
to_h.to_json
|
46
74
|
end
|
47
75
|
end
|
48
76
|
end
|
@@ -5,25 +5,35 @@ module ChangeHealth
|
|
5
5
|
ENDPOINT = '/medicalnetwork/reports/v2'.freeze
|
6
6
|
HEALTH_CHECK_ENDPOINT = ENDPOINT + '/healthcheck'.freeze
|
7
7
|
|
8
|
-
def self.report_list
|
9
|
-
ChangeHealth::
|
8
|
+
def self.report_list(headers: nil)
|
9
|
+
final_headers = ChangeHealth::Request::Claim::Report.report_headers(headers)
|
10
|
+
ChangeHealth::Response::Claim::ReportListData.new(response: ChangeHealth::Connection.new.request(endpoint: ENDPOINT, verb: :get, headers: final_headers))
|
10
11
|
end
|
11
12
|
|
12
|
-
def self.get_report(report_name, as_json_report: true)
|
13
|
+
def self.get_report(report_name, as_json_report: true, headers: nil)
|
13
14
|
return if report_name.nil? || report_name.empty?
|
15
|
+
final_headers = ChangeHealth::Request::Claim::Report.report_headers(headers)
|
16
|
+
|
17
|
+
report_type = ChangeHealth::Response::Claim::ReportData.report_type(report_name)
|
18
|
+
return if report_type.nil?
|
14
19
|
|
15
20
|
individual_report_endpoint = ENDPOINT + '/' + report_name
|
16
|
-
if as_json_report
|
17
|
-
# https://developers.changehealthcare.com/eligibilityandclaims/docs/what-file-types-does-this-api-get-from-the-mailbox
|
18
|
-
report_type = ChangeHealth::Response::Claim::ReportData.report_type(report_name)
|
19
|
-
return if report_type.nil?
|
20
21
|
|
21
|
-
|
22
|
-
|
22
|
+
# https://developers.changehealthcare.com/eligibilityandclaims/docs/what-file-types-does-this-api-get-from-the-mailbox
|
23
|
+
individual_report_endpoint += '/' + report_type if as_json_report
|
23
24
|
|
24
|
-
ChangeHealth::
|
25
|
-
|
26
|
-
|
25
|
+
response = ChangeHealth::Connection.new.request(endpoint: individual_report_endpoint, verb: :get, headers: final_headers)
|
26
|
+
if ChangeHealth::Response::Claim::ReportData.is_277?(report_name)
|
27
|
+
ChangeHealth::Response::Claim::Report277Data
|
28
|
+
.new(report_name,
|
29
|
+
as_json_report,
|
30
|
+
response: response)
|
31
|
+
else
|
32
|
+
ChangeHealth::Response::Claim::Report835Data
|
33
|
+
.new(report_name,
|
34
|
+
as_json_report,
|
35
|
+
response: response)
|
36
|
+
end
|
27
37
|
end
|
28
38
|
|
29
39
|
def self.health_check
|
@@ -33,6 +43,17 @@ module ChangeHealth
|
|
33
43
|
def self.ping
|
34
44
|
self.health_check
|
35
45
|
end
|
46
|
+
|
47
|
+
def self.report_headers(headers)
|
48
|
+
if headers
|
49
|
+
extra_headers = {}
|
50
|
+
extra_headers["X-CHC-Reports-Username"] = headers[:username]
|
51
|
+
extra_headers["X-CHC-Reports-Password"] = headers[:password]
|
52
|
+
extra_headers
|
53
|
+
else
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
end
|
36
57
|
end
|
37
58
|
end
|
38
59
|
end
|
@@ -5,6 +5,7 @@ module ChangeHealth
|
|
5
5
|
ENDPOINT = '/medicalnetwork/professionalclaims/v3'.freeze
|
6
6
|
HEALTH_CHECK_ENDPOINT = ENDPOINT + '/healthcheck'.freeze
|
7
7
|
SUBMISSION_ENDPOINT = ENDPOINT + '/submission'.freeze
|
8
|
+
VALIDATION_ENDPOINT = ENDPOINT + '/validation'.freeze
|
8
9
|
|
9
10
|
property :claimInformation, from: :claim_information, required: false
|
10
11
|
property :controlNumber, from: :control_number, required: true, default: ChangeHealth::Models::CONTROL_NUMBER
|
@@ -12,6 +13,7 @@ module ChangeHealth
|
|
12
13
|
property :receiver, required: false
|
13
14
|
property :submitter, required: false
|
14
15
|
property :subscriber, required: false
|
16
|
+
property :headers, required: false
|
15
17
|
# Need one or the other, trading partner id or trading partner service id
|
16
18
|
property :tradingPartnerId, from: :trading_partner_id, required: false
|
17
19
|
property :tradingPartnerServiceId, from: :trading_partner_service_id, required: false
|
@@ -22,7 +24,15 @@ module ChangeHealth
|
|
22
24
|
end
|
23
25
|
|
24
26
|
def submission
|
25
|
-
ChangeHealth::Response::Claim::SubmissionData.new(response: ChangeHealth::Connection.new.request(
|
27
|
+
ChangeHealth::Response::Claim::SubmissionData.new(response: ChangeHealth::Connection.new.request(
|
28
|
+
endpoint: SUBMISSION_ENDPOINT, body: to_h, headers: professional_headers
|
29
|
+
))
|
30
|
+
end
|
31
|
+
|
32
|
+
def validation
|
33
|
+
ChangeHealth::Response::Claim::SubmissionData.new(response: ChangeHealth::Connection.new.request(
|
34
|
+
endpoint: VALIDATION_ENDPOINT, body: to_h, headers: professional_headers
|
35
|
+
))
|
26
36
|
end
|
27
37
|
|
28
38
|
def self.health_check
|
@@ -30,7 +40,18 @@ module ChangeHealth
|
|
30
40
|
end
|
31
41
|
|
32
42
|
def self.ping
|
33
|
-
|
43
|
+
health_check
|
44
|
+
end
|
45
|
+
|
46
|
+
def professional_headers
|
47
|
+
if self[:headers]
|
48
|
+
extra_headers = {}
|
49
|
+
extra_headers['X-CHC-ClaimSubmission-SubmitterId'] = self[:headers][:submitter_id]
|
50
|
+
extra_headers['X-CHC-ClaimSubmission-BillerId'] = self[:headers][:biller_id]
|
51
|
+
extra_headers['X-CHC-ClaimSubmission-Username'] = self[:headers][:username]
|
52
|
+
extra_headers['X-CHC-ClaimSubmission-Pwd'] = self[:headers][:password]
|
53
|
+
extra_headers
|
54
|
+
end
|
34
55
|
end
|
35
56
|
end
|
36
57
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module ChangeHealth
|
2
|
+
module Response
|
3
|
+
module Claim
|
4
|
+
class Report277Claim < ReportClaim
|
5
|
+
property :info_claim_statuses, required: false
|
6
|
+
property :procedure_codes, required: false
|
7
|
+
|
8
|
+
def add_info_claim_status(info_claim_status)
|
9
|
+
self[:info_claim_statuses] ||= []
|
10
|
+
self[:info_claim_statuses] << info_claim_status
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_procedure_code(procedure_code)
|
14
|
+
self[:procedure_codes] ||= []
|
15
|
+
self[:procedure_codes] << procedure_code
|
16
|
+
end
|
17
|
+
|
18
|
+
def latest_status_category_codes
|
19
|
+
latest_info_claim_status&.status_category_codes
|
20
|
+
end
|
21
|
+
|
22
|
+
def total_charge_amount
|
23
|
+
latest_info_claim_status&.total_charge_amount
|
24
|
+
end
|
25
|
+
|
26
|
+
def latest_status_info_effective_date
|
27
|
+
latest_info_claim_status&.status_information_effective_date
|
28
|
+
end
|
29
|
+
|
30
|
+
def latest_info_claim_status
|
31
|
+
info_claim_statuses&.select do |info|
|
32
|
+
!info.status_information_effective_date.nil? &&
|
33
|
+
info.status_information_effective_date.is_a?(Date) &&
|
34
|
+
info.status_information_effective_date <= Date.today
|
35
|
+
end&.max_by(&:status_information_effective_date)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module ChangeHealth
|
2
|
+
module Response
|
3
|
+
module Claim
|
4
|
+
# Methods only return meaningful data for json reports
|
5
|
+
class Report277Data < ChangeHealth::Response::Claim::ReportData
|
6
|
+
def transactions
|
7
|
+
@raw['transactions']
|
8
|
+
end
|
9
|
+
|
10
|
+
# Only one payer per report
|
11
|
+
def payer_name
|
12
|
+
transactions&.first&.dig('payers')&.first&.dig('organizationName')
|
13
|
+
end
|
14
|
+
|
15
|
+
def report_creation_date
|
16
|
+
ChangeHealth::Models::PARSE_DATE.call(transactions&.first&.dig('transactionSetCreationDate'))
|
17
|
+
end
|
18
|
+
|
19
|
+
def claims
|
20
|
+
report_claims = []
|
21
|
+
|
22
|
+
transactions&.each do |transaction|
|
23
|
+
report_creation_date = ChangeHealth::Models::PARSE_DATE.call(transaction['transactionSetCreationDate'])
|
24
|
+
transaction['payers']&.each do |payer|
|
25
|
+
payer_identification = payer['payerIdentification']
|
26
|
+
payer_name = payer['organizationName']
|
27
|
+
payer['claimStatusTransactions']&.each do |claim_status_txn|
|
28
|
+
claim_status_txn['claimStatusDetails']&.each do |claim_status_detail|
|
29
|
+
service_provider_npi = claim_status_detail.dig('serviceProvider', 'npi')
|
30
|
+
claim_status_detail['patientClaimStatusDetails']&.each do |patient_claim_status_detail|
|
31
|
+
patient_first_name = patient_claim_status_detail.dig('subscriber', 'firstName')
|
32
|
+
patient_last_name = patient_claim_status_detail.dig('subscriber', 'lastName')
|
33
|
+
patient_claim_status_detail['claims']&.each do |claim|
|
34
|
+
procedure_codes = []
|
35
|
+
claim['serviceLines']&.each do |service_line|
|
36
|
+
procedure_codes << service_line.dig('service', 'procedureCode')
|
37
|
+
end
|
38
|
+
claim_status = claim['claimStatus']
|
39
|
+
next if claim_status.nil?
|
40
|
+
|
41
|
+
service_date_begin = ChangeHealth::Models::PARSE_DATE.call(claim_status['claimServiceBeginDate'] || claim_status['claimServiceDate'])
|
42
|
+
service_date_end = ChangeHealth::Models::PARSE_DATE.call(claim_status['claimServiceEndDate'] || claim_status['claimServiceDate'])
|
43
|
+
|
44
|
+
info_claim_statuses = []
|
45
|
+
claim_status['informationClaimStatuses']&.each do |info_claim_status|
|
46
|
+
status_information_effective_date = ChangeHealth::Models::PARSE_DATE.call(info_claim_status['statusInformationEffectiveDate'])
|
47
|
+
total_charge_amount = info_claim_status['totalClaimChargeAmount']
|
48
|
+
|
49
|
+
status_category_codes = []
|
50
|
+
info_claim_status['informationStatuses']&.each do |info_status|
|
51
|
+
status_category_codes << info_status['healthCareClaimStatusCategoryCode']
|
52
|
+
end
|
53
|
+
|
54
|
+
info_claim_statuses << Report277InfoClaimStatus.new(
|
55
|
+
status_category_codes: status_category_codes,
|
56
|
+
total_charge_amount: total_charge_amount,
|
57
|
+
status_information_effective_date: status_information_effective_date
|
58
|
+
)
|
59
|
+
end
|
60
|
+
report_claims << Report277Claim.new(
|
61
|
+
info_claim_statuses: info_claim_statuses,
|
62
|
+
patient_first_name: patient_first_name,
|
63
|
+
patient_last_name: patient_last_name,
|
64
|
+
payer_identification: payer_identification,
|
65
|
+
payer_name: payer_name,
|
66
|
+
procedure_codes: procedure_codes,
|
67
|
+
report_creation_date: report_creation_date,
|
68
|
+
service_date_begin: service_date_begin,
|
69
|
+
service_date_end: service_date_end,
|
70
|
+
service_provider_npi: service_provider_npi
|
71
|
+
)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
report_claims
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module ChangeHealth
|
2
|
+
module Response
|
3
|
+
module Claim
|
4
|
+
class Report277InfoClaimStatus < Hashie::Trash
|
5
|
+
property :status_category_codes, required: false
|
6
|
+
property :total_charge_amount, required: false
|
7
|
+
property :status_information_effective_date, required: false
|
8
|
+
|
9
|
+
def add_status_category_code(status_category_code)
|
10
|
+
self[:status_category_codes] ||= []
|
11
|
+
self[:status_category_codes] << status_category_code
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ChangeHealth
|
2
|
+
module Response
|
3
|
+
module Claim
|
4
|
+
class Report835Claim < ReportClaim
|
5
|
+
property :payer_claim_control_number, required: false
|
6
|
+
property :payment_method_code, required: false
|
7
|
+
property :service_lines, required: false
|
8
|
+
property :total_actual_provider_payment_amount, required: false
|
9
|
+
property :total_charge_amount, required: false
|
10
|
+
|
11
|
+
def procedure_codes
|
12
|
+
service_lines&.map(&:adjudicated_procedure_code)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module ChangeHealth
|
2
|
+
module Response
|
3
|
+
module Claim
|
4
|
+
# Methods only return meaningful data for json reports
|
5
|
+
class Report835Data < ChangeHealth::Response::Claim::ReportData
|
6
|
+
def transactions
|
7
|
+
@raw['transactions']
|
8
|
+
end
|
9
|
+
|
10
|
+
# Only one payer per report
|
11
|
+
def payer_name
|
12
|
+
transactions&.first&.dig('payer')&.dig('name')
|
13
|
+
end
|
14
|
+
|
15
|
+
def payment_method_code
|
16
|
+
transactions&.first&.dig('financialInformation', 'paymentMethodCode')
|
17
|
+
end
|
18
|
+
|
19
|
+
def report_creation_date
|
20
|
+
ChangeHealth::Models::PARSE_DATE.call(transactions&.first&.dig('productionDate'))
|
21
|
+
end
|
22
|
+
|
23
|
+
def total_actual_provider_payment_amount
|
24
|
+
transactions&.first&.dig('financialInformation', 'totalActualProviderPaymentAmount')
|
25
|
+
end
|
26
|
+
|
27
|
+
def claims
|
28
|
+
report_claims = []
|
29
|
+
|
30
|
+
transactions&.each do |transaction|
|
31
|
+
payment_method_code = transaction.dig('financialInformation', 'paymentMethodCode')
|
32
|
+
payer_name = transaction.dig('payer', 'name')
|
33
|
+
payer_identification = transaction.dig('payer', 'payerIdentificationNumber')
|
34
|
+
report_creation_date = ChangeHealth::Models::PARSE_DATE.call(transaction['productionDate'])
|
35
|
+
total_actual_provider_payment_amount = transaction.dig('financialInformation',
|
36
|
+
'totalActualProviderPaymentAmount')
|
37
|
+
|
38
|
+
transaction['detailInfo']&.each do |detail_info|
|
39
|
+
detail_info['paymentInfo']&.each do |payment_info|
|
40
|
+
patient_first_name = payment_info.dig('patientName', 'firstName')
|
41
|
+
patient_last_name = payment_info.dig('patientName', 'lastName')
|
42
|
+
service_provider_npi = payment_info.dig('renderingProvider', 'npi')
|
43
|
+
total_charge_amount = payment_info.dig('claimPaymentInfo', 'totalClaimChargeAmount')
|
44
|
+
payer_claim_control_number = payment_info.dig('claimPaymentInfo', 'payerClaimControlNumber')
|
45
|
+
|
46
|
+
service_date_begin = nil
|
47
|
+
service_date_end = nil
|
48
|
+
service_lines = []
|
49
|
+
payment_info['serviceLines']&.each do |service_line|
|
50
|
+
service_line_date = ChangeHealth::Models::PARSE_DATE.call(service_line['serviceDate'])
|
51
|
+
if service_date_begin.nil? || service_line_date < service_date_begin
|
52
|
+
service_date_begin = service_line_date
|
53
|
+
end
|
54
|
+
if service_date_end.nil? || service_date_end < service_line_date
|
55
|
+
service_date_end = service_line_date
|
56
|
+
end
|
57
|
+
|
58
|
+
adjudicated_procedure_code = service_line.dig('servicePaymentInformation', 'adjudicatedProcedureCode')
|
59
|
+
allowed_actual = service_line.dig('serviceSupplementalAmounts', 'allowedActual')
|
60
|
+
line_item_charge_amount = service_line.dig('servicePaymentInformation', 'lineItemChargeAmount')
|
61
|
+
line_item_provider_payment_amount = service_line.dig('servicePaymentInformation',
|
62
|
+
'lineItemProviderPaymentAmount')
|
63
|
+
|
64
|
+
service_adjustments = []
|
65
|
+
service_line['serviceAdjustments']&.each do |service_adjustment|
|
66
|
+
adjustments = {}
|
67
|
+
# - 2 b/c group code & value, / 2 b/c come in pairs
|
68
|
+
num_adjustments = (service_adjustment.keys.size - 2) / 2
|
69
|
+
(1..num_adjustments).each do |index|
|
70
|
+
adjustment_reason = service_adjustment["adjustmentReasonCode#{index}"]
|
71
|
+
adjustment_amount = service_adjustment["adjustmentAmount#{index}"]
|
72
|
+
adjustments[adjustment_reason] = adjustment_amount
|
73
|
+
end
|
74
|
+
|
75
|
+
claim_adjustment_group_code = service_adjustment['claimAdjustmentGroupCode']
|
76
|
+
|
77
|
+
service_adjustments << Report835ServiceAdjustment.new(
|
78
|
+
adjustments: adjustments,
|
79
|
+
claim_adjustment_group_code: claim_adjustment_group_code
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
service_lines << Report835ServiceLine.new(
|
84
|
+
adjudicated_procedure_code: adjudicated_procedure_code,
|
85
|
+
allowed_actual: allowed_actual,
|
86
|
+
line_item_charge_amount: line_item_charge_amount,
|
87
|
+
line_item_provider_payment_amount: line_item_provider_payment_amount,
|
88
|
+
service_adjustments: service_adjustments
|
89
|
+
)
|
90
|
+
end
|
91
|
+
|
92
|
+
report_claims << Report835Claim.new(
|
93
|
+
patient_first_name: patient_first_name,
|
94
|
+
patient_last_name: patient_last_name,
|
95
|
+
payer_claim_control_number: payer_claim_control_number,
|
96
|
+
payer_identification: payer_identification,
|
97
|
+
payer_name: payer_name,
|
98
|
+
payment_method_code: payment_method_code,
|
99
|
+
report_creation_date: report_creation_date,
|
100
|
+
service_date_begin: service_date_begin,
|
101
|
+
service_date_end: service_date_end,
|
102
|
+
service_lines: service_lines,
|
103
|
+
service_provider_npi: service_provider_npi,
|
104
|
+
total_actual_provider_payment_amount: total_actual_provider_payment_amount,
|
105
|
+
total_charge_amount: total_charge_amount
|
106
|
+
)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
report_claims
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module ChangeHealth
|
2
|
+
module Response
|
3
|
+
module Claim
|
4
|
+
class Report835ServiceAdjustment < Hashie::Trash
|
5
|
+
property :adjustments, required: false
|
6
|
+
property :claim_adjustment_group_code, required: false
|
7
|
+
|
8
|
+
def add_adjustment(adjustment)
|
9
|
+
self[:adjustments] ||= []
|
10
|
+
self[:adjustments] << adjustment
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module ChangeHealth
|
2
|
+
module Response
|
3
|
+
module Claim
|
4
|
+
class Report835ServiceLine < Hashie::Trash
|
5
|
+
property :adjudicated_procedure_code, required: false
|
6
|
+
property :allowed_actual, required: false
|
7
|
+
property :line_item_charge_amount, required: false
|
8
|
+
property :line_item_provider_payment_amount, required: false
|
9
|
+
property :service_adjustments, required: false
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module ChangeHealth
|
2
|
+
module Response
|
3
|
+
module Claim
|
4
|
+
class ReportClaim < Hashie::Trash
|
5
|
+
property :patient_first_name, required: false
|
6
|
+
property :patient_last_name, required: false
|
7
|
+
property :payer_identification, required: false
|
8
|
+
property :payer_name, required: false
|
9
|
+
property :report_creation_date, required: false
|
10
|
+
property :service_date_begin, required: false
|
11
|
+
property :service_date_end, required: false
|
12
|
+
property :service_provider_npi, required: false
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,13 +1,12 @@
|
|
1
1
|
module ChangeHealth
|
2
|
-
|
3
|
-
module Models
|
2
|
+
module Response
|
4
3
|
class Error
|
5
4
|
attr_reader :data
|
6
5
|
|
7
6
|
SIMPLE_RETRY_CODES = %w[
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
42
|
8
|
+
80
|
9
|
+
].freeze
|
11
10
|
|
12
11
|
NO_RESUBMIT_MESSAGES = [
|
13
12
|
'resubmission not allowed',
|
@@ -40,7 +39,9 @@ module ChangeHealth
|
|
40
39
|
|
41
40
|
def retryable?
|
42
41
|
represents_down? ||
|
43
|
-
(code? && SIMPLE_RETRY_CODES.include?(code) && followupAction? && NO_RESUBMIT_MESSAGES.none?
|
42
|
+
(code? && SIMPLE_RETRY_CODES.include?(code) && followupAction? && NO_RESUBMIT_MESSAGES.none? do |msg|
|
43
|
+
followupAction.downcase.include?(msg)
|
44
|
+
end)
|
44
45
|
end
|
45
46
|
|
46
47
|
%w[field description code followupAction location].each do |method_name|
|
@@ -48,7 +49,7 @@ module ChangeHealth
|
|
48
49
|
false == send(method_name).nil?
|
49
50
|
end
|
50
51
|
|
51
|
-
define_method(
|
52
|
+
define_method(method_name.to_s) do
|
52
53
|
@data[method_name]
|
53
54
|
end
|
54
55
|
end
|
@@ -16,13 +16,13 @@ module ChangeHealth
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def errors?
|
19
|
-
|
19
|
+
errors.is_a?(Array) && false == errors.empty?
|
20
20
|
end
|
21
21
|
|
22
22
|
def errors
|
23
23
|
errors = @raw.dig('errors') || []
|
24
24
|
|
25
|
-
errors.flatten.map {|error| ChangeHealth::
|
25
|
+
errors.flatten.map { |error| ChangeHealth::Response::Error.new(error) }
|
26
26
|
end
|
27
27
|
|
28
28
|
def recommend_retry?
|
@@ -34,7 +34,7 @@ module ChangeHealth
|
|
34
34
|
|
35
35
|
return false if error_codes.empty?
|
36
36
|
|
37
|
-
|
37
|
+
error_codes.all?(&:retryable?)
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
data/lib/change_health.rb
CHANGED
@@ -5,9 +5,10 @@ require 'change_health/authentication'
|
|
5
5
|
require 'change_health/change_health_exception'
|
6
6
|
require 'change_health/connection'
|
7
7
|
require 'change_health/extensions'
|
8
|
-
require 'change_health/models/error'
|
9
8
|
require 'change_health/models/model'
|
9
|
+
require 'change_health/models/claim/submission/address'
|
10
10
|
require 'change_health/models/claim/submission/claim_information'
|
11
|
+
require 'change_health/models/claim/submission/drug_identification'
|
11
12
|
require 'change_health/models/claim/submission/provider'
|
12
13
|
require 'change_health/models/claim/submission/service_line'
|
13
14
|
require 'change_health/models/claim/submission/submitter'
|
@@ -20,10 +21,19 @@ require 'change_health/request/eligibility'
|
|
20
21
|
require 'change_health/request/submission'
|
21
22
|
require 'change_health/request/report'
|
22
23
|
require 'change_health/request/trading_partner'
|
24
|
+
require 'change_health/response/error'
|
23
25
|
require 'change_health/response/response_data'
|
24
26
|
require 'change_health/response/claim/submission/submission_data'
|
25
27
|
require 'change_health/response/claim/report/report_list_data'
|
26
28
|
require 'change_health/response/claim/report/report_data'
|
29
|
+
require 'change_health/response/claim/report/report_277_data'
|
30
|
+
require 'change_health/response/claim/report/report_835_data'
|
31
|
+
require 'change_health/response/claim/report/report_claim'
|
32
|
+
require 'change_health/response/claim/report/report_277_claim'
|
33
|
+
require 'change_health/response/claim/report/report_277_info_claim_status'
|
34
|
+
require 'change_health/response/claim/report/report_835_claim'
|
35
|
+
require 'change_health/response/claim/report/report_835_service_adjustment'
|
36
|
+
require 'change_health/response/claim/report/report_835_service_line'
|
27
37
|
require 'change_health/response/eligibility/eligibility_benefit'
|
28
38
|
require 'change_health/response/eligibility/eligibility_benefits'
|
29
39
|
require 'change_health/response/eligibility/eligibility_data'
|
@@ -45,11 +55,11 @@ module ChangeHealth
|
|
45
55
|
end
|
46
56
|
|
47
57
|
def api_endpoint
|
48
|
-
|
58
|
+
Connection.base_uri
|
49
59
|
end
|
50
60
|
|
51
61
|
def to_h
|
52
|
-
|
62
|
+
{
|
53
63
|
client_id: @client_id,
|
54
64
|
client_secret: @client_secret,
|
55
65
|
grant_type: @grant_type,
|
@@ -63,7 +73,7 @@ module ChangeHealth
|
|
63
73
|
self.grant_type = h[:grant_type]
|
64
74
|
self.api_endpoint = h[:api_endpoint]
|
65
75
|
|
66
|
-
|
76
|
+
self
|
67
77
|
end
|
68
78
|
end
|
69
79
|
|