From 37e98b1a81c7b8f45e92e7f2b4c0b88cbc92980d Mon Sep 17 00:00:00 2001 From: Thorsten Eckel Date: Tue, 14 Feb 2017 09:59:41 +0100 Subject: [PATCH 1/3] Working on issue #689 - Ticket state_id and pending_time attributes won't get synced with new OTRS data. --- lib/import/otrs/state_factory.rb | 65 +++++++++++++++++++ .../import/otrs/state/closed_successful.json | 10 +++ .../otrs/state/closed_unsuccessful.json | 10 +++ spec/fixtures/import/otrs/state/merged.json | 10 +++ spec/fixtures/import/otrs/state/new.json | 10 +++ spec/fixtures/import/otrs/state/open.json | 10 +++ .../otrs/state/pending_auto_close_n.json | 10 +++ .../otrs/state/pending_auto_close_p.json | 10 +++ .../import/otrs/state/pending_reminder.json | 10 +++ spec/fixtures/import/otrs/state/removed.json | 10 +++ spec/import/otrs/state_factory_spec.rb | 37 +++++++++++ 11 files changed, 192 insertions(+) create mode 100644 spec/fixtures/import/otrs/state/closed_successful.json create mode 100644 spec/fixtures/import/otrs/state/closed_unsuccessful.json create mode 100644 spec/fixtures/import/otrs/state/merged.json create mode 100644 spec/fixtures/import/otrs/state/new.json create mode 100644 spec/fixtures/import/otrs/state/open.json create mode 100644 spec/fixtures/import/otrs/state/pending_auto_close_n.json create mode 100644 spec/fixtures/import/otrs/state/pending_auto_close_p.json create mode 100644 spec/fixtures/import/otrs/state/pending_reminder.json create mode 100644 spec/fixtures/import/otrs/state/removed.json diff --git a/lib/import/otrs/state_factory.rb b/lib/import/otrs/state_factory.rb index 6da18c9b1..b19802ae9 100644 --- a/lib/import/otrs/state_factory.rb +++ b/lib/import/otrs/state_factory.rb @@ -17,6 +17,71 @@ module Import state.save } end + + def import_loop(records, *_args, &import_block) + super + update_ticket_state + update_ticket_pending_time + end + + def update_ticket_state + agent_new = ::Ticket::State.where( + state_type_id: ::Ticket::StateType.where.not(name: %w(merged removed)) + ).pluck(:id) + + agent_edit = ::Ticket::State.where( + state_type_id: ::Ticket::StateType.where.not(name: %w(new merged removed)) + ).pluck(:id) + + customer_new = ::Ticket::State.where( + state_type_id: ::Ticket::StateType.where.not(name: %w(new closed)) + ).pluck(:id) + + customer_edit = ::Ticket::State.where( + state_type_id: ::Ticket::StateType.where.not(name: %w(open closed)) + ).pluck(:id) + + ticket_state_id = ::ObjectManager::Attribute.get( + object: 'Ticket', + name: 'state_id', + ) + + ticket_state_id[:data_option][:filter] = agent_new + ticket_state_id[:screens][:create_middle][:Customer] = customer_new + ticket_state_id[:screens][:edit][:Agent] = agent_edit + ticket_state_id[:screens][:edit][:Customer] = customer_edit + + update_ticket_attribute(ticket_state_id) + end + + def update_ticket_pending_time + pending_state_ids = ::Ticket::State.where( + state_type_id: ::Ticket::StateType.where(name: ['pending reminder', 'pending action']) + ).pluck(:id) + + ticket_pending_time = ::ObjectManager::Attribute.get( + object: 'Ticket', + name: 'pending_time', + ) + + ticket_pending_time[:data_option][:required_if][:state_id] = pending_state_ids + ticket_pending_time[:data_option][:required_if][:state_id] = pending_state_ids + + update_ticket_attribute(ticket_pending_time) + end + + def update_ticket_attribute(attribute) + ::ObjectManager::Attribute.add( + object_lookup_id: attribute[:object_lookup_id], + name: attribute[:name], + display: attribute[:display], + data_type: attribute[:data_type], + data_option: attribute[:data_option], + active: attribute[:active], + screens: attribute[:screens], + force: true # otherwise _id as a name is not permitted + ) + end end end end diff --git a/spec/fixtures/import/otrs/state/closed_successful.json b/spec/fixtures/import/otrs/state/closed_successful.json new file mode 100644 index 000000000..5b9ca8f04 --- /dev/null +++ b/spec/fixtures/import/otrs/state/closed_successful.json @@ -0,0 +1,10 @@ +{ + "ChangeTime": "2014-04-28 10:53:18", + "ID": "2", + "ValidID": "1", + "TypeID": "3", + "CreateTime": "2014-04-28 10:53:18", + "TypeName": "closed", + "Comment": "Ticket is closed successful.", + "Name": "closed successful" +} \ No newline at end of file diff --git a/spec/fixtures/import/otrs/state/closed_unsuccessful.json b/spec/fixtures/import/otrs/state/closed_unsuccessful.json new file mode 100644 index 000000000..f32d4a20b --- /dev/null +++ b/spec/fixtures/import/otrs/state/closed_unsuccessful.json @@ -0,0 +1,10 @@ +{ + "ChangeTime": "2014-04-28 10:53:18", + "ID": "3", + "ValidID": "1", + "TypeID": "3", + "CreateTime": "2014-04-28 10:53:18", + "TypeName": "closed", + "Comment": "Ticket is closed unsuccessful.", + "Name": "closed unsuccessful" +} \ No newline at end of file diff --git a/spec/fixtures/import/otrs/state/merged.json b/spec/fixtures/import/otrs/state/merged.json new file mode 100644 index 000000000..05ac43a20 --- /dev/null +++ b/spec/fixtures/import/otrs/state/merged.json @@ -0,0 +1,10 @@ +{ + "ChangeTime": "2014-04-28 10:53:18", + "ID": "9", + "ValidID": "1", + "TypeID": "7", + "CreateTime": "2014-04-28 10:53:18", + "TypeName": "merged", + "Comment": "State for merged tickets.", + "Name": "merged" +} \ No newline at end of file diff --git a/spec/fixtures/import/otrs/state/new.json b/spec/fixtures/import/otrs/state/new.json new file mode 100644 index 000000000..b7a302014 --- /dev/null +++ b/spec/fixtures/import/otrs/state/new.json @@ -0,0 +1,10 @@ +{ + "ChangeTime": "2014-04-28 10:53:18", + "ID": "1", + "ValidID": "1", + "TypeID": "1", + "CreateTime": "2014-04-28 10:53:18", + "TypeName": "new", + "Comment": "New ticket created by customer.", + "Name": "new" +} \ No newline at end of file diff --git a/spec/fixtures/import/otrs/state/open.json b/spec/fixtures/import/otrs/state/open.json new file mode 100644 index 000000000..44242b947 --- /dev/null +++ b/spec/fixtures/import/otrs/state/open.json @@ -0,0 +1,10 @@ +{ + "ChangeTime": "2014-04-28 10:53:18", + "ID": "4", + "ValidID": "1", + "TypeID": "2", + "CreateTime": "2014-04-28 10:53:18", + "TypeName": "open", + "Comment": "Open tickets.", + "Name": "open" +} \ No newline at end of file diff --git a/spec/fixtures/import/otrs/state/pending_auto_close_n.json b/spec/fixtures/import/otrs/state/pending_auto_close_n.json new file mode 100644 index 000000000..ae91bc2d9 --- /dev/null +++ b/spec/fixtures/import/otrs/state/pending_auto_close_n.json @@ -0,0 +1,10 @@ +{ + "ChangeTime": "2014-04-28 10:53:18", + "ID": "8", + "ValidID": "1", + "TypeID": "5", + "CreateTime": "2014-04-28 10:53:18", + "TypeName": "pending auto", + "Comment": "Ticket is pending for automatic close.", + "Name": "pending auto close-" +} \ No newline at end of file diff --git a/spec/fixtures/import/otrs/state/pending_auto_close_p.json b/spec/fixtures/import/otrs/state/pending_auto_close_p.json new file mode 100644 index 000000000..41db2766a --- /dev/null +++ b/spec/fixtures/import/otrs/state/pending_auto_close_p.json @@ -0,0 +1,10 @@ +{ + "ChangeTime": "2014-04-28 10:53:18", + "ID": "7", + "ValidID": "1", + "TypeID": "5", + "CreateTime": "2014-04-28 10:53:18", + "TypeName": "pending auto", + "Comment": "Ticket is pending for automatic close.", + "Name": "pending auto close+" +} \ No newline at end of file diff --git a/spec/fixtures/import/otrs/state/pending_reminder.json b/spec/fixtures/import/otrs/state/pending_reminder.json new file mode 100644 index 000000000..54c6712f4 --- /dev/null +++ b/spec/fixtures/import/otrs/state/pending_reminder.json @@ -0,0 +1,10 @@ +{ + "ChangeTime": "2014-04-28 10:53:18", + "ID": "6", + "ValidID": "1", + "TypeID": "4", + "CreateTime": "2014-04-28 10:53:18", + "TypeName": "pending reminder", + "Comment": "Ticket is pending for agent reminder.", + "Name": "pending reminder" +} \ No newline at end of file diff --git a/spec/fixtures/import/otrs/state/removed.json b/spec/fixtures/import/otrs/state/removed.json new file mode 100644 index 000000000..202aed347 --- /dev/null +++ b/spec/fixtures/import/otrs/state/removed.json @@ -0,0 +1,10 @@ +{ + "ChangeTime": "2014-04-28 10:53:18", + "ID": "5", + "ValidID": "1", + "TypeID": "6", + "CreateTime": "2014-04-28 10:53:18", + "TypeName": "removed", + "Comment": "Customer removed ticket.", + "Name": "removed" +} \ No newline at end of file diff --git a/spec/import/otrs/state_factory_spec.rb b/spec/import/otrs/state_factory_spec.rb index 40764dca7..06a5d8c9f 100644 --- a/spec/import/otrs/state_factory_spec.rb +++ b/spec/import/otrs/state_factory_spec.rb @@ -8,4 +8,41 @@ RSpec.describe Import::OTRS::StateFactory do expect(described_class).to receive(:backup) described_class.pre_import_hook([]) end + + def load_state_json(file) + json_fixture("import/otrs/state/#{file}") + end + + it 'updates ObjectManager Ticket state_id and pending_time filter' do + + states = %w(new open merged pending_reminder pending_auto_close_p pending_auto_close_n pending_auto_close_p closed_successful closed_unsuccessful closed_successful removed) + + state_backend_param = [] + states.each do |state| + state_backend_param.push(load_state_json(state)) + end + + ticket_state_id = ::ObjectManager::Attribute.get( + object: 'Ticket', + name: 'state_id', + ) + ticket_pending_time = ::ObjectManager::Attribute.get( + object: 'Ticket', + name: 'pending_time', + ) + + expect { + described_class.import(state_backend_param) + + # sync changes + ticket_state_id.reload + ticket_pending_time.reload + }.to change { + ticket_state_id.data_option + }.and change { + ticket_state_id.screens + }.and change { + ticket_pending_time.data_option + } + end end From 87336810a87d3ab0147527a876b818dd46f86840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bauer?= Date: Tue, 14 Feb 2017 18:40:19 +0100 Subject: [PATCH 2/3] fix postgresql backup dir permission error --- contrib/backup/functions | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contrib/backup/functions b/contrib/backup/functions index e72d31e4a..ddb529ddf 100644 --- a/contrib/backup/functions +++ b/contrib/backup/functions @@ -42,7 +42,8 @@ function backup_db () { if [ "${DB_ADAPTER}" == "mysql2" ]; then mysqldump --opt --single-transaction -u${DB_USER} -p${DB_PASS} ${DB_NAME} | gzip > ${BACKUP_DIR}/${TIMESTAMP}_zammad_db.mysql.gz elif [ "${DB_ADAPTER}" == "postgresql" ]; then - su -c "pg_dump -c ${DB_NAME} | gzip > ${BACKUP_DIR}/${TIMESTAMP}_zammad_db.psql.gz" postgres + su -c "pg_dump -c ${DB_NAME} | gzip > /tmp/${TIMESTAMP}_zammad_db.psql.gz" postgres + mv /tmp/${TIMESTAMP}_zammad_db.psql.gz ${BACKUP_DIR} else echo "DB ADAPTER not found. if its sqlite backup is already saved in filebackup" fi From ef1da2a22eb7f0134bf0e28bf97761fab72175df Mon Sep 17 00:00:00 2001 From: Thorsten Eckel Date: Tue, 14 Feb 2017 18:44:14 +0100 Subject: [PATCH 3/3] Working on issue #689 - Default states and priorites of OTRS won't get used. --- lib/import/otrs/diff.rb | 7 +++ lib/import/otrs/priority_factory.rb | 26 +++++++++ lib/import/otrs/state_factory.rb | 42 ++++++++++++++ lib/import/otrs/sys_config_factory.rb | 22 +++++++ spec/import/otrs/priority_factory_spec.rb | 28 +++++++++ spec/import/otrs/state_factory_spec.rb | 63 +++++++++++++++++++++ spec/import/otrs/sys_config_factory_spec.rb | 16 ++++++ 7 files changed, 204 insertions(+) diff --git a/lib/import/otrs/diff.rb b/lib/import/otrs/diff.rb index 316457953..40104614b 100644 --- a/lib/import/otrs/diff.rb +++ b/lib/import/otrs/diff.rb @@ -9,6 +9,11 @@ module Import diff end + def diff? + return true if @diff + false + end + private def diff_import_possible? @@ -20,6 +25,8 @@ module Import def diff log 'Start diff...' + @diff = true + check_import_mode updateable_objects diff --git a/lib/import/otrs/priority_factory.rb b/lib/import/otrs/priority_factory.rb index ebd405775..7122dfa8f 100644 --- a/lib/import/otrs/priority_factory.rb +++ b/lib/import/otrs/priority_factory.rb @@ -2,6 +2,32 @@ module Import module OTRS module PriorityFactory extend Import::Factory + + # rubocop:disable Style/ModuleFunction + extend self + + def import_loop(records, *_args, &import_block) + super + update_attribute_settings + end + + def update_attribute_settings + return if Import::OTRS.diff? + update_attribute + end + + def update_attribute + priority = ::Ticket::Priority.find_by( + name: Import::OTRS::SysConfigFactory.postmaster_default_lookup(:priority_default_create), + active: true + ) + return if !priority + + priority.default_create = true + priority.callback_loop = true + + priority.save + end end end end diff --git a/lib/import/otrs/state_factory.rb b/lib/import/otrs/state_factory.rb index b19802ae9..b9dcb9eec 100644 --- a/lib/import/otrs/state_factory.rb +++ b/lib/import/otrs/state_factory.rb @@ -20,6 +20,48 @@ module Import def import_loop(records, *_args, &import_block) super + update_attribute_settings + end + + def update_attribute_settings + return if Import::OTRS.diff? + + update_attribute + update_ticket_attributes + end + + def update_attribute + update_default_create + update_default_follow_up + end + + def update_default_create + state = ::Ticket::State.find_by( + name: Import::OTRS::SysConfigFactory.postmaster_default_lookup(:state_default_create), + active: true + ) + return if !state + + state.default_create = true + state.callback_loop = true + + state.save + end + + def update_default_follow_up + state = ::Ticket::State.find_by( + name: Import::OTRS::SysConfigFactory.postmaster_default_lookup(:state_default_follow_up), + active: true + ) + return if !state + + state.default_follow_up = true + state.callback_loop = true + + state.save + end + + def update_ticket_attributes update_ticket_state update_ticket_pending_time end diff --git a/lib/import/otrs/sys_config_factory.rb b/lib/import/otrs/sys_config_factory.rb index 886dc4d17..a17abbe06 100644 --- a/lib/import/otrs/sys_config_factory.rb +++ b/lib/import/otrs/sys_config_factory.rb @@ -9,9 +9,15 @@ module Import settings.each do |setting| next if direct_copy?(setting) next if number_generator?(setting) + next if postmaster_default?(setting) end end + def postmaster_default_lookup(key) + @postmaster_defaults ||= {} + @postmaster_defaults[key] + end + private def direct_settings @@ -46,6 +52,22 @@ module Import true end + + def postmaster_default?(setting) + + relevant_configs = %w(PostmasterDefaultPriority PostmasterDefaultState PostmasterFollowUpState) + return false if !relevant_configs.include?(setting['Key']) + + map = { + 'PostmasterDefaultPriority' => :priority_default_create, + 'PostmasterDefaultState' => :state_default_create, + 'PostmasterFollowUpState' => :state_default_follow_up, + } + + @postmaster_defaults ||= {} + @postmaster_defaults[ map[setting['Key']] ] = setting['Value'] + true + end end end end diff --git a/spec/import/otrs/priority_factory_spec.rb b/spec/import/otrs/priority_factory_spec.rb index 0f3d82288..54ada125f 100644 --- a/spec/import/otrs/priority_factory_spec.rb +++ b/spec/import/otrs/priority_factory_spec.rb @@ -12,4 +12,32 @@ RSpec.describe Import::OTRS::PriorityFactory do expect(::Import::OTRS::Priority).to receive(:new).with(import_data) described_class.import([import_data]) end + + it 'sets default create Priority' do + priority = ::Ticket::Priority.first + priority.default_create = false + priority.callback_loop = true + priority.save + + expect(Import::OTRS::SysConfigFactory).to receive(:postmaster_default_lookup).with(:priority_default_create).and_return(priority.name) + + described_class.update_attribute_settings + priority.reload + + expect(priority.default_create).to be true + end + + it "doesn't set default create Priority in diff import" do + priority = ::Ticket::Priority.first + priority.default_create = false + priority.callback_loop = true + priority.save + + expect(Import::OTRS).to receive(:diff?).and_return(true) + + described_class.update_attribute_settings + priority.reload + + expect(priority.default_create).to be false + end end diff --git a/spec/import/otrs/state_factory_spec.rb b/spec/import/otrs/state_factory_spec.rb index 06a5d8c9f..3601a6547 100644 --- a/spec/import/otrs/state_factory_spec.rb +++ b/spec/import/otrs/state_factory_spec.rb @@ -1,6 +1,8 @@ require 'rails_helper' require 'import/transaction_factory_examples' +RSpec::Matchers.define_negated_matcher :not_change, :change + RSpec.describe Import::OTRS::StateFactory do it_behaves_like 'Import::TransactionFactory' @@ -45,4 +47,65 @@ RSpec.describe Import::OTRS::StateFactory do ticket_pending_time.data_option } end + + it "doesn't update ObjectManager Ticket state_id and pending_time filter in diff import" do + + ticket_state_id = ::ObjectManager::Attribute.get( + object: 'Ticket', + name: 'state_id', + ) + ticket_pending_time = ::ObjectManager::Attribute.get( + object: 'Ticket', + name: 'pending_time', + ) + + expect(Import::OTRS).to receive(:diff?).and_return(true) + + expect { + described_class.update_attribute_settings + + # sync changes + ticket_state_id.reload + ticket_pending_time.reload + }.to not_change { + ticket_state_id.data_option + }.and not_change { + ticket_state_id.screens + }.and not_change { + ticket_pending_time.data_option + } + end + + it 'sets default create and update State' do + state = ::Ticket::State.first + state.default_create = false + state.default_follow_up = false + state.callback_loop = true + state.save + + expect(Import::OTRS::SysConfigFactory).to receive(:postmaster_default_lookup).with(:state_default_create).and_return(state.name) + expect(Import::OTRS::SysConfigFactory).to receive(:postmaster_default_lookup).with(:state_default_follow_up).and_return(state.name) + + described_class.update_attribute + state.reload + + expect(state.default_create).to be true + expect(state.default_follow_up).to be true + end + + it "doesn't set default create and update State in diff import" do + state = ::Ticket::State.first + state.default_create = false + state.default_follow_up = false + state.callback_loop = true + state.save + + expect(Import::OTRS).to receive(:diff?).and_return(true) + + described_class.update_attribute_settings + state.reload + + expect(state.default_create).to be false + expect(state.default_follow_up).to be false + end end diff --git a/spec/import/otrs/sys_config_factory_spec.rb b/spec/import/otrs/sys_config_factory_spec.rb index 119568af4..cf646cb3b 100644 --- a/spec/import/otrs/sys_config_factory_spec.rb +++ b/spec/import/otrs/sys_config_factory_spec.rb @@ -3,4 +3,20 @@ require 'import/import_factory_examples' RSpec.describe Import::OTRS::SysConfigFactory do it_behaves_like 'Import factory' + + it 'stores default postmaster values' do + + value = 'new' + + settings = [ + { + 'Key' => 'PostmasterDefaultState', + 'Value' => value + } + ] + + described_class.import(settings) + + expect(described_class.postmaster_default_lookup(:state_default_create)).to eq(value) + end end