From 2541ec3de62f9bec66940cf114c6bd8145e0ba0d Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 8 Mar 2023 15:04:50 -0500 Subject: [PATCH 01/18] Created AssignmentDueDate Mixin, moved requied methods from assignment.rb --- app/models/assignment.rb | 97 +--------------------------------------- lib/due_date_mixin.rb | 0 2 files changed, 1 insertion(+), 96 deletions(-) create mode 100644 lib/due_date_mixin.rb diff --git a/app/models/assignment.rb b/app/models/assignment.rb index efa0c457329..d60f2a7192b 100644 --- a/app/models/assignment.rb +++ b/app/models/assignment.rb @@ -11,6 +11,7 @@ class Assignment < ApplicationRecord include ReviewAssignment include QuizAssignment include AssignmentHelper + include AssignmentDueDate has_paper_trail # When an assignment is created, it needs to # be created as an instance of a subclass of the Assignment (model) class; @@ -186,38 +187,11 @@ def path path_text end - # Check whether review, metareview, etc.. is allowed - # The permissions of TopicDueDate is the same as AssignmentDueDate. - # Here, column is usually something like 'review_allowed_id' - def check_condition(column, topic_id = nil) - next_due_date = DueDate.get_next_due_date(id, topic_id) - return false if next_due_date.nil? - - right_id = next_due_date.send column - right = DeadlineRight.find(right_id) - right && (right.name == 'OK' || right.name == 'Late') - end - - # Determine if the next due date from now allows for submissions - def submission_allowed(topic_id = nil) - check_condition('submission_allowed_id', topic_id) - end - # Determine if the next due date from now allows to take the quizzes def quiz_allowed(topic_id = nil) check_condition('quiz_allowed_id', topic_id) end - # Determine if the next due date from now allows for reviews - def can_review(topic_id = nil) - check_condition('review_allowed_id', topic_id) - end - - # Determine if the next due date from now allows for metareviews - def metareview_allowed(topic_id = nil) - check_condition('review_of_review_allowed_id', topic_id) - end - # Deletes all instances created as part of assignment and finally destroys itself. def delete(force = nil) begin @@ -294,15 +268,6 @@ def create_node node.save end - # if current stage is submission or review, find the round number - # otherwise, return 0 - def number_of_current_round(topic_id) - next_due_date = DueDate.get_next_due_date(id, topic_id) - return 0 if next_due_date.nil? - - next_due_date.round ||= 0 - end - # For varying rubric feature def current_stage_name(topic_id = nil) if staggered_deadline? @@ -323,17 +288,6 @@ def varying_rubrics_by_round? AssignmentQuestionnaire.where(assignment_id: id, used_in_round: 2).size > 1 end - def link_for_current_stage(topic_id = nil) - return nil if staggered_and_no_topic?(topic_id) - - due_date = find_current_stage(topic_id) - if due_date.nil? || (due_date == 'Finished') || due_date.is_a?(TopicDueDate) - return nil - end - - due_date.description_url - end - def stage_deadline(topic_id = nil) return 'Unknown' if staggered_and_no_topic?(topic_id) @@ -341,22 +295,6 @@ def stage_deadline(topic_id = nil) due_date.nil? || due_date == 'Finished' ? due_date : due_date.due_at.to_s end - def num_review_rounds - due_dates = AssignmentDueDate.where(parent_id: id) - rounds = 0 - due_dates.each do |due_date| - rounds = due_date.round if due_date.round > rounds - end - rounds - end - - def find_current_stage(topic_id = nil) - next_due_date = DueDate.get_next_due_date(id, topic_id) - return 'Finished' if next_due_date.nil? - - next_due_date - end - # Zhewei: this method is almost the same as 'stage_deadline' def current_stage(topic_id = nil) return 'Unknown' if staggered_and_no_topic?(topic_id) @@ -566,39 +504,6 @@ def self.export_fields(options) fields end - def find_due_dates(type) - due_dates.select { |due_date| due_date.deadline_type_id == DeadlineType.find_by(name: type).id } - end - - # Method find_review_period is used in answer_helper.rb to get the start and end dates of a round - def find_review_period(round) - # If round is nil, it means the same questionnaire is used for every round. Thus, we return all periods. - # If round is not nil, we return only the period of that round. - - submission_type = DeadlineType.find_by(name: 'submission').id - review_type = DeadlineType.find_by(name: 'review').id - - due_dates = [] - due_dates += find_due_dates('submission') - due_dates += find_due_dates('review') - due_dates.sort_by!(&:id) - - start_dates = [] - end_dates = [] - - if round.nil? - round = 1 - while self.due_dates.exists?(round: round) - start_dates << due_dates.select { |due_date| due_date.deadline_type_id == submission_type && due_date.round == round }.last - end_dates << due_dates.select { |due_date| due_date.deadline_type_id == review_type && due_date.round == round }.last - round += 1 - end - else - start_dates << due_dates.select { |due_date| due_date.deadline_type_id == submission_type && due_date.round == round }.last - end_dates << due_dates.select { |due_date| due_date.deadline_type_id == review_type && due_date.round == round }.last - end - [start_dates, end_dates] - end # for program 1 like assignment, if same rubric is used in both rounds, # the 'used_in_round' field in 'assignment_questionnaires' will be null, diff --git a/lib/due_date_mixin.rb b/lib/due_date_mixin.rb new file mode 100644 index 00000000000..e69de29bb2d From c21825aaf2e7d2da72bcbe6c1f029e33b27c9446 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 8 Mar 2023 15:04:50 -0500 Subject: [PATCH 02/18] E2323 Refactor DueDate functionality from assignment.rb --- app/models/assignment.rb | 97 +--------------------------------------- lib/due_date_mixin.rb | 0 2 files changed, 1 insertion(+), 96 deletions(-) create mode 100644 lib/due_date_mixin.rb diff --git a/app/models/assignment.rb b/app/models/assignment.rb index efa0c457329..d60f2a7192b 100644 --- a/app/models/assignment.rb +++ b/app/models/assignment.rb @@ -11,6 +11,7 @@ class Assignment < ApplicationRecord include ReviewAssignment include QuizAssignment include AssignmentHelper + include AssignmentDueDate has_paper_trail # When an assignment is created, it needs to # be created as an instance of a subclass of the Assignment (model) class; @@ -186,38 +187,11 @@ def path path_text end - # Check whether review, metareview, etc.. is allowed - # The permissions of TopicDueDate is the same as AssignmentDueDate. - # Here, column is usually something like 'review_allowed_id' - def check_condition(column, topic_id = nil) - next_due_date = DueDate.get_next_due_date(id, topic_id) - return false if next_due_date.nil? - - right_id = next_due_date.send column - right = DeadlineRight.find(right_id) - right && (right.name == 'OK' || right.name == 'Late') - end - - # Determine if the next due date from now allows for submissions - def submission_allowed(topic_id = nil) - check_condition('submission_allowed_id', topic_id) - end - # Determine if the next due date from now allows to take the quizzes def quiz_allowed(topic_id = nil) check_condition('quiz_allowed_id', topic_id) end - # Determine if the next due date from now allows for reviews - def can_review(topic_id = nil) - check_condition('review_allowed_id', topic_id) - end - - # Determine if the next due date from now allows for metareviews - def metareview_allowed(topic_id = nil) - check_condition('review_of_review_allowed_id', topic_id) - end - # Deletes all instances created as part of assignment and finally destroys itself. def delete(force = nil) begin @@ -294,15 +268,6 @@ def create_node node.save end - # if current stage is submission or review, find the round number - # otherwise, return 0 - def number_of_current_round(topic_id) - next_due_date = DueDate.get_next_due_date(id, topic_id) - return 0 if next_due_date.nil? - - next_due_date.round ||= 0 - end - # For varying rubric feature def current_stage_name(topic_id = nil) if staggered_deadline? @@ -323,17 +288,6 @@ def varying_rubrics_by_round? AssignmentQuestionnaire.where(assignment_id: id, used_in_round: 2).size > 1 end - def link_for_current_stage(topic_id = nil) - return nil if staggered_and_no_topic?(topic_id) - - due_date = find_current_stage(topic_id) - if due_date.nil? || (due_date == 'Finished') || due_date.is_a?(TopicDueDate) - return nil - end - - due_date.description_url - end - def stage_deadline(topic_id = nil) return 'Unknown' if staggered_and_no_topic?(topic_id) @@ -341,22 +295,6 @@ def stage_deadline(topic_id = nil) due_date.nil? || due_date == 'Finished' ? due_date : due_date.due_at.to_s end - def num_review_rounds - due_dates = AssignmentDueDate.where(parent_id: id) - rounds = 0 - due_dates.each do |due_date| - rounds = due_date.round if due_date.round > rounds - end - rounds - end - - def find_current_stage(topic_id = nil) - next_due_date = DueDate.get_next_due_date(id, topic_id) - return 'Finished' if next_due_date.nil? - - next_due_date - end - # Zhewei: this method is almost the same as 'stage_deadline' def current_stage(topic_id = nil) return 'Unknown' if staggered_and_no_topic?(topic_id) @@ -566,39 +504,6 @@ def self.export_fields(options) fields end - def find_due_dates(type) - due_dates.select { |due_date| due_date.deadline_type_id == DeadlineType.find_by(name: type).id } - end - - # Method find_review_period is used in answer_helper.rb to get the start and end dates of a round - def find_review_period(round) - # If round is nil, it means the same questionnaire is used for every round. Thus, we return all periods. - # If round is not nil, we return only the period of that round. - - submission_type = DeadlineType.find_by(name: 'submission').id - review_type = DeadlineType.find_by(name: 'review').id - - due_dates = [] - due_dates += find_due_dates('submission') - due_dates += find_due_dates('review') - due_dates.sort_by!(&:id) - - start_dates = [] - end_dates = [] - - if round.nil? - round = 1 - while self.due_dates.exists?(round: round) - start_dates << due_dates.select { |due_date| due_date.deadline_type_id == submission_type && due_date.round == round }.last - end_dates << due_dates.select { |due_date| due_date.deadline_type_id == review_type && due_date.round == round }.last - round += 1 - end - else - start_dates << due_dates.select { |due_date| due_date.deadline_type_id == submission_type && due_date.round == round }.last - end_dates << due_dates.select { |due_date| due_date.deadline_type_id == review_type && due_date.round == round }.last - end - [start_dates, end_dates] - end # for program 1 like assignment, if same rubric is used in both rounds, # the 'used_in_round' field in 'assignment_questionnaires' will be null, diff --git a/lib/due_date_mixin.rb b/lib/due_date_mixin.rb new file mode 100644 index 00000000000..e69de29bb2d From 2cbbafaaa496259d06f34b148ad361bcc11aec56 Mon Sep 17 00:00:00 2001 From: fergione Date: Fri, 10 Mar 2023 17:09:03 -0500 Subject: [PATCH 03/18] Fixed Missing Methods in the due_date_mixin.rb --- lib/due_date_mixin.rb | 96 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/lib/due_date_mixin.rb b/lib/due_date_mixin.rb index e69de29bb2d..5b2f148df20 100644 --- a/lib/due_date_mixin.rb +++ b/lib/due_date_mixin.rb @@ -0,0 +1,96 @@ +#/lib/due_date_mixin.rb +def AssignmentDueDate + # Check whether review, metareview, etc.. is allowed + # The permissions of TopicDueDate is the same as AssignmentDueDate. + # Here, column is usually something like 'review_allowed_id' + def check_condition(column, topic_id = nil) + next_due_date = DueDate.get_next_due_date(id, topic_id) + return false if next_due_date.nil? + + right_id = next_due_date.send column + right = DeadlineRight.find(right_id) + right && (right.name == 'OK' || right.name == 'Late') + end + + # Determine if the next due date from now allows for submissions + def submission_allowed(topic_id = nil) + check_condition('submission_allowed_id', topic_id) + end + # Determine if the next due date from now allows for reviews + def can_review(topic_id = nil) + check_condition('review_allowed_id', topic_id) + end + + # Determine if the next due date from now allows for metareviews + def metareview_allowed(topic_id = nil) + check_condition('review_of_review_allowed_id', topic_id) + end + # if current stage is submission or review, find the round number + # otherwise, return 0 + def number_of_current_round(topic_id) + next_due_date = DueDate.get_next_due_date(id, topic_id) + return 0 if next_due_date.nil? + + next_due_date.round ||= 0 + end + def link_for_current_stage(topic_id = nil) + return nil if staggered_and_no_topic?(topic_id) + + due_date = find_current_stage(topic_id) + if due_date.nil? || (due_date == 'Finished') || due_date.is_a?(TopicDueDate) + return nil + end + + due_date.description_url + end + def num_review_rounds + due_dates = AssignmentDueDate.where(parent_id: id) + rounds = 0 + due_dates.each do |due_date| + rounds = due_date.round if due_date.round > rounds + end + rounds + end + + def find_current_stage(topic_id = nil) + next_due_date = DueDate.get_next_due_date(id, topic_id) + return 'Finished' if next_due_date.nil? + + next_due_date + end + def find_due_dates(type) + due_dates.select { |due_date| due_date.deadline_type_id == DeadlineType.find_by(name: type).id } + end + + # Method find_review_period is used in answer_helper.rb to get the start and end dates of a round + def find_review_period(round) + # If round is nil, it means the same questionnaire is used for every round. Thus, we return all periods. + # If round is not nil, we return only the period of that round. + + submission_type = DeadlineType.find_by(name: 'submission').id + review_type = DeadlineType.find_by(name: 'review').id + + due_dates = [] + due_dates += find_due_dates('submission') + due_dates += find_due_dates('review') + due_dates.sort_by!(&:id) + + start_dates = [] + end_dates = [] + + if round.nil? + round = 1 + while self.due_dates.exists?(round: round) + start_dates << due_dates.select { |due_date| due_date.deadline_type_id == submission_type && due_date.round == round }.last + end_dates << due_dates.select { |due_date| due_date.deadline_type_id == review_type && due_date.round == round }.last + round += 1 + end + else + start_dates << due_dates.select { |due_date| due_date.deadline_type_id == submission_type && due_date.round == round }.last + end_dates << due_dates.select { |due_date| due_date.deadline_type_id == review_type && due_date.round == round }.last + end + [start_dates, end_dates] + end + + # END OF MODULE # +end \ No newline at end of file From f9003493dda9fc0d68e780b2794d1e5d5aea6bce Mon Sep 17 00:00:00 2001 From: Michael Fergione Date: Fri, 10 Mar 2023 22:05:37 -0500 Subject: [PATCH 04/18] Refactor the DueDateMixIn file to fit auto load conventions --- app/models/assignment.rb | 2 +- lib/{due_date_mixin.rb => due_date_mix_in.rb} | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) mode change 100644 => 100755 app/models/assignment.rb rename lib/{due_date_mixin.rb => due_date_mix_in.rb} (98%) mode change 100644 => 100755 diff --git a/app/models/assignment.rb b/app/models/assignment.rb old mode 100644 new mode 100755 index d60f2a7192b..fa842f29d80 --- a/app/models/assignment.rb +++ b/app/models/assignment.rb @@ -11,7 +11,7 @@ class Assignment < ApplicationRecord include ReviewAssignment include QuizAssignment include AssignmentHelper - include AssignmentDueDate + include DueDateMixIn has_paper_trail # When an assignment is created, it needs to # be created as an instance of a subclass of the Assignment (model) class; diff --git a/lib/due_date_mixin.rb b/lib/due_date_mix_in.rb old mode 100644 new mode 100755 similarity index 98% rename from lib/due_date_mixin.rb rename to lib/due_date_mix_in.rb index 5b2f148df20..30dce6af7b4 --- a/lib/due_date_mixin.rb +++ b/lib/due_date_mix_in.rb @@ -1,5 +1,5 @@ -#/lib/due_date_mixin.rb -def AssignmentDueDate +# lib/due_date_mix_in.rb +module DueDateMixIn # Check whether review, metareview, etc.. is allowed # The permissions of TopicDueDate is the same as AssignmentDueDate. # Here, column is usually something like 'review_allowed_id' From 35efe4594e6b15ed8cd65aac3ae1e0496efb2001 Mon Sep 17 00:00:00 2001 From: Michael Fergione Date: Sat, 18 Mar 2023 00:24:26 -0400 Subject: [PATCH 05/18] Add methods to due date mixin, test new arguments --- app/views/student_task/view.html.erb | 4 ++-- lib/due_date_mix_in.rb | 21 ++++++++++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/app/views/student_task/view.html.erb b/app/views/student_task/view.html.erb index 06407fcd03f..1693ab41d60 100644 --- a/app/views/student_task/view.html.erb +++ b/app/views/student_task/view.html.erb @@ -53,14 +53,14 @@ to display the label "Your team" in the student assignment tasks-->
  • <% if @team %> <% if @topics.size > 0 %> - <% if @topic_id && @assignment.submission_allowed(@topic_id) %> + <% if @topic_id && @assignment.submission_allowed(@assignment.id, @participant.user_id) %> <%= link_to t(".your_work"), :controller => 'submitted_content', :action => 'edit', :id => @participant.id %> <%=t ".submit_work" %> <% else %> <%=t ".your_work" %> <%=t ".choose_topic" %> <% end %> <% else %> - <% if @assignment.submission_allowed(@topic_id) %> + <% if @assignment.submission_allowed(@assignment.id, @participant.user_id) %> <%= link_to t(".your_work"), :controller => 'submitted_content', :action => 'edit', :id => @participant.id %> <%=t ".submit_work" %> <% else %> <%=t ".your_work" %> <%=t ".not_allowed" %> diff --git a/lib/due_date_mix_in.rb b/lib/due_date_mix_in.rb index 30dce6af7b4..63c284c144b 100755 --- a/lib/due_date_mix_in.rb +++ b/lib/due_date_mix_in.rb @@ -1,5 +1,9 @@ # lib/due_date_mix_in.rb module DueDateMixIn + def set_topic_by_user + @participant = AssignmentParticipant.find(params[:id]) + @sel_topic_id = SignedUpTeam.topic_id(id, @participant.user_id) + end # Check whether review, metareview, etc.. is allowed # The permissions of TopicDueDate is the same as AssignmentDueDate. # Here, column is usually something like 'review_allowed_id' @@ -9,12 +13,23 @@ def check_condition(column, topic_id = nil) right_id = next_due_date.send column right = DeadlineRight.find(right_id) - right && (right.name == 'OK' || right.name == 'Late') + # check is assignment action deadline is ok or late (i.e. not no) + right && (right.name != 'No') end # Determine if the next due date from now allows for submissions - def submission_allowed(topic_id = nil) - check_condition('submission_allowed_id', topic_id) + def submission_allowed(assignment_id, participant_id) + # check_condition('submission_allowed_id', topic_id) + # @topic_id = SignedUpTeam.topic_id(@assignemnt.id,@participant.user_id) + topic_id = SignedUpTeam.topic_id(id, participant_id) + # only need to pass @particpiant to search, can this be done locally + next_due_date = DueDate.get_next_due_date(id, topic_id) + return false if next_due_date.nil? + + right_id = next_due_date.submission_allowed_id + right = DeadlineRight.find(right_id) + # check is assignment action deadline is ok or late (i.e. not no) + right && (right.name != 'No') end # Determine if the next due date from now allows for reviews def can_review(topic_id = nil) From 0028f4313b212bd8f44afb7fffb0c46cc9741f1c Mon Sep 17 00:00:00 2001 From: Michael Fergione Date: Mon, 20 Mar 2023 20:30:30 -0400 Subject: [PATCH 06/18] Finished removing check_condition and updating student task view --- app/views/student_task/view.html.erb | 6 +++--- lib/due_date_mix_in.rb | 26 +++++++++++++++++++++----- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/app/views/student_task/view.html.erb b/app/views/student_task/view.html.erb index 1693ab41d60..705841e1c2d 100644 --- a/app/views/student_task/view.html.erb +++ b/app/views/student_task/view.html.erb @@ -27,7 +27,7 @@ <% if @use_bookmark %>
  • - <% if @topic_id and @assignment.submission_allowed(@topic_id) %> + <% if @topic_id and @assignment.submission_allowed(@participant.user_id) %> <%= link_to "View bookmarks", :controller=>'bookmarks', :action=> 'list', :id => @topic_id %> <%=t ".view_bookmarks_lengthy" %> <% else %> <%=t ".view_bookmarks" %><%=t ".choose_topic" %> @@ -53,14 +53,14 @@ to display the label "Your team" in the student assignment tasks-->
  • <% if @team %> <% if @topics.size > 0 %> - <% if @topic_id && @assignment.submission_allowed(@assignment.id, @participant.user_id) %> + <% if @topic_id && @assignment.submission_allowed(@participant.user_id) %> <%= link_to t(".your_work"), :controller => 'submitted_content', :action => 'edit', :id => @participant.id %> <%=t ".submit_work" %> <% else %> <%=t ".your_work" %> <%=t ".choose_topic" %> <% end %> <% else %> - <% if @assignment.submission_allowed(@assignment.id, @participant.user_id) %> + <% if @assignment.submission_allowed(@participant.user_id) %> <%= link_to t(".your_work"), :controller => 'submitted_content', :action => 'edit', :id => @participant.id %> <%=t ".submit_work" %> <% else %> <%=t ".your_work" %> <%=t ".not_allowed" %> diff --git a/lib/due_date_mix_in.rb b/lib/due_date_mix_in.rb index 63c284c144b..8845f256013 100755 --- a/lib/due_date_mix_in.rb +++ b/lib/due_date_mix_in.rb @@ -18,7 +18,7 @@ def check_condition(column, topic_id = nil) end # Determine if the next due date from now allows for submissions - def submission_allowed(assignment_id, participant_id) + def submission_allowed(participant_id = nil) # check_condition('submission_allowed_id', topic_id) # @topic_id = SignedUpTeam.topic_id(@assignemnt.id,@participant.user_id) topic_id = SignedUpTeam.topic_id(id, participant_id) @@ -32,13 +32,29 @@ def submission_allowed(assignment_id, participant_id) right && (right.name != 'No') end # Determine if the next due date from now allows for reviews - def can_review(topic_id = nil) - check_condition('review_allowed_id', topic_id) + def can_review(participant_id = nil) + topic_id = SignedUpTeam.topic_id(id, participant_id) + next_due_date = DueDate.get_next_due_date(id, topic_id) + return false if next_due_date.nil? + + right_id = next_due_date.submission_allowed_id + right = DeadlineRight.find(right_id) + # check is assignment action deadline is ok or late (i.e. not no) + right && (right.name != 'No') end # Determine if the next due date from now allows for metareviews - def metareview_allowed(topic_id = nil) - check_condition('review_of_review_allowed_id', topic_id) + def metareview_allowed(participant_id = nil) + if participant_id.nil? topic_id = nil + else topic_id = SignedUpTeam.topic_id(id, participant_id) + end + next_due_date = DueDate.get_next_due_date(id, topic_id) + return false if next_due_date.nil? + + right_id = next_due_date.review_of_review_allowed_id # meta-review id + right = DeadlineRight.find(right_id) + # check is assignment action deadline is ok or late (i.e. not no) + right && (right.name != 'No') end # if current stage is submission or review, find the round number # otherwise, return 0 From e96096850276fc1d84b33d6383ab4ddfd5b2900f Mon Sep 17 00:00:00 2001 From: Michael Fergione Date: Tue, 21 Mar 2023 18:53:34 -0400 Subject: [PATCH 07/18] Added seperate test file for testing mixin in spec, started process of test updating --- spec/lib/due_date_mix_in_test.rb | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 spec/lib/due_date_mix_in_test.rb diff --git a/spec/lib/due_date_mix_in_test.rb b/spec/lib/due_date_mix_in_test.rb new file mode 100644 index 00000000000..e69de29bb2d From 848a8dc6abfb76942e5e0ab28cd93e9ac106f14d Mon Sep 17 00:00:00 2001 From: Michael Fergione Date: Tue, 21 Mar 2023 20:23:42 -0400 Subject: [PATCH 08/18] Fixed Tests for _allowed methods, fixed rubocop violations --- app/models/assignment.rb | 5 --- lib/due_date_mix_in.rb | 73 ++++++++++++++++++++------------ spec/lib/due_date_mix_in_test.rb | 73 ++++++++++++++++++++++++++++++++ spec/models/assignment_spec.rb | 11 ++++- 4 files changed, 129 insertions(+), 33 deletions(-) diff --git a/app/models/assignment.rb b/app/models/assignment.rb index fa842f29d80..0dd2dbd1e61 100755 --- a/app/models/assignment.rb +++ b/app/models/assignment.rb @@ -187,11 +187,6 @@ def path path_text end - # Determine if the next due date from now allows to take the quizzes - def quiz_allowed(topic_id = nil) - check_condition('quiz_allowed_id', topic_id) - end - # Deletes all instances created as part of assignment and finally destroys itself. def delete(force = nil) begin diff --git a/lib/due_date_mix_in.rb b/lib/due_date_mix_in.rb index 8845f256013..b75d6972fad 100755 --- a/lib/due_date_mix_in.rb +++ b/lib/due_date_mix_in.rb @@ -1,43 +1,40 @@ +# frozen_String_literal: true + # lib/due_date_mix_in.rb module DueDateMixIn - def set_topic_by_user - @participant = AssignmentParticipant.find(params[:id]) - @sel_topic_id = SignedUpTeam.topic_id(id, @participant.user_id) - end - # Check whether review, metareview, etc.. is allowed - # The permissions of TopicDueDate is the same as AssignmentDueDate. - # Here, column is usually something like 'review_allowed_id' - def check_condition(column, topic_id = nil) - next_due_date = DueDate.get_next_due_date(id, topic_id) - return false if next_due_date.nil? - - right_id = next_due_date.send column - right = DeadlineRight.find(right_id) - # check is assignment action deadline is ok or late (i.e. not no) - right && (right.name != 'No') - end - # Determine if the next due date from now allows for submissions def submission_allowed(participant_id = nil) - # check_condition('submission_allowed_id', topic_id) - # @topic_id = SignedUpTeam.topic_id(@assignemnt.id,@participant.user_id) - topic_id = SignedUpTeam.topic_id(id, participant_id) + # Find topic id for given participant for selected assignment + # Return nil if no participant is given + topic_id = if participant_id.nil? + yield nil + else + SignedUpTeam.topic_id(id, participant_id) + end # only need to pass @particpiant to search, can this be done locally next_due_date = DueDate.get_next_due_date(id, topic_id) return false if next_due_date.nil? + # find the quiz allowed id, then check if that deadline is passed right_id = next_due_date.submission_allowed_id right = DeadlineRight.find(right_id) # check is assignment action deadline is ok or late (i.e. not no) right && (right.name != 'No') end + # Determine if the next due date from now allows for reviews + # Shoule be renamed to review_allowed from can_review def can_review(participant_id = nil) - topic_id = SignedUpTeam.topic_id(id, participant_id) + topic_id = if participant_id.nil? + yield nil + else + SignedUpTeam.topic_id(id, participant_id) + end next_due_date = DueDate.get_next_due_date(id, topic_id) return false if next_due_date.nil? - right_id = next_due_date.submission_allowed_id + # find the quiz allowed id, then check if that deadline is passed + right_id = next_due_date.review_allowed_id right = DeadlineRight.find(right_id) # check is assignment action deadline is ok or late (i.e. not no) right && (right.name != 'No') @@ -45,17 +42,38 @@ def can_review(participant_id = nil) # Determine if the next due date from now allows for metareviews def metareview_allowed(participant_id = nil) - if participant_id.nil? topic_id = nil - else topic_id = SignedUpTeam.topic_id(id, participant_id) - end + topic_id = if participant_id.nil? + yield nil + else + SignedUpTeam.topic_id(id, participant_id) + end next_due_date = DueDate.get_next_due_date(id, topic_id) return false if next_due_date.nil? + # find the quiz allowed id, then check if that deadline is passed right_id = next_due_date.review_of_review_allowed_id # meta-review id right = DeadlineRight.find(right_id) # check is assignment action deadline is ok or late (i.e. not no) right && (right.name != 'No') end + + # Determine if the next due date from now allows to take the quizzes + def quiz_allowed(participant_id = nil) + topic_id = if participant_id.nil? + yield nil + else + SignedUpTeam.topic_id(id, participant_id) + end + next_due_date = DueDate.get_next_due_date(id, topic_id) + return false if next_due_date.nil? + + # find the quiz allowed id, then check if that deadline is passed + right_id = next_due_date.quiz_allowed_id + right = DeadlineRight.find(right_id) + # check is assignment action deadline is ok or late (i.e. not no) + right && (right.name != 'No') + end + # if current stage is submission or review, find the round number # otherwise, return 0 def number_of_current_round(topic_id) @@ -64,6 +82,7 @@ def number_of_current_round(topic_id) next_due_date.round ||= 0 end + def link_for_current_stage(topic_id = nil) return nil if staggered_and_no_topic?(topic_id) @@ -74,6 +93,7 @@ def link_for_current_stage(topic_id = nil) due_date.description_url end + def num_review_rounds due_dates = AssignmentDueDate.where(parent_id: id) rounds = 0 @@ -89,6 +109,7 @@ def find_current_stage(topic_id = nil) next_due_date end + def find_due_dates(type) due_dates.select { |due_date| due_date.deadline_type_id == DeadlineType.find_by(name: type).id } end @@ -124,4 +145,4 @@ def find_review_period(round) end # END OF MODULE # -end \ No newline at end of file +end diff --git a/spec/lib/due_date_mix_in_test.rb b/spec/lib/due_date_mix_in_test.rb index e69de29bb2d..444bb60a67b 100644 --- a/spec/lib/due_date_mix_in_test.rb +++ b/spec/lib/due_date_mix_in_test.rb @@ -0,0 +1,73 @@ +describe Assignment do + let(:assignment) { build(:assignment, id: 1, name: 'no assignment', participants: [participant], teams: [team], max_team_size: 2) } + let(:instructor) { build(:instructor, id: 6) } + let(:student) { build(:student, id: 3, name: 'no one') } + let(:review_response_map) { build(:review_response_map, response: [response], reviewer: build(:participant), reviewee: build(:assignment_team)) } + let(:teammate_review_response_map) { build(:review_response_map, type: 'TeammateReviewResponseMap') } + let(:participant) { build(:participant, id: 1) } + let(:question) { double('Question') } + let(:team) { build(:assignment_team, id: 1, name: 'no team') } + let(:response) { build(:response) } + let(:course) { build(:course) } + let(:assignment_due_date) do + build(:assignment_due_date, due_at: '2011-11-11 11:11:11', deadline_name: 'Review', + description_url: 'https://expertiza.ncsu.edu/', round: 1) + end + let(:topic_due_date) { build(:topic_due_date, deadline_name: 'Submission', description_url: 'https://github.com/expertiza/expertiza') } + let(:deadline_type) { build(:deadline_type, id: 1) } + let(:assignment_questionnaire1) { build(:assignment_questionnaire, id: 1, assignment_id: 1, questionnaire_id: 1) } + let(:assignment_questionnaire2) { build(:assignment_questionnaire, id: 2, assignment_id: 1, questionnaire_id: 2) } + let(:questionnaire1) { build(:questionnaire, id: 1, type: 'ReviewQuestionnaire') } + let(:questionnaire2) { build(:questionnaire, id: 2, type: 'MetareviewQuestionnaire') } + + describe '#submission_allowed' do + it 'returns true when the next topic due date is allowed to submit sth' do + #allow(assignment).to receive(:check_condition).with('submission_allowed_id', 123).and_return(true) + #expect(assignment.submission_allowed(123)).to be true + assignment_due_date = double('AssignmentDueDate') + assignment_topic_id = double('AssignmentTopicId') + allow(SignedUpTeam).to receive(:topic_id).with(1, 1).and_return(assignment_topic_id) # 1,1 + allow(DueDate).to receive(:get_next_due_date).with(1, assignment_topic_id).and_return(assignment_due_date) + allow(assignment_due_date).to receive(:submission_allowed_id).and_return(1) + allow(DeadlineRight).to receive(:find).with(1).and_return(double('DeadlineRight', name: 'OK')) + expect(assignment.submission_allowed(1)).to be true + end + end + + describe '#quiz_allowed' do + it 'returns false when the next topic due date is not allowed to do quiz' do + assignment_due_date = double('AssignmentDueDate') + assignment_topic_id = double('AssignmentTopicId') + allow(SignedUpTeam).to receive(:topic_id).with(1, 1).and_return(assignment_topic_id) # 1,1 + allow(DueDate).to receive(:get_next_due_date).with(1, assignment_topic_id).and_return(assignment_due_date) + allow(assignment_due_date).to receive(:quiz_allowed_id).and_return(1) + allow(DeadlineRight).to receive(:find).with(1).and_return(double('DeadlineRight', name: 'OK')) + expect(assignment.quiz_allowed(1)).to be true + end + end + + describe '#metareview_allowed' do + it 'returns true when the next assignment due date is not allowed to do metareview' do + assignment_due_date = double('AssignmentDueDate') + assignment_topic_id = double('AssignmentTopicId') + allow(SignedUpTeam).to receive(:topic_id).with(1, 1).and_return(assignment_topic_id) # 1,1 + allow(DueDate).to receive(:get_next_due_date).with(1, assignment_topic_id).and_return(assignment_due_date) + allow(assignment_due_date).to receive(:review_of_review_allowed_id).and_return(1) + allow(DeadlineRight).to receive(:find).with(1).and_return(double('DeadlineRight', name: 'OK')) + expect(assignment.metareview_allowed(1)).to be true + end + end + + describe '#can_review' do + it 'returns true when the next assignment due date is not allowed to do metareview' do + assignment_due_date = double('AssignmentDueDate') + assignment_topic_id = double('AssignmentTopicId') + allow(SignedUpTeam).to receive(:topic_id).with(1, 1).and_return(assignment_topic_id) # 1,1 + allow(DueDate).to receive(:get_next_due_date).with(1, assignment_topic_id).and_return(assignment_due_date) + allow(assignment_due_date).to receive(:review_allowed_id).and_return(1) + allow(DeadlineRight).to receive(:find).with(1).and_return(double('DeadlineRight', name: 'OK')) + expect(assignment.can_review(1)).to be true + end + end + +end diff --git a/spec/models/assignment_spec.rb b/spec/models/assignment_spec.rb index 0bb5f50fb12..b8db60cef0f 100644 --- a/spec/models/assignment_spec.rb +++ b/spec/models/assignment_spec.rb @@ -266,8 +266,15 @@ describe '#submission_allowed' do it 'returns true when the next topic due date is allowed to submit sth' do - allow(assignment).to receive(:check_condition).with('submission_allowed_id', 123).and_return(true) - expect(assignment.submission_allowed(123)).to be true + #allow(assignment).to receive(:check_condition).with('submission_allowed_id', 123).and_return(true) + #expect(assignment.submission_allowed(123)).to be true + assignment_due_date = double('AssignmentDueDate') + assignment_topic_id = double('AssignmentTopicId') + allow(SignedUpTeam).to receive(:topic_id).with(1, 1).and_return(assignment_topic_id) # 1,1 + allow(DueDate).to receive(:get_next_due_date).with(1, assignment_topic_id).and_return(assignment_due_date) + allow(assignment_due_date).to receive(:submission_allowed_id).and_return(1) + allow(DeadlineRight).to receive(:find).with(1).and_return(double('DeadlineRight', name: 'OK')) + expect(assignment.check_condition('review_allowed_id')).to be true end end From 6c09259a8f437b86222e8ccd3f6d106e337c0ace Mon Sep 17 00:00:00 2001 From: Michael Fergione Date: Tue, 21 Mar 2023 22:08:38 -0400 Subject: [PATCH 09/18] Updated student_task/view.html.erb with refactored methods --- app/views/student_task/view.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/student_task/view.html.erb b/app/views/student_task/view.html.erb index 705841e1c2d..396a671ff6e 100644 --- a/app/views/student_task/view.html.erb +++ b/app/views/student_task/view.html.erb @@ -105,7 +105,7 @@ to display the label "Your team" in the student assignment tasks--> <%if @assignment.require_quiz%> <% if @authorization == 'participant' or @can_take_quiz == true %>
  • - <% if @assignment.require_quiz and (@assignment.quiz_allowed(@topic_id) or @assignment.current_stage(@topic_id) == "Finished") %> + <% if @assignment.require_quiz and (@assignment.quiz_allowed(@participant.user_id) or @assignment.current_stage(@topic_id) == "Finished") %> <%= link_to t(".take_quizzes"), student_quizzes_path(:id => @participant.id) %> <% else %> <%=t ".take_quizzes" %> From d02fced922648edfd6f468f0fbceb263b58ee211 Mon Sep 17 00:00:00 2001 From: Michael Fergione Date: Wed, 22 Mar 2023 18:41:15 -0400 Subject: [PATCH 10/18] Seperate topic_id finding based on participant into new method, find_topic_id --- lib/due_date_mix_in.rb | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/lib/due_date_mix_in.rb b/lib/due_date_mix_in.rb index b75d6972fad..7168fd442ba 100755 --- a/lib/due_date_mix_in.rb +++ b/lib/due_date_mix_in.rb @@ -2,16 +2,21 @@ # lib/due_date_mix_in.rb module DueDateMixIn - # Determine if the next due date from now allows for submissions - def submission_allowed(participant_id = nil) - # Find topic id for given participant for selected assignment - # Return nil if no participant is given + # finds the topic_id given the participant user_id + def find_topic_id(participant_id) topic_id = if participant_id.nil? - yield nil + nil else SignedUpTeam.topic_id(id, participant_id) end - # only need to pass @particpiant to search, can this be done locally + end + + # Determine if the next due date from now allows for submissions + def submission_allowed(participant_id = nil) + # Find topic id for given participant for selected assignment + # Return nil if no participant is given + topic_id = find_topic_id(participant_id) + # only need to pass @participiant to search, can this be done locally next_due_date = DueDate.get_next_due_date(id, topic_id) return false if next_due_date.nil? @@ -23,13 +28,9 @@ def submission_allowed(participant_id = nil) end # Determine if the next due date from now allows for reviews - # Shoule be renamed to review_allowed from can_review + # Should be renamed to review_allowed from can_review def can_review(participant_id = nil) - topic_id = if participant_id.nil? - yield nil - else - SignedUpTeam.topic_id(id, participant_id) - end + topic_id = find_topic_id(participant_id) next_due_date = DueDate.get_next_due_date(id, topic_id) return false if next_due_date.nil? @@ -42,11 +43,7 @@ def can_review(participant_id = nil) # Determine if the next due date from now allows for metareviews def metareview_allowed(participant_id = nil) - topic_id = if participant_id.nil? - yield nil - else - SignedUpTeam.topic_id(id, participant_id) - end + topic_id = find_topic_id(participant_id) next_due_date = DueDate.get_next_due_date(id, topic_id) return false if next_due_date.nil? From 2fb862d3136acbd791390e4d70aff45c48c3742c Mon Sep 17 00:00:00 2001 From: Michael Fergione Date: Wed, 22 Mar 2023 20:01:50 -0400 Subject: [PATCH 11/18] Fixed methods missing find_topic_id --- lib/due_date_mix_in.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/due_date_mix_in.rb b/lib/due_date_mix_in.rb index 7168fd442ba..a0beaad04b6 100755 --- a/lib/due_date_mix_in.rb +++ b/lib/due_date_mix_in.rb @@ -56,11 +56,7 @@ def metareview_allowed(participant_id = nil) # Determine if the next due date from now allows to take the quizzes def quiz_allowed(participant_id = nil) - topic_id = if participant_id.nil? - yield nil - else - SignedUpTeam.topic_id(id, participant_id) - end + topic_id = find_topic_id(participant_id) next_due_date = DueDate.get_next_due_date(id, topic_id) return false if next_due_date.nil? From 939170540d59c2c4343d5f5388ccbb5795a635d8 Mon Sep 17 00:00:00 2001 From: Michael Fergione Date: Wed, 22 Mar 2023 20:43:11 -0400 Subject: [PATCH 12/18] Removed tests in assignment_spec.rb for methods moved to mixin test --- spec/models/assignment_spec.rb | 54 ---------------------------------- 1 file changed, 54 deletions(-) diff --git a/spec/models/assignment_spec.rb b/spec/models/assignment_spec.rb index b8db60cef0f..0c27ac1947e 100644 --- a/spec/models/assignment_spec.rb +++ b/spec/models/assignment_spec.rb @@ -245,60 +245,6 @@ end end - describe '#check_condition' do - context 'when the next due date is nil' do - it 'returns false ' do - allow(DueDate).to receive(:get_next_due_date).with(1, nil).and_return(nil) - expect(assignment.check_condition('review_allowed_id')).to be false - end - end - - context 'when the next due date is allowed to review submissions' do - it 'returns true' do - assignment_due_date = double('AssignmentDueDate') - allow(DueDate).to receive(:get_next_due_date).with(1, nil).and_return(assignment_due_date) - allow(assignment_due_date).to receive(:send).with('review_allowed_id').and_return(1) - allow(DeadlineRight).to receive(:find).with(1).and_return(double('DeadlineRight', name: 'OK')) - expect(assignment.check_condition('review_allowed_id')).to be true - end - end - end - - describe '#submission_allowed' do - it 'returns true when the next topic due date is allowed to submit sth' do - #allow(assignment).to receive(:check_condition).with('submission_allowed_id', 123).and_return(true) - #expect(assignment.submission_allowed(123)).to be true - assignment_due_date = double('AssignmentDueDate') - assignment_topic_id = double('AssignmentTopicId') - allow(SignedUpTeam).to receive(:topic_id).with(1, 1).and_return(assignment_topic_id) # 1,1 - allow(DueDate).to receive(:get_next_due_date).with(1, assignment_topic_id).and_return(assignment_due_date) - allow(assignment_due_date).to receive(:submission_allowed_id).and_return(1) - allow(DeadlineRight).to receive(:find).with(1).and_return(double('DeadlineRight', name: 'OK')) - expect(assignment.check_condition('review_allowed_id')).to be true - end - end - - describe '#quiz_allowed' do - it 'returns false when the next topic due date is not allowed to do quiz' do - allow(assignment).to receive(:check_condition).with('quiz_allowed_id', 456).and_return(false) - expect(assignment.quiz_allowed(456)).to be false - end - end - - describe '#can_review' do - it "returns false when the next assignment due date is not allowed to review other's work" do - allow(assignment).to receive(:check_condition).with('review_allowed_id', nil).and_return(true) - expect(assignment.can_review).to be true - end - end - - describe '#metareview_allowed' do - it 'returns true when the next assignment due date is not allowed to do metareview' do - allow(assignment).to receive(:check_condition).with(any_args).and_return(false) - expect(assignment.metareview_allowed).to be false - end - end - describe '#delete' do before(:each) do allow(ReviewResponseMap).to receive(:where).with(reviewed_object_id: 1).and_return([review_response_map]) From 228d2994a7bedbb715e3cd82b837b22d58aecb57 Mon Sep 17 00:00:00 2001 From: Yash Sanjay Sonar Date: Mon, 27 Mar 2023 00:10:04 -0400 Subject: [PATCH 13/18] number_of_current_round refactor --- lib/due_date_mix_in.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/due_date_mix_in.rb b/lib/due_date_mix_in.rb index a0beaad04b6..2da5ac325a7 100755 --- a/lib/due_date_mix_in.rb +++ b/lib/due_date_mix_in.rb @@ -69,7 +69,8 @@ def quiz_allowed(participant_id = nil) # if current stage is submission or review, find the round number # otherwise, return 0 - def number_of_current_round(topic_id) + def number_of_current_round(participant_id = nil) + topic_id = find_topic_id(participant_id) next_due_date = DueDate.get_next_due_date(id, topic_id) return 0 if next_due_date.nil? From 65c3a7d08ab7300585eeb4f801c98e6f70a001ec Mon Sep 17 00:00:00 2001 From: Yash Sanjay Sonar Date: Mon, 27 Mar 2023 00:22:40 -0400 Subject: [PATCH 14/18] occurences changed --- app/views/sign_up_sheet/review_bids_others_work.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/sign_up_sheet/review_bids_others_work.html.erb b/app/views/sign_up_sheet/review_bids_others_work.html.erb index bb6d95c3cfa..539406b588a 100644 --- a/app/views/sign_up_sheet/review_bids_others_work.html.erb +++ b/app/views/sign_up_sheet/review_bids_others_work.html.erb @@ -67,7 +67,7 @@ <% last_response_round = @latest_response.round %> <%end%> - <% current_round = @assignment.number_of_current_round(topic_id) %> + <% current_round = @assignment.number_of_current_round(@participant.user_id) %> <%= link_to "View", {:controller => 'response', :action => 'view', :id => @latest_response.id} %> From 2cf6ecd05427ffb7b9581fa0cc868bd438dc121f Mon Sep 17 00:00:00 2001 From: Yash Sanjay Sonar Date: Mon, 27 Mar 2023 00:24:27 -0400 Subject: [PATCH 15/18] func call changed --- app/views/student_review/list.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/student_review/list.html.erb b/app/views/student_review/list.html.erb index ccd4a49c43c..28fa08f45f8 100755 --- a/app/views/student_review/list.html.erb +++ b/app/views/student_review/list.html.erb @@ -21,7 +21,7 @@ <%= render :partial => 'responses', :locals => {:mappings => @review_mappings, :title => 'Review'} %> - <% if @assignment.staggered_deadline? or @assignment.number_of_current_round(@topic_id) == 1 or (@assignment.number_of_current_round(@topic_id) > 1 and @assignment.allow_selecting_additional_reviews_after_1st_round) %> + <% if @assignment.staggered_deadline? or @assignment.number_of_current_round(@participant.user_id) == 1 or (@assignment.number_of_current_round(@participant.user_id) > 1 and @assignment.allow_selecting_additional_reviews_after_1st_round) %> <% if @assignment.dynamic_reviewer_assignment? %> <% if @num_reviews_in_progress >= Assignment.max_outstanding_reviews %>

    From 3ad77de115406874b898b6d71fedc133cbd97e2e Mon Sep 17 00:00:00 2001 From: Yash Sanjay Sonar Date: Mon, 27 Mar 2023 00:24:50 -0400 Subject: [PATCH 16/18] func called --- app/views/submitted_content/_self_review.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/submitted_content/_self_review.html.erb b/app/views/submitted_content/_self_review.html.erb index 32073e13423..9e05c654a4b 100644 --- a/app/views/submitted_content/_self_review.html.erb +++ b/app/views/submitted_content/_self_review.html.erb @@ -36,7 +36,7 @@ <% last_response_round = @latest_response.round %> <% end %> - <% current_round = @assignment.number_of_current_round(@topic_id) %> + <% current_round = @assignment.number_of_current_round(@participant.user_id) %>    <%= link_to 'View', {:controller => 'response', :action => 'view', :id => @latest_response.id} %> From 69eb835adc85b793e346e68fd2e518c75ce6d373 Mon Sep 17 00:00:00 2001 From: Yash Sanjay Sonar Date: Mon, 27 Mar 2023 00:29:13 -0400 Subject: [PATCH 17/18] find_current_stage refactored --- lib/due_date_mix_in.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/due_date_mix_in.rb b/lib/due_date_mix_in.rb index 2da5ac325a7..61cb2be423b 100755 --- a/lib/due_date_mix_in.rb +++ b/lib/due_date_mix_in.rb @@ -97,7 +97,7 @@ def num_review_rounds rounds end - def find_current_stage(topic_id = nil) + def find_current_stage(participant_id = nil) next_due_date = DueDate.get_next_due_date(id, topic_id) return 'Finished' if next_due_date.nil? From 948246b75952da82a2877ca0ecac94f114d9a263 Mon Sep 17 00:00:00 2001 From: Yash Sanjay Sonar Date: Mon, 27 Mar 2023 00:31:21 -0400 Subject: [PATCH 18/18] topic id called --- lib/due_date_mix_in.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/due_date_mix_in.rb b/lib/due_date_mix_in.rb index 61cb2be423b..3edeec31b7f 100755 --- a/lib/due_date_mix_in.rb +++ b/lib/due_date_mix_in.rb @@ -98,6 +98,7 @@ def num_review_rounds end def find_current_stage(participant_id = nil) + topic_id = find_topic_id(participant_id) next_due_date = DueDate.get_next_due_date(id, topic_id) return 'Finished' if next_due_date.nil?