codeRIT/hackathon_manager

View on GitHub
app/jobs/bulk_message_job.rb

Summary

Maintainability
A
0 mins
Test Coverage
class BulkMessageJob < ApplicationJob
  queue_as :default

  def perform(message)
    return unless message.status == "queued"

    message.update_attribute(:started_at, Time.now)

    recipients = self.class.build_recipients(message.recipients)

    recipients.each do |recipient|
      UserMailer.bulk_message_email(message.id, recipient).deliver_later
    end

    message.update_attribute(:delivered_at, Time.now)
  end

  def self.build_recipients(recipient_types)
    recipients = Set.new
    recipient_types.each do |type|
      recipients += user_ids(type)
    end
    recipients
  end

  # rubocop:disable CyclomaticComplexity
  def self.user_ids(type)
    case type
    when "all"
      # Everyone, including organizers that completed a questionnaire
      User.non_organizer.pluck(:id) + Questionnaire.pluck(:user_id)
    when "incomplete"
      # Incomplete applications, excluding organizers that don't have a questionnaire
      User.non_organizer.pluck(:id) - Questionnaire.pluck(:user_id)
    when "complete"
      Questionnaire.pluck(:user_id)
    when "accepted"
      Questionnaire.where(acc_status: "accepted").pluck(:user_id)
    when "denied"
      Questionnaire.where(acc_status: "denied").pluck(:user_id)
    when "waitlisted"
      Questionnaire.where(acc_status: "waitlist").pluck(:user_id)
    when "late-waitlisted"
      Questionnaire.where(acc_status: "late_waitlist").pluck(:user_id)
    when "rsvp-confirmed"
      Questionnaire.where(acc_status: "rsvp_confirmed").pluck(:user_id)
    when "rsvp-denied"
      Questionnaire.where(acc_status: "rsvp_denied").pluck(:user_id)
    when "checked-in"
      Questionnaire.where("checked_in_at IS NOT NULL").pluck(:user_id)
    when "non-checked-in"
      Questionnaire.where("(acc_status = 'accepted' OR acc_status = 'rsvp_confirmed' OR acc_status = 'rsvp_denied') AND checked_in_at IS NULL").pluck(:user_id)
    when "non-checked-in-excluding"
      Questionnaire.where("acc_status != 'accepted' AND acc_status != 'rsvp_confirmed' AND acc_status != 'rsvp_denied' AND checked_in_at IS NULL").pluck(:user_id)
    when /(.*)::(\d*)/
      user_ids_from_query(type)
    else
      raise "Unknown recipient type: #{type.inspect}"
    end
  end
  # rubocop:enable CyclomaticComplexity

  def self.user_ids_from_query(type)
    # Parse the query
    # See app/models/message_recipient_query.rb for how this works
    recipient_query = MessageRecipientQuery.parse(type)
    model = recipient_query.model

    # Build the recipients query
    case recipient_query.type
    when "bus-list"
      model.passengers.pluck(:user_id)
    when "school"
      Questionnaire.where("school_id = ? AND (acc_status = 'rsvp_confirmed' OR acc_status = 'accepted')", model.id).pluck(:user_id)
    when "blazer"
      result = Blazer::RunStatement.new.perform(Blazer.data_sources[model.data_source], model.statement)
      user_id_column = result.columns.index("user_id")
      raise "Blazer query is missing required \"user_id\" column" unless user_id_column.present?

      result.rows.map { |row| row[user_id_column] }
    else
      raise "Unknown recipient query type: #{recipient_query.type.inspect} (in message recipient query: #{type.inspect}"
    end
  end
end