Association-Merci-Edgar/Merci-Edgar

View on GitHub
app/workers/contacts_import_worker.rb

Summary

Maintainability
C
1 day
Test Coverage
class ContactsImportWorker
  include SidekiqStatus::Worker
  sidekiq_options retry: false

  def perform(import_id)
    import = ContactsImport.find(import_id.to_i)
    Account.current_id = import.account_id
    current_account = import.account
    raise "Un autre import est déjà en cours. Merci d'attendre qu'il soit terminé" if current_account.importing_now
    current_account.importing_now = true
    current_account.save!

    user = import.user
    at(1, "Préparation du fichier...")
    import.contacts_file.cache_stored_file!
    at(1, "Suppression des anciens contacts tests...")
    current_account.destroy_test_contacts
    imported_at = import.updated_at.to_i
    current_account.test_imported_at = import.test_mode ? imported_at : nil
    current_account.last_import_at = imported_at unless import.test_mode
    current_account.importing_now = true
    current_account.save!
    at(1, "Démarrage de l'import...")

    filename = import.contacts_file.filename
    log_message, error = import_spreadsheet_file(import)

    if error.present?
      self.payload = { invalid_file: true, message: log_message }
      self.payload = { message: error }
      UserMailer.contacts_import_invalid(user).deliver unless import.test_mode
    else
      imported_contacts = Contact.where(imported_at: imported_at)
      nb_duplicates = imported_contacts.where("duplicate_id IS NOT NULL").count
      nb_imported_contacts = imported_contacts.count
      self.payload = { nb_imported_contacts: nb_imported_contacts, nb_duplicates: nb_duplicates, imported_at: imported_at, message: log_message }
      UserMailer.contacts_import_email(user, { account: current_account, filename: import.filename, imported_at: imported_at }).deliver unless import.test_mode
    end
  rescue StandardError => e
    UserMailer.contacts_import_error(user).deliver unless import.test_mode
  ensure
    if current_account
      current_account.importing_now = false
      current_account.save!
      import.destroy unless import.test_mode
    end
  end


  def import_spreadsheet_file(import)
    error_messages = []
    ActiveRecord::Base.transaction do
      at(1,"Conversion du fichier...")

      spreadsheet = SpreadsheetFile.new(import.contacts_file.file.path, import.contacts_kind)
      if spreadsheet.invalid?
        log_message = spreadsheet.errors.messages.values.flatten.join(' / ')
        return [ log_message, :invalid_file ]
      end

      log_message = import.updated_at.to_i

      imported_index = 0
      test_mode = import.test_mode
      nb_lines = spreadsheet.nb_lines

      total = test_mode && 20 < nb_lines ? 20 : nb_lines
      log_message = ""
      at(1,"Lecture du fichier...")

      total_chunks = SmarterCSV.process(spreadsheet.csv_path, col_sep: spreadsheet.col_sep, chunk_size: 100, file_encoding: spreadsheet.file_encoding, convert_values_to_numeric: {only: [:places_assises, :places_debout, :places_mixte, :ouverture_plateau, :profondeur_plateau, :hauteur_plateau]}) do |chunk|
        chunk.each do |row|
          imported_index += 1

          break if import.test_mode && imported_index > 20
          row[:imported_at] = import.updated_at.to_i
          row[:first_name_last_name_order] = import.first_name_last_name_order

          fine_contact, invalid_keys = spreadsheet.kind_klass.from_csv(row)

          if import.test_mode
            log_message << "#{row[:nom]} en cours d'import...\n"
            log_message << ">> Problème dans les colonnes #{invalid_keys.join(',')}\n" if invalid_keys.present?
            at(imported_index, log_message)
          end

          begin
            unless fine_contact.save
              error_messages << fine_contact.errors.full_messages
            end
          rescue StandardError => e
            error_messages << e.message
            break
          end
        end
      end
      [log_message, error_messages.join(', ')]
    end
  end

end