From c8c2fe521ba12644d10749f84e6b99de1eabe7bc Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sun, 18 Nov 2012 11:56:48 +0100 Subject: [PATCH] Reorganized object observers. --- app/models/channel/email_parser.rb | 2 +- app/models/channel/twitter2.rb | 2 +- .../history.rb} | 4 +- app/models/observer/ticket/close_time.rb | 21 ++ app/models/observer/ticket/first_response.rb | 25 ++ app/models/observer/ticket/last_contact.rb | 43 +++ app/models/observer/ticket/notification.rb | 274 ++++++++++++++++++ .../observer/ticket/user_ticket_counter.rb | 25 ++ test/unit/history_test.rb | 2 +- 9 files changed, 394 insertions(+), 4 deletions(-) rename app/models/{history_observer.rb => observer/history.rb} (98%) create mode 100644 app/models/observer/ticket/close_time.rb create mode 100644 app/models/observer/ticket/first_response.rb create mode 100644 app/models/observer/ticket/last_contact.rb create mode 100644 app/models/observer/ticket/notification.rb create mode 100644 app/models/observer/ticket/user_ticket_counter.rb diff --git a/app/models/channel/email_parser.rb b/app/models/channel/email_parser.rb index 42b1f1ef0..8b32a9ce0 100644 --- a/app/models/channel/email_parser.rb +++ b/app/models/channel/email_parser.rb @@ -387,7 +387,7 @@ class Channel::EmailParser end # execute ticket events - Ticket::Observer::Notification.transaction + Observer::Ticket::Notification.transaction # run postmaster post filter filters = { diff --git a/app/models/channel/twitter2.rb b/app/models/channel/twitter2.rb index 6b57476c1..efd7af976 100644 --- a/app/models/channel/twitter2.rb +++ b/app/models/channel/twitter2.rb @@ -76,7 +76,7 @@ class Channel::Twitter2 end # execute ticket events - Ticket::Observer::Notification.transaction + Observer::Ticket::Notification.transaction end end diff --git a/app/models/history_observer.rb b/app/models/observer/history.rb similarity index 98% rename from app/models/history_observer.rb rename to app/models/observer/history.rb index f7db311a7..be5203b05 100644 --- a/app/models/history_observer.rb +++ b/app/models/observer/history.rb @@ -1,4 +1,6 @@ -class HistoryObserver < ActiveRecord::Observer +require 'history' + +class Observer::History < ActiveRecord::Observer include UserInfo observe :ticket, :user, 'ticket::_article' diff --git a/app/models/observer/ticket/close_time.rb b/app/models/observer/ticket/close_time.rb new file mode 100644 index 000000000..cb4a1c392 --- /dev/null +++ b/app/models/observer/ticket/close_time.rb @@ -0,0 +1,21 @@ +class Observer::Ticket::CloseTime < ActiveRecord::Observer + observe 'ticket' + + def after_update(record) +# puts 'check close time' + + # check if close_time is already set + return true if record.close_time + + # check if ticket is closed now + ticket_state = Ticket::State.find( record.ticket_state_id ) + ticket_state_type = Ticket::StateType.find( ticket_state.ticket_state_type_id ) + return true if ticket_state_type.name != 'closed' + + # set close_time + record.close_time = Time.now + + # save ticket + record.save + end +end \ No newline at end of file diff --git a/app/models/observer/ticket/first_response.rb b/app/models/observer/ticket/first_response.rb new file mode 100644 index 000000000..05bf8fef7 --- /dev/null +++ b/app/models/observer/ticket/first_response.rb @@ -0,0 +1,25 @@ +class Observer::Ticket::FirstResponse < ActiveRecord::Observer + observe 'ticket::_article' + + def after_create(record) +# puts 'check first response' + + # if article in internal + return true if record.internal + + # if sender is not agent + return true if record.ticket_article_sender.name != 'Agent' + + # if article is a message to customer + return true if !record.ticket_article_type.communication + + # check if first_response is already set + return true if record.ticket.first_response + + # set first_response + record.ticket.first_response = Time.now + + # save ticket + record.ticket.save + end +end \ No newline at end of file diff --git a/app/models/observer/ticket/last_contact.rb b/app/models/observer/ticket/last_contact.rb new file mode 100644 index 000000000..a02f68624 --- /dev/null +++ b/app/models/observer/ticket/last_contact.rb @@ -0,0 +1,43 @@ +class Observer::Ticket::LastContact < ActiveRecord::Observer + observe 'ticket::_article' + + def after_create(record) +# puts 'check last contact' + + # if article in internal + return true if record.internal + + # if article is a message to customer + return true if !record.ticket_article_type.communication + + # if sender is not customer + if record.ticket_article_sender.name == 'Customer' + + # check if last communication is done by agent, else do not set last_contact_customer + if record.ticket.last_contact_customer == nil || + record.ticket.last_contact_agent == nil || + record.ticket.last_contact_agent.to_i > record.ticket.last_contact_customer.to_i + record.ticket.last_contact_customer = Time.now + + # set last_contact + record.ticket.last_contact = Time.now + + # save ticket + record.ticket.save + end + end + + # if sender is not agent + if record.ticket_article_sender.name == 'Agent' + + # set last_contact_agent + record.ticket.last_contact_agent = Time.now + + # set last_contact + record.ticket.last_contact = Time.now + + # save ticket + record.ticket.save + end + end +end \ No newline at end of file diff --git a/app/models/observer/ticket/notification.rb b/app/models/observer/ticket/notification.rb new file mode 100644 index 000000000..707f9b7ea --- /dev/null +++ b/app/models/observer/ticket/notification.rb @@ -0,0 +1,274 @@ +class Observer::Ticket::Notification < ActiveRecord::Observer + observe :ticket, 'ticket::_article' + + @@event_buffer = [] + + def self.transaction + +# puts '@@event_buffer' +# puts @@event_buffer.inspect + @@event_buffer.each { |event| + + # get current state of objects + if event[:name] == 'Ticket::Article' + article = Ticket::Article.find( event[:id] ) + ticket = article.ticket + else + ticket = Ticket.find( event[:id] ) + article = ticket.articles[-1] + end + + # send new ticket notification to agents + if event[:name] == 'Ticket' && event[:type] == 'create' + + puts 'send new ticket notify to agent' + send_notify( + { + :event => event, + :recipient => 'to_work_on', # group|owner|to_work_on|customer + :subject => 'New Ticket (#{ticket.title})', + :body => 'Hi #{recipient.firstname}, + +a new Ticket (#{ticket.title}) via #{article.ticket_article_type.name}. + +Group: #{ticket.group.name} +Owner: #{ticket.owner.firstname} #{ticket.owner.lastname} +State: #{ticket.ticket_state.name} + +From: #{article.from} + +#{article.body} + + +#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}/#{article.id} +' + }, + ticket, + article + ) + end + + # send new ticket notification to customers + if event[:name] == 'Ticket' && event[:type] == 'create' + + # only for incoming emails + next if article.ticket_article_type.name != 'email' + + puts 'send new ticket notify to customer' + send_notify( + { + :event => event, + :recipient => 'customer', # group|owner|to_work_on|customer + :subject => 'New Ticket has been created! (#{ticket.title})', + :body => 'Thanks for your email. A new ticket has been created. + +You wrote: + +#{article.body} + + +Your email will be answered by a human ASAP + +Have fun with Zammad! :-) + +Your Zammad Team +' + }, + ticket, + article + ) + end + + # send follow up notification + if event[:name] == 'Ticket::Article' && event[:type] == 'create' + + # only send article notifications after init article is created (handled by ticket create event) + next if ticket.articles.count.to_i <= 1 + + puts 'send new ticket::article notify' + + if article.ticket_article_sender.name == 'Customer' + send_notify( + { + :event => event, + :recipient => 'to_work_on', # group|owner|to_work_on|customer + :subject => 'Follow Up (#{ticket.title})', + :body => 'Hi #{recipient.firstname}, + +a follow Up (#{ticket.title}) via #{article.ticket_article_type.name}. + +Group: #{ticket.group.name} +Owner: #{ticket.owner.firstname} #{ticket.owner.lastname} +State: #{ticket.ticket_state.name} + +From: #{article.from} + +#{article.body} + + +#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}/#{article.id} +' + }, + ticket, + article + ) + end + + # send new note notification to owner + # if agent == created.id + if article.ticket_article_sender.name == 'Agent' && article.created_by_id != article.ticket.owner_id + send_notify( + { + :event => event, + :recipient => 'owner', # group|owner|to_work_on + :subject => 'Updated (#{ticket.title})', + :body => 'Hi #{recipient.firstname}, + +updated (#{ticket.title}) via #{article.ticket_article_type.name}. + +Group: #{ticket.group.name} +Owner: #{ticket.owner.firstname} #{ticket.owner.lastname} +State: #{ticket.ticket_state.name} + +From: #{article.from} + +#{article.body} + + +#{config.http_type}://#{config.fqdn}/#ticket/zoom/#{ticket.id}/#{article.id} +' + }, + ticket, + article + ) + end + end + } + + # reset buffer + @@event_buffer = [] + end + + def self.send_notify(data, ticket, article) + + # find recipients + recipients = [] + + # group of agents to work on + if data[:recipient] == 'group' + recipients = ticket.agent_of_group() + + # owner + elsif data[:recipient] == 'owner' + if ticket.owner_id != 1 + recipients.push ticket.owner + end + + # customer + elsif data[:recipient] == 'customer' + if ticket.customer_id != 1 +# temporarily disabled +# recipients.push ticket.customer + end + + # owner or group of agents to work on + elsif data[:recipient] == 'to_work_on' + if ticket.owner_id != 1 + recipients.push ticket.owner + else + recipients = ticket.agent_of_group() + end + end + + # send notifications + recipient_list = '' + notification_subject = '' + recipients.each do |user| + next if !user.email || user.email == '' + + # add recipient_list + if recipient_list != '' + recipient_list += ',' + end + recipient_list += user.email.to_s + + # prepare subject & body + notification = {} + [:subject, :body].each { |key| + notification[key.to_sym] = NotificationFactory.build( + :string => data[key.to_sym], + :objects => { + :ticket => ticket, + :article => article, + :recipient => user, + } + ) + } + notification_subject = notification[:subject] + + # rebuild subject + notification[:subject] = ticket.subject_build( notification[:subject] ) + + # send notification + NotificationFactory.send( + :recipient => user, + :subject => notification[:subject], + :body => notification[:body] + ) + end + + # add history record + if recipient_list != '' + History.history_create( + :o_id => ticket.id, + :history_type => 'notification', + :history_object => 'Ticket', + :value_from => notification_subject, + :value_to => recipient_list, + :created_by_id => article.created_by_id || 1 + ) + end + end + + def after_create(record) +# puts 'CREATED!!!!' +# puts record.inspect + e = { + :name => record.class.name, + :type => 'create', + :data => record, + :id => record.id, + } + @@event_buffer.push e + end + + def before_update(record) + puts 'before_update' + current = record.class.find(record.id) + + # do not send anything if nothing has changed + return if current.attributes == record.attributes + +# puts 'UPDATE!!!!!!!!' +# puts 'current' +# puts current.inspect +# puts 'record' +# puts record.inspect + + e = { + :name => record.class.name, + :type => 'update', + :data => record, + :id => record.id, + } + @@event_buffer.push e + end + + def after_update(record) +# puts 'after_update' +# puts record.inspect +# puts '-----' +# puts @a.inspect +# AuditTrail.new(record, "UPDATED") + end +end \ No newline at end of file diff --git a/app/models/observer/ticket/user_ticket_counter.rb b/app/models/observer/ticket/user_ticket_counter.rb new file mode 100644 index 000000000..8ecb81adc --- /dev/null +++ b/app/models/observer/ticket/user_ticket_counter.rb @@ -0,0 +1,25 @@ +class Observer::Ticket::UserTicketCounter < ActiveRecord::Observer + observe 'ticket' + + def after_create(record) + user_ticket_counter_update(record) + end + def after_update(record) + user_ticket_counter_update(record) + end + + def user_ticket_counter_update(record) + return if !record.customer_id + + ticket_state_list_open = Ticket::State.where( :ticket_state_type_id => Ticket::StateType.where(:name => ['new','open', 'pending reminder', 'pending action']) ) + ticket_state_list_closed = Ticket::State.where( :ticket_state_type_id => Ticket::StateType.where(:name => ['closed'] ) ) + + tickets_open = Ticket.where( :customer_id => record.customer_id, :ticket_state_id => ticket_state_list_open ).count() + tickets_closed = Ticket.where( :customer_id => record.customer_id, :ticket_state_id => ticket_state_list_closed ).count() + + customer = User.find( record.customer_id ) + customer[:preferences][:tickets_open] = tickets_open + customer[:preferences][:tickets_closed] = tickets_closed + customer.save + end +end \ No newline at end of file diff --git a/test/unit/history_test.rb b/test/unit/history_test.rb index 93c7202ed..888c702c7 100644 --- a/test/unit/history_test.rb +++ b/test/unit/history_test.rb @@ -141,7 +141,7 @@ class HistoryTest < ActiveSupport::TestCase end # execute ticket events - Ticket::Observer::Notification.transaction + Observer::Ticket::Notification.transaction # remember ticket tickets.push ticket