transaction.rb 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
  2. class Observer::Transaction < ActiveRecord::Observer
  3. observe :ticket, 'ticket::_article', :user, :organization, :tag
  4. def self.reset
  5. EventBuffer.reset('transaction')
  6. end
  7. def self.commit(params = {})
  8. # add attribute of interface handle (e. g. to send (no) notifications if a agent
  9. # is creating a ticket via application_server, but send it if it's created via
  10. # postmaster)
  11. params[:interface_handle] = ApplicationHandleInfo.current
  12. # execute object transactions
  13. Observer::Transaction.perform(params)
  14. end
  15. def self.perform(params)
  16. # return if we run import mode
  17. return if Setting.get('import_mode')
  18. # get buffer
  19. list = EventBuffer.list('transaction')
  20. # reset buffer
  21. EventBuffer.reset('transaction')
  22. # get async backends
  23. sync_backends = []
  24. Setting.where(area: 'Transaction::Backend::Sync').order(:name).each do |setting|
  25. backend = Setting.get(setting.name)
  26. next if params[:disable]&.include?(backend)
  27. sync_backends.push backend.constantize
  28. end
  29. # get uniq objects
  30. list_objects = get_uniq_changes(list)
  31. list_objects.each_value do |objects|
  32. objects.each_value do |item|
  33. # execute sync backends
  34. sync_backends.each do |backend|
  35. execute_singel_backend(backend, item, params)
  36. end
  37. # execute async backends
  38. Delayed::Job.enqueue(Transaction::BackgroundJob.new(item, params))
  39. end
  40. end
  41. end
  42. def self.execute_singel_backend(backend, item, params)
  43. Rails.logger.debug { "Execute singel backend #{backend}" }
  44. begin
  45. UserInfo.current_user_id = nil
  46. integration = backend.new(item, params)
  47. integration.perform
  48. rescue => e
  49. Rails.logger.error e
  50. end
  51. end
  52. =begin
  53. result = get_uniq_changes(events)
  54. result = {
  55. 'Ticket' =>
  56. 1 => {
  57. object: 'Ticket',
  58. type: 'create',
  59. object_id: 123,
  60. article_id: 123,
  61. user_id: 123,
  62. created_at: Time.zone.now,
  63. },
  64. 9 => {
  65. object: 'Ticket',
  66. type: 'update',
  67. object_id: 123,
  68. changes: {
  69. attribute1: [before, now],
  70. attribute2: [before, now],
  71. },
  72. user_id: 123,
  73. created_at: Time.zone.now,
  74. },
  75. },
  76. }
  77. result = {
  78. 'Ticket' =>
  79. 9 => {
  80. object: 'Ticket',
  81. type: 'update',
  82. object_id: 123,
  83. article_id: 123,
  84. changes: {
  85. attribute1: [before, now],
  86. attribute2: [before, now],
  87. },
  88. user_id: 123,
  89. created_at: Time.zone.now,
  90. },
  91. },
  92. }
  93. =end
  94. def self.get_uniq_changes(events)
  95. list_objects = {}
  96. events.each do |event|
  97. # simulate article create as ticket update
  98. article = nil
  99. if event[:object] == 'Ticket::Article'
  100. article = Ticket::Article.find_by(id: event[:id])
  101. next if !article
  102. next if event[:type] == 'update'
  103. # set new event infos
  104. ticket = Ticket.find_by(id: article.ticket_id)
  105. event[:object] = 'Ticket'
  106. event[:id] = ticket.id
  107. event[:type] = 'update'
  108. event[:changes] = nil
  109. end
  110. # get current state of objects
  111. object = event[:object].constantize.find_by(id: event[:id])
  112. # next if object is already deleted
  113. next if !object
  114. if !list_objects[event[:object]]
  115. list_objects[event[:object]] = {}
  116. end
  117. if !list_objects[event[:object]][object.id]
  118. list_objects[event[:object]][object.id] = {}
  119. end
  120. store = list_objects[event[:object]][object.id]
  121. store[:object] = event[:object]
  122. store[:object_id] = object.id
  123. store[:user_id] = event[:user_id]
  124. store[:created_at] = event[:created_at]
  125. if !store[:type] || store[:type] == 'update'
  126. store[:type] = event[:type]
  127. end
  128. # merge changes
  129. if event[:changes]
  130. if !store[:changes]
  131. store[:changes] = event[:changes]
  132. else
  133. event[:changes].each do |key, value|
  134. if !store[:changes][key]
  135. store[:changes][key] = value
  136. else
  137. store[:changes][key][1] = value[1]
  138. end
  139. end
  140. end
  141. end
  142. # remember article id if exists
  143. if article
  144. store[:article_id] = article.id
  145. end
  146. end
  147. list_objects
  148. end
  149. def after_create(record)
  150. # return if we run import mode
  151. return true if Setting.get('import_mode')
  152. e = {
  153. object: record.class.name,
  154. type: 'create',
  155. data: record,
  156. id: record.id,
  157. user_id: record.created_by_id,
  158. created_at: Time.zone.now,
  159. }
  160. EventBuffer.add('transaction', e)
  161. true
  162. end
  163. def before_update(record)
  164. # return if we run import mode
  165. return true if Setting.get('import_mode')
  166. # ignore certain attributes
  167. real_changes = {}
  168. record.changes_to_save.each do |key, value|
  169. next if key == 'updated_at'
  170. next if key == 'first_response_at'
  171. next if key == 'close_at'
  172. next if key == 'last_contact_agent_at'
  173. next if key == 'last_contact_customer_at'
  174. next if key == 'last_contact_at'
  175. next if key == 'article_count'
  176. next if key == 'create_article_type_id'
  177. next if key == 'create_article_sender_id'
  178. real_changes[key] = value
  179. end
  180. # do not send anything if nothing has changed
  181. return true if real_changes.blank?
  182. changed_by_id = if record.respond_to?('updated_by_id')
  183. record.updated_by_id
  184. else
  185. record.created_by_id
  186. end
  187. e = {
  188. object: record.class.name,
  189. type: 'update',
  190. data: record,
  191. changes: real_changes,
  192. id: record.id,
  193. user_id: changed_by_id,
  194. created_at: Time.zone.now,
  195. }
  196. EventBuffer.add('transaction', e)
  197. true
  198. end
  199. end