notification.rb 10 KB

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