Add compress_dates endpoint

fixes LS-2849
flag=pace_plans

test plan:
- Create a course with a start date, module item assignments, pace plans
enabled, and a pace plan created with various durations set on the
pace plan module items
- Hit /api/v1/courses/:course_id/pace_plans/:pace_plan_id/compress_dates?
pace_plan[end_date]="AN_END_DATE_CLOSE_TO_START_DATE"
- Verify durations have been compressed on pace plan module items
- Verify those durations were not actually saved to the database

Change-Id: I563d24ade95e0135b4b986b3497dbac3fe5de7b6
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/279307
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Ed Schiebel <eschiebel@instructure.com>
QA-Review: Ed Schiebel <eschiebel@instructure.com>
Product-Review: Ed Schiebel <eschiebel@instructure.com>
This commit is contained in:
Eric Saupe 2021-11-22 16:10:35 -08:00 committed by Ed Schiebel
parent f47580be57
commit feed630a07
6 changed files with 49 additions and 9 deletions

View File

@ -22,7 +22,7 @@ class PacePlansController < ApplicationController
before_action :load_course
before_action :require_feature_flag
before_action :authorize_action
before_action :load_pace_plan, only: %i[api_show update publish]
before_action :load_pace_plan, only: %i[api_show publish update]
include Api::V1::Course
include Api::V1::Progress
@ -132,6 +132,25 @@ class PacePlansController < ApplicationController
end
end
def compress_dates
@pace_plan = PacePlan.new(create_params)
@pace_plan.course = @course
start_date = params.dig(:pace_plan, :start_date).present? ? Date.parse(params.dig(:pace_plan, :start_date)) : @pace_plan.start_date
compressed_module_items = @pace_plan.compress_dates(save: false, start_date: start_date)
.sort do |a, b|
a.module_item.position <=> b.module_item.position
end
days_from_start_date = 0
compressed_dates = {}
compressed_module_items.each do |item|
days_from_start_date += item.duration
compressed_dates[item.module_item_id] = start_date + days_from_start_date.days
end
render json: compressed_dates.to_json
end
private
def latest_progress

View File

@ -148,8 +148,8 @@ class PacePlan < ActiveRecord::Base
update(workflow_state: "active", published_at: DateTime.current)
end
def compress_dates!
PacePlanHardEndDateCompressor.compress(self, pace_plan_module_items, save: true)
def compress_dates(save: true, start_date: self.start_date)
PacePlanHardEndDateCompressor.compress(self, pace_plan_module_items, save: save, start_date: start_date)
end
def student_enrollments

View File

@ -2382,6 +2382,7 @@ CanvasRails::Application.routes.draw do
get "courses/:course_id/pace_plans/:id", action: :api_show
put "courses/:course_id/pace_plans/:id", action: :update
post "courses/:course_id/pace_plans/:id/publish", action: :publish
get "courses/:course_id/pace_plans/compress_dates", action: :compress_dates
end
scope(controller: :eportfolios_api) do

View File

@ -24,9 +24,9 @@ class PacePlanDueDatesCalculator
@pace_plan = pace_plan
end
def get_due_dates(items, enrollment = nil)
def get_due_dates(items, enrollment = nil, start_date: nil)
due_dates = {}
start_date = enrollment&.start_at&.to_date || pace_plan.start_date
start_date = start_date || enrollment&.start_at&.to_date || pace_plan.start_date
# We have to make sure we start counting from one day before the plan start, so that the first day is inclusive.
# If the plan start date is enabled (i.e., not on a blackout date) we can just subtract one working day.

View File

@ -29,12 +29,13 @@ class PacePlanHardEndDateCompressor
# @param compress_items_after [integer] an optional integer representing the position of that you want to start at when
# compressing items, rather than compressing them all
# @params save [boolean] set to yes if you want the items saved after being modified.
def self.compress(pace_plan, items, enrollment: nil, compress_items_after: nil, save: false)
# @params start_date [Date] the start date of the plan. Used to calculate the number of days to the hard end date
def self.compress(pace_plan, items, enrollment: nil, compress_items_after: nil, save: false, start_date: nil)
return if compress_items_after && compress_items_after >= items.length - 1
return items if items.empty?
start_date_of_item_group = enrollment&.start_at || pace_plan.start_date
due_dates = PacePlanDueDatesCalculator.new(pace_plan).get_due_dates(items, enrollment)
start_date_of_item_group = start_date || enrollment&.start_at || pace_plan.start_date
due_dates = PacePlanDueDatesCalculator.new(pace_plan).get_due_dates(items, enrollment, start_date: start_date_of_item_group)
if compress_items_after
starting_item = items[compress_items_after]

View File

@ -39,6 +39,7 @@ describe PacePlansController, type: :controller do
before :once do
course_with_teacher(active_all: true)
@course.update(start_at: "2021-09-30")
student_in_course(active_all: true)
pace_plan_model(course: @course)
@student_enrollment = @student.enrollments.first
@ -374,4 +375,22 @@ describe PacePlansController, type: :controller do
expect(json_response["workflow_state"]).to eq("queued")
end
end
describe "GET #compress_dates" do
it "returns a compressed list of dates" do
pace_plan_params = @valid_params.merge(end_date: @pace_plan.start_date + 5.days)
get :compress_dates, params: { course_id: @course.id, pace_plan: pace_plan_params }
expect(response).to be_successful
json_response = JSON.parse(response.body)
expect(json_response.values).to eq(%w[2021-09-30 2021-10-03])
end
it "supports changing durations and start dates" do
pace_plan_params = @valid_params.merge(start_date: "2021-11-01", end_date: "2021-11-06")
get :compress_dates, params: { course_id: @course.id, pace_plan: pace_plan_params }
expect(response).to be_successful
json_response = JSON.parse(response.body)
expect(json_response.values).to eq(%w[2021-11-01 2021-11-06])
end
end
end