# == Schema Information # # Table name: journals # # id :integer not null, primary key # journalized_id :integer default("0"), not null # journalized_type :string(30) default(""), not null # user_id :integer default("0"), not null # notes :text(4294967295) # created_on :datetime not null # private_notes :boolean default("0"), not null # parent_id :integer # comments_count :integer default("0") # reply_id :integer # review_id :integer # commit_id :string(255) # diff :text(4294967295) # line_code :string(255) # path :string(255) # state :integer default("0") # resolve_at :datetime # resolveer_id :integer # need_respond :boolean default("0") # updated_on :datetime # # Indexes # # index_journals_on_created_on (created_on) # index_journals_on_journalized_id (journalized_id) # index_journals_on_parent_id (parent_id) # index_journals_on_review_id (review_id) # index_journals_on_user_id (user_id) # journals_journalized_id (journalized_id,journalized_type) # class Journal < ApplicationRecord serialize :diff, JSON alias_attribute :note, :notes belongs_to :user belongs_to :issue, foreign_key: :journalized_id, :touch => true, optional: true belongs_to :journalized, polymorphic: true belongs_to :review, optional: true belongs_to :resolveer, class_name: 'User', foreign_key: :resolveer_id, optional: true belongs_to :parent_journal, class_name: 'Journal', foreign_key: :parent_id, optional: true, counter_cache: :comments_count belongs_to :reply_journal, class_name: 'Journal', foreign_key: :reply_id, optional: true has_many :journal_details, :dependent => :delete_all has_many :attachments, as: :container, dependent: :destroy has_many :first_ten_children_journals, -> { order(created_on: :asc).limit(20)}, class_name: 'Journal', foreign_key: :parent_id has_many :children_journals, class_name: 'Journal', foreign_key: :parent_id, dependent: :destroy scope :journal_includes, ->{includes(:user, :journal_details, :attachments)} scope :parent_journals, ->{where(parent_id: nil)} scope :children_journals, lambda{|journal_id| where(parent_id: journal_id)} enum state: {opened: 0, resolved: 1, disabled: 2} after_save :associate_attachment_container def is_journal_detail? self.notes.blank? && self.journal_details.present? end # 关附件到功能 def associate_attachment_container return if self.issue&.project_id.to_i == 0 att_ids = [] # 附件的格式为(/api/attachments/ + 附件id)的形式,提取出id进行附件属性关联,做附件访问权限控制 att_ids += self.notes.to_s.scan(/\(\/api\/attachments\/.+\)/).map{|s|s.match(/\d+/)[0]} att_ids += self.notes.to_s.scan(/\/api\/attachments\/.+\"/).map{|s|s.match(/\d+/)[0]} att_ids += self.notes.to_s.scan(/\/api\/attachments\/\d+/).map{|s|s.match(/\d+/)[0]} if att_ids.present? Attachment.where(id: att_ids).where("container_type IS NULL OR container_type = 'Journal'").update_all(container_id: self.issue.project_id, container_type: "Project") end att_ids2 = [] # uuid_regex= /[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/ # 附件的格式为(/api/attachments/ + uuid)的形式,提取出id进行附件属性关联,做附件访问权限控制 att_ids2 += self.notes.to_s.scan(/\(\/api\/attachments\/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\)/).map{|s|s.match(/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/)[0]} att_ids2 += self.notes.to_s.scan(/\/api\/attachments\/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/).map{|s|s.match(/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/)[0]} if att_ids2.present? Attachment.where(uuid: att_ids).where("container_type IS NULL OR container_type = 'Journal'").update_all(container_id: self.issue.project_id, container_type: "Project") end end def operate_content content = "" detail = self.journal_details.take case detail.property when 'issue' return "创建了疑修" when 'attachment' old_value = Attachment.where("id in (?) or uuid in (?)", detail.old_value.to_s.split(","), detail.old_value.to_s.split(",")).pluck(:filename).join("、") new_value = Attachment.where("id in (?) or uuid in (?)", detail.value.to_s.split(","), detail.value.to_s.split(",")).pluck(:filename).join("、") if old_value.nil? || old_value.blank? content += "添加了#{new_value}附件" else new_value = "无" if new_value.blank? content += "将附件由#{old_value}更改为#{new_value}" end when 'issue_tag' old_value = IssueTag.where(id: detail.old_value.split(",")).pluck(:name).join("、") new_value = IssueTag.where(id: detail.value.split(",")).pluck(:name).join("、") if old_value.nil? || old_value.blank? content += "添加了#{new_value}标记" else new_value = "无" if new_value.blank? content += "将标记由#{old_value}更改为#{new_value}" end when 'assigner' old_value = User.where(id: detail.old_value.split(",")).map{|u| u.real_name}.join("、") new_value = User.where(id: detail.value.split(",")).map{|u| u.real_name}.join("、") if old_value.nil? || old_value.blank? content += "添加负责人#{new_value}" else new_value = "无" if new_value.blank? content += "将负责人由#{old_value}更改为#{new_value}" end when 'attr' content = "将" case detail.prop_key when 'subject' return "修改了标题" when 'description' return "修改了描述" when 'status_id' old_value = IssueStatus.find_by_id(detail.old_value)&.name new_value = IssueStatus.find_by_id(detail.value)&.name content += "状态" when 'priority_id' old_value = IssuePriority.find_by_id(detail.old_value)&.name new_value = IssuePriority.find_by_id(detail.value)&.name content += "优先级" when 'fixed_version_id' old_value = Version.find_by_id(detail.old_value)&.name new_value = Version.find_by_id(detail.value)&.name content += "里程碑" when 'branch_name' old_value = detail.old_value new_value = detail.value content += "关联分支" when 'start_date' old_value = detail.old_value new_value = detail.value content += "开始日期" when 'due_date' old_value = detail.old_value new_value = detail.value content += "结束日期" when 'assigned_to_id' old_value = User.find_by_id(detail.old_value)&.real_name new_value = User.find_by_id(detail.value)&.real_name content += "负责人" end if old_value.nil? || old_value.blank? content += "设置为#{new_value}" else new_value = "无" if new_value.blank? content += "由#{old_value}更改为#{new_value}" end end end def journal_content send_details = [] if self.is_journal_detail? details = self.journal_details.select(:property, :prop_key, :old_value, :value).pluck(:property, :prop_key, :old_value, :value) if details.size > 0 details.each do |de| if de[0] == "attr" content = "" else content = "附件" end old_value = de[2] value = de[3] if de[1].to_i > 0 prop_name = "" else prop_name = I18n.t("journal_detail.#{de[1]}") case de[1] when "description" old_value = "描述已更新" value = "修改了描述" when "is_private" old_value = I18n.t("journal_detail.#{de[2]}") value = I18n.t("journal_detail.#{de[3]}") when "assigned_to_id" u = User.select(:id, :login, :lastname, :firstname, :nickname) old_value = de[2].to_i > 0 ? u.find_by_id(de[2]).try(:show_real_name) : "" assign_user = de[3].to_i > 0 ? u.find_by_id(de[3]) : "" if assign_user.present? value = assign_user.try(:show_real_name) else value = "" end when "tracker_id" t = Tracker.select(:id, :name) old_value = de[2].to_i > 0 ? t.find_by_id(de[2]).try(:name) : "" tracker_name = de[3].to_i > 0 ? t.find_by_id(de[3]) : "" if tracker_name value = tracker_name.try(:name) else value = "" end when "status_id" t = IssueStatus.select(:id, :name) old_value = de[2].to_i > 0 ? t.find_by_id(de[2]).try(:name) : "" type_name = de[3].to_i > 0 ? t.find_by_id(de[3]) : "" if type_name value = type_name.try(:name) else value = "" end when "priority_id" t = IssuePriority.select(:id, :name) old_value = de[2].to_i > 0 ? t.find_by_id(de[2]).try(:name): "" type_name = de[3].to_i > 0 ? t.find_by_id(de[3]) : "" if type_name value = type_name.try(:name) else value = "" end when "issue_tags_value" t = IssueTag.select(:id, :name) old_value = de[2].to_i > 0 ? t.where(id: de[2].split(",")).select(:id,:name,:color).as_json : "" if de[3].present? value = t.where(id: de[3].split(",")).select(:id,:name,:color).as_json else value = "" end when "fixed_version_id" t = Version.select(:id, :name) old_value = de[2].to_i > 0 ? t.find_by_id(de[2]).try(:name) : "" type_name = de[3].to_i > 0 ? t.find_by_id(de[3]) : "" if type_name value = type_name.try(:name) else value = "" end when "end_time" t = IssueTime.select(:id, :start_time, :end_time) type_name = de[2].to_i > 0 ? t.find_by_id(de[2]) : "" if type_name.present? old_value = "停止工作" d_value = type_name.end_time.to_i - type_name.start_time.to_i value = "#{Time.at(d_value).utc.strftime('%H h %M min %S s')}" else old_value = "停止工作" value = "" end when "issue_depend" t = Issue.select(:id,:subject ) type_name = de[3].present? ? t&.find_by_id(de[3]) : "" if type_name.present? old_value = "增加依赖" value = { id: de[3], name: type_name.try(:subject) } else old_value = "增加依赖" value = "" end when "destroy_issue_depend" t = Issue.select(:id,:subject ) type_name = de[3].present? ? t&.find_by_id(de[3]) : "" if type_name.present? old_value = "删除依赖" value = { id: de[3], name: type_name.try(:subject) } else old_value = "删除依赖" value = "" end when "done_ratio" old_value = "#{de[2]}%" value = "#{de[3]}%" else old_value = de[2] value = de[3] end end prop_hash = { detail: (content + prop_name), old_value: old_value, value: value } send_details.push(prop_hash) end end end send_details end def to_builder Jbuilder.new do |journal| journal.(self, :id, :notes, :comments_count) if self.parent_journal.present? journal.parent_journal self.parent_journal.to_builder end if self.reply_journal.present? journal.reply_journal self.reply_journal.to_builder end end end end