Newer
Older
dmpopidor / app / controllers / api / v0 / plans_controller.rb
# frozen_string_literal: true

class Api::V0::PlansController < Api::V0::BaseController

  before_action :authenticate

  ##
  # Creates a new plan based on the information passed in JSON to the API
  def create
    @template = Template.live(params[:template_id])
    unless Api::V0::PlansPolicy.new(@user, @template).create?
      raise Pundit::NotAuthorizedError
    end

    plan_user = User.find_by(email: params[:plan][:email])
    # ensure user exists
    if plan_user.blank?
      User.invite!({ email: params[:plan][:email] }, @user)
      plan_user = User.find_by(email: params[:plan][:email])
      plan_user.org = @user.org
      plan_user.save
    end
    # ensure user's organisation is the same as api user's
    unless plan_user.org == @user.org
      raise Pundit::NotAuthorizedError, _("user must be in your organisation")
    end

    # initialize the plan
    @plan = Plan.new
    if plan_user.surname.blank?
      @plan.principal_investigator = nil
    else
      @plan.principal_investigator = plan_user.anem(false)
    end

    @plan.data_contact = plan_user.email
    # set funder name to template's org, or original template's org
    if @template.customization_of.nil?
      @plan.funder_name = @template.org.name
    else
      @plan.funder_name = Template.where(
        family_id: @template.customization_of
      ).first.org.name
    end
    @plan.template = @template
    @plan.title = params[:plan][:title]
    if @plan.save
      @plan.assign_creator(plan_user)
      respond_with @plan
    else
      # the plan did not save
      self.headers["WWW-Authenticate"] = "Token realm=\"\""
      render json: _("Bad Parameters"), status: 400
    end
  end

  def index
    unless Api::V0::PlansPolicy.new(@user, nil).index?
      raise Pundit::NotAuthorizedError
    end
    if params[:per_page].present? && params[:per_page].to_i > Rails.configuration.branding[:application][:api_max_page_size]
      params[:per_page] = Rails.configuration.branding[:application][:api_max_page_size]
    end
    @plans = @user.org.plans.includes( [ {roles: :user}, {answers: :question_options} ,
      template: [ { phases: { sections: { questions: [:question_format, :themes ] } } }, :org]
      ])

    # Filter on list of users
    user_ids = extract_param_list(params, "user")
    @plans = @plans.where(roles: {user_id: user_ids, access: Role.bit_values(:editor)}) if user_ids.present?
    # filter on dates
    if params["created_after"].present? || params["created_before"].present?
      @plans = @plans.where(created_at: dates_to_range(params,"created_after","created_before"))
    end
    if params["updated_after"].present? || params["updated_before"].present?
      @plans = @plans.where(updated_at: dates_to_range(params,"updated_after","updated_before"))
    end
    if params["remove_tests"].present? && params["remove_tests"].downcase == "true"
      @plans = @plans.where.not(visibility: Plan.visibilities[:is_test])
    end
    # filter on funder (dmptemplate_id)
    template_ids = extract_param_list(params, "template")
    @plans = @plans.where(templates: {family_id: template_ids}) if template_ids.present?
    # filter on id(s)
    plan_ids = extract_param_list(params, "plan")
    @plans = @plans.where(id: plan_ids ) if plan_ids.present?
    # apply pagination after filtering
    @plans = paginate @plans
    respond_with @plans
  end

  private

  def extract_param_list(params, attribute)
    list = params.fetch(attribute+"[]", [])
    val = params.fetch(attribute, [])
    list << val if val.present?
    list
  end

  # takes in the params hash and converts to a date-range
  def dates_to_range(hash,start,stop)
    today = Date.today
    start_date = Date.parse(hash.fetch(start, today.prev_month.to_date.to_s))
    end_date = Date.parse(hash.fetch(stop, today.to_date.to_s)) + 1.day
    start_date..end_date
  end

end