sanger/sequencescape

View on GitHub
app/controllers/qc_reports_controller.rb

Summary

Maintainability
A
1 hr
Test Coverage
C
73%
# frozen_string_literal: true
class QcReportsController < ApplicationController
  before_action :login_required
  before_action :check_required, only: :create

  def index # rubocop:todo Metrics/AbcSize
    # Build a conditions hash of acceptable parameters, ignoring those that are blank

    @qc_reports = QcReport.for_report_page(conditions).page(params[:page]).includes(:study, :product)
    @qc_report = QcReport.new(exclude_existing: true, study_id: params[:study_id])
    @studies = Study.alphabetical.pluck(:name, :id)
    @states = QcReport.available_states.map { |s| [s.humanize, s] }

    @all_products = Product.alphabetical.all.map { |product| [product.display_name, product.id] }
    @active_products =
      Product.with_stock_report.active.alphabetical.all.map { |product| [product.display_name, product.id] }
    @plate_purposes = PlatePurpose.pluck(:name).sort
  end

  # rubocop:todo Metrics/MethodLength
  def show # rubocop:todo Metrics/AbcSize
    qc_report = QcReport.find_by!(report_identifier: params[:id])
    queue_count = qc_report.queued? ? Delayed::Job.count : 0
    @report_presenter = Presenters::QcReportPresenter.new(qc_report, queue_count)

    respond_to do |format|
      format.html

      format.csv do
        file = nil
        begin
          file = Tempfile.new(@report_presenter.filename)
          @report_presenter.to_csv(file)
          file.flush
        ensure
          file.close unless file.nil?
        end
        send_file file.path, content_type: 'text/csv', filename: @report_presenter.filename
      end if qc_report.available?
    end
  end

  # rubocop:enable Metrics/MethodLength

  def create # rubocop:todo Metrics/AbcSize, Metrics/MethodLength
    study = Study.find_by(id: params[:qc_report][:study_id])
    exclude_existing = params[:qc_report][:exclude_existing] == '1'
    qc_report =
      QcReport.new(
        study: study,
        product_criteria: @product.stock_criteria,
        exclude_existing: exclude_existing,
        plate_purposes: params[:qc_report][:plate_purposes].try(:reject, &:blank?)
      )

    if qc_report.save
      flash[:notice] = 'Your report has been requested and will be presented on this page when complete.'
      redirect_to qc_report
    else
      # We failed to save
      error_messages = qc_report.errors.full_messages.join('; ')
      flash[:error] = "Failed to create report: #{error_messages}"
      redirect_back fallback_location: root_path
    end
  end

  # On form submit of a qc_file. Strictly speaking this should be an update action
  # on the qc_report itself. However we don't want to force the user to extract
  # the report identifier from the file.
  def qc_file
    qc_file = params[:qc_report_file]
    overide_qc = params[:overide_qc_decision] == '1'
    file = QcReport::File.new(qc_file, overide_qc, qc_file.original_filename, qc_file.content_type)
    if file.process
      redirect_to file.qc_report
    else
      flash[:error] = "Failed to read report: #{file.errors.join('; ')}"
      redirect_back fallback_location: root_path
    end
  end

  private

  def check_required # rubocop:todo Metrics/AbcSize
    return fail('No report options were provided') if params[:qc_report].blank?
    return fail('You must select a product') if params[:qc_report][:product_id].nil?

    @product = Product.find_by(id: params[:qc_report][:product_id])
    return fail('Could not find product') if @product.nil?
    return fail("#{product.name} is inactive") if @product.deprecated?
    return fail("#{product.name} does not have any stock criteria set") if @product.stock_criteria.nil?

    true
  end

  def fail(message)
    redirect_back fallback_location: root_path, alert: message
    false
  end

  def conditions # rubocop:todo Metrics/AbcSize
    conds = {}
    conds[:study_id] = params[:study_id] if params[:study_id].present?
    conds[:product_criteria] = { product_id: params[:product_id] } if params[:product_id].present?
    conds[:state] = params[:state] if params[:state].present?
    conds
  end
end