dobtco/procure-io

View on GitHub
app/controllers/projects_controller.rb

Summary

Maintainability
A
0 mins
Test Coverage
class ProjectsController < ApplicationController
  # Load
  load_resource


  before_filter only: [:new] { |c| c.authorize! :create, Project }
  before_filter only: [:admin] { |c| c.authorize! :collaborate_on, @project }
  before_filter only: [:import_csv, :post_import_csv] { |c| c.authorize! :import_bids, @project }
  before_filter only: [:export_csv, :post_export_csv] { |c| c.authorize! :export_bids, @project }
  before_filter only: [:review_mode, :post_review_mode] { |c| c.authorize! :change_review_mode, @project }
  before_filter only: [:teams, :add_team, :remove_team] { |c| c.authorize! :manage_teams, @project }
  before_filter only: [:edit, :update] { |c| c.authorize! :update, @project }
  before_filter :ensure_user_has_permission_to_create_project, only: :create

  def index
    search_results = Project.searcher(params)
    @projects = search_results[:results]
    @filter_params = { category: params[:category], q: params[:q] }

    respond_to do |format|
      format.html do
        @bootstrap_data = serialized(@projects, SearchProjectSerializer, meta: search_results[:meta])
      end

      format.json { render_serialized(@projects, SearchProjectSerializer, meta: search_results[:meta]) }
      format.rss { render layout: false }
    end
  end

  # generic landing page for the backend
  def admin
    redirect_to (can? :update, @project) ? edit_project_path : project_bids_path(@project)
  end

  def comments
    authorize! :comment_on, @project
    current_user.read_notifications(@project, :project_comment)
    @comments_json = serialized(@project.comments).to_json
  end

  def teams
    @teams = @project.teams.order("teams.name").references(:teams)
  end

  def add_team
    @team = @project.organization.teams.find(params[:team_id])
    @project.teams << @team
    redirect_to :back
  end

  def remove_team
    @team = @project.organization.teams.find(params[:team_id])
    @project.teams.delete(@team) unless @team.is_owners
    redirect_to :back
  end

  def show
    authorize! :read, @project
    current_user.read_notifications(@project, :project_amended, :added_your_team_to_project, :question_answered) if current_user
    @questions = @project.questions
    impressionist(@project)
  end

  def new
  end

  def create
    @project.assign_attributes(project_params)

    if @project.save
      @project.teams << current_user.highest_ranking_team_for_organization(@project.organization)
      redirect_to created_project_path(@project)
    else
      render "new"
    end
  end

  def created
  end

  def edit
    current_user.read_notifications(@project, :added_your_team_to_project)
  end

  def update
    if @project.update_attributes(project_params)
      @project.tags = []

      params[:project][:tags].split(",").each do |name|
        @tag = Tag.where("lower(name) = ?", name.strip.downcase).first || Tag.create(name: name.strip)
        @project.tags << @tag
      end

      params[:new_attachments].each do |new_attachment|
        @project.project_attachments.create(upload: new_attachment)
      end

      redirect_to edit_project_path(@project)
    else
      render :edit
    end
  end

  def destroy
    authorize! :destroy, @project
    @project.destroy
    redirect_to root_path
  end

  def import_csv
  end

  def post_import_csv
    file_contents = params.delete(:file).read
    importer = CsvBidImporter.delay.new(@project, file_contents, params, current_user)
    flash[:success] = "Hang tight, we're importing your bids. Give us a minute, and we'll notify you when we're done."
    redirect_to project_bids_path(@project)
  end

  def export_csv
  end

  def post_export_csv
    require 'csv'
    @bids = @project.bids.submitted

    bids_csv = CSV.generate do |csv|
      headers = ["Vendor Name"]
      headers.push *@project.response_fields.map(&:label)
      headers.push "Labels", "Status", "Submitted At"
      csv << headers

      @bids.each do |bid|
        bid_row = [(bid.vendor ? bid.vendor.name : "-")]
        responses = bid.responses

        @project.response_fields.each do |response_field|
          response = responses.select { |br| br.response_field_id == response_field.id }[0]
          bid_row.push(response ? response.value : '')
        end

        bid_row.push bid.labels.map(&:name).join(', '), bid.text_status, bid.submitted_at
        csv << bid_row
      end
    end

    send_data(bids_csv, type: 'test/csv', filename: "#{@project.title.parameterize.underscore}_bids_export_#{Time.now.strftime("%m_%d_%y")}.csv")
  end

  def review_mode
  end

  def post_review_mode
    @project.update_attributes pick(params[:project], :review_mode)
    flash[:success] = t('g.updated_project_review_mode')
    redirect_to review_mode_project_path(@project)
  end

  def response_fields
    authorize! :manage_response_fields, @project
  end

  def reviewer_leaderboard
    bid_ids = @project.bids.pluck(:id)

    @leaderboard = BidReview.select("user_id, COUNT(user_id) as review_count").where("bid_id IN (?)", bid_ids).group("user_id")

    if @project.review_mode == Project.review_modes[:stars]
      @leaderboard = @leaderboard.where(starred: true)
    else # one_through_five
      @leaderboard = @leaderboard.where("rating IS NOT NULL")
    end

    @leaderboard = @leaderboard.order("review_count DESC").paginate(page: params[:page])
  end

  private
  def project_params(*extra_params)
    filtered_params = params.require(:project).permit(:featured, :title, :abstract, :body, :bids_due_at,
                                                      :question_period_ends_at, :posted, *extra_params)

    if !filtered_params[:body].blank?
      require 'sanitize'
      filtered_params[:body] = Sanitize.clean(filtered_params[:body], Sanitize::Config::RELAXED)
    end

    {current_user: current_user}.merge(filtered_params)
  end

  def ensure_user_has_permission_to_create_project
    @project.organization_id = params[:project][:organization_id]

    if !(can? :create, @project)
      # @todo this is pretty annoying behavior.
      flash.now[:error] = "Sorry, you don't have permission to create a new project for that organization."
      render "new"
    end
  end
end