From 5aa51f82a675e1afe7c5cff5b7b44760d1b14752 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Thu, 19 May 2016 15:01:02 +0200 Subject: [PATCH] Added support for zendesk custom fields. --- app/models/object_manager/attribute.rb | 28 +++- lib/import/zendesk.rb | 115 ++++++++++------ test/integration/zendesk_import_test.rb | 169 ++++++++++++------------ 3 files changed, 187 insertions(+), 125 deletions(-) diff --git a/app/models/object_manager/attribute.rb b/app/models/object_manager/attribute.rb index 211bc3150..6cd18a4ef 100644 --- a/app/models/object_manager/attribute.rb +++ b/app/models/object_manager/attribute.rb @@ -383,8 +383,10 @@ returns end data_type = nil - if attribute.data_type =~ /^input|select|richtext|textarea$/ + if attribute.data_type =~ /^input|select|richtext|textarea|checkbox$/ data_type = :string + elsif attribute.data_type =~ /^integer$/ + data_type = :integer elsif attribute.data_type =~ /^boolean|active$/ data_type = :boolean elsif attribute.data_type =~ /^datetime$/ @@ -395,7 +397,7 @@ returns # change field if model.column_names.include?(attribute.name) - if attribute.data_type =~ /^input|select|richtext|textarea$/ + if attribute.data_type =~ /^input|select|richtext|textarea|checkbox$/ ActiveRecord::Migration.change_column( model.table_name, attribute.name, @@ -403,7 +405,7 @@ returns limit: attribute.data_option[:maxlength], null: true ) - elsif attribute.data_type =~ /^boolean|active|datetime|date$/ + elsif attribute.data_type =~ /^integer|datetime|date$/ ActiveRecord::Migration.change_column( model.table_name, attribute.name, @@ -411,6 +413,14 @@ returns default: attribute.data_option[:default], null: true ) + elsif attribute.data_type =~ /^boolean|active$/ + ActiveRecord::Migration.change_column( + model.table_name, + attribute.name, + data_type, + default: attribute.data_option[:default], + null: false + ) else raise "Unknown attribute.data_type '#{attribute.data_type}', can't update attribute" end @@ -424,7 +434,7 @@ returns end # create field - if attribute.data_type =~ /^input|select|richtext|textarea$/ + if attribute.data_type =~ /^input|select|richtext|textarea|checkbox$/ ActiveRecord::Migration.add_column( model.table_name, attribute.name, @@ -432,6 +442,14 @@ returns limit: attribute.data_option[:maxlength], null: true ) + elsif attribute.data_type =~ /^integer$/ + ActiveRecord::Migration.add_column( + model.table_name, + attribute.name, + data_type, + default: attribute.data_option[:default], + null: true + ) elsif attribute.data_type =~ /^boolean|active$/ ActiveRecord::Migration.add_column( model.table_name, @@ -471,7 +489,7 @@ returns def check_name if name - return true if name !~ /_(id|ids)$/i && name !~ /^id$/i + return true if name !~ /_(id|ids)$/i && name !~ /^id$/i && name !~ /\s/ end raise "Name can't get used, *_id and *_ids are not allowed" end diff --git a/lib/import/zendesk.rb b/lib/import/zendesk.rb index a86261e77..b8b1ead3c 100644 --- a/lib/import/zendesk.rb +++ b/lib/import/zendesk.rb @@ -182,21 +182,21 @@ module Import::Zendesk return { - :Group => { - :total => 1234, - :done => 13, + Group: { + total: 1234, + done: 13, }, - :Organization => { - :total => 1234, - :done => 13, + Organization: { + total: 1234, + done: 13, }, - :User => { - :total => 1234, - :done => 13, + User: { + total: 1234, + done: 13, }, - :Ticket => { - :total => 1234, - :done => 13, + Ticket: { + total: 1234, + done: 13, }, } @@ -206,7 +206,6 @@ module Import::Zendesk data = statistic - # TODO: Ticket, User, Organization fields { Group: { done: Group.count, @@ -334,8 +333,8 @@ module Import::Zendesk zendesk_field['key'] # TODO: y?! end - @zendesk_ticket_field_mapping ||= {} - @zendesk_ticket_field_mapping[ zendesk_field.id ] = name + @zendesk_field_mapping ||= {} + @zendesk_field_mapping[ zendesk_field.id ] = name data_type = zendesk_field.type data_option = { @@ -348,6 +347,16 @@ module Import::Zendesk data_option = { future: true, past: true, + diff: 0, + }.merge( data_option ) + + elsif zendesk_field.type == 'checkbox' + + data_type = 'checkbox' + data_option = { + type: zendesk_field.type, + default: '', + options: {}, }.merge( data_option ) elsif zendesk_field.type == 'regexp' @@ -355,14 +364,32 @@ module Import::Zendesk data_type = 'input' data_option = { type: 'text', + maxlength: 255, regex: zendesk_field.regexp_for_validation, }.merge( data_option ) + elsif zendesk_field.type == 'decimal' + + data_type = 'input' + data_option = { + type: 'text', + maxlength: 255, + }.merge( data_option ) + + elsif zendesk_field.type == 'integer' + + data_type = 'integer' + data_option = { + min: 0, + max: 999_999_999, + }.merge( data_option ) + elsif zendesk_field.type == 'text' data_type = 'input' data_option = { type: zendesk_field.type, + maxlength: 255, }.merge( data_option ) elsif zendesk_field.type == 'textarea' @@ -370,9 +397,10 @@ module Import::Zendesk data_type = 'input' data_option = { type: zendesk_field.type, + maxlength: 255, }.merge( data_option ) - elsif zendesk_field.type == 'tagger' + elsif zendesk_field.type == 'tagger' || zendesk_field.type == 'dropdown' # \"custom_field_options\"=>[{\"id\"=>28353445 # \"name\"=>\"Another Value\" @@ -386,7 +414,6 @@ module Import::Zendesk # \"name\"=>\"Value 2\" # \"raw_name\"=>\"Value 2\" # \"value\"=>\"key2\"}]}> - # " options = {} @@ -403,6 +430,7 @@ module Import::Zendesk data_type = 'select' data_option = { + default: '', options: options, }.merge( data_option ) end @@ -425,6 +453,7 @@ module Import::Zendesk }.merge(screens) } end + name.gsub!(/\s/, '_') ObjectManager::Attribute.add( object: local_object, @@ -435,11 +464,11 @@ module Import::Zendesk editable: !zendesk_field.removable, active: zendesk_field.active, screens: screens, - pending_migration: false, position: zendesk_field.position, created_by_id: 1, updated_by_id: 1, ) + ObjectManager::Attribute.migration_execute end # OAuth @@ -481,6 +510,7 @@ module Import::Zendesk @zendesk_organization_mapping = {} @client.organizations.each { |zendesk_organization| + custom_fields = get_fields(zendesk_organization.organization_fields) local_organization_fields = { name: zendesk_organization.name, @@ -490,10 +520,9 @@ module Import::Zendesk # }.merge(zendesk_organization.organization_fields) # TODO updated_by_id: 1, created_by_id: 1 - } - - local_organization = Organization.create_if_not_exists( local_organization_fields ) + }.merge(custom_fields) + local_organization = Organization.create_if_not_exists(local_organization_fields) @zendesk_organization_mapping[ zendesk_organization.id ] = local_organization.id } end @@ -511,7 +540,7 @@ module Import::Zendesk role_customer = Role.lookup(name: 'Customer') @client.users.all! { |zendesk_user| - + custom_fields = get_fields(zendesk_user.user_fields) local_user_fields = { login: zendesk_user.id.to_s, # Zendesk users may have no other identifier than the ID, e.g. twitter users firstname: zendesk_user.name, @@ -527,7 +556,7 @@ module Import::Zendesk last_login: zendesk_user.last_login_at, updated_by_id: 1, created_by_id: 1 - } + }.merge(custom_fields) if @zendesk_user_group_mapping[ zendesk_user.id ] @@ -616,19 +645,7 @@ module Import::Zendesk article_type_facebook_feed_comment = Ticket::Article::Type.lookup(name: 'facebook feed comment') @client.tickets.all! { |zendesk_ticket| - - zendesk_ticket_fields = {} - zendesk_ticket.custom_fields.each { |zendesk_ticket_field| - - field_name = @zendesk_ticket_field_mapping[ zendesk_ticket_field['id'] ] - field_value = zendesk_ticket_field['value'] - if @zendesk_ticket_field_value_mapping[ field_name ] - field_value = @zendesk_ticket_field_value_mapping[ field_name ][ field_value ] - end - - zendesk_ticket_fields[ field_name ] = field_value - } - + custom_fields = get_custom_fields(zendesk_ticket.custom_fields) local_ticket_fields = { id: zendesk_ticket.id, title: zendesk_ticket.subject, @@ -643,8 +660,7 @@ module Import::Zendesk created_at: zendesk_ticket.created_at, updated_by_id: @zendesk_user_mapping[ zendesk_ticket.requester_id ] || 1, created_by_id: @zendesk_user_mapping[ zendesk_ticket.requester_id ] || 1, - # }.merge(zendesk_ticket_fields) TODO - } + }.merge(custom_fields) ticket_author = User.find( @zendesk_user_mapping[ zendesk_ticket.requester_id ] || 1 ) local_ticket_fields[:create_article_sender_id] = if ticket_author.role?('Customer') @@ -1042,4 +1058,27 @@ module Import::Zendesk ActiveRecord::Base.connection.reset_pk_sequence!(table) end + def get_custom_fields(custom_fields) + return {} if !custom_fields + fields = {} + custom_fields.each { |custom_field| + field_name = @zendesk_field_mapping[ custom_field['id'] ].gsub(/\s/, '_') + field_value = custom_field['value'] + if @zendesk_ticket_field_value_mapping[ field_name ] + field_value = @zendesk_ticket_field_value_mapping[ field_name ][ field_value ] + end + fields[ field_name ] = field_value + } + fields + end + + def get_fields(user_fields) + return {} if !user_fields + fields = {} + user_fields.each {|key, value| + fields[key] = value + } + fields + end + end diff --git a/test/integration/zendesk_import_test.rb b/test/integration/zendesk_import_test.rb index 1fab59be1..64ef28755 100644 --- a/test/integration/zendesk_import_test.rb +++ b/test/integration/zendesk_import_test.rb @@ -28,8 +28,8 @@ class ZendeskImportTest < ActiveSupport::TestCase compare_statistic = { 'Tickets' => 143, 'TicketFields' => 13, - 'UserFields' => 1, - 'OrganizationFields' => 1, + 'UserFields' => 2, + 'OrganizationFields' => 2, 'Groups' => 2, 'Organizations' => 1, 'Users' => 141, @@ -39,18 +39,18 @@ class ZendeskImportTest < ActiveSupport::TestCase 'Automations' => 5 } - assert_equal( compare_statistic, remote_statistic, 'statistic' ) + assert_equal(compare_statistic, remote_statistic, 'statistic') end # check count of imported items test 'check counts' do - assert_equal( 143, User.count, 'users' ) - assert_equal( 3, Group.count, 'groups' ) - assert_equal( 6, Role.count, 'roles' ) - assert_equal( 2, Organization.count, 'organizations' ) - assert_equal( 143, Ticket.count, 'tickets' ) - assert_equal( 151, Ticket::Article.count, 'ticket articles' ) - assert_equal( 2, Store.count, 'ticket article attachments' ) + assert_equal(143, User.count, 'users') + assert_equal(3, Group.count, 'groups') + assert_equal(6, Role.count, 'roles') + assert_equal(2, Organization.count, 'organizations') + assert_equal(143, Ticket.count, 'tickets') + assert_equal(151, Ticket::Article.count, 'ticket articles') + assert_equal(2, Store.count, 'ticket article attachments') # TODO: Macros, Views, Automations... end @@ -58,24 +58,25 @@ class ZendeskImportTest < ActiveSupport::TestCase # check imported users and permission test 'check users' do - role_admin = Role.find_by( name: 'Admin' ) - role_agent = Role.find_by( name: 'Agent' ) - role_customer = Role.find_by( name: 'Customer' ) + role_admin = Role.find_by(name: 'Admin') + role_agent = Role.find_by(name: 'Agent') + role_customer = Role.find_by(name: 'Customer') - group_users = Group.find_by( name: 'Users' ) - group_support = Group.find_by( name: 'Support' ) - group_additional_group = Group.find_by( name: 'Additional Group' ) + group_users = Group.find_by(name: 'Users') + group_support = Group.find_by(name: 'Support') + group_additional_group = Group.find_by(name: 'Additional Group') checks = [ { id: 4, data: { - firstname: 'Bob', - lastname: 'Smith', - login: '1150734731', - email: 'bob.smith@znuny.com', - active: true, - phone: '00114124', + firstname: 'Bob', + lastname: 'Smith', + login: '1150734731', + email: 'bob.smith@znuny.com', + active: true, + phone: '00114124', + lieblingstier: 'Hundä', }, roles: [role_agent, role_admin], groups: [group_support], @@ -83,11 +84,12 @@ class ZendeskImportTest < ActiveSupport::TestCase { id: 5, data: { - firstname: 'Hansimerkur', - lastname: '', - login: '1202726471', - email: 'hansimerkur@znuny.com', - active: true, + firstname: 'Hansimerkur', + lastname: '', + login: '1202726471', + email: 'hansimerkur@znuny.com', + active: true, + lieblingstier: nil, }, roles: [role_agent, role_admin], groups: [group_additional_group, group_support], @@ -131,26 +133,18 @@ class ZendeskImportTest < ActiveSupport::TestCase ] checks.each { |check| - user = User.find( check[:id] ) - - assert_equal( check[:data][:firstname], user.firstname, 'firstname' ) - assert_equal( check[:data][:lastname], user.lastname, 'lastname' ) - assert_equal( check[:data][:login], user.login, 'login' ) - assert_equal( check[:data][:email], user.email, 'email' ) - assert_equal( check[:data][:phone], user.phone, 'phone' ) - assert_equal( check[:data][:active], user.active, 'active' ) - - assert_equal( check[:roles], user.roles.to_a, "#{user.login} roles" ) - assert_equal( check[:groups], user.groups.to_a, "#{user.login} groups" ) + user = User.find(check[:id]) + check[:data].each {|key, value| + assert_equal(value, user[key], "user.#{key} for user_id #{check[:id]}") + } + assert_equal(check[:roles], user.roles.to_a, "#{user.login} roles") + assert_equal(check[:groups], user.groups.to_a, "#{user.login} groups") } end # check user fields test 'check user fields' do - local_fields = User.column_names - - # TODO copmare_fields = %w( id organization_id @@ -182,9 +176,11 @@ class ZendeskImportTest < ActiveSupport::TestCase updated_by_id created_by_id created_at - updated_at) + updated_at + lieblingstier + custom_dropdown) - assert_equal( copmare_fields, local_fields, 'user fields' ) + assert_equal(copmare_fields, local_fields, 'user fields') end # check groups/queues @@ -215,10 +211,10 @@ class ZendeskImportTest < ActiveSupport::TestCase ] checks.each { |check| - group = Group.find( check[:id] ) - - assert_equal( check[:data][:name], group.name, 'name' ) - assert_equal( check[:data][:active], group.active, 'active' ) + group = Group.find(check[:id]) + check[:data].each {|key, value| + assert_equal(value, group[key], "group.#{key} for group_id #{check[:id]}") + } } end @@ -231,6 +227,8 @@ class ZendeskImportTest < ActiveSupport::TestCase data: { name: 'Zammad Foundation', note: '', + api_key: nil, + custom_dropdown: nil, }, }, { @@ -238,24 +236,23 @@ class ZendeskImportTest < ActiveSupport::TestCase data: { name: 'Znuny', note: nil, + api_key: 'my api öäüß', + custom_dropdown: 'b', }, }, ] checks.each { |check| - organization = Organization.find( check[:id] ) - - assert_equal( check[:data][:name], organization.name, 'name' ) - assert_equal( check[:data][:note], organization.note, 'note' ) + organization = Organization.find(check[:id]) + check[:data].each {|key, value| + assert_equal(value, organization[key], "organization.#{key} for organization_id #{check[:id]}") + } } end # check organization fields test 'check organization fields' do - local_fields = Organization.column_names - - # TODO copmare_fields = %w( id name @@ -265,9 +262,11 @@ class ZendeskImportTest < ActiveSupport::TestCase updated_by_id created_by_id created_at - updated_at) + updated_at + api_key + custom_dropdown) - assert_equal( copmare_fields, local_fields, 'organization fields' ) + assert_equal(copmare_fields, local_fields, 'organization fields') end # check imported tickets @@ -278,7 +277,8 @@ class ZendeskImportTest < ActiveSupport::TestCase id: 2, data: { title: 'test', - note: 'This is the first comment. Feel free to delete this sample ticket.', + #note: 'This is the first comment. Feel free to delete this sample ticket.', + note: 'test email', create_article_type_id: 1, create_article_sender_id: 2, article_count: 2, @@ -288,13 +288,20 @@ class ZendeskImportTest < ActiveSupport::TestCase owner_id: 1, customer_id: 6, organization_id: 2, + test_checkbox: 'f', + custom_integer: 999, + custom_dropdown: 'key2', + custom_decimal: '1.6', + not_existing: nil, }, }, { id: 3, data: { title: 'Bob Smith, here is the test ticket you requested', - note: 'test email', + note: 'Hello! This is a Zendesk ticket. We are going to go through the basic support ticket operation in Zendesk. + +If you\'re reading this message in your email, click the ticket number link that immediately follows the line \'You have been assigned to this t', create_article_type_id: 10, create_article_sender_id: 2, article_count: 4, @@ -304,13 +311,18 @@ class ZendeskImportTest < ActiveSupport::TestCase owner_id: 1, customer_id: 7, organization_id: nil, + test_checkbox: 'f', + custom_integer: nil, + custom_dropdown: '', + custom_decimal: nil, + not_existing: nil, }, }, { id: 5, data: { title: 'Twitter', - note: '@DesafioCaracol sh q acaso sto se vale ver el jueg...', + note: "@gabyalanisr Brandon Arely Snuppy Jaz Jerry Liz Irvig & Wera\nY Losa Otrs Yop \npero si quieres Los Que Puedas", create_article_type_id: 6, create_article_sender_id: 2, article_count: 1, @@ -357,18 +369,10 @@ class ZendeskImportTest < ActiveSupport::TestCase ] checks.each { |check| - ticket = Ticket.find( check[:id] ) - - assert_equal( check[:data][:title], ticket.title, "title of Ticket.find(#{check[:id]})" ) - assert_equal( check[:data][:create_article_type_id], ticket.create_article_type_id, "created_article_type_id of Ticket.find(#{check[:id]})" ) - assert_equal( check[:data][:create_article_sender_id], ticket.create_article_sender_id, "created_article_sender_id of Ticket.find(#{check[:id]})" ) - assert_equal( check[:data][:article_count], ticket.article_count, "article_count of Ticket.find(#{check[:id]})" ) - assert_equal( check[:data][:state_id], ticket.state.id, "state_id of Ticket.find(#{check[:id]})" ) - assert_equal( check[:data][:group_id], ticket.group.id, "group_id of Ticket.find(#{check[:id]})" ) - assert_equal( check[:data][:priority_id], ticket.priority.id, "priority_id of Ticket.find(#{check[:id]})" ) - assert_equal( check[:data][:owner_id], ticket.owner.id, "owner_id of Ticket.find(#{check[:id]})" ) - assert_equal( check[:data][:customer_id], ticket.customer.id, "customer_id of Ticket.find(#{check[:id]})" ) - assert_equal( check[:data][:organization_id], ticket.organization.try(:id), "organization_id of Ticket.find(#{check[:id]})" ) + ticket = Ticket.find(check[:id]) + check[:data].each {|key, value| + assert_equal(value, ticket[key], "ticket.#{key} for ticket_id #{check[:id]}") + } } end @@ -404,27 +408,22 @@ class ZendeskImportTest < ActiveSupport::TestCase checks.each { |check| article = Ticket::Article.find(check[:id]) - assert_equal( check[:data][:count], article.attachments.count, 'attachemnt count' ) + assert_equal(check[:data][:count], article.attachments.count, 'attachemnt count') - (1..check[:data][:count] ).each { |attachment_counter| + (1..check[:data][:count]).each { |attachment_counter| attachment = article.attachments[ attachment_counter - 1 ] compare_attachment = check[:data][ attachment_counter ] - assert_equal( compare_attachment[:filename], attachment.filename, 'attachment file name' ) - - assert_equal( compare_attachment[:preferences], attachment[:preferences], 'attachment preferences') - + assert_equal(compare_attachment[:filename], attachment.filename, 'attachment file name') + assert_equal(compare_attachment[:preferences], attachment[:preferences], 'attachment preferences') } } end # check ticket fields test 'check ticket fields' do - local_fields = Ticket.column_names - - # TODO copmare_fields = %w( id group_id @@ -463,9 +462,15 @@ class ZendeskImportTest < ActiveSupport::TestCase updated_by_id created_by_id created_at - updated_at) + updated_at + custom_decimal + test_checkbox + custom_date + custom_integer + custom_regex + custom_dropdown) - assert_equal( copmare_fields, local_fields, 'ticket fields' ) + assert_equal(copmare_fields, local_fields, 'ticket fields') end end