notification.rb 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
  2. class Transaction::Notification
  3. =begin
  4. {
  5. object: 'Ticket',
  6. type: 'update',
  7. object_id: 123,
  8. via_web: true,
  9. changes: {
  10. 'attribute1' => [before, now],
  11. 'attribute2' => [before, now],
  12. }
  13. user_id: 123,
  14. },
  15. =end
  16. def initialize(item, params = {})
  17. @item = item
  18. @params = params
  19. end
  20. def perform
  21. # return if we run import mode
  22. return if Setting.get('import_mode')
  23. return if @item[:object] != 'Ticket'
  24. return if @params[:disable_notification]
  25. ticket = Ticket.find(@item[:object_id])
  26. if @item[:article_id]
  27. article = Ticket::Article.find(@item[:article_id])
  28. # ignore notifications
  29. sender = Ticket::Article::Sender.lookup(id: article.sender_id)
  30. if sender && sender.name == 'System'
  31. return if @item[:changes].empty?
  32. article = nil
  33. end
  34. end
  35. # find recipients
  36. recipients_and_channels = []
  37. =begin
  38. # group of agents to work on
  39. if data[:recipient] == 'group'
  40. recipients = ticket.agent_of_group()
  41. # owner
  42. elsif data[:recipient] == 'owner'
  43. if ticket.owner_id != 1
  44. recipients.push ticket.owner
  45. end
  46. # customer
  47. elsif data[:recipient] == 'customer'
  48. if ticket.customer_id != 1
  49. # temporarily disabled
  50. # recipients.push ticket.customer
  51. end
  52. # owner or group of agents to work on
  53. elsif data[:recipient] == 'to_work_on'
  54. if ticket.owner_id != 1
  55. recipients.push ticket.owner
  56. else
  57. recipients = ticket.agent_of_group()
  58. end
  59. end
  60. =end
  61. # loop through all users
  62. possible_recipients = ticket.agent_of_group
  63. if ticket.owner_id == 1
  64. possible_recipients.push ticket.owner
  65. end
  66. already_checked_recipient_ids = {}
  67. possible_recipients.each {|user|
  68. result = NotificationFactory::Mailer.notification_settings(user, ticket, @item[:type])
  69. next if !result
  70. next if already_checked_recipient_ids[result[:user].id]
  71. already_checked_recipient_ids[result[:user].id] = true
  72. recipients_and_channels.push result
  73. }
  74. # send notifications
  75. recipient_list = ''
  76. recipients_and_channels.each do |item|
  77. user = item[:user]
  78. channels = item[:channels]
  79. # ignore user who changed it by him self via web
  80. if @params[:via_web]
  81. next if article && article.updated_by_id == user.id
  82. next if !article && @item[:user_id] == user.id
  83. end
  84. # ignore inactive users
  85. next if !user.active
  86. # ignore if no changes has been done
  87. changes = human_changes(user, ticket)
  88. next if @item[:type] == 'update' && !article && (!changes || changes.empty?)
  89. # check if today already notified
  90. if @item[:type] == 'reminder_reached' || @item[:type] == 'escalation' || @item[:type] == 'escalation_warning'
  91. identifier = user.email
  92. if !identifier || identifier == ''
  93. identifier = user.login
  94. end
  95. already_notified = false
  96. History.list('Ticket', ticket.id).each {|history|
  97. next if history['type'] != 'notification'
  98. next if history['value_to'] !~ /\(#{Regexp.escape(@item[:type])}:/
  99. next if history['value_to'] !~ /#{Regexp.escape(identifier)}\(/
  100. next if !history['created_at'].today?
  101. already_notified = true
  102. }
  103. next if already_notified
  104. end
  105. # create online notification
  106. used_channels = []
  107. if channels['online']
  108. used_channels.push 'online'
  109. created_by_id = @item[:user_id] || 1
  110. # delete old notifications
  111. if @item[:type] == 'reminder_reached'
  112. seen = false
  113. created_by_id = 1
  114. OnlineNotification.remove_by_type('Ticket', ticket.id, @item[:type], user)
  115. elsif @item[:type] == 'escalation' || @item[:type] == 'escalation_warning'
  116. seen = false
  117. created_by_id = 1
  118. OnlineNotification.remove_by_type('Ticket', ticket.id, 'escalation', user)
  119. OnlineNotification.remove_by_type('Ticket', ticket.id, 'escalation_warning', user)
  120. # on updates without state changes create unseen messages
  121. elsif @item[:type] != 'create' && (!@item[:changes] || @item[:changes].empty? || !@item[:changes]['state_id'])
  122. seen = false
  123. else
  124. seen = ticket.online_notification_seen_state(user.id)
  125. end
  126. OnlineNotification.add(
  127. type: @item[:type],
  128. object: 'Ticket',
  129. o_id: ticket.id,
  130. seen: seen,
  131. created_by_id: created_by_id,
  132. user_id: user.id,
  133. )
  134. Rails.logger.debug "sent ticket online notifiaction to agent (#{@item[:type]}/#{ticket.id}/#{user.email})"
  135. end
  136. # ignore email channel notificaiton and empty emails
  137. if !channels['email'] || !user.email || user.email == ''
  138. add_recipient_list(ticket, user, used_channels, @item[:type])
  139. next
  140. end
  141. used_channels.push 'email'
  142. add_recipient_list(ticket, user, used_channels, @item[:type])
  143. # get user based notification template
  144. # if create, send create message / block update messages
  145. template = nil
  146. if @item[:type] == 'create'
  147. template = 'ticket_create'
  148. elsif @item[:type] == 'update'
  149. template = 'ticket_update'
  150. elsif @item[:type] == 'reminder_reached'
  151. template = 'ticket_reminder_reached'
  152. elsif @item[:type] == 'escalation'
  153. template = 'ticket_escalation'
  154. elsif @item[:type] == 'escalation_warning'
  155. template = 'ticket_escalation_warning'
  156. else
  157. raise "unknown type for notification #{@item[:type]}"
  158. end
  159. current_user = User.lookup(id: @item[:user_id])
  160. if !current_user
  161. current_user = User.lookup(id: 1)
  162. end
  163. NotificationFactory::Mailer.notification(
  164. template: template,
  165. user: user,
  166. objects: {
  167. ticket: ticket,
  168. article: article,
  169. recipient: user,
  170. current_user: current_user,
  171. changes: changes,
  172. },
  173. references: ticket.get_references,
  174. main_object: ticket,
  175. )
  176. Rails.logger.debug "sent ticket email notifiaction to agent (#{@item[:type]}/#{ticket.id}/#{user.email})"
  177. end
  178. end
  179. def add_recipient_list(ticket, user, channels, type)
  180. return if channels.empty?
  181. identifier = user.email
  182. if !identifier || identifier == ''
  183. identifier = user.login
  184. end
  185. recipient_list = "#{identifier}(#{type}:#{channels.join(',')})"
  186. History.add(
  187. o_id: ticket.id,
  188. history_type: 'notification',
  189. history_object: 'Ticket',
  190. value_to: recipient_list,
  191. created_by_id: @item[:user_id] || 1
  192. )
  193. end
  194. def human_changes(user, record)
  195. return {} if !@item[:changes]
  196. locale = user.preferences[:locale] || 'en-us'
  197. # only show allowed attributes
  198. attribute_list = ObjectManager::Attribute.by_object_as_hash('Ticket', user)
  199. #puts "AL #{attribute_list.inspect}"
  200. user_related_changes = {}
  201. @item[:changes].each {|key, value|
  202. # if no config exists, use all attributes
  203. if !attribute_list || attribute_list.empty?
  204. user_related_changes[key] = value
  205. # if config exists, just use existing attributes for user
  206. elsif attribute_list[key.to_s]
  207. user_related_changes[key] = value
  208. end
  209. }
  210. changes = {}
  211. user_related_changes.each {|key, value|
  212. # get attribute name
  213. attribute_name = key.to_s
  214. object_manager_attribute = attribute_list[attribute_name]
  215. if attribute_name[-3, 3] == '_id'
  216. attribute_name = attribute_name[ 0, attribute_name.length - 3 ].to_s
  217. end
  218. # add item to changes hash
  219. if key.to_s == attribute_name
  220. changes[attribute_name] = value
  221. end
  222. # if changed item is an _id field/reference, do an lookup for the realy values
  223. value_id = []
  224. value_str = [ value[0], value[1] ]
  225. if key.to_s[-3, 3] == '_id'
  226. value_id[0] = value[0]
  227. value_id[1] = value[1]
  228. if record.respond_to?(attribute_name) && record.send(attribute_name)
  229. relation_class = record.send(attribute_name).class
  230. if relation_class && value_id[0]
  231. relation_model = relation_class.lookup(id: value_id[0])
  232. if relation_model
  233. if relation_model['name']
  234. value_str[0] = relation_model['name']
  235. elsif relation_model.respond_to?('fullname')
  236. value_str[0] = relation_model.send('fullname')
  237. end
  238. end
  239. end
  240. if relation_class && value_id[1]
  241. relation_model = relation_class.lookup(id: value_id[1])
  242. if relation_model
  243. if relation_model['name']
  244. value_str[1] = relation_model['name']
  245. elsif relation_model.respond_to?('fullname')
  246. value_str[1] = relation_model.send('fullname')
  247. end
  248. end
  249. end
  250. end
  251. end
  252. # check if we have an dedcated display name for it
  253. display = attribute_name
  254. if object_manager_attribute && object_manager_attribute[:display]
  255. # delete old key
  256. changes.delete(display)
  257. # set new key
  258. display = object_manager_attribute[:display].to_s
  259. end
  260. changes[display] = if object_manager_attribute && object_manager_attribute[:translate]
  261. from = Translation.translate(locale, value_str[0])
  262. to = Translation.translate(locale, value_str[1])
  263. [from, to]
  264. else
  265. [value_str[0].to_s, value_str[1].to_s]
  266. end
  267. }
  268. changes
  269. end
  270. end