class Api::V1::Issues::CreateService < ApplicationService include ActiveModel::Model include Api::V1::Issues::Concerns::Checkable include Api::V1::Issues::Concerns::Loadable attr_reader :project, :current_user attr_reader :status_id, :priority_id, :milestone_id, :branch_name, :start_date, :due_date, :subject, :description, :blockchain_token_num attr_reader :issue_tag_ids, :assigner_ids, :attachment_ids, :receivers_login attr_accessor :created_issue validates :subject, presence: true validates :status_id, :priority_id, presence: true validates :project, :current_user, presence: true validates :blockchain_token_num, numericality: {greater_than: 0}, allow_blank: true def initialize(project, params, current_user = nil) @project = project @current_user = current_user @status_id = params[:status_id] @priority_id = params[:priority_id] @milestone_id = params[:milestone_id] @branch_name = params[:branch_name] @start_date = params[:start_date] @due_date = params[:due_date] @subject = params[:subject] @description = params[:description] @blockchain_token_num = params[:blockchain_token_num] @issue_tag_ids = params[:issue_tag_ids] @assigner_ids = params[:assigner_ids] @attachment_ids = params[:attachment_ids] @receivers_login = params[:receivers_login] end def call raise Error, errors.full_messages.join(", ") unless valid? ActiveRecord::Base.transaction do check_issue_status(status_id) check_issue_priority(priority_id) check_milestone(milestone_id) if milestone_id.present? check_issue_tags(issue_tag_ids) unless issue_tag_ids.blank? check_assigners(assigner_ids) unless assigner_ids.blank? check_attachments(attachment_ids) unless attachment_ids.blank? check_atme_receivers(receivers_login) unless receivers_login.blank? check_blockchain_token_num(current_user.id, project.id, blockchain_token_num) if blockchain_token_num.present? load_assigners(assigner_ids) unless assigner_ids.blank? load_attachments(attachment_ids) unless attachment_ids.blank? load_issue_tags(issue_tag_ids) unless issue_tag_ids.blank? load_atme_receivers(receivers_login) unless receivers_login.blank? try_lock("Api::V1::Issues::CreateService:#{project.id}") # 开始写数据,加锁 @created_issue = Issue.new(issue_attributes) build_author_participants build_assigner_participants unless assigner_ids.blank? build_atme_participants if @atme_receivers.present? build_issue_journal_details build_issue_project_trends @created_issue.assigners = @assigners unless assigner_ids.blank? @created_issue.attachments = @attachments unless attachment_ids.blank? @created_issue.issue_tags = @issue_tags unless issue_tag_ids.blank? @created_issue.issue_tags_value = @issue_tags.order("id asc").pluck(:id).join(",") unless issue_tag_ids.blank? @created_issue.save! if Site.has_blockchain? && @project.use_blockchain if @created_issue.blockchain_token_num.present? && @created_issue.blockchain_token_num > 0 Blockchain::CreateIssue.call({user_id: current_user.id, project_id: @created_issue.project_id, token_num: @created_issue.blockchain_token_num}) end push_activity_2_blockchain("issue_create", @created_issue) end project.del_project_issue_cache_delete_count # 把缓存里存储项目删除issue的个数清除掉 # 新增时向grimoirelab推送事件 IssueWebhookJob.set(wait: 5.seconds).perform_later(@created_issue.id) # @信息发送 AtmeService.call(current_user, @atme_receivers, @created_issue) unless receivers_login.blank? # 发消息 if Site.has_notice_menu? SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @created_issue&.id, assigner_ids) unless assigner_ids.blank? SendTemplateMessageJob.perform_later('ProjectIssue', current_user.id, @created_issue&.id) end # 触发webhook TouchWebhookJob.set(wait: 5.seconds).perform_later('IssueCreate', @created_issue&.id, current_user.id) TouchWebhookJob.set(wait: 5.seconds).perform_later('IssueLabel', @created_issue&.id, current_user.id, {issue_tag_ids: [[], issue_tag_ids]}) unless issue_tag_ids.blank? TouchWebhookJob.set(wait: 5.seconds).perform_later('IssueAssign', @created_issue&.id, current_user.id, {assigner_ids: [[], assigner_ids]}) unless assigner_ids.blank? unlock("Api::V1::Issues::CreateService:#{project.id}") # 结束写数据,解锁 end return @created_issue end private def issue_attributes issue_attributes = { subject: subject, project_id: project.id, author_id: current_user.id, tracker_id: Tracker.first.id, status_id: status_id, priority_id: priority_id, project_issues_index: (project.get_last_project_issues_index + 1), issue_type: "1", issue_classify: "issue" } issue_attributes.merge!({description: description}) if description.present? issue_attributes.merge!({fixed_version_id: milestone_id}) if milestone_id.present? issue_attributes.merge!({start_date: start_date}) if start_date.present? issue_attributes.merge!({due_date: due_date}) if due_date.present? issue_attributes.merge!({branch_name: branch_name}) if branch_name.present? issue_attributes.merge!({blockchain_token_num: blockchain_token_num}) if blockchain_token_num.present? issue_attributes end def build_author_participants @created_issue.issue_participants.new({participant_type: "authored", participant_id: current_user.id}) end def build_assigner_participants assigner_ids.each do |aid| @created_issue.issue_participants.new({participant_type: "assigned", participant_id: aid}) end end def build_atme_participants @atme_receivers.each do |receiver| @created_issue.issue_participants.new({participant_type: "atme", participant_id: receiver.id}) end end def build_issue_project_trends @created_issue.project_trends.new({user_id: current_user.id, project_id: @project.id, action_type: "create"}) @created_issue.project_trends.new({user_id: current_user.id, project_id: @project.id, action_type: ProjectTrend::CLOSE}) if status_id.to_i == 5 end def build_issue_journal_details journal = @created_issue.journals.new({user_id: current_user.id}) journal.journal_details.new({property: "issue", prop_key: 1, old_value: '', value: ''}) end end