scinote-web/app/models/report.rb

156 lines
4.4 KiB
Ruby
Raw Normal View History

2020-10-14 18:12:32 +08:00
# frozen_string_literal: true
2017-06-23 21:19:08 +08:00
class Report < ApplicationRecord
2016-02-12 23:52:43 +08:00
include SearchableModel
include SearchableByNameModel
2016-02-12 23:52:43 +08:00
auto_strip_attributes :name, :description, nullify: false
2016-02-12 23:52:43 +08:00
validates :name,
length: { minimum: Constants::NAME_MIN_LENGTH,
maximum: Constants::NAME_MAX_LENGTH },
uniqueness: { scope: %i(user_id project_id), case_sensitive: false }
validates :description, length: { maximum: Constants::TEXT_MAX_LENGTH }
2016-02-12 23:52:43 +08:00
validates :project, presence: true
validates :user, presence: true
belongs_to :project, inverse_of: :reports
belongs_to :user, inverse_of: :reports
belongs_to :team, inverse_of: :reports
2017-06-28 21:21:32 +08:00
belongs_to :last_modified_by,
foreign_key: 'last_modified_by_id',
class_name: 'User',
optional: true
2016-02-12 23:52:43 +08:00
# Report either has many report elements (if grouped by timestamp),
# or many module elements (if grouped by module)
has_many :report_elements, inverse_of: :report, dependent: :delete_all
2016-02-12 23:52:43 +08:00
def self.search(
user,
include_archived,
query = nil,
2017-05-05 22:41:23 +08:00
page = 1,
_current_team = nil,
options = {}
2016-02-12 23:52:43 +08:00
)
project_ids =
Project
.search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT)
2017-04-11 20:55:44 +08:00
.pluck(:id)
2016-02-12 23:52:43 +08:00
2017-05-05 22:41:23 +08:00
new_query =
Report
2016-02-12 23:52:43 +08:00
.distinct
2017-05-05 22:41:23 +08:00
.where('reports.project_id IN (?)', project_ids)
.where_attributes_like(%i(name description), query, options)
2016-02-12 23:52:43 +08:00
# Show all results if needed
if page == Constants::SEARCH_NO_LIMIT
2016-02-12 23:52:43 +08:00
new_query
else
new_query
.limit(Constants::SEARCH_LIMIT)
.offset((page - 1) * Constants::SEARCH_LIMIT)
2016-02-12 23:52:43 +08:00
end
end
def self.viewable_by_user(user, teams)
where(project: Project.viewable_by_user(user, teams))
end
2016-02-12 23:52:43 +08:00
def root_elements
2020-10-14 18:12:32 +08:00
report_elements.order(:position).select { |el| el.parent.blank? }
2016-02-12 23:52:43 +08:00
end
# Save the JSON represented contents to this report
# (this action will overwrite any existing report elements)
def save_with_contents(json_contents)
begin
Report.transaction do
2020-10-14 18:12:32 +08:00
# First, save the report itself
2016-02-12 23:52:43 +08:00
save!
# Secondly, delete existing report elements
report_elements.destroy_all
# Lastly, iterate through contents
json_contents.each_with_index do |json_el, i|
save_json_element(json_el, i, nil)
end
end
rescue ActiveRecord::ActiveRecordError, ArgumentError
return false
end
2020-10-14 18:12:32 +08:00
true
2016-02-12 23:52:43 +08:00
end
2016-07-21 19:11:15 +08:00
# Clean report elements from report
# the function runs before the report is edit
def cleanup_report
2020-10-14 18:12:32 +08:00
report_elements.each(&:clean_removed_or_archived_elements)
2016-07-21 19:11:15 +08:00
end
def self.generate_whole_project_report(project, current_user, current_team)
2020-10-17 00:25:01 +08:00
report_contents = gen_element_content(project, Extends::EXPORT_ALL_PROJECT_ELEMENTS)
report = Report.new
report.name = loop do
dummy_name = SecureRandom.hex(10)
break dummy_name unless Report.where(name: dummy_name).exists?
end
report.project = project
report.user = current_user
report.team = current_team
report.last_modified_by = current_user
report.save_with_contents(report_contents)
report
end
2020-10-17 00:25:01 +08:00
def self.gen_element_content(parent, children)
elements = []
2020-10-17 00:25:01 +08:00
children.each do |element|
element_hash = lambda { |object|
hash_object = {
'type_of' => element[:type_of] || element[:type_of_lambda].call(object),
'id' => { element[:id_key] => object.id },
'sort_order' => element[:sort_order],
2020-10-22 20:29:35 +08:00
'children' => gen_element_content(object, element[:children] || [])
2020-10-17 00:25:01 +08:00
}
hash_object['id'][element[:parent_id_key]] = parent.id if element[:parent_id_key]
hash_object
}
2020-10-14 18:08:04 +08:00
2020-10-17 00:25:01 +08:00
if element[:relation]
(element[:relation].inject(parent) { |p, method| p.public_send(method) }).each do |child|
elements.push(element_hash.call(child))
end
else
elements.push(element_hash.call(parent))
2020-10-14 18:08:04 +08:00
end
end
2020-10-17 00:25:01 +08:00
elements
end
2016-02-12 23:52:43 +08:00
private
# Recursively save a single JSON element
def save_json_element(json_element, index, parent)
el = ReportElement.new
el.position = index
el.report = self
el.parent = parent
2017-03-09 23:02:52 +08:00
el.type_of = json_element['type_of']
el.sort_order = json_element['sort_order']
el.set_element_references(json_element['id'])
2016-02-12 23:52:43 +08:00
el.save!
2017-03-09 23:02:52 +08:00
if json_element['children'].present?
json_element['children'].each_with_index do |child, i|
2016-02-12 23:52:43 +08:00
save_json_element(child, i, el)
end
end
end
end