create.rb 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. class Service::Ticket::Create < Service::BaseWithCurrentUser
  3. include Service::Concerns::HandlesCoreWorkflow
  4. def execute(ticket_data:)
  5. Transaction.execute do
  6. handle_shared_draft(ticket_data)
  7. set_core_workflow_information(ticket_data, ::Ticket, 'create_middle')
  8. article_data = ticket_data.delete(:article)
  9. tag_data = ticket_data.delete(:tags)
  10. link_data = ticket_data.delete(:links)
  11. find_or_create_customer(ticket_data)
  12. preprocess_ticket_data! ticket_data
  13. Ticket.new(ticket_data).tap do |ticket|
  14. Pundit.authorize current_user, ticket, :create?
  15. ticket.save!
  16. create_article(ticket, article_data)
  17. assign_tags(ticket, tag_data)
  18. add_links(ticket, link_data)
  19. end
  20. end
  21. end
  22. private
  23. def create_article(ticket, article_data)
  24. return if article_data.blank?
  25. preprocess_article_data! ticket, article_data
  26. Service::Ticket::Article::Create
  27. .new(current_user: current_user)
  28. .execute(article_data: article_data, ticket: ticket)
  29. end
  30. def assign_tags(ticket, tag_data)
  31. return if tag_data.blank?
  32. tag_data.each do |tag|
  33. next if !::Tag.tag_allowed?(name: tag.strip, user_id: current_user.id)
  34. ticket.tag_add(tag.strip)
  35. end
  36. end
  37. def add_links(ticket, link_data)
  38. return if link_data.blank?
  39. link_data.each do |link|
  40. Link.add(
  41. link_type: link[:link_type],
  42. link_object_target: link[:link_object].class.name,
  43. link_object_target_value: link[:link_object].id,
  44. link_object_source: 'Ticket',
  45. link_object_source_value: ticket.id,
  46. )
  47. end
  48. end
  49. def find_or_create_customer(ticket_data)
  50. return if ticket_data[:customer].blank? || ticket_data[:customer].is_a?(::User)
  51. email_address = ticket_data[:customer]
  52. EmailAddressValidation.new(email_address).valid!
  53. customer = User.find_by(email: email_address.downcase)
  54. if customer.present?
  55. ticket_data[:customer] = customer
  56. return
  57. end
  58. customer = User.create(
  59. firstname: '',
  60. lastname: '',
  61. email: email_address,
  62. password: '',
  63. active: true,
  64. )
  65. ticket_data[:customer] = customer
  66. end
  67. # Desktop UI supplies this data from frontend
  68. # Mobile UI leaves this processing for GraphQL
  69. def preprocess_ticket_data!(ticket_data)
  70. if customer?(ticket_data[:group]&.id)
  71. ticket_data[:customer_id] = current_user.id
  72. ticket_data.delete(:external_references)
  73. end
  74. move_issue_trackers_links_to_preferences(ticket_data)
  75. end
  76. # Desktop UI supplies this data from frontend
  77. # Mobile UI leaves this processing for GraphQL
  78. def preprocess_article_data!(ticket, article_input)
  79. if customer? ticket.group_id
  80. preprocess_permission_customer! ticket, article_input
  81. return
  82. end
  83. case article_input[:sender]
  84. when 'Customer'
  85. preprocess_article_data_customer! ticket, article_input
  86. when 'Agent'
  87. preprocess_article_data_agent! ticket, article_input
  88. end
  89. end
  90. def move_issue_trackers_links_to_preferences(ticket_data)
  91. external_references = ticket_data.delete(:external_references)
  92. return if external_references.blank?
  93. %i[github gitlab].each do |key|
  94. input = external_references[key]
  95. next if input.blank? || !Setting.get("#{key}_integration")
  96. ticket_data[:preferences] ||= {}
  97. ticket_data[:preferences][key] = { issue_links: input.map(&:to_s) }
  98. end
  99. # idoit
  100. idoit_object_ids = external_references[:idoit]
  101. return if idoit_object_ids.blank? || !Setting.get('idoit_integration')
  102. ticket_data[:preferences] ||= {}
  103. ticket_data[:preferences][:idoit] = { object_ids: idoit_object_ids }
  104. end
  105. def customer?(group_id)
  106. return if !current_user.permissions?('ticket.customer')
  107. !current_user.group_access?(group_id, :create)
  108. end
  109. def preprocess_permission_customer!(ticket, article_input)
  110. article_input.merge!(
  111. from: current_user.fullname,
  112. to: group_name(ticket)
  113. )
  114. end
  115. def preprocess_article_data_customer!(ticket, article_input)
  116. article_input.merge!(
  117. from: customer_recipient_line(ticket),
  118. to: group_name(ticket)
  119. )
  120. end
  121. def preprocess_article_data_agent!(ticket, article_input)
  122. article_input.merge!(
  123. from: group_name(ticket),
  124. to: customer_recipient_line(ticket)
  125. )
  126. end
  127. def group_name(ticket)
  128. ticket.group&.name || ''
  129. end
  130. def customer_recipient_line(ticket)
  131. customer = ticket.customer
  132. return if !customer
  133. Channel::EmailBuild.recipient_line "#{customer.firstname} #{customer.lastname}".presence, customer.email
  134. end
  135. def handle_shared_draft(ticket_data)
  136. shared_draft = ticket_data.delete(:shared_draft)
  137. return if !shared_draft
  138. if shared_draft.group_id != ticket_data[:group].id || !shared_draft.group.shared_drafts?
  139. raise Exceptions::UnprocessableEntity, __('Shared draft cannot be selected for this ticket.')
  140. end
  141. shared_draft.destroy!
  142. end
  143. end