diff --git a/lib/quickbooks/service/base_service_json.rb b/lib/quickbooks/service/base_service_json.rb index ab1ee641..f39a0556 100644 --- a/lib/quickbooks/service/base_service_json.rb +++ b/lib/quickbooks/service/base_service_json.rb @@ -8,23 +8,32 @@ class BaseServiceJSON < BaseService private + # Intuit typical response: + # {"Fault":{"Error":[{"Message":"Duplicate Name Exists Error","Detail":"The name supplied already exists. : null","code":"6240"}],"type":"ValidationFault"},"time":"2024-06-23T04:29:11.688-07:00"} + # + # Intuit intermittently returns an alternate response: + # {"fault":{"error":[{"message":"Duplicate Name Exists Error","detail":"The name supplied already exists. : null","code":"6240"}],"type":"ValidationFault"},"batchItemResponse":[],"attachableResponse":[],"time":1719142418269,"cdcresponse":[]} + def dereference_response(hsh, key) + hsh[key] || hsh[key.downcase] + end + def parse_json(json) @last_response_json = json end def response_is_error? - @last_response_json['Fault'].present? + dereference_response(@last_response_json, 'Fault').present? end def parse_intuit_error error = {:message => "", :detail => "", :type => nil, :code => 0} resp = JSON.parse(@last_response_json) - fault = resp['Fault'] + fault = dereference_response(resp, 'Fault') if fault.present? error[:type] = fault['type'] if fault.has_key?('type') - if fault_error = fault['Error'].first - error[:message] = fault_error['Message'] - error[:detail] = fault_error['Detail'] + if fault_error = dereference_response(fault, 'Error').first + error[:message] = dereference_response(fault_error, 'Message') + error[:detail] = dereference_response(fault_error, 'Detail') error[:code] = fault_error['code'] end end diff --git a/lib/quickbooks/service/change_service.rb b/lib/quickbooks/service/change_service.rb index af704ea9..ebeec657 100644 --- a/lib/quickbooks/service/change_service.rb +++ b/lib/quickbooks/service/change_service.rb @@ -2,7 +2,7 @@ module Quickbooks module Service class ChangeService < BaseService - def url_for_query(query = nil, start_position = 1, max_results = 20) + def url_for_query(query = nil, start_position = 1, max_results = 20, options = {}) # note: options are currently ignored q = entity q = "#{q}&#{query}" if query.present? diff --git a/spec/fixtures/json/tax_service_error_dup2.json b/spec/fixtures/json/tax_service_error_dup2.json new file mode 100644 index 00000000..64a0a7c8 --- /dev/null +++ b/spec/fixtures/json/tax_service_error_dup2.json @@ -0,0 +1,16 @@ +{ +"fault": { + "error": [ + { + "message": "Duplicate Name Exists Error", + "detail": "The name supplied already exists. : null", + "code": "6240" + } + ], + "type": "ValidationFault" +}, +"batchItemResponse": [], +"attachableResponse": [], +"time": "1719142418269", +"cdcresponse": [] +} diff --git a/spec/lib/quickbooks/service/tax_service_spec.rb b/spec/lib/quickbooks/service/tax_service_spec.rb index c1838f4a..c52c3443 100644 --- a/spec/lib/quickbooks/service/tax_service_spec.rb +++ b/spec/lib/quickbooks/service/tax_service_spec.rb @@ -48,6 +48,15 @@ }.to raise_error(Quickbooks::IntuitRequestException, /The name supplied already exists/) end + # Empirically observed alternate response from Intuit sandbox + it "catch exception if create tax code failed with alternate response" do + stub_http_request(:post, url, ["200", "OK"], json_fixture(:tax_service_error_dup2)) + tax_service.tax_rate_details = tax_rate_details + expect { + subject.create(tax_service) + }.to raise_error(Quickbooks::IntuitRequestException, /The name supplied already exists/) + end + it "can not create tax service without tax_code" do ts = model.new expect {