class Ecs::ImportCourseStudentAchievementService < ApplicationService Error = Class.new(StandardError) attr_reader :ec_year, :course_evaluation, :attachment def initialize(course_evaluation, attachment_id) @course_evaluation = course_evaluation @ec_year = course_evaluation.ec_course.ec_year @attachment = Attachment.find_by(id: attachment_id) end def call raise Error, '文件不存在' if attachment.blank? raise Error, '请先导入学生数据' if ec_year.ec_year_students.count.zero? path = attachment.diskfile excel = Ecs::ImportAchievementExcel.new(path) ActiveRecord::Base.transaction do course_evaluation.ec_student_achievements.delete_all handler = excel.average_score_template? ? :average_score_handler : :detail_score_handler EcStudentAchievement.bulk_insert(*achievement_columns) do |worker| excel.read_each do |arr| send(handler, worker, arr) end end score_type = excel.average_score_template? ? :average : :detail current_course_evaluation.update!(import_status: true, score_type: score_type) end rescue BaseImportExcel::Error => ex raise Error, ex.message end private def achievement_columns %i[ score student_name student_number position ec_year_student_id ec_course_evaluation_id ec_course_evaluation_subitem_id created_at updated_at ] end def average_score_handler(worker, arr) items_size = course_evaluation.ec_course_evaluation_subitems.size ec_year.ec_year_students.find_each do |student| course_evaluation.ec_course_evaluation_subitems.each_with_index do |evaluation_subitem, index| course_evaluation.evaluation_count.times do |times| score = arr[times * items_size + index].to_i # 共4个分项:第一次考核的第三项下标为 0 * 4 + 2,即 2 attrs = { score: score, student_name: student.name, student_number: student.student_id, position: times + 1, ec_year_student_id: student.id, ec_course_evaluation_id: course_evaluation.id, ec_course_evaluation_subitem_id: evaluation_subitem.id } worker.add(attrs) end end end end def detail_score_handler(worker, arr) student = ec_year_students.find_by(student_id: arr[0].is_a?(Float) ? arr[0].to_i : arr[0].to_s.strip) return if student.blank? items_size = course_evaluation.ec_course_evaluation_subitems.size course_evaluation.ec_course_evaluation_subitems.each_with_index do |evaluation_subitem, index| course_evaluation.evaluation_count.times do |times| # 因为0和1是学号和姓名,所以下标要 + 2 score = arr[times * items_size + 2 + index].to_i # 共4个分项:第一次考核的第三项下标为 0 * 4 + 2 + 2,即 arr[4] attrs = { score: score, student_name: student.name, student_number: student.student_id, position: times + 1, ec_year_student_id: student.id, ec_course_evaluation_id: course_evaluation.id, ec_course_evaluation_subitem_id: evaluation_subitem.id } worker.add(attrs) end end end end