Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion app/controllers/api/v2/plans_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ module Api
module V2
class PlansController < BaseApiController # rubocop:todo Style/Documentation
respond_to :json
before_action :set_complete_param, only: %i[show index]

# GET /api/v2/plans/:id
def show
raise Pundit::NotAuthorizedError unless @scopes.include?('read')

@plan = Plan.find_by(id: params[:id])
@plan = Plan.includes(roles: :user).find_by(id: params[:id])

raise Pundit::NotAuthorizedError unless @plan.present?

Expand All @@ -28,6 +29,10 @@ def index
@items = paginate_response(results: @plans)
render '/api/v2/plans/index', status: :ok
end

def set_complete_param
@complete = params[:complete].to_s.downcase == 'true'
end
end
end
end
12 changes: 11 additions & 1 deletion app/policies/api/v2/plans_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,17 @@ def initialize(resource_owner) # rubocop:todo Lint/MissingSuper
end

def resolve
Plan.joins(:roles)
Plan.joins(
:roles
).includes(
:identifiers,
:research_outputs,
:template,
funder: :identifiers,
contributors: [:identifiers, { org: :identifiers }],
org: %i[region identifiers],
roles: [user: [:identifiers, { org: :identifiers }]]
)
.where(roles: { user_id: @resource_owner.id, active: true })
.distinct
end
Expand Down
19 changes: 9 additions & 10 deletions app/policies/api/v2/templates_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,22 @@ def initialize(resource_owner) # rubocop:todo Lint/MissingSuper
end

def resolve
# create the sql where clause
where_clause = <<-SQL
(visibility = 0 AND org_id = ?) OR
(visibility = 1 AND customization_of IS NULL)
SQL

# get the templates
Template
.includes(org: :identifiers)
.joins(:org)
.published
.where(
where_clause,
@resource_owner.org&.id
)
.merge(accessible_templates)
.order(:title)
end

private

def accessible_templates
org_templates = Template.organisationally_visible.where(org_id: @resource_owner.org&.id)
public_templates = Template.publicly_visible.where(customization_of: nil)
org_templates.or(public_templates)
end
end
end
end
Expand Down
30 changes: 25 additions & 5 deletions app/presenters/api/v2/plan_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ module Api
module V2
# Helper class for the API V2 project / DMP
class PlanPresenter
attr_reader :data_contact, :contributors, :costs
attr_reader :data_contact, :contributors, :costs, :complete_plan_data

def initialize(plan:)
def initialize(plan:, complete: false)
@contributors = []
return unless plan.present?

Expand All @@ -22,6 +22,8 @@ def initialize(plan:)
end

@costs = plan_costs(plan: @plan)

@complete_plan_data = fetch_all_q_and_a if complete
end

# Extract the ARK or DOI for the DMP OR use its URL if none exists
Expand All @@ -44,16 +46,34 @@ def plan_costs(plan:)

# TODO: define a new 'Currency' question type that includes a float field
# any currency type selector (e.g GBP or USD)
answers = plan.answers.includes(question: :themes).select do |answer|
answer.question.themes.include?(theme)
end
answers = plan.answers
.joins(question: :themes)
.where(themes: { id: theme.id })
.includes(:question)

answers.map do |answer|
# TODO: Investigate whether question level guidance should be the description
{ title: answer.question.text, description: nil,
currency_code: 'usd', value: answer.text }
end
end

# Fetch all questions and answers from a plan, regardless of theme
def fetch_all_q_and_a
answers = @plan.answers.includes(:question)
return [] unless answers.present?

answers.filter_map do |answer|
q = answer.question
next unless q.present?

{
title: "Question #{q.number || q.id}",
question: q.text.to_s,
answer: answer.text.to_s
}
end
end
end
end
end
36 changes: 24 additions & 12 deletions app/presenters/api/v2/research_output_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,25 +55,37 @@ def fetch_q_and_a_as_single_statement(themes:)
fetch_q_and_a(themes: themes).collect { |item| item[:description] }.join('<br>')
end

def fetch_q_and_a(themes:) # rubocop:disable Metrics/CyclomaticComplexity
def fetch_q_and_a(themes:)
return [] unless themes.is_a?(Array) && themes.any?

themes.filter_map do |theme|
qs = questions_for_theme(theme)
descr = qs.filter_map do |q|
a = @plan.answers.find { |ans| ans.question_id == q.id }
next unless a.present?
answers = answers_for_themes(themes)

format_q_and_a(q, a)
end
next if descr.blank?
descs_by_theme = build_descriptions_by_theme_hash(answers, themes)

{ title: theme, description: descr }
descs_by_theme.map do |theme, descs|
{ title: theme, description: descs }
end
end

def questions_for_theme(theme)
@plan.questions.select { |q| q.themes.collect(&:title).include?(theme) }
def answers_for_themes(themes)
@plan.answers
.joins(question: :themes)
.where(themes: { title: themes })
.includes(question: :themes)
.distinct
end

def build_descriptions_by_theme_hash(answers, themes)
descs_by_theme = Hash.new { |h, k| h[k] = [] }

answers.each do |answer|
answer.question.themes.each do |theme|
next unless themes.include?(theme.title)

descs_by_theme[theme.title] << format_q_and_a(answer.question, answer)
end
end
descs_by_theme
end

def format_q_and_a(question, answer)
Expand Down
15 changes: 14 additions & 1 deletion app/views/api/v2/plans/_show.json.jbuilder
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

json.schema 'https://github.com/RDA-DMP-Common/RDA-DMP-Common-Standard/tree/master/examples/JSON/JSON-schema/1.0'

presenter = Api::V2::PlanPresenter.new(plan: plan)
presenter = Api::V2::PlanPresenter.new(plan: plan, complete: @complete)

# Note the symbol of the dmproadmap json object
# nested in extensions which is the container for the json template object, etc.
Expand Down Expand Up @@ -68,5 +68,18 @@ unless @minimal
json.title template.title
end
end

if @complete
json.complete_plan do
q_and_a = presenter.complete_plan_data
next if q_and_a.blank?

json.array! q_and_a do |item|
json.title item[:title]
json.question item[:question]
json.answer item[:answer]
end
end
end
end
end
Loading