Skip to content
Merged
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
38 changes: 2 additions & 36 deletions app/api/submission/portfolio_evidence_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,6 @@ def self.logger
authenticated?
end

TASK_STATES = {
ready_for_feedback: 1,
assess_in_portfolio: 1,
discuss: 2,
rediscuss: 2,
attention_required: 0,
demonstrate: 2,
complete: 3
}.freeze

desc 'Upload and generate doubtfire-task-specific submission document'
params do
optional :file0, type: File, desc: 'file 0.'
Expand All @@ -53,32 +43,8 @@ def self.logger
error!({ error: "This task requires a group submission. Ensure you are in a group for the unit's #{task_definition.group_set.name}" }, 403)
end

# Check that prerequisite tasks are in the required minimum submitted state
prerequisites = task_definition.task_prerequisites
prerequisites.each do |prerequisite|
prereq_td = prerequisite.prerequisite
minimum_status = TaskStatus.find(prerequisite.task_status_id)


prereq_task = project.task_for_task_definition(prereq_td)

verb =
case minimum_status
when TaskStatus.complete
'completed'
when TaskStatus.discuss
'discussed'
when TaskStatus.rediscuss
'rediscussed'
when TaskStatus.demonstrate
'demonstrated'
when TaskStatus.ready_for_feedback
'submitted'
end

if !prereq_task.ready_or_complete? || TASK_STATES[prereq_task.status] < TASK_STATES[minimum_status.status_key]
error!({ error: "Cannot submit this task until prerequisite '#{prereq_td.abbreviation}' has been #{verb}" }, 409)
end
if (prerequisite_error = task.unmet_prerequisite_error)
error!({ error: prerequisite_error }, 409)
end

trigger = if params[:trigger] && params[:trigger].tr('"\'', '') == 'need_help'
Expand Down
5 changes: 5 additions & 0 deletions app/api/tasks_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ class TasksApi < Grape::API
error!({ error: 'Cannot set this task status to ready to mark without uploading documents.' }, 403)
end

if !needs_upload_docs && %w[ready_for_feedback assess_in_portfolio].include?(params[:trigger]) &&
(prerequisite_error = task.unmet_prerequisite_error)
error!({ error: prerequisite_error }, 409)
end

if params[:trigger] == 'assess_in_portfolio' && !authorise?(current_user, project, :assess)
# Prevent students from upading status if task definition doesn't enable it
if !task_definition.assess_in_portfolio_only
Expand Down
33 changes: 33 additions & 0 deletions app/models/task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@
include ApplicationHelper
include GradeHelper

PREREQUISITE_STATUS_LEVELS = {
ready_for_feedback: 1,
assess_in_portfolio: 1,
discuss: 2,
rediscuss: 2,
attention_required: 0,
demonstrate: 2,
complete: 3
}.freeze

attr_accessor :discussion_confirmed_for_transition

#
Expand Down Expand Up @@ -550,6 +560,29 @@
[:complete, :discuss, :rediscuss, :demonstrate, :ready_for_feedback, :assess_in_portfolio].include? status
end

def unmet_prerequisite_error
task_definition.task_prerequisites.each do |prerequisite|
prereq_td = prerequisite.prerequisite
minimum_status = TaskStatus.find(prerequisite.task_status_id)
prereq_task = project.task_for_task_definition(prereq_td)

next if prereq_task.ready_or_complete? &&
PREREQUISITE_STATUS_LEVELS[prereq_task.status] >= PREREQUISITE_STATUS_LEVELS[minimum_status.status_key]

verb = case minimum_status

Check failure on line 572 in app/models/task.rb

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add a default clause to this "case" statement.

See more on https://sonarcloud.io/project/issues?id=doubtfire-lms_doubtfire-api&issues=AaFDW1Wc3qngZRsORIAE&open=AaFDW1Wc3qngZRsORIAE&pullRequest=712
when TaskStatus.complete then 'completed'
when TaskStatus.discuss then 'discussed'
when TaskStatus.rediscuss then 'rediscussed'
when TaskStatus.demonstrate then 'demonstrated'
when TaskStatus.ready_for_feedback then 'submitted'
end

return "Cannot submit this task until prerequisite '#{prereq_td.abbreviation}' has been #{verb}"
end

nil
end

def submitted_status?
[:working_on_it, :not_started, :fix_and_resubmit, :redo, :need_help].exclude? status
end
Expand Down
39 changes: 39 additions & 0 deletions test/api/tasks_api_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,45 @@ def test_cant_submit_until_prerequisites_submitted
unit.destroy
end

def test_cant_set_upload_free_task_ready_for_feedback_until_prerequisites_met
unit = FactoryBot.create(:unit, student_count: 1, task_count: 2)
prerequisite_definition, task_definition = unit.task_definitions.first(2)
prerequisite_definition.update!(target_grade: 0)
task_definition.update!(target_grade: 3, upload_requirements: [])
project = unit.active_projects.first
task = project.task_for_task_definition(task_definition)
prerequisite_task = project.task_for_task_definition(prerequisite_definition)
prerequisite = TaskPrerequisite.create!(
task_definition: task_definition,
prerequisite: prerequisite_definition,
task_status_id: TaskStatus.ready_for_feedback.id
)

add_auth_header_for(user: project.user)
path = "/api/projects/#{project.id}/task_def_id/#{task_definition.id}"

put path, { trigger: 'ready_for_feedback' }
assert_equal 409, last_response.status
assert_equal "Cannot submit this task until prerequisite '#{prerequisite_definition.abbreviation}' has been submitted",
last_response_body['error']
assert_equal TaskStatus.not_started, task.reload.task_status

prerequisite.update!(task_status_id: TaskStatus.complete.id)
prerequisite_task.update!(task_status: TaskStatus.ready_for_feedback)

put path, { trigger: 'ready_for_feedback' }
assert_equal 409, last_response.status
assert_equal "Cannot submit this task until prerequisite '#{prerequisite_definition.abbreviation}' has been completed",
last_response_body['error']
assert_equal TaskStatus.not_started, task.reload.task_status

prerequisite_task.update!(task_status: TaskStatus.complete)

put path, { trigger: 'ready_for_feedback' }
assert_equal 200, last_response.status
assert_equal TaskStatus.ready_for_feedback, task.reload.task_status
end

def test_prerequisites_task_status
# Create a unit and two task definitions
unit = FactoryBot.create(:unit, student_count: 1, task_count: 10)
Expand Down
Loading