create.rb 4.5 KB

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