canvas-lms/lib/canvas/account_reports.rb

125 lines
4.3 KiB
Ruby

#
# Copyright (C) 2011 - 2013 Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
require 'zip/zip'
module Canvas::AccountReports
REPORTS = {}
# account id is ignored; use PluginSetting to enable a subset of reports
def self.add_account_reports(account_id, module_name, reports)
reports.each do |report_type, details|
details = {:title => details} if details.is_a? String
details[:module] ||= module_name
details[:proc] ||= "Canvas::AccountReports::#{module_name}".constantize.method(report_type)
REPORTS[report_type] = details
end
end
# again, id is ignored; use PluginSetting to enable a subset of reports
def self.for_account(id)
settings = Canvas::Plugin.find(:account_reports).settings
return REPORTS.dup unless settings
enabled_reports = settings.select { |report, enabled| enabled }.map(&:first)
Hash[*REPORTS.select { |report, details| enabled_reports.include?(report) }.flatten]
end
def self.generate_report(account_report)
account_report.update_attribute(:workflow_state, 'running')
account_report.start_at ||= Time.now
begin
REPORTS[account_report.report_type][:proc].call(account_report)
rescue => e
account_report.logger.error e
er = ErrorReport.log_exception(:default, e, :user => account_report.user)
self.message_recipient(account_report, "Generating the report, #{account_report.report_type.to_s.titleize}, failed. Please report the following error code to your system administrator: ErrorReport:#{er.id}")
end
end
def self.generate_file_name(account_report, ext)
"#{account_report.report_type}_#{Time.now.strftime('%d_%b_%Y')}_#{account_report.id}_.#{ext}"
end
def self.generate_file(account_report, ext = 'csv')
temp = Tempfile.open(generate_file_name(account_report, ext))
filepath = temp.path
temp.close!
filepath
end
def self.message_recipient(account_report, message, csv=nil)
user = account_report.user
account = account_report.account
notification = Notification.by_name("Report Generated")
notification = Notification.by_name("Report Generation Failed") if !csv
attachment = nil
if csv.is_a? Hash
filename = generate_file_name(account_report, "zip")
temp = Tempfile.open(filename)
filepath = temp.path
temp.close!
Zip::ZipFile.open(filepath, Zip::ZipFile::CREATE) do |zipfile|
csv.each do |report_name, contents|
zipfile.get_output_stream(report_name + ".csv") { |f| f << contents }
end
zipfile
end
filetype = 'application/zip'
elsif csv
require 'action_controller_test_process'
ext = csv !~ /\n/ && File.extname(csv)
case ext
when ".csv"
filename = File.basename(csv);
filepath = csv
filetype = 'text/csv'
when ".zip"
filetype = 'application/zip'
when ".txt"
filename = File.basename(csv);
filepath = csv
filetype = 'text/rtf'
else
filename = generate_file_name(account_report, "csv")
f = Tempfile.open(filename)
f << csv
f.close
filepath = f.path
filetype = 'text/csv'
end
end
if filename
attachment = account.attachments.create!(
:uploaded_data => ActionController::TestUploadedFile.new(filepath, filetype, true),
:display_name => filename,
:user => user
)
end
account_report.message = message
account_report.attachment = attachment
account_report.workflow_state = csv ? 'complete' : 'error'
account_report.update_attribute(:progress, 100)
account_report.end_at ||= Time.now
account_report.save
notification.create_message(account_report, [user])
message
end
end