create.rb 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. # Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. class Service::Ticket::Article::Create < Service::BaseWithCurrentUser
  3. def execute(article_data:, ticket:)
  4. article_data.delete(:ticket_id)
  5. attachments_raw = article_data.delete(:attachments) || {}
  6. time_unit = article_data.delete(:time_unit)
  7. subtype = article_data.delete(:subtype)
  8. preprocess_article_data(article_data, ticket)
  9. ticket.articles.new(article_data).tap do |article|
  10. transform_article(article, attachments_raw, subtype)
  11. article.save!
  12. time_accounting(article, time_unit)
  13. form_id_cleanup(attachments_raw)
  14. end
  15. end
  16. private
  17. def preprocess_article_data(article_data, ticket)
  18. preprocess_type(article_data)
  19. preprocess_to_cc(article_data)
  20. preprocess_sender(article_data, ticket)
  21. preprocess_for_customer(article_data, ticket)
  22. end
  23. def preprocess_type(article_data)
  24. type_name = article_data[:type] || 'note'
  25. article_data[:type] = Ticket::Article::Type.lookup(name: type_name)
  26. end
  27. def preprocess_to_cc(article_data)
  28. %i[to cc].each do |field|
  29. article_data[field] = article_data[field].join(', ') if article_data[field].is_a? Array
  30. article_data[field] ||= ''
  31. end
  32. end
  33. def preprocess_sender(article_data, ticket)
  34. sender_name = if agent_on_ticket?(ticket)
  35. article_data[:sender].presence || 'Agent'
  36. else
  37. 'Customer'
  38. end
  39. article_data[:sender] = Ticket::Article::Sender.lookup(name: sender_name)
  40. end
  41. def preprocess_for_customer(article_data, ticket)
  42. return if agent_on_ticket?(ticket)
  43. if %w[note web].exclude? article_data[:type]&.name
  44. article_data[:type] = Ticket::Article::Type.lookup(name: 'note')
  45. end
  46. article_data.delete :origin_by_id
  47. article_data[:internal] = false
  48. end
  49. def transform_article(article, attachments_raw, subtype)
  50. transform_attachments(article, attachments_raw)
  51. # transform_to_from(article)
  52. transform_subtype(article, subtype)
  53. end
  54. def transform_subtype(article, subtype)
  55. article.preferences[:subtype] = subtype if subtype.present?
  56. end
  57. def transform_to_from(article)
  58. customer_display_name = display_name(article.ticket.customer)
  59. group_name = article.ticket.group.name
  60. if article.sender.name.eql?('Customer')
  61. article.from = customer_display_name
  62. article.to = group_name
  63. else
  64. article.to = customer_display_name if article.to.blank?
  65. article.from = group_name
  66. end
  67. end
  68. def transform_attachments(article, attachments_raw)
  69. inline_attachments = []
  70. if article.body && article.content_type&.include?('text/html')
  71. (article.body, inline_attachments) = HtmlSanitizer.replace_inline_images(article.body, article.ticket_id)
  72. end
  73. article.attachments = attached_attachments(attachments_raw) + inline_attachments_map(inline_attachments)
  74. end
  75. def inline_attachments_map(inline_attachments)
  76. inline_attachments.map do |elem|
  77. elem.slice(:data, :filename, :preferences)
  78. end
  79. end
  80. def attached_attachments(attachments_raw)
  81. form_id = attachments_raw[:form_id]
  82. file_meta = attachments_raw[:files]
  83. return [] if form_id.blank?
  84. UploadCache
  85. .new(form_id)
  86. .attachments
  87. .select do |elem|
  88. file_meta.any? { |file| check_attachment_match(elem, file) }
  89. end
  90. end
  91. def check_attachment_match(attachment, file)
  92. if file[:type].present? && attachment[:preferences].present? && attachment[:preferences]['Content-Type'].present?
  93. file[:name] == attachment[:filename] && file[:type] == attachment[:preferences]['Content-Type']
  94. end
  95. file[:name] == attachment[:filename]
  96. end
  97. def time_accounting(article, time_unit)
  98. return if time_unit.blank?
  99. Ticket::TimeAccounting.create!(
  100. ticket_id: article.ticket_id,
  101. ticket_article_id: article.id,
  102. time_unit: time_unit,
  103. )
  104. end
  105. def form_id_cleanup(attachments_raw)
  106. form_id = attachments_raw[:form_id]
  107. return if form_id.blank?
  108. # clear in-progress state from taskbar
  109. Taskbar
  110. .where(user_id: current_user.id)
  111. .first { |taskbar| taskbar.persisted_form_id == form_id }&.update!(state: {})
  112. # remove temporary attachment cache
  113. UploadCache
  114. .new(form_id)
  115. .destroy
  116. end
  117. def agent_on_ticket?(_ticket)
  118. current_user.permissions?('ticket.agent')
  119. end
  120. def display_name(user)
  121. if user.fullname.present? && user.email.present?
  122. return Channel::EmailBuild.recipient_line user.fullname, user.email
  123. end
  124. return user.fullname if user.fullname.present?
  125. display_name_fallback(user)
  126. end
  127. def display_name_fallback(user)
  128. user.email.presence || user.phone.presence || user.login.presence || '-'
  129. end
  130. end