|
| 1 | +require "zip" |
| 2 | + |
| 3 | +class GenerateDataExportJob < ApplicationJob |
| 4 | + queue_as :default |
| 5 | + |
| 6 | + def perform(*args) |
| 7 | + data_export = args[0] |
| 8 | + # Prevent an already-started or already-completed job from running again |
| 9 | + return unless data_export.status == "queued" |
| 10 | + |
| 11 | + data_export.update_attribute(:started_at, Time.now) |
| 12 | + |
| 13 | + begin |
| 14 | + case data_export.export_type |
| 15 | + when "sponsor_dump_rsvp_confirmed" |
| 16 | + generate__sponsor_dump(data_export, "rsvp_confirmed") |
| 17 | + when "sponsor_dump_checked_in" |
| 18 | + generate__sponsor_dump(data_export, "checked_in") |
| 19 | + else |
| 20 | + raise "Unknown export type: #{data_export.export_type}" |
| 21 | + end |
| 22 | + |
| 23 | + data_export.update_attribute(:finished_at, Time.now) |
| 24 | + rescue => ex |
| 25 | + data_export.update_attribute(:started_at, nil) |
| 26 | + data_export.update_attribute(:finished_at, nil) |
| 27 | + # Re-raise the original exception |
| 28 | + raise |
| 29 | + end |
| 30 | + end |
| 31 | + |
| 32 | + private |
| 33 | + |
| 34 | + def generate__sponsor_dump(data_export, attendee_type) |
| 35 | + print data_export.file.name |
| 36 | + |
| 37 | + case attendee_type |
| 38 | + when "rsvp_confirmed" |
| 39 | + questionnaires = Questionnaire.where(acc_status: "rsvp_confirmed", can_share_info: true) |
| 40 | + when "checked_in" |
| 41 | + questionnaires = Questionnaire.where("checked_in_at > 0", can_share_info: true) |
| 42 | + else |
| 43 | + raise "Unknown attendee type: #{attendee_type}" |
| 44 | + end |
| 45 | + |
| 46 | + Dir.mktmpdir("data-export") do |dir| |
| 47 | + folder_path = File.join(dir, data_export.file_basename) |
| 48 | + Dir.mkdir(folder_path) |
| 49 | + zipfile_name = "#{data_export.file_basename}.zip" |
| 50 | + zipfile_path = File.join(dir, zipfile_name) |
| 51 | + |
| 52 | + # Download all of the resumes & generate CSV |
| 53 | + csv_data = [] |
| 54 | + resume_paths = [] |
| 55 | + questionnaires.each do |q| |
| 56 | + csv_row = [ |
| 57 | + q.first_name, |
| 58 | + q.last_name, |
| 59 | + q.school_name, |
| 60 | + q.email, |
| 61 | + q.vcs_url, |
| 62 | + q.portfolio_url, |
| 63 | + ] |
| 64 | + |
| 65 | + if q.resume.attached? |
| 66 | + filename = "#{q.id}-#{q.resume.filename.sanitized}" |
| 67 | + puts "--> Downloading #{q.id} resume, filename '#{filename}'" |
| 68 | + path = File.join(folder_path, filename) |
| 69 | + File.open(path, "wb") do |file| |
| 70 | + file.write(q.resume.download) |
| 71 | + end |
| 72 | + resume_paths << { path: path, filename: filename } |
| 73 | + csv_row << filename |
| 74 | + else |
| 75 | + csv_row << "" # No resume file |
| 76 | + end |
| 77 | + |
| 78 | + csv_data << csv_row |
| 79 | + end |
| 80 | + |
| 81 | + csvfile_name = "000-Attendees.csv" |
| 82 | + csvfile_path = File.join(folder_path, csvfile_name) |
| 83 | + CSV.open(csvfile_path, "wb") do |csv| |
| 84 | + csv << ["Fist name", "Last name", "School", "Email", "VCS URL", "Portfolio URL", "Resume filename"] |
| 85 | + csv_data.each do |row| |
| 86 | + csv << row |
| 87 | + end |
| 88 | + end |
| 89 | + |
| 90 | + # Zip up all of the files |
| 91 | + Zip::File.open(zipfile_path, Zip::File::CREATE) do |zipfile| |
| 92 | + # Add the CSV |
| 93 | + zipfile.add(csvfile_name, csvfile_path) |
| 94 | + # Add all resume files |
| 95 | + resume_paths.each do |resume| |
| 96 | + path = resume[:path] |
| 97 | + filename = resume[:filename] |
| 98 | + # Two arguments: |
| 99 | + # - The name of the file as it will appear in the archive |
| 100 | + # - The original file, including the path to find it |
| 101 | + zipfile.add(filename, path) |
| 102 | + end |
| 103 | + end |
| 104 | + |
| 105 | + # Attach the zip file to the record |
| 106 | + data_export.file.attach( |
| 107 | + io: File.open(zipfile_path), |
| 108 | + filename: zipfile_name, |
| 109 | + content_type: "application/zip", |
| 110 | + ) |
| 111 | + end |
| 112 | + end |
| 113 | +end |
0 commit comments