2016-10-19 03:11:36 +00:00
|
|
|
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
|
2016-04-15 21:56:10 +00:00
|
|
|
|
|
|
|
class Observer::Transaction < ActiveRecord::Observer
|
2016-07-06 06:13:44 +00:00
|
|
|
observe :ticket, 'ticket::_article', :user, :organization, :tag
|
2016-04-14 07:17:13 +00:00
|
|
|
|
2017-07-26 18:46:31 +00:00
|
|
|
def self.reset
|
|
|
|
EventBuffer.reset('transaction')
|
|
|
|
end
|
|
|
|
|
2016-04-14 07:17:13 +00:00
|
|
|
def self.commit(params = {})
|
|
|
|
|
2016-08-20 19:29:22 +00:00
|
|
|
# add attribute of interface handle (e. g. to send (no) notifications if a agent
|
|
|
|
# is creating a ticket via application_server, but send it if it's created via
|
|
|
|
# postmaster)
|
|
|
|
params[:interface_handle] = ApplicationHandleInfo.current
|
2016-04-15 21:56:10 +00:00
|
|
|
|
|
|
|
# execute object transactions
|
|
|
|
Observer::Transaction.perform(params)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.perform(params)
|
|
|
|
|
|
|
|
# return if we run import mode
|
|
|
|
return if Setting.get('import_mode')
|
|
|
|
|
|
|
|
# get buffer
|
|
|
|
list = EventBuffer.list('transaction')
|
|
|
|
|
|
|
|
# reset buffer
|
|
|
|
EventBuffer.reset('transaction')
|
|
|
|
|
2016-05-03 00:36:44 +00:00
|
|
|
# get asyn backends
|
|
|
|
sync_backends = []
|
2017-10-01 12:25:52 +00:00
|
|
|
Setting.where(area: 'Transaction::Backend::Sync').order(:name).each do |setting|
|
2016-05-03 00:36:44 +00:00
|
|
|
backend = Setting.get(setting.name)
|
2017-11-23 08:09:44 +00:00
|
|
|
next if params[:disable]&.include?(backend)
|
2018-10-09 06:17:41 +00:00
|
|
|
|
2016-05-03 00:36:44 +00:00
|
|
|
sync_backends.push Kernel.const_get(backend)
|
2017-10-01 12:25:52 +00:00
|
|
|
end
|
2016-05-03 00:36:44 +00:00
|
|
|
|
2016-04-15 21:56:10 +00:00
|
|
|
# get uniq objects
|
|
|
|
list_objects = get_uniq_changes(list)
|
2017-11-23 08:09:44 +00:00
|
|
|
list_objects.each_value do |objects|
|
|
|
|
objects.each_value do |item|
|
2016-05-03 00:36:44 +00:00
|
|
|
|
|
|
|
# execute sync backends
|
2017-10-01 12:25:52 +00:00
|
|
|
sync_backends.each do |backend|
|
2016-05-03 00:36:44 +00:00
|
|
|
execute_singel_backend(backend, item, params)
|
2017-10-01 12:25:52 +00:00
|
|
|
end
|
2016-05-03 00:36:44 +00:00
|
|
|
|
|
|
|
# execute async backends
|
2016-04-22 06:55:10 +00:00
|
|
|
Delayed::Job.enqueue(Transaction::BackgroundJob.new(item, params))
|
2017-10-01 12:25:52 +00:00
|
|
|
end
|
|
|
|
end
|
2016-04-15 21:56:10 +00:00
|
|
|
end
|
|
|
|
|
2016-05-03 00:36:44 +00:00
|
|
|
def self.execute_singel_backend(backend, item, params)
|
2018-03-20 17:47:49 +00:00
|
|
|
Rails.logger.debug { "Execute singel backend #{backend}" }
|
2016-05-03 00:36:44 +00:00
|
|
|
begin
|
|
|
|
UserInfo.current_user_id = nil
|
|
|
|
integration = backend.new(item, params)
|
|
|
|
integration.perform
|
|
|
|
rescue => e
|
|
|
|
Rails.logger.error 'ERROR: ' + backend.inspect
|
|
|
|
Rails.logger.error 'ERROR: ' + e.inspect
|
2017-03-03 08:28:45 +00:00
|
|
|
Rails.logger.error e.backtrace.inspect
|
2016-05-03 00:36:44 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-04-15 21:56:10 +00:00
|
|
|
=begin
|
|
|
|
|
|
|
|
result = get_uniq_changes(events)
|
|
|
|
|
|
|
|
result = {
|
2016-04-22 06:55:10 +00:00
|
|
|
'Ticket' =>
|
|
|
|
1 => {
|
|
|
|
object: 'Ticket',
|
|
|
|
type: 'create',
|
|
|
|
object_id: 123,
|
|
|
|
article_id: 123,
|
2016-04-27 07:31:11 +00:00
|
|
|
user_id: 123,
|
2016-07-10 22:47:21 +00:00
|
|
|
created_at: Time.zone.now,
|
2016-04-22 06:55:10 +00:00
|
|
|
},
|
|
|
|
9 => {
|
|
|
|
object: 'Ticket',
|
|
|
|
type: 'update',
|
|
|
|
object_id: 123,
|
|
|
|
changes: {
|
|
|
|
attribute1: [before, now],
|
|
|
|
attribute2: [before, now],
|
|
|
|
},
|
2016-04-27 07:31:11 +00:00
|
|
|
user_id: 123,
|
2016-07-10 22:47:21 +00:00
|
|
|
created_at: Time.zone.now,
|
2016-04-22 06:55:10 +00:00
|
|
|
},
|
2016-04-15 21:56:10 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
result = {
|
2016-04-22 06:55:10 +00:00
|
|
|
'Ticket' =>
|
|
|
|
9 => {
|
|
|
|
object: 'Ticket',
|
|
|
|
type: 'update',
|
|
|
|
object_id: 123,
|
|
|
|
article_id: 123,
|
|
|
|
changes: {
|
|
|
|
attribute1: [before, now],
|
|
|
|
attribute2: [before, now],
|
|
|
|
},
|
2016-04-27 07:31:11 +00:00
|
|
|
user_id: 123,
|
2016-07-10 22:47:21 +00:00
|
|
|
created_at: Time.zone.now,
|
2016-04-22 06:55:10 +00:00
|
|
|
},
|
2016-04-15 21:56:10 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def self.get_uniq_changes(events)
|
|
|
|
list_objects = {}
|
2017-10-01 12:25:52 +00:00
|
|
|
events.each do |event|
|
2016-04-15 21:56:10 +00:00
|
|
|
|
2016-04-22 06:55:10 +00:00
|
|
|
# simulate article create as ticket update
|
|
|
|
article = nil
|
|
|
|
if event[:object] == 'Ticket::Article'
|
2018-06-05 10:37:52 +00:00
|
|
|
article = Ticket::Article.find_by(id: event[:id])
|
2016-04-15 21:56:10 +00:00
|
|
|
next if !article
|
2016-04-22 06:55:10 +00:00
|
|
|
next if event[:type] == 'update'
|
|
|
|
|
|
|
|
# set new event infos
|
2018-06-05 10:37:52 +00:00
|
|
|
ticket = Ticket.find_by(id: article.ticket_id)
|
2016-04-22 06:55:10 +00:00
|
|
|
event[:object] = 'Ticket'
|
|
|
|
event[:id] = ticket.id
|
|
|
|
event[:type] = 'update'
|
|
|
|
event[:changes] = nil
|
|
|
|
end
|
2016-04-15 21:56:10 +00:00
|
|
|
|
2016-04-22 06:55:10 +00:00
|
|
|
# get current state of objects
|
2018-06-05 10:37:52 +00:00
|
|
|
object = Kernel.const_get(event[:object]).find_by(id: event[:id])
|
2016-04-15 21:56:10 +00:00
|
|
|
|
2016-04-22 06:55:10 +00:00
|
|
|
# next if object is already deleted
|
|
|
|
next if !object
|
2016-04-15 21:56:10 +00:00
|
|
|
|
2016-04-22 06:55:10 +00:00
|
|
|
if !list_objects[event[:object]]
|
|
|
|
list_objects[event[:object]] = {}
|
|
|
|
end
|
|
|
|
if !list_objects[event[:object]][object.id]
|
|
|
|
list_objects[event[:object]][object.id] = {}
|
|
|
|
end
|
|
|
|
store = list_objects[event[:object]][object.id]
|
|
|
|
store[:object] = event[:object]
|
|
|
|
store[:object_id] = object.id
|
2016-04-27 07:31:11 +00:00
|
|
|
store[:user_id] = event[:user_id]
|
2016-07-10 22:47:21 +00:00
|
|
|
store[:created_at] = event[:created_at]
|
2016-04-15 21:56:10 +00:00
|
|
|
|
2016-04-22 06:55:10 +00:00
|
|
|
if !store[:type] || store[:type] == 'update'
|
|
|
|
store[:type] = event[:type]
|
|
|
|
end
|
2016-04-15 21:56:10 +00:00
|
|
|
|
2016-04-22 06:55:10 +00:00
|
|
|
# merge changes
|
|
|
|
if event[:changes]
|
|
|
|
if !store[:changes]
|
|
|
|
store[:changes] = event[:changes]
|
|
|
|
else
|
2017-10-01 12:25:52 +00:00
|
|
|
event[:changes].each do |key, value|
|
2016-04-22 06:55:10 +00:00
|
|
|
if !store[:changes][key]
|
|
|
|
store[:changes][key] = value
|
|
|
|
else
|
|
|
|
store[:changes][key][1] = value[1]
|
|
|
|
end
|
2017-10-01 12:25:52 +00:00
|
|
|
end
|
2016-04-15 21:56:10 +00:00
|
|
|
end
|
2016-04-22 06:55:10 +00:00
|
|
|
end
|
2016-04-15 21:56:10 +00:00
|
|
|
|
2016-04-22 06:55:10 +00:00
|
|
|
# remember article id if exists
|
|
|
|
if article
|
|
|
|
store[:article_id] = article.id
|
2016-04-15 21:56:10 +00:00
|
|
|
end
|
2017-10-01 12:25:52 +00:00
|
|
|
end
|
2016-04-15 21:56:10 +00:00
|
|
|
list_objects
|
|
|
|
end
|
|
|
|
|
|
|
|
def after_create(record)
|
|
|
|
|
|
|
|
# return if we run import mode
|
2017-06-16 22:53:20 +00:00
|
|
|
return true if Setting.get('import_mode')
|
2016-04-15 21:56:10 +00:00
|
|
|
|
|
|
|
e = {
|
2016-04-22 06:55:10 +00:00
|
|
|
object: record.class.name,
|
2016-04-15 21:56:10 +00:00
|
|
|
type: 'create',
|
|
|
|
data: record,
|
|
|
|
id: record.id,
|
2016-04-27 07:31:11 +00:00
|
|
|
user_id: record.created_by_id,
|
2016-07-10 22:47:21 +00:00
|
|
|
created_at: Time.zone.now,
|
2016-04-15 21:56:10 +00:00
|
|
|
}
|
|
|
|
EventBuffer.add('transaction', e)
|
2017-06-16 22:53:20 +00:00
|
|
|
true
|
2016-04-15 21:56:10 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def before_update(record)
|
|
|
|
|
|
|
|
# return if we run import mode
|
2017-06-16 22:53:20 +00:00
|
|
|
return true if Setting.get('import_mode')
|
2016-04-15 21:56:10 +00:00
|
|
|
|
|
|
|
# ignore certain attributes
|
|
|
|
real_changes = {}
|
2017-10-01 12:25:52 +00:00
|
|
|
record.changes_to_save.each do |key, value|
|
2016-04-15 21:56:10 +00:00
|
|
|
next if key == 'updated_at'
|
2016-09-14 07:15:30 +00:00
|
|
|
next if key == 'first_response_at'
|
|
|
|
next if key == 'close_at'
|
|
|
|
next if key == 'last_contact_agent_at'
|
|
|
|
next if key == 'last_contact_customer_at'
|
|
|
|
next if key == 'last_contact_at'
|
2016-04-15 21:56:10 +00:00
|
|
|
next if key == 'article_count'
|
|
|
|
next if key == 'create_article_type_id'
|
|
|
|
next if key == 'create_article_sender_id'
|
2018-10-09 06:17:41 +00:00
|
|
|
|
2016-04-15 21:56:10 +00:00
|
|
|
real_changes[key] = value
|
2017-10-01 12:25:52 +00:00
|
|
|
end
|
2016-04-15 21:56:10 +00:00
|
|
|
|
|
|
|
# do not send anything if nothing has changed
|
2017-11-23 08:09:44 +00:00
|
|
|
return true if real_changes.blank?
|
2016-04-14 07:17:13 +00:00
|
|
|
|
2016-07-06 06:13:44 +00:00
|
|
|
changed_by_id = nil
|
2016-07-07 05:16:13 +00:00
|
|
|
changed_by_id = if record.respond_to?('updated_by_id')
|
|
|
|
record.updated_by_id
|
|
|
|
else
|
|
|
|
record.created_by_id
|
|
|
|
end
|
2016-07-06 06:13:44 +00:00
|
|
|
|
2016-04-15 21:56:10 +00:00
|
|
|
e = {
|
2016-04-22 06:55:10 +00:00
|
|
|
object: record.class.name,
|
2016-04-15 21:56:10 +00:00
|
|
|
type: 'update',
|
|
|
|
data: record,
|
|
|
|
changes: real_changes,
|
|
|
|
id: record.id,
|
2016-07-06 06:13:44 +00:00
|
|
|
user_id: changed_by_id,
|
2016-07-10 22:47:21 +00:00
|
|
|
created_at: Time.zone.now,
|
2016-04-15 21:56:10 +00:00
|
|
|
}
|
|
|
|
EventBuffer.add('transaction', e)
|
2017-06-16 22:53:20 +00:00
|
|
|
true
|
2016-04-14 07:17:13 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|