transaction.rb 5.2 KB

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