Fixes #3661 - FreshDesk Import Error - undefined method `body' for 10:Integer.
This commit is contained in:
parent
7f9c477cf4
commit
0ded6e542b
9 changed files with 108 additions and 6 deletions
|
@ -8,7 +8,7 @@ class Sequencer
|
||||||
|
|
||||||
def self.sequence
|
def self.sequence
|
||||||
[
|
[
|
||||||
'Sequencer::Unit::Import::Freshdesk::Request',
|
'Import::Freshdesk::Request',
|
||||||
'Import::Freshdesk::Resources',
|
'Import::Freshdesk::Resources',
|
||||||
'Import::Freshdesk::ModelClass',
|
'Import::Freshdesk::ModelClass',
|
||||||
'Import::Freshdesk::Perform',
|
'Import::Freshdesk::Perform',
|
||||||
|
|
|
@ -8,7 +8,7 @@ class Sequencer
|
||||||
|
|
||||||
def self.sequence
|
def self.sequence
|
||||||
[
|
[
|
||||||
'Sequencer::Unit::Import::Freshdesk::Request',
|
'Import::Freshdesk::Request',
|
||||||
'Import::Freshdesk::Resources',
|
'Import::Freshdesk::Resources',
|
||||||
'Import::Freshdesk::ModelClass',
|
'Import::Freshdesk::ModelClass',
|
||||||
'Import::Freshdesk::Perform',
|
'Import::Freshdesk::Perform',
|
||||||
|
|
|
@ -33,6 +33,8 @@ class Sequencer
|
||||||
end
|
end
|
||||||
|
|
||||||
def sum_deeply(existing:, additions:)
|
def sum_deeply(existing:, additions:)
|
||||||
|
return existing if additions.nil?
|
||||||
|
|
||||||
existing.merge(additions) do |_key, oldval, newval|
|
existing.merge(additions) do |_key, oldval, newval|
|
||||||
if oldval.is_a?(Hash) || newval.is_a?(Hash)
|
if oldval.is_a?(Hash) || newval.is_a?(Hash)
|
||||||
sum_deeply(
|
sum_deeply(
|
||||||
|
|
|
@ -6,6 +6,9 @@ class Sequencer
|
||||||
module Freshdesk
|
module Freshdesk
|
||||||
class ObjectCount < Sequencer::Unit::Common::Provider::Attribute
|
class ObjectCount < Sequencer::Unit::Common::Provider::Attribute
|
||||||
include ::Sequencer::Unit::Import::Common::Model::Statistics::Mixin::EmptyDiff
|
include ::Sequencer::Unit::Import::Common::Model::Statistics::Mixin::EmptyDiff
|
||||||
|
prepend ::Sequencer::Unit::Import::Common::Model::Mixin::Skip::Action
|
||||||
|
|
||||||
|
skip_action :skipped, :failed
|
||||||
|
|
||||||
uses :model_class, :resources
|
uses :model_class, :resources
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,9 @@ class Sequencer
|
||||||
module Import
|
module Import
|
||||||
module Freshdesk
|
module Freshdesk
|
||||||
class Perform < Sequencer::Unit::Base
|
class Perform < Sequencer::Unit::Base
|
||||||
|
prepend ::Sequencer::Unit::Import::Common::Model::Mixin::Skip::Action
|
||||||
|
|
||||||
|
skip_action :skipped, :failed
|
||||||
|
|
||||||
uses :resources, :object, :import_job, :dry_run, :field_map, :id_map
|
uses :resources, :object, :import_job, :dry_run, :field_map, :id_map
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ class Sequencer
|
||||||
rescue Net::HTTPClientError => e
|
rescue Net::HTTPClientError => e
|
||||||
handle_exception e, iteration
|
handle_exception e, iteration
|
||||||
end
|
end
|
||||||
|
|
||||||
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_error(response, iteration)
|
def handle_error(response, iteration)
|
||||||
|
|
|
@ -5,6 +5,7 @@ class Sequencer
|
||||||
module Import
|
module Import
|
||||||
module Freshdesk
|
module Freshdesk
|
||||||
class Resources < Sequencer::Unit::Common::Provider::Named
|
class Resources < Sequencer::Unit::Common::Provider::Named
|
||||||
|
include ::Sequencer::Unit::Import::Common::Model::Mixin::HandleFailure
|
||||||
|
|
||||||
uses :response
|
uses :response
|
||||||
|
|
||||||
|
@ -12,6 +13,9 @@ class Sequencer
|
||||||
|
|
||||||
def resources
|
def resources
|
||||||
JSON.parse(response.body)
|
JSON.parse(response.body)
|
||||||
|
rescue => e
|
||||||
|
logger.error "Won't be continued, because no response is available."
|
||||||
|
handle_failure(e)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,24 +24,47 @@ class Sequencer
|
||||||
field_map: field_map,
|
field_map: field_map,
|
||||||
id_map: id_map,
|
id_map: id_map,
|
||||||
},
|
},
|
||||||
expecting: [:response])
|
expecting: %i[action response])
|
||||||
break if result[:response].header['link'].blank?
|
break if iteration_should_stop?(result)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def request_params
|
def request_params
|
||||||
{
|
{
|
||||||
page: iteration + 1,
|
page: page,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def page
|
||||||
|
iteration + 1
|
||||||
|
end
|
||||||
|
|
||||||
def object
|
def object
|
||||||
self.class.name.demodulize.singularize
|
@object ||= self.class.name.demodulize.singularize
|
||||||
end
|
end
|
||||||
|
|
||||||
def sequence_name
|
def sequence_name
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def iteration_should_stop?(result)
|
||||||
|
return true if result[:action] == :failed
|
||||||
|
return true if result[:response].header['link'].blank?
|
||||||
|
|
||||||
|
max_page_reached?
|
||||||
|
end
|
||||||
|
|
||||||
|
# https://github.com/zammad/zammad/issues/3661
|
||||||
|
# https://developers.freshdesk.com/api/#list_all_tickets
|
||||||
|
def max_page_reached?
|
||||||
|
return false if object != 'Ticket'
|
||||||
|
return false if page <= 300
|
||||||
|
|
||||||
|
logger.warn "Reached max Freshdesk API page number #{page} for #{object}. Stopping further requests to prevent errors."
|
||||||
|
true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe ::Sequencer::Sequence::Import::Freshdesk::GenericObject, sequencer: :sequence, db_strategy: 'reset' do
|
||||||
|
context 'when importing group list with generic object' do
|
||||||
|
let(:resources_payloud) do
|
||||||
|
[
|
||||||
|
{
|
||||||
|
'id' => 80_000_374_715,
|
||||||
|
'name' => 'QA',
|
||||||
|
'description' => 'Members of the QA team belong to this group',
|
||||||
|
'escalate_to' => nil,
|
||||||
|
'unassigned_for' => nil,
|
||||||
|
'business_hour_id' => nil,
|
||||||
|
'group_type' => 'support_agent_group',
|
||||||
|
'created_at' => '2021-04-09T13:23:59Z',
|
||||||
|
'updated_at' => '2021-04-09T13:23:59Z'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'id' => 80_000_374_716,
|
||||||
|
'name' => 'Testing',
|
||||||
|
'description' => 'Members of the Testing team belong to this group',
|
||||||
|
'escalate_to' => nil,
|
||||||
|
'unassigned_for' => nil,
|
||||||
|
'business_hour_id' => nil,
|
||||||
|
'group_type' => 'support_agent_group',
|
||||||
|
'created_at' => '2021-04-09T13:23:59Z',
|
||||||
|
'updated_at' => '2021-04-09T13:23:59Z'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:process_payload) do
|
||||||
|
{
|
||||||
|
import_job: build_stubbed(:import_job, name: 'Import::Freshdesk', payload: {}),
|
||||||
|
dry_run: false,
|
||||||
|
object: 'Group',
|
||||||
|
request_params: {},
|
||||||
|
field_map: {},
|
||||||
|
id_map: {},
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
# Mock the groups get request
|
||||||
|
stub_request(:get, 'https://yours.freshdesk.com/api/v2/groups?per_page=100').to_return(status: 200, body: JSON.generate(resources_payloud), headers: {})
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'add groups' do
|
||||||
|
expect { process(process_payload) }.to change(Group, :count).by(2)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when list request fails' do
|
||||||
|
before do
|
||||||
|
allow(Sequencer::Unit::Import::Freshdesk::Request).to receive(:handle_error).with(any_args).and_return(true)
|
||||||
|
stub_request(:get, 'https://yours.freshdesk.com/api/v2/groups?per_page=100').to_return(status: 400, headers: {})
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'check that a failing response do not raise a hard error' do
|
||||||
|
expect { process(process_payload) }.to change(Group, :count).by(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue