require 'csv' require 'activerecord-import' require 'zip' module CanvasSync module Processors class ProvisioningReportProcessor # Used by the {CanvasSync::Importers::BulkImporter bulk importer}. The keys are # CSV columns and the values are the database columns. USERS_CSV_MAPPING = { canvas_user_id: :canvas_user_id, user_id: :sis_id, email: :email, first_name: :first_name, last_name: :last_name, status: :status, login_id: :login_id } COURSES_CSV_MAPPING = { canvas_course_id: :canvas_course_id, course_id: :sis_id, short_name: :short_name, long_name: :long_name, canvas_account_id: :canvas_account_id, canvas_term_id: :canvas_term_id, term_id: :term_sis_id, start_date: :start_date, end_date: :end_date, status: :status } ENROLLMENTS_CSV_MAPPING = { canvas_enrollment_id: :canvas_enrollment_id, canvas_course_id: :canvas_course_id, course_id: :course_sis_id, canvas_user_id: :canvas_user_id, user_id: :user_sis_id, role: :role, role_id: :role_id, canvas_section_id: :canvas_section_id, section_id: :section_sis_id, status: :status, base_role_type: :base_role_type } SECTIONS_CSV_MAPPING = { canvas_section_id: :canvas_section_id, section_id: :sis_id, canvas_course_id: :canvas_course_id, name: :name, status: :status, start_date: :start_date, end_date: :end_date } # Processes a provisioning report using the bulk importer. # # options must contain a models key. If there is only one model # Canvas downloads the single report directly as a CSV. If it's # more than one model Canvas downloads a ZIP file, so we have to # extract that and iterate through it for processing. # # @param report_file_path [String] # @param options [Hash] def self.process(report_file_path, options) if options[:models].length == 1 send("process_#{options[:models][0]}", report_file_path) else unzipped_file_path = extract(report_file_path) Dir[unzipped_file_path + "/*.csv"].each do |file_path| model_name = file_path.split("/").last.split(".").first send("process_#{model_name}", file_path) end end end private def self.extract(file_path) unzipped_file_path = "#{file_path}_unzipped" Zip::File.open(file_path) do |zip_file| zip_file.each do |f| f_path = File.join(unzipped_file_path, f.name) FileUtils.mkdir_p(File.dirname(f_path)) zip_file.extract(f, f_path) unless File.exist?(f_path) end end unzipped_file_path end def self.process_users(report_file_path) CanvasSync::Importers::BulkImporter.import( report_file_path, USERS_CSV_MAPPING, User, :canvas_user_id, true) end def self.process_courses(report_file_path) CanvasSync::Importers::BulkImporter.import(report_file_path, COURSES_CSV_MAPPING, Course, :canvas_course_id) end def self.process_enrollments(report_file_path) CanvasSync::Importers::BulkImporter.import( report_file_path, ENROLLMENTS_CSV_MAPPING, Enrollment, :canvas_enrollment_id, true) end def self.process_sections(report_file_path) CanvasSync::Importers::BulkImporter.import(report_file_path, SECTIONS_CSV_MAPPING, Section, :canvas_section_id) end end end end