From 18b88920e7146cf15438af22d0bd8dc16e5743e5 Mon Sep 17 00:00:00 2001 From: Martin Gruner Date: Tue, 1 Jun 2021 09:44:33 +0000 Subject: [PATCH] Fixes #3582 - Freshdesk import attribute ID mapping lookup constants fail application boot in systems with changed default names. --- .../import/freshdesk/conversation/mapping.rb | 48 +++++++++++-------- .../import/freshdesk/description/mapping.rb | 34 +++++++------ .../unit/import/freshdesk/ticket/mapping.rb | 34 +++++++------ 3 files changed, 66 insertions(+), 50 deletions(-) diff --git a/lib/sequencer/unit/import/freshdesk/conversation/mapping.rb b/lib/sequencer/unit/import/freshdesk/conversation/mapping.rb index bea8a6b36..d80b0f58e 100644 --- a/lib/sequencer/unit/import/freshdesk/conversation/mapping.rb +++ b/lib/sequencer/unit/import/freshdesk/conversation/mapping.rb @@ -8,27 +8,33 @@ class Sequencer uses :resource, :id_map - SOURCE_MAP = { - 0 => ::Ticket::Article::Type.select(:id).find_by(name: 'email').id, # Reply - 1 => ::Ticket::Article::Type.select(:id).find_by(name: 'email').id, # Email - 2 => ::Ticket::Article::Type.select(:id).find_by(name: 'web').id, # Note - 3 => ::Ticket::Article::Type.select(:id).find_by(name: 'phone').id, # Phone - 4 => ::Ticket::Article::Type.select(:id).find_by(name: 'note').id, # UNKNOWN! - 5 => ::Ticket::Article::Type.select(:id).find_by(name: 'twitter status').id, # Created from tweets - 6 => ::Ticket::Article::Type.select(:id).find_by(name: 'web').id, # Created from survey feedback - 7 => ::Ticket::Article::Type.select(:id).find_by(name: 'facebook feed post').id, # Created from Facebook post - 8 => ::Ticket::Article::Type.select(:id).find_by(name: 'email').id, # Created from Forwarded Email - 9 => ::Ticket::Article::Type.select(:id).find_by(name: 'note').id, # Created from Phone - 10 => ::Ticket::Article::Type.select(:id).find_by(name: 'note').id, # Created from Mobihelp - 11 => ::Ticket::Article::Type.select(:id).find_by(name: 'note').id, # E-Commerce - }.freeze + # Since the imports rely on a fresh Zammad installation, we + # can require the default article types and senders to be present. + def source_map # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity + @source_map ||= { + 0 => ::Ticket::Article::Type.select(:id).find_by(name: 'email')&.id, # Reply + 1 => ::Ticket::Article::Type.select(:id).find_by(name: 'email')&.id, # Email + 2 => ::Ticket::Article::Type.select(:id).find_by(name: 'web')&.id, # Note + 3 => ::Ticket::Article::Type.select(:id).find_by(name: 'phone')&.id, # Phone + 4 => ::Ticket::Article::Type.select(:id).find_by(name: 'note')&.id, # UNKNOWN! + 5 => ::Ticket::Article::Type.select(:id).find_by(name: 'twitter status')&.id, # Created from tweets + 6 => ::Ticket::Article::Type.select(:id).find_by(name: 'web')&.id, # Created from survey feedback + 7 => ::Ticket::Article::Type.select(:id).find_by(name: 'facebook feed post')&.id, # Created from Facebook post + 8 => ::Ticket::Article::Type.select(:id).find_by(name: 'email')&.id, # Created from Forwarded Email + 9 => ::Ticket::Article::Type.select(:id).find_by(name: 'note')&.id, # Created from Phone + 10 => ::Ticket::Article::Type.select(:id).find_by(name: 'note')&.id, # Created from Mobihelp + 11 => ::Ticket::Article::Type.select(:id).find_by(name: 'note')&.id, # E-Commerce + }.freeze + end - INCOMING_MAP = { - true => ::Ticket::Article::Sender.select(:id).find_by(name: 'Customer').id, - false => ::Ticket::Article::Sender.select(:id).find_by(name: 'Agent').id, - }.freeze + def incoming_map + @incoming_map ||= { + true => ::Ticket::Article::Sender.select(:id).find_by(name: 'Customer')&.id, + false => ::Ticket::Article::Sender.select(:id).find_by(name: 'Agent')&.id, + }.freeze + end - def process # rubocop:disable Metrics/AbcSize + def process # rubocop:disable Metrics/AbcSize provide_mapped do { from: resource['from_email'], @@ -41,8 +47,8 @@ class Sequencer message_id: resource['id'], updated_by_id: user_id, created_by_id: user_id, - sender_id: INCOMING_MAP[ resource['incoming'] ], - type_id: SOURCE_MAP[ resource['source'] ], + sender_id: incoming_map[ resource['incoming'] ], + type_id: source_map[ resource['source'] ], created_at: resource['created_at'], updated_at: resource['updated_at'], } diff --git a/lib/sequencer/unit/import/freshdesk/description/mapping.rb b/lib/sequencer/unit/import/freshdesk/description/mapping.rb index 725d930fa..befb9298f 100644 --- a/lib/sequencer/unit/import/freshdesk/description/mapping.rb +++ b/lib/sequencer/unit/import/freshdesk/description/mapping.rb @@ -8,20 +8,24 @@ class Sequencer uses :resource, :id_map - SOURCE_MAP = { - 0 => ::Ticket::Article::Type.select(:id).find_by(name: 'email').id, # Reply - 1 => ::Ticket::Article::Type.select(:id).find_by(name: 'email').id, # Email - 2 => ::Ticket::Article::Type.select(:id).find_by(name: 'web').id, # Note - 3 => ::Ticket::Article::Type.select(:id).find_by(name: 'phone').id, # Phone - 4 => ::Ticket::Article::Type.select(:id).find_by(name: 'note').id, # UNKNOWN! - 5 => ::Ticket::Article::Type.select(:id).find_by(name: 'twitter status').id, # Created from tweets - 6 => ::Ticket::Article::Type.select(:id).find_by(name: 'web').id, # Created from survey feedback - 7 => ::Ticket::Article::Type.select(:id).find_by(name: 'facebook feed post').id, # Created from Facebook post - 8 => ::Ticket::Article::Type.select(:id).find_by(name: 'email').id, # Created from Forwarded Email - 9 => ::Ticket::Article::Type.select(:id).find_by(name: 'note').id, # Created from Phone - 10 => ::Ticket::Article::Type.select(:id).find_by(name: 'note').id, # Created from Mobihelp - 11 => ::Ticket::Article::Type.select(:id).find_by(name: 'note').id, # E-Commerce - }.freeze + # Since the imports rely on a fresh Zammad installation, we + # can require the default article types to be present. + def source_map # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity + @source_map ||= { + 0 => ::Ticket::Article::Type.select(:id).find_by(name: 'email')&.id, # Reply + 1 => ::Ticket::Article::Type.select(:id).find_by(name: 'email')&.id, # Email + 2 => ::Ticket::Article::Type.select(:id).find_by(name: 'web')&.id, # Note + 3 => ::Ticket::Article::Type.select(:id).find_by(name: 'phone')&.id, # Phone + 4 => ::Ticket::Article::Type.select(:id).find_by(name: 'note')&.id, # UNKNOWN! + 5 => ::Ticket::Article::Type.select(:id).find_by(name: 'twitter status')&.id, # Created from tweets + 6 => ::Ticket::Article::Type.select(:id).find_by(name: 'web')&.id, # Created from survey feedback + 7 => ::Ticket::Article::Type.select(:id).find_by(name: 'facebook feed post')&.id, # Created from Facebook post + 8 => ::Ticket::Article::Type.select(:id).find_by(name: 'email')&.id, # Created from Forwarded Email + 9 => ::Ticket::Article::Type.select(:id).find_by(name: 'note')&.id, # Created from Phone + 10 => ::Ticket::Article::Type.select(:id).find_by(name: 'note')&.id, # Created from Mobihelp + 11 => ::Ticket::Article::Type.select(:id).find_by(name: 'note')&.id, # E-Commerce + }.freeze + end def process # rubocop:disable Metrics/AbcSize provide_mapped do @@ -35,7 +39,7 @@ class Sequencer internal: false, message_id: "ticketid#{resource['id']}@freshdesk.com", sender_id: ::Ticket::Article::Sender.select(:id).find_by(name: 'Customer').id, - type_id: SOURCE_MAP[ resource['source'] ], + type_id: source_map[ resource['source'] ], updated_by_id: requester_id, created_by_id: requester_id, created_at: resource['created_at'], diff --git a/lib/sequencer/unit/import/freshdesk/ticket/mapping.rb b/lib/sequencer/unit/import/freshdesk/ticket/mapping.rb index a032461ac..ad557e8c8 100644 --- a/lib/sequencer/unit/import/freshdesk/ticket/mapping.rb +++ b/lib/sequencer/unit/import/freshdesk/ticket/mapping.rb @@ -8,19 +8,25 @@ class Sequencer uses :resource, :id_map - PRIORITY_MAP = { - 1 => ::Ticket::Priority.find_by(name: '1 low').id, # low - 2 => ::Ticket::Priority.find_by(name: '2 normal').id, # medium - 3 => ::Ticket::Priority.find_by(name: '3 high').id, # high - 4 => ::Ticket::Priority.find_by(name: '3 high').id, # urgent - }.freeze + # Since the imports rely on a fresh Zammad installation, we + # can require the default priority and state names to be present. + def priority_map + @priority_map ||= { + 1 => ::Ticket::Priority.find_by(name: '1 low')&.id, # low + 2 => ::Ticket::Priority.find_by(name: '2 normal')&.id, # medium + 3 => ::Ticket::Priority.find_by(name: '3 high')&.id, # high + 4 => ::Ticket::Priority.find_by(name: '3 high')&.id, # urgent + }.freeze + end - STATE_MAP = { - 2 => ::Ticket::State.find_by(name: 'open').id, # open - 3 => ::Ticket::State.find_by(name: 'open').id, # pending - 4 => ::Ticket::State.find_by(name: 'closed').id, # resolved - 5 => ::Ticket::State.find_by(name: 'closed').id, # closed - }.freeze + def state_map + @state_map ||= { + 2 => ::Ticket::State.find_by(name: 'open')&.id, # open + 3 => ::Ticket::State.find_by(name: 'open')&.id, # pending + 4 => ::Ticket::State.find_by(name: 'closed')&.id, # resolved + 5 => ::Ticket::State.find_by(name: 'closed')&.id, # closed + }.freeze + end def process # rubocop:disable Metrics/AbcSize provide_mapped do @@ -28,8 +34,8 @@ class Sequencer title: resource['subject'], number: resource['id'], group_id: group_id, - priority_id: PRIORITY_MAP[resource['priority']], - state_id: STATE_MAP[resource['status']], + priority_id: priority_map[resource['priority']], + state_id: state_map[resource['status']], owner_id: owner_id, customer_id: customer_id, created_at: resource['created_at'],