From c34a407651602bcd044b3b5c7625366cd9a83782 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sun, 7 Feb 2016 14:00:29 +0100 Subject: [PATCH 01/19] Added support of default preferences and implemented agent notifications based on preferences settings. --- app/models/channel/driver/mail_stdin.rb | 4 + .../ticket/notification/background_job.rb | 123 ++++-- app/models/ticket.rb | 6 +- app/models/user.rb | 39 +- config/application.rb | 53 +++ test/unit/ticket_notification_test.rb | 363 ++++++++++++++++++ test/unit/user_test.rb | 57 +++ 7 files changed, 608 insertions(+), 37 deletions(-) diff --git a/app/models/channel/driver/mail_stdin.rb b/app/models/channel/driver/mail_stdin.rb index cdfd250f0..3f6397048 100644 --- a/app/models/channel/driver/mail_stdin.rb +++ b/app/models/channel/driver/mail_stdin.rb @@ -8,6 +8,10 @@ process emails from STDIN cat /path/to/mail.eml | rails r 'Channel::Driver::MailStdin.new' +e. g. + +cat test/fixtures/mail1.box | rails r 'Channel::Driver::MailStdin.new' + =end def initialize diff --git a/app/models/observer/ticket/notification/background_job.rb b/app/models/observer/ticket/notification/background_job.rb index b73b96a27..ce3897579 100644 --- a/app/models/observer/ticket/notification/background_job.rb +++ b/app/models/observer/ticket/notification/background_job.rb @@ -13,7 +13,7 @@ class Observer::Ticket::Notification::BackgroundJob end # find recipients - recipients = [] + recipients_and_channels = [] =begin # group of agents to work on @@ -43,15 +43,68 @@ class Observer::Ticket::Notification::BackgroundJob end =end - if ticket.owner_id != 1 - recipients.push ticket.owner - else - recipients = ticket.agent_of_group() + # loop through all users + possible_recipients = ticket.agent_of_group + if ticket.owner_id == 1 + possible_recipients.push ticket.owner end + already_checked_recipient_ids = {} + possible_recipients.each {|user| + next if already_checked_recipient_ids[user.id] + already_checked_recipient_ids[user.id] = true + next if !user.preferences + next if !user.preferences['notification_config'] + matrix = user.preferences['notification_config']['matrix'] + if ticket.owner_id != user.id + if user.preferences['notification_config']['group_ids'] || + (user.preferences['notification_config']['group_ids'].class == Array && (!user.preferences['notification_config']['group_ids'].empty? || user.preferences['notification_config']['group_ids'][0] != '-')) + hit = false + user.preferences['notification_config']['group_ids'].each {|notify_group_id| + user.group_ids.each {|local_group_id| + if local_group_id.to_s == notify_group_id.to_s + hit = true + end + } + } + next if !hit + end + end + next if !matrix + next if !matrix[@p[:type]] + data = matrix[@p[:type]] + next if !data + next if !data['criteria'] + channels = data['channel'] + if data['criteria']['owned_by_me'] && ticket.owner_id == user.id + data = { + user: user, + channels: channels + } + recipients_and_channels.push data + next + end + if data['criteria']['owned_by_nobody'] && ticket.owner_id == 1 + data = { + user: user, + channels: channels + } + recipients_and_channels.push data + next + end + next unless data['criteria']['no'] + data = { + user: user, + channels: channels + } + recipients_and_channels.push data + next + } # send notifications recipient_list = '' - recipients.each do |user| + recipients_and_channels.each do |item| + user = item[:user] + channels = item[:channels] # ignore user who changed it by him self via web if @via_web @@ -62,32 +115,35 @@ class Observer::Ticket::Notification::BackgroundJob # ignore inactive users next if !user.active - # create online notification - seen = ticket.online_notification_seen_state(user.id) - OnlineNotification.add( - type: @p[:type], - object: 'Ticket', - o_id: ticket.id, - seen: seen, - created_by_id: ticket.updated_by_id || 1, - user_id: user.id, - ) - - # create email notification - next if !user.email || user.email == '' - - # add recipient_list - if recipient_list != '' - recipient_list += ',' - end - recipient_list += user.email.to_s - # ignore if no changes has been done changes = human_changes(user, ticket) - if @p[:type] == 'update' && !article && ( !changes || changes.empty? ) + next if @p[:type] == 'update' && !article && ( !changes || changes.empty? ) + + # create online notification + used_channels = [] + if channels['online'] + used_channels.push 'online' + seen = ticket.online_notification_seen_state(user.id) + OnlineNotification.add( + type: @p[:type], + object: 'Ticket', + o_id: ticket.id, + seen: seen, + created_by_id: ticket.updated_by_id || 1, + user_id: user.id, + ) + Rails.logger.info "send ticket online notifiaction to agent (#{@p[:type]}/#{ticket.id}/#{user.email})" + end + + # ignore email channel notificaiton and empty emails + if !channels['email'] && (!user.email || user.email == '') + add_recipient_list(recipient_list, user, channels) next end + used_channels.push 'email' + recipient_list = add_recipient_list(recipient_list, user, used_channels) + # get user based notification template # if create, send create message / block update messages if @p[:type] == 'create' @@ -113,10 +169,9 @@ class Observer::Ticket::Notification::BackgroundJob } # rebuild subject - notification[:subject] = ticket.subject_build( notification[:subject] ) + notification[:subject] = ticket.subject_build(notification[:subject]) - # send notification - Rails.logger.info "send ticket notifiaction to agent (#{@p[:type]}/#{ticket.id}/#{user.email})" + Rails.logger.info "send ticket email notifiaction to agent (#{@p[:type]}/#{ticket.id}/#{user.email})" NotificationFactory.send( recipient: user, @@ -138,6 +193,14 @@ class Observer::Ticket::Notification::BackgroundJob ) end + def add_recipient_list(recipient_list, user, channels) + return recipient_list if channels.empty? + if recipient_list != '' + recipient_list += ',' + end + recipient_list += "#{user.email}(#{channels.join(',')})" + end + def human_changes(user, record) return {} if !@p[:changes] diff --git a/app/models/ticket.rb b/app/models/ticket.rb index 7477083fb..7141ce12d 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -84,7 +84,11 @@ returns =end def agent_of_group - Group.find( group_id ).users.where( active: true ).joins(:roles).where( 'roles.name' => Z_ROLENAME_AGENT, 'roles.active' => true ).uniq() + Group.find(group_id) + .users.where(active: true) + .joins(:roles) + .where('roles.name' => Z_ROLENAME_AGENT, 'roles.active' => true) + .uniq() end =begin diff --git a/app/models/user.rb b/app/models/user.rb index a2f0c5371..58a22ba2f 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -29,15 +29,15 @@ class User < ApplicationModel include User::Assets extend User::Search - before_create :check_name, :check_email, :check_login, :check_password - before_update :check_password, :check_email, :check_login + before_create :check_name, :check_email, :check_login, :check_password, :check_preferences_default + before_update :check_password, :check_email, :check_login, :check_preferences_default after_create :avatar_for_email_check after_update :avatar_for_email_check after_destroy :avatar_destroy notify_clients_support has_and_belongs_to_many :groups, after_add: :cache_update, after_remove: :cache_update - has_and_belongs_to_many :roles, after_add: :cache_update, after_remove: :cache_update + has_and_belongs_to_many :roles, after_add: [:cache_update, :check_notifications], after_remove: :cache_update has_and_belongs_to_many :organizations, after_add: :cache_update, after_remove: :cache_update has_many :tokens, after_add: :cache_update, after_remove: :cache_update has_many :authorizations, after_add: :cache_update, after_remove: :cache_update @@ -451,7 +451,7 @@ returns list of active users in role - result = User.of_role('Agent') + result = User.of_role('Agent', group_ids) returns @@ -459,9 +459,15 @@ returns =end - def self.of_role(role) + def self.of_role(role, group_ids = nil) roles_ids = Role.where(active: true, name: role).map(&:id) - User.where(active: true).joins(:users_roles).where('roles_users.role_id IN (?)', roles_ids) + if !group_ids + return User.where(active: true).joins(:users_roles).where('roles_users.role_id IN (?)', roles_ids) + end + User.where(active: true) + .joins(:users_roles) + .joins(:users_groups) + .where('roles_users.role_id IN (?) AND users_groups.group_ids IN (?)', roles_ids, group_ids) end private @@ -584,6 +590,13 @@ returns Avatar.remove('User', id) end + def check_preferences_default + return if !@preferences_default + return if @preferences_default.empty? + preferences_tmp = @preferences_default.merge(preferences) + self.preferences = preferences_tmp + end + def check_password # set old password again if not given @@ -605,4 +618,18 @@ returns crypted = Digest::SHA2.hexdigest(password) self.password = "{sha2}#{crypted}" end + + def check_notifications(o) + default = Rails.configuration.preferences_default_by_role + return if !default + default.deep_stringify_keys! + return if !default[o.name] + if !@preferences_default + @preferences_default = {} + end + default[o.name].each {|key, value| + next if @preferences_default[key] + @preferences_default[key] = value + } + end end diff --git a/config/application.rb b/config/application.rb index b5740febf..200fdb37a 100644 --- a/config/application.rb +++ b/config/application.rb @@ -50,5 +50,58 @@ module Zammad # define cache store config.cache_store = :file_store, "tmp/cache_file_store_#{Rails.env}" + # default preferences by role + config.preferences_default_by_role = { + Agent: { + notification_config: { + matrix: { + create: { + criteria: { + owned_by_me: true, + owned_by_nobody: true, + no: false, + }, + channel: { + email: true, + online: true, + } + }, + update: { + criteria: { + owned_by_me: true, + owned_by_nobody: true, + no: false, + }, + channel: { + email: true, + online: true, + } + }, + reminder_reached: { + criteria: { + owned_by_me: true, + owned_by_nobody: true, + no: false, + }, + channel: { + email: true, + online: true, + } + }, + escalation: { + criteria: { + owned_by_me: true, + owned_by_nobody: true, + no: false, + }, + channel: { + email: true, + online: true, + } + } + } + } + } + } end end diff --git a/test/unit/ticket_notification_test.rb b/test/unit/ticket_notification_test.rb index 0bbfb7e42..16a90b494 100644 --- a/test/unit/ticket_notification_test.rb +++ b/test/unit/ticket_notification_test.rb @@ -383,6 +383,369 @@ class TicketNotificationTest < ActiveSupport::TestCase end + test 'ticket notification - z preferences tests' do + + agent1.preferences['notification_config']['matrix']['create']['criteria']['owned_by_me'] = true + agent1.preferences['notification_config']['matrix']['create']['criteria']['owned_by_nobody'] = false + agent1.preferences['notification_config']['matrix']['create']['criteria']['no'] = false + agent1.preferences['notification_config']['matrix']['update']['criteria']['owned_by_me'] = true + agent1.preferences['notification_config']['matrix']['update']['criteria']['owned_by_nobody'] = false + agent1.preferences['notification_config']['matrix']['update']['criteria']['no'] = false + agent1.save + + agent2.preferences['notification_config']['matrix']['create']['criteria']['owned_by_me'] = false + agent2.preferences['notification_config']['matrix']['create']['criteria']['owned_by_nobody'] = false + agent2.preferences['notification_config']['matrix']['create']['criteria']['no'] = true + agent2.preferences['notification_config']['matrix']['update']['criteria']['owned_by_me'] = false + agent2.preferences['notification_config']['matrix']['update']['criteria']['owned_by_nobody'] = false + agent2.preferences['notification_config']['matrix']['update']['criteria']['no'] = true + agent2.save + + # create ticket in group + ticket1 = Ticket.create( + title: 'some notification test - z preferences tests 1', + group: Group.lookup(name: 'Users'), + customer: customer, + state: Ticket::State.lookup(name: 'new'), + priority: Ticket::Priority.lookup(name: '2 normal'), + updated_by_id: customer.id, + created_by_id: customer.id, + ) + Ticket::Article.create( + ticket_id: ticket1.id, + from: 'some_sender@example.com', + to: 'some_recipient@example.com', + subject: 'some subject', + message_id: 'some@id', + body: 'some message', + internal: false, + sender: Ticket::Article::Sender.where(name: 'Customer').first, + type: Ticket::Article::Type.where(name: 'email').first, + updated_by_id: customer.id, + created_by_id: customer.id, + ) + + # execute ticket events + Rails.configuration.webserver_is_active = false + Observer::Ticket::Notification.transaction + #puts Delayed::Job.all.inspect + Delayed::Worker.new.work_off + + # verify notifications to agent1 + agent2 + assert_equal(0, notification_check(ticket1, agent1), ticket1.id) + assert_equal(1, notification_check(ticket1, agent2), ticket1.id) + + # update ticket attributes + ticket1.title = "#{ticket1.title} - #2" + ticket1.priority = Ticket::Priority.lookup(name: '3 high') + ticket1.save + + # execute ticket events + Observer::Ticket::Notification.transaction + #puts Delayed::Job.all.inspect + Delayed::Worker.new.work_off + + # verify notifications to agent1 + agent2 + assert_equal(0, notification_check(ticket1, agent1), ticket1.id) + assert_equal(2, notification_check(ticket1, agent2), ticket1.id) + + # create ticket in group + ticket2 = Ticket.create( + title: 'some notification test - z preferences tests 2', + group: Group.lookup(name: 'Users'), + customer: customer, + owner: agent1, + state: Ticket::State.lookup(name: 'new'), + priority: Ticket::Priority.lookup(name: '2 normal'), + updated_by_id: customer.id, + created_by_id: customer.id, + ) + Ticket::Article.create( + ticket_id: ticket2.id, + from: 'some_sender@example.com', + to: 'some_recipient@example.com', + subject: 'some subject', + message_id: 'some@id', + body: 'some message', + internal: false, + sender: Ticket::Article::Sender.where(name: 'Customer').first, + type: Ticket::Article::Type.where(name: 'email').first, + updated_by_id: customer.id, + created_by_id: customer.id, + ) + + # execute ticket events + Observer::Ticket::Notification.transaction + #puts Delayed::Job.all.inspect + Delayed::Worker.new.work_off + + # verify notifications to agent1 + agent2 + assert_equal(1, notification_check(ticket2, agent1), ticket2.id) + assert_equal(1, notification_check(ticket2, agent2), ticket2.id) + + # update ticket attributes + ticket2.title = "#{ticket2.title} - #2" + ticket2.priority = Ticket::Priority.lookup(name: '3 high') + ticket2.save + + # execute ticket events + Observer::Ticket::Notification.transaction + #puts Delayed::Job.all.inspect + Delayed::Worker.new.work_off + + # verify notifications to agent1 + agent2 + assert_equal(2, notification_check(ticket2, agent1), ticket2.id) + assert_equal(2, notification_check(ticket2, agent2), ticket2.id) + + # create ticket in group + ticket3 = Ticket.create( + title: 'some notification test - z preferences tests 3', + group: Group.lookup(name: 'Users'), + customer: customer, + owner: agent2, + state: Ticket::State.lookup(name: 'new'), + priority: Ticket::Priority.lookup(name: '2 normal'), + updated_by_id: customer.id, + created_by_id: customer.id, + ) + Ticket::Article.create( + ticket_id: ticket3.id, + from: 'some_sender@example.com', + to: 'some_recipient@example.com', + subject: 'some subject', + message_id: 'some@id', + body: 'some message', + internal: false, + sender: Ticket::Article::Sender.where(name: 'Customer').first, + type: Ticket::Article::Type.where(name: 'email').first, + updated_by_id: customer.id, + created_by_id: customer.id, + ) + + # execute ticket events + Observer::Ticket::Notification.transaction + #puts Delayed::Job.all.inspect + Delayed::Worker.new.work_off + + # verify notifications to agent1 + agent2 + assert_equal(0, notification_check(ticket3, agent1), ticket3.id) + assert_equal(1, notification_check(ticket3, agent2), ticket3.id) + + # update ticket attributes + ticket3.title = "#{ticket3.title} - #2" + ticket3.priority = Ticket::Priority.lookup(name: '3 high') + ticket3.save + + # execute ticket events + Observer::Ticket::Notification.transaction + #puts Delayed::Job.all.inspect + Delayed::Worker.new.work_off + + # verify notifications to agent1 + agent2 + assert_equal(0, notification_check(ticket3, agent1), ticket3.id) + assert_equal(2, notification_check(ticket3, agent2), ticket3.id) + + agent1.preferences['notification_config']['matrix']['create']['criteria']['owned_by_me'] = true + agent1.preferences['notification_config']['matrix']['create']['criteria']['owned_by_nobody'] = false + agent1.preferences['notification_config']['matrix']['create']['criteria']['no'] = true + agent1.preferences['notification_config']['matrix']['update']['criteria']['owned_by_me'] = true + agent1.preferences['notification_config']['matrix']['update']['criteria']['owned_by_nobody'] = false + agent1.preferences['notification_config']['matrix']['update']['criteria']['no'] = true + agent1.preferences['notification_config']['group_ids'] = [Group.lookup(name: 'Users').id.to_s] + agent1.save + + agent2.preferences['notification_config']['matrix']['create']['criteria']['owned_by_me'] = false + agent2.preferences['notification_config']['matrix']['create']['criteria']['owned_by_nobody'] = false + agent2.preferences['notification_config']['matrix']['create']['criteria']['no'] = true + agent2.preferences['notification_config']['matrix']['update']['criteria']['owned_by_me'] = false + agent2.preferences['notification_config']['matrix']['update']['criteria']['owned_by_nobody'] = false + agent2.preferences['notification_config']['matrix']['update']['criteria']['no'] = true + agent1.preferences['notification_config']['group_ids'] = ['-'] + agent2.save + + # create ticket in group + ticket4 = Ticket.create( + title: 'some notification test - z preferences tests 4', + group: Group.lookup(name: 'Users'), + customer: customer, + state: Ticket::State.lookup(name: 'new'), + priority: Ticket::Priority.lookup(name: '2 normal'), + updated_by_id: customer.id, + created_by_id: customer.id, + ) + Ticket::Article.create( + ticket_id: ticket4.id, + from: 'some_sender@example.com', + to: 'some_recipient@example.com', + subject: 'some subject', + message_id: 'some@id', + body: 'some message', + internal: false, + sender: Ticket::Article::Sender.where(name: 'Customer').first, + type: Ticket::Article::Type.where(name: 'email').first, + updated_by_id: customer.id, + created_by_id: customer.id, + ) + + # execute ticket events + Rails.configuration.webserver_is_active = false + Observer::Ticket::Notification.transaction + #puts Delayed::Job.all.inspect + Delayed::Worker.new.work_off + + # verify notifications to agent1 + agent2 + assert_equal(1, notification_check(ticket4, agent1), ticket4.id) + assert_equal(1, notification_check(ticket4, agent2), ticket4.id) + + # update ticket attributes + ticket4.title = "#{ticket4.title} - #2" + ticket4.priority = Ticket::Priority.lookup(name: '3 high') + ticket4.save + + # execute ticket events + Observer::Ticket::Notification.transaction + #puts Delayed::Job.all.inspect + Delayed::Worker.new.work_off + + # verify notifications to agent1 + agent2 + assert_equal(2, notification_check(ticket4, agent1), ticket4.id) + assert_equal(2, notification_check(ticket4, agent2), ticket4.id) + + agent1.preferences['notification_config']['matrix']['create']['criteria']['owned_by_me'] = true + agent1.preferences['notification_config']['matrix']['create']['criteria']['owned_by_nobody'] = false + agent1.preferences['notification_config']['matrix']['create']['criteria']['no'] = true + agent1.preferences['notification_config']['matrix']['update']['criteria']['owned_by_me'] = true + agent1.preferences['notification_config']['matrix']['update']['criteria']['owned_by_nobody'] = false + agent1.preferences['notification_config']['matrix']['update']['criteria']['no'] = true + agent1.preferences['notification_config']['group_ids'] = [Group.lookup(name: 'Users').id.to_s] + agent1.save + + agent2.preferences['notification_config']['matrix']['create']['criteria']['owned_by_me'] = false + agent2.preferences['notification_config']['matrix']['create']['criteria']['owned_by_nobody'] = false + agent2.preferences['notification_config']['matrix']['create']['criteria']['no'] = true + agent2.preferences['notification_config']['matrix']['update']['criteria']['owned_by_me'] = false + agent2.preferences['notification_config']['matrix']['update']['criteria']['owned_by_nobody'] = false + agent2.preferences['notification_config']['matrix']['update']['criteria']['no'] = true + agent2.preferences['notification_config']['group_ids'] = [99] + agent2.save + + # create ticket in group + ticket5 = Ticket.create( + title: 'some notification test - z preferences tests 5', + group: Group.lookup(name: 'Users'), + customer: customer, + state: Ticket::State.lookup(name: 'new'), + priority: Ticket::Priority.lookup(name: '2 normal'), + updated_by_id: customer.id, + created_by_id: customer.id, + ) + Ticket::Article.create( + ticket_id: ticket5.id, + from: 'some_sender@example.com', + to: 'some_recipient@example.com', + subject: 'some subject', + message_id: 'some@id', + body: 'some message', + internal: false, + sender: Ticket::Article::Sender.where(name: 'Customer').first, + type: Ticket::Article::Type.where(name: 'email').first, + updated_by_id: customer.id, + created_by_id: customer.id, + ) + + # execute ticket events + Rails.configuration.webserver_is_active = false + Observer::Ticket::Notification.transaction + #puts Delayed::Job.all.inspect + Delayed::Worker.new.work_off + + # verify notifications to agent1 + agent2 + assert_equal(1, notification_check(ticket5, agent1), ticket5.id) + assert_equal(0, notification_check(ticket5, agent2), ticket5.id) + + # update ticket attributes + ticket5.title = "#{ticket5.title} - #2" + ticket5.priority = Ticket::Priority.lookup(name: '3 high') + ticket5.save + + # execute ticket events + Observer::Ticket::Notification.transaction + #puts Delayed::Job.all.inspect + Delayed::Worker.new.work_off + + # verify notifications to agent1 + agent2 + assert_equal(2, notification_check(ticket5, agent1), ticket5.id) + assert_equal(0, notification_check(ticket5, agent2), ticket5.id) + + agent1.preferences['notification_config']['matrix']['create']['criteria']['owned_by_me'] = true + agent1.preferences['notification_config']['matrix']['create']['criteria']['owned_by_nobody'] = false + agent1.preferences['notification_config']['matrix']['create']['criteria']['no'] = true + agent1.preferences['notification_config']['matrix']['update']['criteria']['owned_by_me'] = true + agent1.preferences['notification_config']['matrix']['update']['criteria']['owned_by_nobody'] = false + agent1.preferences['notification_config']['matrix']['update']['criteria']['no'] = true + agent1.preferences['notification_config']['group_ids'] = [999] + agent1.save + + agent2.preferences['notification_config']['matrix']['create']['criteria']['owned_by_me'] = true + agent2.preferences['notification_config']['matrix']['create']['criteria']['owned_by_nobody'] = false + agent2.preferences['notification_config']['matrix']['create']['criteria']['no'] = true + agent2.preferences['notification_config']['matrix']['update']['criteria']['owned_by_me'] = true + agent2.preferences['notification_config']['matrix']['update']['criteria']['owned_by_nobody'] = false + agent2.preferences['notification_config']['matrix']['update']['criteria']['no'] = true + agent2.preferences['notification_config']['group_ids'] = [999] + agent2.save + + # create ticket in group + ticket6 = Ticket.create( + title: 'some notification test - z preferences tests 6', + group: Group.lookup(name: 'Users'), + customer: customer, + owner: agent1, + state: Ticket::State.lookup(name: 'new'), + priority: Ticket::Priority.lookup(name: '2 normal'), + updated_by_id: customer.id, + created_by_id: customer.id, + ) + Ticket::Article.create( + ticket_id: ticket6.id, + from: 'some_sender@example.com', + to: 'some_recipient@example.com', + subject: 'some subject', + message_id: 'some@id', + body: 'some message', + internal: false, + sender: Ticket::Article::Sender.where(name: 'Customer').first, + type: Ticket::Article::Type.where(name: 'email').first, + updated_by_id: customer.id, + created_by_id: customer.id, + ) + + # execute ticket events + Rails.configuration.webserver_is_active = false + Observer::Ticket::Notification.transaction + #puts Delayed::Job.all.inspect + Delayed::Worker.new.work_off + + # verify notifications to agent1 + agent2 + assert_equal(1, notification_check(ticket6, agent1), ticket6.id) + assert_equal(0, notification_check(ticket6, agent2), ticket6.id) + + # update ticket attributes + ticket6.title = "#{ticket6.title} - #2" + ticket6.priority = Ticket::Priority.lookup(name: '3 high') + ticket6.save + + # execute ticket events + Observer::Ticket::Notification.transaction + #puts Delayed::Job.all.inspect + Delayed::Worker.new.work_off + + # verify notifications to agent1 + agent2 + assert_equal(2, notification_check(ticket6, agent1), ticket6.id) + assert_equal(0, notification_check(ticket6, agent2), ticket6.id) + + end + test 'ticket notification events' do # create ticket in group diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb index a23afd6e0..1c4a1437f 100644 --- a/test/unit/user_test.rb +++ b/test/unit/user_test.rb @@ -287,4 +287,61 @@ class UserTest < ActiveSupport::TestCase user.destroy } end + + test 'user default preferences' do + groups = Group.where(name: 'Users') + roles = Role.where(name: 'Agent') + agent1 = User.create_or_update( + login: 'agent-default-preferences1@example.com', + firstname: 'Preferences', + lastname: 'Agent1', + email: 'agent-default-preferences1@example.com', + password: 'agentpw', + active: true, + roles: roles, + groups: groups, + preferences: { + locale: 'de-de', + }, + updated_by_id: 1, + created_by_id: 1, + ) + assert(agent1.preferences) + assert(agent1.preferences['locale']) + assert_equal(agent1.preferences['locale'], 'de-de') + assert(agent1.preferences['notification_config']) + assert(agent1.preferences['notification_config']['matrix']) + assert(agent1.preferences['notification_config']['matrix']['create']) + assert(agent1.preferences['notification_config']['matrix']['update']) + + roles = Role.where(name: 'Customer') + customer1 = User.create_or_update( + login: 'customer-default-preferences1@example.com', + firstname: 'Preferences', + lastname: 'Customer1', + email: 'customer-default-preferences1@example.com', + password: 'customerpw', + active: true, + roles: roles, + preferences: { + locale: 'de-de', + }, + updated_by_id: 1, + created_by_id: 1, + ) + assert(customer1.preferences) + assert(customer1.preferences['locale']) + assert_equal(customer1.preferences['locale'], 'de-de') + assert_not(customer1.preferences['notification_config']) + + customer1.roles = Role.where(name: 'Agent') + assert(customer1.preferences) + assert(customer1.preferences['locale']) + assert_equal(customer1.preferences['locale'], 'de-de') + assert(customer1.preferences['notification_config']) + assert(customer1.preferences['notification_config']['matrix']['create']) + assert(customer1.preferences['notification_config']['matrix']['update']) + + end + end From cbac73f1ef3edc9ca77215ff268226c355f465a0 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sun, 7 Feb 2016 14:13:37 +0100 Subject: [PATCH 02/19] Save record after new role assignment. --- test/unit/user_test.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb index 1c4a1437f..1c23ee0b8 100644 --- a/test/unit/user_test.rb +++ b/test/unit/user_test.rb @@ -335,6 +335,7 @@ class UserTest < ActiveSupport::TestCase assert_not(customer1.preferences['notification_config']) customer1.roles = Role.where(name: 'Agent') + customer1.save assert(customer1.preferences) assert(customer1.preferences['locale']) assert_equal(customer1.preferences['locale'], 'de-de') From ea640474a3004d280775d702a94e9b5042687a77 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sun, 7 Feb 2016 16:17:45 +0100 Subject: [PATCH 03/19] Merged migrations. --- db/migrate/20120101000010_create_ticket.rb | 1 + db/migrate/20150971000001_update_settings4.rb | 6 ++--- db/migrate/20151109000001_create_chat.rb | 19 ++++++++++++++ db/migrate/20151210000001_update_chat4.rb | 25 ------------------- ...0151213000001_update_ticket_preferences.rb | 5 ---- 5 files changed, 23 insertions(+), 33 deletions(-) delete mode 100644 db/migrate/20151210000001_update_chat4.rb delete mode 100644 db/migrate/20151213000001_update_ticket_preferences.rb diff --git a/db/migrate/20120101000010_create_ticket.rb b/db/migrate/20120101000010_create_ticket.rb index 5485d7eac..2c0912898 100644 --- a/db/migrate/20120101000010_create_ticket.rb +++ b/db/migrate/20120101000010_create_ticket.rb @@ -63,6 +63,7 @@ class CreateTicket < ActiveRecord::Migration t.column :escalation_time, :timestamp, null: true t.column :pending_time, :timestamp, null: true t.column :type, :string, limit: 100, null: true + t.column :preferences, :text, limit: 500.kilobytes + 1, null: true t.column :updated_by_id, :integer, null: false t.column :created_by_id, :integer, null: false t.timestamps null: false diff --git a/db/migrate/20150971000001_update_settings4.rb b/db/migrate/20150971000001_update_settings4.rb index 7011961a7..37f10480f 100644 --- a/db/migrate/20150971000001_update_settings4.rb +++ b/db/migrate/20150971000001_update_settings4.rb @@ -60,9 +60,9 @@ class UpdateSettings4 < ActiveRecord::Migration name: 'ticket_hook_position', tag: 'select', options: { - 'left' => 'Left', - 'right' => 'Right', - 'none' => 'None', + 'left' => 'left', + 'right' => 'right', + 'none' => 'none', }, }, ], diff --git a/db/migrate/20151109000001_create_chat.rb b/db/migrate/20151109000001_create_chat.rb index 50d856c3d..716a5bbef 100644 --- a/db/migrate/20151109000001_create_chat.rb +++ b/db/migrate/20151109000001_create_chat.rb @@ -77,6 +77,25 @@ class CreateChat < ActiveRecord::Migration created_by_id: 1, ) + Scheduler.create_or_update( + name: 'Closed chat sessions where participients are offline.', + method: 'Chat.cleanup_close', + period: 60 * 15, + prio: 2, + active: true, + updated_by_id: 1, + created_by_id: 1, + ) + Scheduler.create_or_update( + name: 'Cleanup closed sessions.', + method: 'Chat.cleanup', + period: 5.days, + prio: 2, + active: true, + updated_by_id: 1, + created_by_id: 1, + ) + end def down diff --git a/db/migrate/20151210000001_update_chat4.rb b/db/migrate/20151210000001_update_chat4.rb deleted file mode 100644 index 0abdcc321..000000000 --- a/db/migrate/20151210000001_update_chat4.rb +++ /dev/null @@ -1,25 +0,0 @@ -class UpdateChat4 < ActiveRecord::Migration - def up - Scheduler.create_or_update( - name: 'Closed chat sessions where participients are offline.', - method: 'Chat.cleanup_close', - period: 60 * 15, - prio: 2, - active: true, - updated_by_id: 1, - created_by_id: 1, - ) - Scheduler.create_or_update( - name: 'Cleanup closed sessions.', - method: 'Chat.cleanup', - period: 5.days, - prio: 2, - active: true, - updated_by_id: 1, - created_by_id: 1, - ) - end - - def down - end -end diff --git a/db/migrate/20151213000001_update_ticket_preferences.rb b/db/migrate/20151213000001_update_ticket_preferences.rb deleted file mode 100644 index 24da07c97..000000000 --- a/db/migrate/20151213000001_update_ticket_preferences.rb +++ /dev/null @@ -1,5 +0,0 @@ -class UpdateTicketPreferences < ActiveRecord::Migration - def up - add_column :tickets, :preferences, :text, limit: 500.kilobytes + 1, null: true - end -end From 372e185dc0ba3b8ea8b928cf2e65434cbf3401e6 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sun, 7 Feb 2016 16:36:10 +0100 Subject: [PATCH 04/19] Added check if binary was written correctly. --- app/models/store/file.rb | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/app/models/store/file.rb b/app/models/store/file.rb index 6654e58b7..4004f703e 100644 --- a/app/models/store/file.rb +++ b/app/models/store/file.rb @@ -11,9 +11,13 @@ add new file to store store_file_id = Store::File.add(binary_data) +do also verify of written data + + store_file_id = Store::File.add(binary_data, true) + =end - def self.add(data) + def self.add(data, verify = true) sha = Digest::SHA256.hexdigest(data) file = Store::File.find_by(sha: sha) @@ -30,6 +34,15 @@ add new file to store provider: adapter_name, sha: sha, ) + + # verify + if verify + read_data = adapter.get(sha) + read_sha = Digest::SHA256.hexdigest(read_data) + if sha != read_sha + fail "Content not written correctly (provider #{adapter_name})." + end + end end file end From a304744b3ffecbb9b634dc7e3eefeb2b4ae41cf1 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sun, 7 Feb 2016 16:53:21 +0100 Subject: [PATCH 05/19] Split each notification recipient into one record. --- .../ticket/notification/background_job.rb | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/app/models/observer/ticket/notification/background_job.rb b/app/models/observer/ticket/notification/background_job.rb index ce3897579..837950b2d 100644 --- a/app/models/observer/ticket/notification/background_job.rb +++ b/app/models/observer/ticket/notification/background_job.rb @@ -137,12 +137,12 @@ class Observer::Ticket::Notification::BackgroundJob # ignore email channel notificaiton and empty emails if !channels['email'] && (!user.email || user.email == '') - add_recipient_list(recipient_list, user, channels) + add_recipient_list(ticket, user, used_channels) next end used_channels.push 'email' - recipient_list = add_recipient_list(recipient_list, user, used_channels) + add_recipient_list(ticket, user, used_channels) # get user based notification template # if create, send create message / block update messages @@ -181,9 +181,11 @@ class Observer::Ticket::Notification::BackgroundJob ) end - # add history record - return if recipient_list == '' + end + def add_recipient_list(ticket, user, channels) + return if channels.empty? + recipient_list = "#{user.email}(#{channels.join(',')})" History.add( o_id: ticket.id, history_type: 'notification', @@ -193,14 +195,6 @@ class Observer::Ticket::Notification::BackgroundJob ) end - def add_recipient_list(recipient_list, user, channels) - return recipient_list if channels.empty? - if recipient_list != '' - recipient_list += ',' - end - recipient_list += "#{user.email}(#{channels.join(',')})" - end - def human_changes(user, record) return {} if !@p[:changes] From 1aee8eef09f4473581ac391a950c9ae99832591b Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sun, 7 Feb 2016 17:17:27 +0100 Subject: [PATCH 06/19] Improved stored user identifier. --- app/models/observer/ticket/notification/background_job.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/models/observer/ticket/notification/background_job.rb b/app/models/observer/ticket/notification/background_job.rb index 837950b2d..84d459235 100644 --- a/app/models/observer/ticket/notification/background_job.rb +++ b/app/models/observer/ticket/notification/background_job.rb @@ -185,7 +185,11 @@ class Observer::Ticket::Notification::BackgroundJob def add_recipient_list(ticket, user, channels) return if channels.empty? - recipient_list = "#{user.email}(#{channels.join(',')})" + identifier = user.email + if !identifier && identifier == '' + identifier = user.login + end + recipient_list = "#{identifier}(#{channels.join(',')})" History.add( o_id: ticket.id, history_type: 'notification', From 4f7474ac7a9a9814174378924971d2919be740ab Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sun, 7 Feb 2016 17:18:07 +0100 Subject: [PATCH 07/19] Replaced IO.read with IO.binread. --- test/integration/elasticsearch_test.rb | 8 +-- test/unit/email_parser_test.rb | 68 +++++++++++++------------- test/unit/email_process_bounce_test.rb | 2 +- test/unit/email_process_test.rb | 14 +++--- test/unit/store_test.rb | 4 +- 5 files changed, 48 insertions(+), 48 deletions(-) diff --git a/test/integration/elasticsearch_test.rb b/test/integration/elasticsearch_test.rb index 22cc132c7..5878bbcd2 100644 --- a/test/integration/elasticsearch_test.rb +++ b/test/integration/elasticsearch_test.rb @@ -124,7 +124,7 @@ class ElasticsearchTest < ActiveSupport::TestCase Store.add( object: 'Ticket::Article', o_id: article1.id, - data: IO.read("#{Rails.root}/test/fixtures/es-normal.txt"), + data: IO.binread("#{Rails.root}/test/fixtures/es-normal.txt"), filename: 'es-normal.txt', preferences: {}, created_by_id: 1, @@ -135,7 +135,7 @@ class ElasticsearchTest < ActiveSupport::TestCase Store.add( object: 'Ticket::Article', o_id: article1.id, - data: IO.read("#{Rails.root}/test/fixtures/es-pdf1.pdf"), + data: IO.binread("#{Rails.root}/test/fixtures/es-pdf1.pdf"), filename: 'es-pdf1.pdf', preferences: {}, created_by_id: 1, @@ -146,7 +146,7 @@ class ElasticsearchTest < ActiveSupport::TestCase Store.add( object: 'Ticket::Article', o_id: article1.id, - data: IO.read("#{Rails.root}/test/fixtures/es-box1.box"), + data: IO.binread("#{Rails.root}/test/fixtures/es-box1.box"), filename: 'mail1.box', preferences: {}, created_by_id: 1, @@ -157,7 +157,7 @@ class ElasticsearchTest < ActiveSupport::TestCase Store.add( object: 'Ticket::Article', o_id: article1.id, - data: IO.read("#{Rails.root}/test/fixtures/es-too-big.txt"), + data: IO.binread("#{Rails.root}/test/fixtures/es-too-big.txt"), filename: 'es-too-big.txt', preferences: {}, created_by_id: 1, diff --git a/test/unit/email_parser_test.rb b/test/unit/email_parser_test.rb index 953954a8b..e0894da86 100644 --- a/test/unit/email_parser_test.rb +++ b/test/unit/email_parser_test.rb @@ -6,7 +6,7 @@ class EmailParserTest < ActiveSupport::TestCase test 'parse' do files = [ { - data: IO.read('test/fixtures/mail1.box'), + data: IO.binread('test/fixtures/mail1.box'), body_md5: 'b57d21dcac6b05e1aa67af51a9e4c1ec', params: { from: 'John.Smith@example.com', @@ -16,7 +16,7 @@ class EmailParserTest < ActiveSupport::TestCase }, }, { - data: IO.read('test/fixtures/mail2.box'), + data: IO.binread('test/fixtures/mail2.box'), body_md5: '154c7d3ae7b94f99589df62882841b08', params: { from: 'Martin Edenhofer ', @@ -34,7 +34,7 @@ Old programmers never die. They just branch to a new address. }, }, { - data: IO.read('test/fixtures/mail3.box'), + data: IO.binread('test/fixtures/mail3.box'), body_md5: '96a0a7847c1c60e82058db8f8bff8136', params: { from: '"Günther John | Example GmbH" ', @@ -44,7 +44,7 @@ Old programmers never die. They just branch to a new address. }, }, { - data: IO.read('test/fixtures/mail4.box'), + data: IO.binread('test/fixtures/mail4.box'), body_md5: '9fab9a0e8523011fde0f3ecd80f8d72c', params: { from: '"Günther Katja | Example GmbH" ', @@ -75,7 +75,7 @@ Liebe Grüße! }, }, { - data: IO.read('test/fixtures/mail5.box'), + data: IO.binread('test/fixtures/mail5.box'), body_md5: 'f34033e9a34bb5367062dd5df21115df', params: { from: 'marc.smith@example.com (Marc Smith)', @@ -85,7 +85,7 @@ Liebe Grüße! }, }, { - data: IO.read('test/fixtures/mail6.box'), + data: IO.binread('test/fixtures/mail6.box'), body_md5: '683ac042e94e99a8bb5e8ced7893b1d7', params: { from: '"Hans BÄKOSchönland" ', @@ -108,7 +108,7 @@ Test5:= }, }, { - data: IO.read('test/fixtures/mail7.box'), + data: IO.binread('test/fixtures/mail7.box'), body_md5: 'c78f6a91905538ee32bc0bf71f70fcf2', params: { from: 'Eike.Ehringer@example.com', @@ -148,7 +148,7 @@ Managing Director: Martin Edenhofer", }, }, { - data: IO.read('test/fixtures/mail8.box'), + data: IO.binread('test/fixtures/mail8.box'), body_md5: 'ca502c70a1b006f5184d1f0bf79d5799', attachments: [ { @@ -188,7 +188,7 @@ Hof }, }, { - data: IO.read('test/fixtures/mail9.box'), + data: IO.binread('test/fixtures/mail9.box'), body_md5: 'c70de14cc69b17b07850b570d7a4fbe7', attachments: [ { @@ -209,7 +209,7 @@ Hof }, }, { - data: IO.read('test/fixtures/mail10.box'), + data: IO.binread('test/fixtures/mail10.box'), body_md5: 'ddfad696bd34d83f607763180243f3c5', attachments: [ { @@ -230,7 +230,7 @@ Hof }, }, { - data: IO.read('test/fixtures/mail11.box'), + data: IO.binread('test/fixtures/mail11.box'), body_md5: 'cf8b26d9fc4ce9abb19a36ce3a130c79', attachments: [ { @@ -247,7 +247,7 @@ Hof }, }, { - data: IO.read('test/fixtures/mail12.box'), + data: IO.binread('test/fixtures/mail12.box'), body_md5: '8b48e082bc77e927d395448875259172', attachments: [ { @@ -268,7 +268,7 @@ Hof }, }, { - data: IO.read('test/fixtures/mail13.box'), + data: IO.binread('test/fixtures/mail13.box'), body_md5: '58806e006b14b04a535784a5462d09b0', attachments: [ { @@ -285,7 +285,7 @@ Hof }, }, { - data: IO.read('test/fixtures/mail14.box'), + data: IO.binread('test/fixtures/mail14.box'), body_md5: '154c7d3ae7b94f99589df62882841b08', attachments: [ { @@ -307,7 +307,7 @@ Hof }, # spam email { - data: IO.read('test/fixtures/mail15.box'), + data: IO.binread('test/fixtures/mail15.box'), body_md5: '5872ddcdfdf6bfe40f36cd0408fca667', attachments: [ # :preferences=>{"Message-ID"=>"", "Content-Type"=>"application/octet-stream; name=\"\xBC\xA8\xD0\xA7\xB9\xDC\xC0\xED,\xBE\xBF\xBE\xB9\xCB\xAD\xB4\xED\xC1\xCB.xls\"", "Mime-Type"=>"application/octet-stream", "Charset"=>"UTF-8"}} @@ -327,7 +327,7 @@ Hof }, # spam email { - data: IO.read('test/fixtures/mail16.box'), + data: IO.binread('test/fixtures/mail16.box'), body_md5: '91e698a1ba3679dff398ba3587b3f3d9', params: { from: nil, @@ -339,7 +339,7 @@ Hof }, # spam email { - data: IO.read('test/fixtures/mail17.box'), + data: IO.binread('test/fixtures/mail17.box'), body_md5: 'c32d6502f47435e613a2112625118270', params: { from: '"都琹" ', @@ -350,7 +350,7 @@ Hof }, }, { - data: IO.read('test/fixtures/mail18.box'), + data: IO.binread('test/fixtures/mail18.box'), body_md5: '66f20e8557095762ccad9a6cb6f59c3a', params: { from: 'postmaster@example.com', @@ -361,7 +361,7 @@ Hof }, }, { - data: IO.read('test/fixtures/mail19.box'), + data: IO.binread('test/fixtures/mail19.box'), body_md5: '0bf7e746158d121bce7e2c46b64b0d39', params: { from: '"我" <>', @@ -372,7 +372,7 @@ Hof }, }, { - data: IO.read('test/fixtures/mail20.box'), + data: IO.binread('test/fixtures/mail20.box'), body_md5: 'ddcbbb850491ae9a174c4f1e42309f84', params: { from: 'Health and Care-Mall ', @@ -413,7 +413,7 @@ Wade to give it seemed like this. Yeah but one for any longer. Everything you go }, }, { - data: IO.read('test/fixtures/mail21.box'), + data: IO.binread('test/fixtures/mail21.box'), body_md5: 'c9fb828072385643e528ab3a9ce7f10c', params: { from: 'Viagra Super Force Online ', @@ -424,7 +424,7 @@ Wade to give it seemed like this. Yeah but one for any longer. Everything you go }, }, { - data: IO.read('test/fixtures/mail22.box'), + data: IO.binread('test/fixtures/mail22.box'), body_md5: '7dd64b40dce1aa3053fc7bbdea136612', params: { from: 'Gilbertina Suthar ', @@ -454,7 +454,7 @@ Freemont and pulling out several minutes. }, { - data: IO.read('test/fixtures/mail23.box'), + data: IO.binread('test/fixtures/mail23.box'), body_md5: '545a1b067fd10ac636c20b44f5df8868', params: { from: 'marketingmanager@nthcpghana.com', @@ -465,7 +465,7 @@ Freemont and pulling out several minutes. }, }, { - data: IO.read('test/fixtures/mail24.box'), + data: IO.binread('test/fixtures/mail24.box'), body_md5: '5872ddcdfdf6bfe40f36cd0408fca667', params: { from: 'oracle@IG0-1-DB01.example.com', @@ -486,7 +486,7 @@ Freemont and pulling out several minutes. ], }, { - data: IO.read('test/fixtures/mail25.box'), + data: IO.binread('test/fixtures/mail25.box'), body_md5: '436f71d8d8a4ffbd3f18fc9de7d7f767', params: { from: 'oracle@IG0-1-DB01.example.com', @@ -504,7 +504,7 @@ end }, }, { - data: IO.read('test/fixtures/mail26.box'), + data: IO.binread('test/fixtures/mail26.box'), body_md5: 'c68fd31c71a463c7ea820ccdf672c680', params: { from: 'gate ', @@ -534,7 +534,7 @@ gate GmbH * Gladbacher Str. 74 * 40219 Düsseldorf ], }, { - data: IO.read('test/fixtures/mail27.box'), + data: IO.binread('test/fixtures/mail27.box'), body_md5: 'd41d8cd98f00b204e9800998ecf8427e', params: { from: 'caoyaoewfzfw@21cn.com', @@ -552,7 +552,7 @@ gate GmbH * Gladbacher Str. 74 * 40219 Düsseldorf ], }, { - data: IO.read('test/fixtures/mail28.box'), + data: IO.binread('test/fixtures/mail28.box'), body_md5: '5872ddcdfdf6bfe40f36cd0408fca667', params: { from: 'kontakt@example.de', @@ -574,7 +574,7 @@ gate GmbH * Gladbacher Str. 74 * 40219 Düsseldorf ], }, { - data: IO.read('test/fixtures/mail29.box'), + data: IO.binread('test/fixtures/mail29.box'), body_md5: 'bd34701dd5246b7651f67aeea6dd0fd3', params: { from: 'Example Sales ', @@ -605,7 +605,7 @@ Registration AG Ulm HRB 534075 * General Manager Holger Felgner }, }, { - data: IO.read('test/fixtures/mail30.box'), + data: IO.binread('test/fixtures/mail30.box'), body_md5: 'b4038e70d25854a023bce604c9f7a7ff', params: { from: 'Manfred Haert ', @@ -651,7 +651,7 @@ Weil wir die Echtheit oder Vollständigkeit der in dieser Nachricht enthaltenen }, }, { - data: IO.read('test/fixtures/mail31.box'), + data: IO.binread('test/fixtures/mail31.box'), body_md5: '10484f3b096e85e7001da387c18871d5', params: { from: '"bertha mou" ', @@ -662,7 +662,7 @@ Weil wir die Echtheit oder Vollständigkeit der in dieser Nachricht enthaltenen }, }, { - data: IO.read('test/fixtures/mail32.box'), + data: IO.binread('test/fixtures/mail32.box'), body_md5: '6bed82e0d079e521f506e4e5d3529107', params: { from: '"Dana.Qin" ', @@ -673,7 +673,7 @@ Weil wir die Echtheit oder Vollständigkeit der in dieser Nachricht enthaltenen }, }, { - data: IO.read('test/fixtures/mail34.box'), + data: IO.binread('test/fixtures/mail34.box'), body_md5: 'b6e46176404ec81b3ab412fe71dff0f0', params: { from: 'Bay ', @@ -685,7 +685,7 @@ Weil wir die Echtheit oder Vollständigkeit der in dieser Nachricht enthaltenen }, }, { - data: IO.read('test/fixtures/mail36.box'), + data: IO.binread('test/fixtures/mail36.box'), body_md5: '428327fb533b387b3efca181ae0c25d0', params: { from: 'Martin Smith ', diff --git a/test/unit/email_process_bounce_test.rb b/test/unit/email_process_bounce_test.rb index d8aac65f7..a7cac1293 100644 --- a/test/unit/email_process_bounce_test.rb +++ b/test/unit/email_process_bounce_test.rb @@ -28,7 +28,7 @@ class EmailProcessBounceTest < ActiveSupport::TestCase created_by_id: 1, ) sleep 1 - email_raw_string = IO.read('test/fixtures/mail33-undelivered-mail-returned-to-sender.box') + email_raw_string = IO.binread('test/fixtures/mail33-undelivered-mail-returned-to-sender.box') ticket_p, article_p, user_p = Channel::EmailParser.new.process( {}, email_raw_string) assert_equal(ticket.id, ticket_p.id) assert_equal('new', ticket_p.state.name) diff --git a/test/unit/email_process_test.rb b/test/unit/email_process_test.rb index 26aca33b4..4df8d6dae 100644 --- a/test/unit/email_process_test.rb +++ b/test/unit/email_process_test.rb @@ -131,7 +131,7 @@ Some Text", }, }, { - data: IO.read('test/fixtures/mail21.box'), + data: IO.binread('test/fixtures/mail21.box'), success: true, result: { 0 => { @@ -184,7 +184,7 @@ ___ }, }, { - data: IO.read('test/fixtures/mail22.box'), + data: IO.binread('test/fixtures/mail22.box'), success: true, result: { 0 => { @@ -217,7 +217,7 @@ Freemont and pulling out several minutes. }, }, { - data: IO.read('test/fixtures/mail23.box'), + data: IO.binread('test/fixtures/mail23.box'), success: true, result: { 0 => { @@ -1870,7 +1870,7 @@ Some Text', } }, { - data: IO.read('test/fixtures/mail30.box'), + data: IO.binread('test/fixtures/mail30.box'), success: true, result: { 0 => { @@ -1906,7 +1906,7 @@ Some Text', } }, { - data: IO.read('test/fixtures/mail31.box'), + data: IO.binread('test/fixtures/mail31.box'), success: true, result: { 0 => { @@ -1930,7 +1930,7 @@ Some Text', } }, { - data: IO.read('test/fixtures/mail32.box'), + data: IO.binread('test/fixtures/mail32.box'), success: true, result: { 0 => { @@ -1954,7 +1954,7 @@ Some Text', } }, { - data: IO.read('test/fixtures/mail35.box'), + data: IO.binread('test/fixtures/mail35.box'), success: true, result: { 0 => { diff --git a/test/unit/store_test.rb b/test/unit/store_test.rb index e409a6143..d810c3a35 100644 --- a/test/unit/store_test.rb +++ b/test/unit/store_test.rb @@ -15,12 +15,12 @@ class StoreTest < ActiveSupport::TestCase o_id: 2, }, { - data: IO.read('test/fixtures/test1.pdf'), + data: IO.binread('test/fixtures/test1.pdf'), filename: 'test.pdf', o_id: 3, }, { - data: IO.read('test/fixtures/test1.pdf'), + data: IO.binread('test/fixtures/test1.pdf'), filename: 'test-again.pdf', o_id: 4, }, From 21dcfda82c97f40229518e337b00ce3d7d250653 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sun, 7 Feb 2016 17:18:40 +0100 Subject: [PATCH 08/19] Fixed oder after migration got merged. --- test/integration/zendesk_import_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/zendesk_import_test.rb b/test/integration/zendesk_import_test.rb index 8082abea1..e27fefb81 100644 --- a/test/integration/zendesk_import_test.rb +++ b/test/integration/zendesk_import_test.rb @@ -459,11 +459,11 @@ class ZendeskImportTest < ActiveSupport::TestCase escalation_time pending_time type + preferences updated_by_id created_by_id created_at - updated_at - preferences) + updated_at) assert_equal( copmare_fields, local_fields, 'ticket fields' ) end From 73f27f48ae27fe6a8a6ad7f5b8b20e9994dd3722 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sun, 7 Feb 2016 18:46:44 +0100 Subject: [PATCH 09/19] Improved error handling. --- lib/sessions/backend/ticket_overview_list.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/sessions/backend/ticket_overview_list.rb b/lib/sessions/backend/ticket_overview_list.rb index 04ee027db..7b14aede7 100644 --- a/lib/sessions/backend/ticket_overview_list.rb +++ b/lib/sessions/backend/ticket_overview_list.rb @@ -14,6 +14,7 @@ class Sessions::Backend::TicketOverviewList overviews = Ticket::Overviews.all( current_user: @user, ) + return if !overviews result = [] overviews.each { |overview| overview_data = Ticket::Overviews.list( From 06e9a6abbe16d698a453172ab60ba4b244a50e0d Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sun, 7 Feb 2016 21:42:48 +0100 Subject: [PATCH 10/19] Improved search description. --- .../app/controllers/_dashboard/first_steps_clues.coffee | 2 +- app/assets/javascripts/app/controllers/dashboard.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/app/controllers/_dashboard/first_steps_clues.coffee b/app/assets/javascripts/app/controllers/_dashboard/first_steps_clues.coffee index 970be7da8..d02bcb764 100644 --- a/app/assets/javascripts/app/controllers/_dashboard/first_steps_clues.coffee +++ b/app/assets/javascripts/app/controllers/_dashboard/first_steps_clues.coffee @@ -11,7 +11,7 @@ class App.FirstStepsClues extends App.Controller { container: '.search-holder' headline: 'Search' - text: 'Here you can search for ticket, customers and organizations. To find everything use the §*§-Placeholder' + text: 'Here you can search for ticket, customers and organizations. You can use the §*§-Placeholder as wildcard. E. g. §smi*§ or §rosent*l§. You also can use ||double quotes|| for searching phrases §"some phrase"§.' } { container: '.user-menu' diff --git a/app/assets/javascripts/app/controllers/dashboard.coffee b/app/assets/javascripts/app/controllers/dashboard.coffee index 606a9f3dd..4152ecc58 100644 --- a/app/assets/javascripts/app/controllers/dashboard.coffee +++ b/app/assets/javascripts/app/controllers/dashboard.coffee @@ -2,7 +2,7 @@ class App.Dashboard extends App.Controller clueAccess: true events: 'click .tabs .tab': 'toggle' - 'click .intro': 'clues' + 'click .js-intro': 'clues' constructor: -> super From cbbf34c2711aa7e5127c175eadfb732929394a0d Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sun, 7 Feb 2016 21:53:47 +0100 Subject: [PATCH 11/19] Improved inline markup. --- app/assets/javascripts/app/lib/app_post/i18n.coffee | 3 ++- public/assets/tests/core.js | 10 ++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/app/lib/app_post/i18n.coffee b/app/assets/javascripts/app/lib/app_post/i18n.coffee index 6183be418..a754c0ade 100644 --- a/app/assets/javascripts/app/lib/app_post/i18n.coffee +++ b/app/assets/javascripts/app/lib/app_post/i18n.coffee @@ -186,7 +186,8 @@ class _i18nSingleton extends Spine.Module # apply inline markup translated - .replace(/\*(.+?)\*/gm, '$1') + .replace(/\|\|(.+?)\|\|/gm, '$1') + .replace(/\|(.+?)\|/gm, '$1') .replace(/_(.+?)_/gm, '$1') .replace(/§(.+?)§/gm, '$1') diff --git a/public/assets/tests/core.js b/public/assets/tests/core.js index a42c514a6..110f66947 100644 --- a/public/assets/tests/core.js +++ b/public/assets/tests/core.js @@ -274,9 +274,12 @@ test( "i18n", function() { translated = App.i18n.translateContent('%s %s test', 123, 'xxx'); equal( translated, '123 xxx test', 'de-de - %s %s' ); - translated = App.i18n.translateContent('*%s* %s test', 123, 'xxx'); + translated = App.i18n.translateContent('|%s| %s test', 123, 'xxx'); equal( translated, '123 xxx test', 'de-de - *%s* %s' ); + translated = App.i18n.translateContent('||%s|| %s test', 123, 'xxx'); + equal( translated, '123 xxx test', 'de-de - *%s* %s' ); + translated = App.i18n.translateContent('_%s_ %s test', 123, 'xxx'); equal( translated, '123 xxx test', 'de-de - _%s_ %s' ); @@ -311,9 +314,12 @@ test( "i18n", function() { translated = App.i18n.translateContent('%s %s test', 123, 'xxx'); equal( translated, '123 xxx test', 'en-us - %s %s' ); - translated = App.i18n.translateContent('*%s* %s test', 123, 'xxx'); + translated = App.i18n.translateContent('|%s| %s test', 123, 'xxx'); equal( translated, '123 xxx test', 'en-us - *%s* %s' ); + translated = App.i18n.translateContent('||%s|| %s test', 123, 'xxx'); + equal( translated, '123 xxx test', 'en-us - *%s* %s' ); + translated = App.i18n.translateContent('_%s_ %s test', 123, 'xxx'); equal( translated, '123 xxx test', 'en-us - _%s_ %s' ); From 405be366479881864db17dbe6c87ed7a422ca709 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Mon, 8 Feb 2016 06:57:54 +0100 Subject: [PATCH 12/19] Improved shown information. --- .../controllers/_profile/notification.coffee | 74 +++++++------------ .../app/views/profile/notification.jst.eco | 2 +- 2 files changed, 28 insertions(+), 48 deletions(-) diff --git a/app/assets/javascripts/app/controllers/_profile/notification.coffee b/app/assets/javascripts/app/controllers/_profile/notification.coffee index 51588ee29..4169e3f7e 100644 --- a/app/assets/javascripts/app/controllers/_profile/notification.coffee +++ b/app/assets/javascripts/app/controllers/_profile/notification.coffee @@ -11,56 +11,37 @@ class Index extends App.Controller render: => # matrix - config = {} - config['matrix'] = {} - config['matrix']['create'] = {} - config['matrix']['create']['name'] = 'new Ticket' - config['matrix']['create']['criteria'] = {} - config['matrix']['create']['criteria']['owned_by_me'] = true - config['matrix']['create']['criteria']['owned_by_nobody'] = true - config['matrix']['create']['criteria']['no'] = false - config['matrix']['create']['channel'] = {} - config['matrix']['create']['channel']['email'] = true - config['matrix']['create']['channel']['online'] = false - config['matrix']['update'] = {} - config['matrix']['update']['name'] = 'Ticket update' - config['matrix']['update']['criteria'] = {} - config['matrix']['update']['criteria']['owned_by_me'] = true - config['matrix']['update']['criteria']['owned_by_nobody'] = false - config['matrix']['update']['criteria']['no'] = false - config['matrix']['update']['channel'] = {} - config['matrix']['update']['channel']['email'] = true - config['matrix']['update']['channel']['online'] = false - config['matrix']['move_into'] = {} - config['matrix']['move_into']['name'] = 'Ticket moved into my group' - config['matrix']['move_into']['criteria'] = {} - config['matrix']['move_into']['criteria']['owned_by_me'] = true - config['matrix']['move_into']['criteria']['owned_by_nobody'] = true - config['matrix']['move_into']['criteria']['no'] = false - config['matrix']['move_into']['channel'] = {} - config['matrix']['move_into']['channel']['email'] = true - config['matrix']['move_into']['channel']['online'] = false - config['matrix']['escalation'] = {} - config['matrix']['escalation']['name'] = 'Ticket escalation' - config['matrix']['escalation']['criteria'] = {} - config['matrix']['escalation']['criteria']['owned_by_me'] = true - config['matrix']['escalation']['criteria']['owned_by_nobody'] = true - config['matrix']['escalation']['criteria']['no'] = false - config['matrix']['escalation']['channel'] = {} - config['matrix']['escalation']['channel']['email'] = true - config['matrix']['escalation']['channel']['online'] = false + config = + group_ids: [] + matrix: + create: + name: 'new Ticket' + update: + name: 'Ticket update' + reminder_reached: + name: 'Ticket reminder reached' + escalation: + name: 'Ticket escalation' user_config = @Session.get('preferences').notification_config if user_config config = $.extend(true, {}, config, user_config) - console.log('oo', config) + # groups + user_group_config = true + if !user_config || !user_config['group_ids'] || _.isEmpty(user_config['group_ids']) || user_config['group_ids'][0] is '-' + user_group_config = false + groups = [] group_ids = @Session.get('group_ids') if group_ids for group_id in group_ids group = App.Group.find(group_id) groups.push group + if !user_group_config + if !config['group_ids'] + config['group_ids'] = [] + config['group_ids'].push group_id.toString() @html App.view('profile/notification')( groups: groups, config: config ) @@ -72,7 +53,6 @@ class Index extends App.Controller params.notification_config = {} form_params = @formParam(e.target) - console.log('P',form_params) for key, value of form_params if key is 'group_ids' if typeof value isnt 'object' @@ -110,8 +90,8 @@ class Index extends App.Controller email: true online: false } - console.log('P2',params) - + if !params.notification_config.group_ids || _.isEmpty(params.notification_config.group_ids) + params.notification_config.group_ids = ['-'] @formDisable(e) # get data @@ -127,12 +107,12 @@ class Index extends App.Controller success: (data, status, xhr) => App.User.full( - App.Session.get( 'id' ), + App.Session.get('id'), => - App.Event.trigger( 'ui:rerender' ) + App.Event.trigger('ui:rerender') @notify( type: 'success' - msg: App.i18n.translateContent( 'Successfully!' ) + msg: App.i18n.translateContent('Successfully!') ) , true @@ -140,10 +120,10 @@ class Index extends App.Controller error: (xhr, status, error) => @render() - data = JSON.parse( xhr.responseText ) + data = JSON.parse(xhr.responseText) @notify( type: 'error' - msg: App.i18n.translateContent( data.message ) + msg: App.i18n.translateContent(data.message) ) App.Config.set( 'Notifications', { prio: 2600, name: 'Notifications', parent: '#profile', target: '#profile/notifications', role: ['Agent'], controller: Index }, 'NavBarProfile' ) diff --git a/app/assets/javascripts/app/views/profile/notification.jst.eco b/app/assets/javascripts/app/views/profile/notification.jst.eco index d2db68717..158d6db69 100644 --- a/app/assets/javascripts/app/views/profile/notification.jst.eco +++ b/app/assets/javascripts/app/views/profile/notification.jst.eco @@ -31,7 +31,7 @@

<%- @T( 'Groups' ) %>

- + <%- @T('For "owned by nobody" and "no criteria" only notify about tickets in theres groups.') %>
<% if @groups: %> From f7bfad14eb818cbe97bb48837803a2c2ddb091d5 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Mon, 8 Feb 2016 06:58:28 +0100 Subject: [PATCH 13/19] Fixed identifier condition. --- app/models/observer/ticket/notification/background_job.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/observer/ticket/notification/background_job.rb b/app/models/observer/ticket/notification/background_job.rb index 84d459235..82ea495b4 100644 --- a/app/models/observer/ticket/notification/background_job.rb +++ b/app/models/observer/ticket/notification/background_job.rb @@ -186,7 +186,7 @@ class Observer::Ticket::Notification::BackgroundJob def add_recipient_list(ticket, user, channels) return if channels.empty? identifier = user.email - if !identifier && identifier == '' + if !identifier || identifier == '' identifier = user.login end recipient_list = "#{identifier}(#{channels.join(',')})" From 6569aed25925911be5228b9d8e1581bea7710ea7 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Mon, 8 Feb 2016 06:59:10 +0100 Subject: [PATCH 14/19] Moved large screen breakpoint from 1280 to 1260 px. --- app/assets/stylesheets/zammad.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/zammad.scss b/app/assets/stylesheets/zammad.scss index ed02c37bd..48c036d46 100644 --- a/app/assets/stylesheets/zammad.scss +++ b/app/assets/stylesheets/zammad.scss @@ -15,7 +15,7 @@ $navigationWidth: 260px; $highlight-color: hsl(205,90%,60%); -$largeScreenBreakpoint: 1280px; +$largeScreenBreakpoint: 1260px; html { height: 100%; From c13dcac0f12ec6059be6974bb8f5bc170e39ce32 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Mon, 8 Feb 2016 08:12:04 +0100 Subject: [PATCH 15/19] Added migration to update default preferences. --- app/models/user.rb | 63 +++++++++++++------ ...160208000001_update_default_preferences.rb | 5 ++ 2 files changed, 48 insertions(+), 20 deletions(-) create mode 100644 db/migrate/20160208000001_update_default_preferences.rb diff --git a/app/models/user.rb b/app/models/user.rb index 58a22ba2f..5b49f7017 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -470,6 +470,49 @@ returns .where('roles_users.role_id IN (?) AND users_groups.group_ids IN (?)', roles_ids, group_ids) end +=begin + +update/sync default preferences of users in a dedecated role + + result = User.update_default_preferences('Agent') + +returns + + result = true # false + +=end + + def self.update_default_preferences(role_name) + role = Role.lookup(name: role_name) + User.of_role(role_name).each {|user| + user.check_notifications(role) + user.check_preferences_default + user.save + } + true + end + + def check_notifications(o) + default = Rails.configuration.preferences_default_by_role + return if !default + default.deep_stringify_keys! + return if !default[o.name] + if !@preferences_default + @preferences_default = {} + end + default[o.name].each {|key, value| + next if @preferences_default[key] + @preferences_default[key] = value + } + end + + def check_preferences_default + return if !@preferences_default + return if @preferences_default.empty? + preferences_tmp = @preferences_default.merge(preferences) + self.preferences = preferences_tmp + end + private def cache_delete @@ -590,13 +633,6 @@ returns Avatar.remove('User', id) end - def check_preferences_default - return if !@preferences_default - return if @preferences_default.empty? - preferences_tmp = @preferences_default.merge(preferences) - self.preferences = preferences_tmp - end - def check_password # set old password again if not given @@ -619,17 +655,4 @@ returns self.password = "{sha2}#{crypted}" end - def check_notifications(o) - default = Rails.configuration.preferences_default_by_role - return if !default - default.deep_stringify_keys! - return if !default[o.name] - if !@preferences_default - @preferences_default = {} - end - default[o.name].each {|key, value| - next if @preferences_default[key] - @preferences_default[key] = value - } - end end diff --git a/db/migrate/20160208000001_update_default_preferences.rb b/db/migrate/20160208000001_update_default_preferences.rb new file mode 100644 index 000000000..d7f3760db --- /dev/null +++ b/db/migrate/20160208000001_update_default_preferences.rb @@ -0,0 +1,5 @@ +class UpdateDefaultPreferences < ActiveRecord::Migration + def up + User.update_default_preferences('Agent') + end +end From e2ba5ac5761b2a6fd7e17c1808b5d8ce08349c27 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Mon, 8 Feb 2016 08:25:27 +0100 Subject: [PATCH 16/19] Updated preferences_default_by_role. --- config/application.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/application.rb b/config/application.rb index 200fdb37a..b599993a4 100644 --- a/config/application.rb +++ b/config/application.rb @@ -80,7 +80,7 @@ module Zammad reminder_reached: { criteria: { owned_by_me: true, - owned_by_nobody: true, + owned_by_nobody: false, no: false, }, channel: { @@ -91,7 +91,7 @@ module Zammad escalation: { criteria: { owned_by_me: true, - owned_by_nobody: true, + owned_by_nobody: false, no: false, }, channel: { From 52dc82bff9177bdd362a13441b251af79d1007d7 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Mon, 8 Feb 2016 08:27:02 +0100 Subject: [PATCH 17/19] Added order bei login for ticket.agent_of_group. --- app/models/ticket.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/ticket.rb b/app/models/ticket.rb index 7141ce12d..c7358446d 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -88,6 +88,7 @@ returns .users.where(active: true) .joins(:roles) .where('roles.name' => Z_ROLENAME_AGENT, 'roles.active' => true) + .order('users.login') .uniq() end From f7652d7f6c1930b53eb7d2342564045ccc2eff49 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Mon, 8 Feb 2016 08:30:38 +0100 Subject: [PATCH 18/19] Fixed channel selection. --- .../javascripts/app/controllers/_profile/notification.coffee | 2 +- app/assets/javascripts/app/views/profile/notification.jst.eco | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/app/controllers/_profile/notification.coffee b/app/assets/javascripts/app/controllers/_profile/notification.coffee index 4169e3f7e..d3cfd56f8 100644 --- a/app/assets/javascripts/app/controllers/_profile/notification.coffee +++ b/app/assets/javascripts/app/controllers/_profile/notification.coffee @@ -88,7 +88,7 @@ class Index extends App.Controller else params.notification_config[area[0]][area[1]][area[2]] = { email: true - online: false + online: true } if !params.notification_config.group_ids || _.isEmpty(params.notification_config.group_ids) params.notification_config.group_ids = ['-'] diff --git a/app/assets/javascripts/app/views/profile/notification.jst.eco b/app/assets/javascripts/app/views/profile/notification.jst.eco index 158d6db69..c0f5e363c 100644 --- a/app/assets/javascripts/app/views/profile/notification.jst.eco +++ b/app/assets/javascripts/app/views/profile/notification.jst.eco @@ -22,7 +22,7 @@ - + <% end %> <% end %> From 9193e836cd67cb4bf45aa0f0e2e0367aab07462b Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Mon, 8 Feb 2016 12:01:32 +0100 Subject: [PATCH 19/19] Fixed online/email channel selection on notification. --- .../ticket/notification/background_job.rb | 2 +- test/unit/ticket_notification_test.rb | 186 +++++++++++++----- 2 files changed, 136 insertions(+), 52 deletions(-) diff --git a/app/models/observer/ticket/notification/background_job.rb b/app/models/observer/ticket/notification/background_job.rb index 82ea495b4..2f93161e7 100644 --- a/app/models/observer/ticket/notification/background_job.rb +++ b/app/models/observer/ticket/notification/background_job.rb @@ -136,7 +136,7 @@ class Observer::Ticket::Notification::BackgroundJob end # ignore email channel notificaiton and empty emails - if !channels['email'] && (!user.email || user.email == '') + if !channels['email'] || !user.email || user.email == '' add_recipient_list(ticket, user, used_channels) next end diff --git a/test/unit/ticket_notification_test.rb b/test/unit/ticket_notification_test.rb index 16a90b494..4eb878893 100644 --- a/test/unit/ticket_notification_test.rb +++ b/test/unit/ticket_notification_test.rb @@ -92,8 +92,8 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications to agent1 + agent2 - assert_equal(1, notification_check(ticket1, agent1), ticket1.id) - assert_equal(1, notification_check(ticket1, agent2), ticket1.id) + assert_equal(1, notification_check(ticket1, agent1, 'email'), ticket1.id) + assert_equal(1, notification_check(ticket1, agent2, 'email'), ticket1.id) # create ticket in group ticket1 = Ticket.create( @@ -127,8 +127,8 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications to agent1 + agent2 - assert_equal(0, notification_check(ticket1, agent1), ticket1.id) - assert_equal(1, notification_check(ticket1, agent2), ticket1.id) + assert_equal(0, notification_check(ticket1, agent1, 'email'), ticket1.id) + assert_equal(1, notification_check(ticket1, agent2, 'email'), ticket1.id) end test 'ticket notification - simple' do @@ -165,8 +165,8 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications to agent1 + agent2 - assert_equal(1, notification_check(ticket1, agent1), ticket1.id) - assert_equal(1, notification_check(ticket1, agent2), ticket1.id) + assert_equal(1, notification_check(ticket1, agent1, 'email'), ticket1.id) + assert_equal(1, notification_check(ticket1, agent2, 'email'), ticket1.id) # update ticket attributes ticket1.title = "#{ticket1.title} - #2" @@ -179,8 +179,8 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications to agent1 + agent2 - assert_equal(2, notification_check(ticket1, agent1), ticket1.id) - assert_equal(2, notification_check(ticket1, agent2), ticket1.id) + assert_equal(2, notification_check(ticket1, agent1, 'email'), ticket1.id) + assert_equal(2, notification_check(ticket1, agent2, 'email'), ticket1.id) # add article to ticket Ticket::Article.create( @@ -201,8 +201,8 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications to not to agent1 but to agent2 - assert_equal(2, notification_check(ticket1, agent1), ticket1.id) - assert_equal(3, notification_check(ticket1, agent2), ticket1.id) + assert_equal(2, notification_check(ticket1, agent1, 'email'), ticket1.id) + assert_equal(3, notification_check(ticket1, agent2, 'email'), ticket1.id) # update ticket by user ticket1.owner_id = agent1.id @@ -226,8 +226,8 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications to not to agent1 but to agent2 - assert_equal(2, notification_check(ticket1, agent1), ticket1.id) - assert_equal(3, notification_check(ticket1, agent2), ticket1.id) + assert_equal(2, notification_check(ticket1, agent1, 'email'), ticket1.id) + assert_equal(3, notification_check(ticket1, agent2, 'email'), ticket1.id) # create ticket with agent1 as owner ticket2 = Ticket.create( @@ -261,8 +261,8 @@ class TicketNotificationTest < ActiveSupport::TestCase assert(ticket2, 'ticket created') # verify notifications to no one - assert_equal(0, notification_check(ticket2, agent1), ticket2.id) - assert_equal(0, notification_check(ticket2, agent2), ticket2.id) + assert_equal(0, notification_check(ticket2, agent1, 'email'), ticket2.id) + assert_equal(0, notification_check(ticket2, agent2, 'email'), ticket2.id) # update ticket ticket2.title = "#{ticket2.title} - #2" @@ -276,8 +276,8 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications to no one - assert_equal(0, notification_check(ticket2, agent1), ticket2.id) - assert_equal(0, notification_check(ticket2, agent2), ticket2.id) + assert_equal(0, notification_check(ticket2, agent1, 'email'), ticket2.id) + assert_equal(0, notification_check(ticket2, agent2, 'email'), ticket2.id) # update ticket ticket2.title = "#{ticket2.title} - #3" @@ -291,8 +291,8 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications to agent1 and not to agent2 - assert_equal(1, notification_check(ticket2, agent1), ticket2.id) - assert_equal(0, notification_check(ticket2, agent2), ticket2.id) + assert_equal(1, notification_check(ticket2, agent1, 'email'), ticket2.id) + assert_equal(0, notification_check(ticket2, agent2, 'email'), ticket2.id) # create ticket with agent2 and agent1 as owner ticket3 = Ticket.create( @@ -326,8 +326,8 @@ class TicketNotificationTest < ActiveSupport::TestCase assert(ticket3, 'ticket created') # verify notifications to agent1 and not to agent2 - assert_equal(1, notification_check(ticket3, agent1), ticket3.id) - assert_equal(0, notification_check(ticket3, agent2), ticket3.id) + assert_equal(1, notification_check(ticket3, agent1, 'email'), ticket3.id) + assert_equal(0, notification_check(ticket3, agent2, 'email'), ticket3.id) # update ticket ticket3.title = "#{ticket3.title} - #2" @@ -341,8 +341,8 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications to no one - assert_equal(1, notification_check(ticket3, agent1), ticket3.id) - assert_equal(0, notification_check(ticket3, agent2), ticket3.id) + assert_equal(1, notification_check(ticket3, agent1, 'email'), ticket3.id) + assert_equal(0, notification_check(ticket3, agent2, 'email'), ticket3.id) # update ticket ticket3.title = "#{ticket3.title} - #3" @@ -356,8 +356,8 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications to agent1 and not to agent2 - assert_equal(2, notification_check(ticket3, agent1), ticket3.id) - assert_equal(0, notification_check(ticket3, agent2), ticket3.id) + assert_equal(2, notification_check(ticket3, agent1, 'email'), ticket3.id) + assert_equal(0, notification_check(ticket3, agent2, 'email'), ticket3.id) # update article / not notification should be sent article_inbound.internal = true @@ -369,8 +369,8 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications not to agent1 and not to agent2 - assert_equal(2, notification_check(ticket3, agent1), ticket3.id) - assert_equal(0, notification_check(ticket3, agent2), ticket3.id) + assert_equal(2, notification_check(ticket3, agent1, 'email'), ticket3.id) + assert_equal(0, notification_check(ticket3, agent2, 'email'), ticket3.id) delete = ticket1.destroy assert(delete, 'ticket1 destroy') @@ -432,8 +432,8 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications to agent1 + agent2 - assert_equal(0, notification_check(ticket1, agent1), ticket1.id) - assert_equal(1, notification_check(ticket1, agent2), ticket1.id) + assert_equal(0, notification_check(ticket1, agent1, 'email'), ticket1.id) + assert_equal(1, notification_check(ticket1, agent2, 'email'), ticket1.id) # update ticket attributes ticket1.title = "#{ticket1.title} - #2" @@ -446,8 +446,8 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications to agent1 + agent2 - assert_equal(0, notification_check(ticket1, agent1), ticket1.id) - assert_equal(2, notification_check(ticket1, agent2), ticket1.id) + assert_equal(0, notification_check(ticket1, agent1, 'email'), ticket1.id) + assert_equal(2, notification_check(ticket1, agent2, 'email'), ticket1.id) # create ticket in group ticket2 = Ticket.create( @@ -480,8 +480,8 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications to agent1 + agent2 - assert_equal(1, notification_check(ticket2, agent1), ticket2.id) - assert_equal(1, notification_check(ticket2, agent2), ticket2.id) + assert_equal(1, notification_check(ticket2, agent1, 'email'), ticket2.id) + assert_equal(1, notification_check(ticket2, agent2, 'email'), ticket2.id) # update ticket attributes ticket2.title = "#{ticket2.title} - #2" @@ -494,8 +494,8 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications to agent1 + agent2 - assert_equal(2, notification_check(ticket2, agent1), ticket2.id) - assert_equal(2, notification_check(ticket2, agent2), ticket2.id) + assert_equal(2, notification_check(ticket2, agent1, 'email'), ticket2.id) + assert_equal(2, notification_check(ticket2, agent2, 'email'), ticket2.id) # create ticket in group ticket3 = Ticket.create( @@ -528,8 +528,8 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications to agent1 + agent2 - assert_equal(0, notification_check(ticket3, agent1), ticket3.id) - assert_equal(1, notification_check(ticket3, agent2), ticket3.id) + assert_equal(0, notification_check(ticket3, agent1, 'email'), ticket3.id) + assert_equal(1, notification_check(ticket3, agent2, 'email'), ticket3.id) # update ticket attributes ticket3.title = "#{ticket3.title} - #2" @@ -542,8 +542,8 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications to agent1 + agent2 - assert_equal(0, notification_check(ticket3, agent1), ticket3.id) - assert_equal(2, notification_check(ticket3, agent2), ticket3.id) + assert_equal(0, notification_check(ticket3, agent1, 'email'), ticket3.id) + assert_equal(2, notification_check(ticket3, agent2, 'email'), ticket3.id) agent1.preferences['notification_config']['matrix']['create']['criteria']['owned_by_me'] = true agent1.preferences['notification_config']['matrix']['create']['criteria']['owned_by_nobody'] = false @@ -594,8 +594,8 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications to agent1 + agent2 - assert_equal(1, notification_check(ticket4, agent1), ticket4.id) - assert_equal(1, notification_check(ticket4, agent2), ticket4.id) + assert_equal(1, notification_check(ticket4, agent1, 'email'), ticket4.id) + assert_equal(1, notification_check(ticket4, agent2, 'email'), ticket4.id) # update ticket attributes ticket4.title = "#{ticket4.title} - #2" @@ -608,8 +608,8 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications to agent1 + agent2 - assert_equal(2, notification_check(ticket4, agent1), ticket4.id) - assert_equal(2, notification_check(ticket4, agent2), ticket4.id) + assert_equal(2, notification_check(ticket4, agent1, 'email'), ticket4.id) + assert_equal(2, notification_check(ticket4, agent2, 'email'), ticket4.id) agent1.preferences['notification_config']['matrix']['create']['criteria']['owned_by_me'] = true agent1.preferences['notification_config']['matrix']['create']['criteria']['owned_by_nobody'] = false @@ -660,8 +660,8 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications to agent1 + agent2 - assert_equal(1, notification_check(ticket5, agent1), ticket5.id) - assert_equal(0, notification_check(ticket5, agent2), ticket5.id) + assert_equal(1, notification_check(ticket5, agent1, 'email'), ticket5.id) + assert_equal(0, notification_check(ticket5, agent2, 'email'), ticket5.id) # update ticket attributes ticket5.title = "#{ticket5.title} - #2" @@ -674,8 +674,8 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications to agent1 + agent2 - assert_equal(2, notification_check(ticket5, agent1), ticket5.id) - assert_equal(0, notification_check(ticket5, agent2), ticket5.id) + assert_equal(2, notification_check(ticket5, agent1, 'email'), ticket5.id) + assert_equal(0, notification_check(ticket5, agent2, 'email'), ticket5.id) agent1.preferences['notification_config']['matrix']['create']['criteria']['owned_by_me'] = true agent1.preferences['notification_config']['matrix']['create']['criteria']['owned_by_nobody'] = false @@ -727,8 +727,10 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications to agent1 + agent2 - assert_equal(1, notification_check(ticket6, agent1), ticket6.id) - assert_equal(0, notification_check(ticket6, agent2), ticket6.id) + assert_equal(1, notification_check(ticket6, agent1, 'email'), ticket6.id) + assert_equal(1, notification_check(ticket6, agent1, 'online'), ticket6.id) + assert_equal(0, notification_check(ticket6, agent2, 'email'), ticket6.id) + assert_equal(0, notification_check(ticket6, agent2, 'online'), ticket6.id) # update ticket attributes ticket6.title = "#{ticket6.title} - #2" @@ -741,8 +743,89 @@ class TicketNotificationTest < ActiveSupport::TestCase Delayed::Worker.new.work_off # verify notifications to agent1 + agent2 - assert_equal(2, notification_check(ticket6, agent1), ticket6.id) - assert_equal(0, notification_check(ticket6, agent2), ticket6.id) + assert_equal(2, notification_check(ticket6, agent1, 'email'), ticket6.id) + assert_equal(2, notification_check(ticket6, agent1, 'online'), ticket6.id) + assert_equal(0, notification_check(ticket6, agent2, 'email'), ticket6.id) + assert_equal(0, notification_check(ticket6, agent2, 'online'), ticket6.id) + + agent1.preferences['notification_config']['matrix']['create']['criteria']['owned_by_me'] = true + agent1.preferences['notification_config']['matrix']['create']['criteria']['owned_by_nobody'] = false + agent1.preferences['notification_config']['matrix']['create']['criteria']['no'] = true + agent1.preferences['notification_config']['matrix']['create']['channel']['email'] = false + agent1.preferences['notification_config']['matrix']['create']['channel']['online'] = true + agent1.preferences['notification_config']['matrix']['update']['criteria']['owned_by_me'] = true + agent1.preferences['notification_config']['matrix']['update']['criteria']['owned_by_nobody'] = false + agent1.preferences['notification_config']['matrix']['update']['criteria']['no'] = true + agent1.preferences['notification_config']['matrix']['update']['channel']['email'] = false + agent1.preferences['notification_config']['matrix']['update']['channel']['online'] = true + agent1.preferences['notification_config']['group_ids'] = [999] + agent1.save + + agent2.preferences['notification_config']['matrix']['create']['criteria']['owned_by_me'] = true + agent2.preferences['notification_config']['matrix']['create']['criteria']['owned_by_nobody'] = false + agent2.preferences['notification_config']['matrix']['create']['criteria']['no'] = true + agent2.preferences['notification_config']['matrix']['create']['channel']['email'] = false + agent2.preferences['notification_config']['matrix']['create']['channel']['online'] = true + agent2.preferences['notification_config']['matrix']['update']['criteria']['owned_by_me'] = true + agent2.preferences['notification_config']['matrix']['update']['criteria']['owned_by_nobody'] = false + agent2.preferences['notification_config']['matrix']['update']['criteria']['no'] = true + agent2.preferences['notification_config']['matrix']['update']['channel']['email'] = false + agent2.preferences['notification_config']['matrix']['update']['channel']['online'] = true + agent2.preferences['notification_config']['group_ids'] = [999] + agent2.save + + # create ticket in group + ticket7 = Ticket.create( + title: 'some notification test - z preferences tests 7', + group: Group.lookup(name: 'Users'), + customer: customer, + owner: agent1, + state: Ticket::State.lookup(name: 'new'), + priority: Ticket::Priority.lookup(name: '2 normal'), + updated_by_id: customer.id, + created_by_id: customer.id, + ) + Ticket::Article.create( + ticket_id: ticket7.id, + from: 'some_sender@example.com', + to: 'some_recipient@example.com', + subject: 'some subject', + message_id: 'some@id', + body: 'some message', + internal: false, + sender: Ticket::Article::Sender.where(name: 'Customer').first, + type: Ticket::Article::Type.where(name: 'email').first, + updated_by_id: customer.id, + created_by_id: customer.id, + ) + + # execute ticket events + Rails.configuration.webserver_is_active = false + Observer::Ticket::Notification.transaction + #puts Delayed::Job.all.inspect + Delayed::Worker.new.work_off + + # verify notifications to agent1 + agent2 + assert_equal(0, notification_check(ticket7, agent1, 'email'), ticket7.id) + assert_equal(1, notification_check(ticket7, agent1, 'online'), ticket7.id) + assert_equal(0, notification_check(ticket7, agent2, 'email'), ticket7.id) + assert_equal(0, notification_check(ticket7, agent2, 'online'), ticket7.id) + + # update ticket attributes + ticket7.title = "#{ticket7.title} - #2" + ticket7.priority = Ticket::Priority.lookup(name: '3 high') + ticket7.save + + # execute ticket events + Observer::Ticket::Notification.transaction + #puts Delayed::Job.all.inspect + Delayed::Worker.new.work_off + + # verify notifications to agent1 + agent2 + assert_equal(0, notification_check(ticket7, agent1, 'email'), ticket7.id) + assert_equal(2, notification_check(ticket7, agent1, 'online'), ticket7.id) + assert_equal(0, notification_check(ticket7, agent2, 'email'), ticket7.id) + assert_equal(0, notification_check(ticket7, agent2, 'online'), ticket7.id) end @@ -970,13 +1053,14 @@ class TicketNotificationTest < ActiveSupport::TestCase end - def notification_check(ticket, recipient) + def notification_check(ticket, recipient, type) result = ticket.history_get() count = 0 result.each {|item| next if item['type'] != 'notification' next if item['object'] != 'Ticket' next if item['value_to'] !~ /#{recipient.email}/i + next if item['value_to'] !~ /#{type}/i count += 1 } count
checked<% end %>/> checked<% end %>/> checked<% end %>/>checked<% end %>/>checked<% end %>/>