2020-10-27 00:50:13 +08:00
# frozen_string_literal: true
2011-02-01 09:57:29 +08:00
#
2017-04-28 04:06:18 +08:00
# Copyright (C) 2011 - present Instructure, Inc.
2011-02-01 09:57:29 +08:00
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
module SIS
2011-10-13 07:28:30 +08:00
class EnrollmentImporter < BaseImporter
2018-02-26 22:49:15 +08:00
def process ( messages )
i = Work . new ( @batch , @root_account , @logger , messages )
2016-01-19 01:52:17 +08:00
2023-04-29 04:59:51 +08:00
Enrollment . suspend_callbacks ( :set_update_cached_due_dates ,
:add_to_favorites_later ,
:recache_course_grade_distribution ,
:update_user_account_associations_if_necessary ) do
2020-07-17 05:04:26 +08:00
User . skip_updating_account_associations do
Enrollment . process_as_sis ( @sis_options ) do
yield i
while i . any_left_to_process?
i . process_batch
2011-09-28 06:35:20 +08:00
end
2011-05-07 05:27:27 +08:00
end
end
2011-02-01 09:57:29 +08:00
end
2020-02-11 00:24:28 +08:00
2019-05-09 05:34:32 +08:00
i . enrollments_to_update_sis_batch_ids . uniq . sort . in_groups_of ( 1000 , false ) do | batch |
2017-03-15 01:48:55 +08:00
Enrollment . where ( id : batch ) . update_all ( sis_batch_id : @batch . id )
2023-03-29 04:37:44 +08:00
# update observer enrollments linked to the above if they have a sis_batch_id
Shard . partition_by_shard ( batch ) do | shard_enrollment_ids |
Enrollment . where . not ( sis_batch_id : nil )
. joins ( " INNER JOIN #{ Enrollment . quoted_table_name } AS se ON enrollments.associated_user_id=se.user_id AND enrollments.course_section_id=se.course_section_id " )
. where ( se : { id : shard_enrollment_ids } )
2023-04-08 00:15:11 +08:00
. in_batches ( of : 10_000 )
2023-03-29 04:37:44 +08:00
. update_all ( sis_batch_id : @batch . id )
end
2018-05-17 12:59:57 +08:00
end
2011-05-07 05:27:27 +08:00
# We batch these up at the end because we don't want to keep touching the same course over and over,
# and to avoid hitting other callbacks for the course (especially broadcast_policy)
2018-07-24 12:43:37 +08:00
if Course . method_defined? ( :recache_grade_distribution )
i . courses_to_touch_ids . to_a . in_groups_of ( 1000 , false ) do | batch |
courses = Course . where ( id : batch )
courses . touch_all
courses . each ( & :recache_grade_distribution )
end
2013-09-05 23:58:09 +08:00
end
2013-09-11 05:01:09 +08:00
i . courses_to_recache_due_dates . to_a . in_groups_of ( 1000 , false ) do | batch |
2018-03-02 00:45:11 +08:00
batch . each do | course_id , user_ids |
2022-04-06 02:31:52 +08:00
DueDateCacher . recompute_users_for_course ( user_ids . uniq , course_id , nil , sis_import : true , update_grades : true )
2013-09-11 05:01:09 +08:00
end
end
2011-04-22 22:05:33 +08:00
# We batch these up at the end because normally a user would get several enrollments, and there's no reason
# to update their account associations on each one.
2011-09-07 02:07:54 +08:00
i . incrementally_update_account_associations
User . update_account_associations ( i . update_account_association_user_ids . to_a , account_chain_cache : i . account_chain_cache )
2013-09-05 23:58:09 +08:00
i . users_to_touch_ids . to_a . in_groups_of ( 1000 , false ) do | batch |
2015-12-10 06:21:13 +08:00
User . where ( id : batch ) . touch_all
2019-05-07 01:28:16 +08:00
User . where ( id : UserObserver . where ( user_id : batch ) . select ( :observer_id ) ) . touch_all
ids_to_touch = ( batch + UserObserver . where ( user_id : batch ) . pluck ( :observer_id ) ) . uniq
User . touch_and_clear_cache_keys ( ids_to_touch , :enrollments ) if ids_to_touch . any?
2013-09-05 23:58:09 +08:00
end
2021-11-15 23:09:24 +08:00
i . enrollments_to_add_to_favorites . filter_map ( & :id ) . each_slice ( 1000 ) do | sliced_ids |
2018-05-17 13:59:54 +08:00
Enrollment . delay ( priority : Delayed :: LOW_PRIORITY , strand : " batch_add_to_favorites_ #{ @root_account . global_id } " )
. batch_add_to_favorites ( sliced_ids )
2018-03-14 04:09:25 +08:00
end
2021-04-22 01:14:56 +08:00
if i . enrollments_to_delete . any?
new_data = Enrollment :: BatchStateUpdater . destroy_batch (
i . enrollments_to_delete ,
sis_batch : @batch ,
ignore_due_date_caching_for : i . courses_to_recache_due_dates
)
i . roll_back_data . push ( * new_data )
end
2018-06-03 01:27:38 +08:00
SisBatchRollBackData . bulk_insert_roll_back_data ( i . roll_back_data )
2018-03-14 04:09:25 +08:00
2018-08-24 00:39:42 +08:00
i . success_count + i . enrollments_to_delete . count
2011-09-07 02:07:54 +08:00
end
class Work
2023-04-29 04:59:51 +08:00
attr_accessor :enrollments_to_update_sis_batch_ids ,
:courses_to_touch_ids ,
:incrementally_update_account_associations_user_ids ,
:update_account_association_user_ids ,
:account_chain_cache ,
:users_to_touch_ids ,
:success_count ,
:courses_to_recache_due_dates ,
:enrollments_to_add_to_favorites ,
:roll_back_data ,
:enrollments_to_delete
2011-09-07 02:07:54 +08:00
2018-02-26 22:49:15 +08:00
def initialize ( batch , root_account , logger , messages )
2014-03-19 23:57:19 +08:00
@batch = batch
2011-09-07 02:07:54 +08:00
@root_account = root_account
@logger = logger
@messages = messages
@update_account_association_user_ids = Set . new
@incrementally_update_account_associations_user_ids = Set . new
@users_to_touch_ids = Set . new
@courses_to_touch_ids = Set . new
2018-03-02 00:45:11 +08:00
@courses_to_recache_due_dates = { }
2018-03-14 04:09:25 +08:00
@enrollments_to_add_to_favorites = [ ]
2011-09-07 02:07:54 +08:00
@enrollments_to_update_sis_batch_ids = [ ]
2018-05-12 17:27:03 +08:00
@roll_back_data = [ ]
@enrollments_to_delete = [ ]
2011-09-07 02:07:54 +08:00
@account_chain_cache = { }
@course = @section = nil
2012-12-08 03:28:30 +08:00
@course_roles_by_account_id = { }
2011-09-07 02:07:54 +08:00
@enrollment_batch = [ ]
@success_count = 0
end
2017-03-10 09:50:11 +08:00
# Pass a single instance of SIS::Models::Enrollment
def add_enrollment ( enrollment )
2015-06-17 10:10:51 +08:00
raise ImportError , " No course_id or section_id given for an enrollment " unless enrollment . valid_context?
raise ImportError , " No user_id given for an enrollment " unless enrollment . valid_user?
raise ImportError , " Improper status \" #{ enrollment . status } \" for an enrollment " unless enrollment . valid_status?
2018-03-22 09:36:40 +08:00
return if @batch . skip_deletes? && enrollment . status =~ / deleted /i
2013-01-18 00:22:15 +08:00
2015-06-17 10:10:51 +08:00
@enrollment_batch << enrollment
2018-02-26 22:49:15 +08:00
process_batch if @enrollment_batch . size > = Setting . get ( " sis_enrollment_batch_size " , " 100 " ) . to_i # no idea if this is a good number
2011-09-07 02:07:54 +08:00
end
def any_left_to_process?
! @enrollment_batch . empty?
end
def process_batch
return unless any_left_to_process?
2021-09-23 00:25:11 +08:00
2018-05-17 13:59:54 +08:00
enrollment_info = nil
until @enrollment_batch . empty?
enrollment_info = @enrollment_batch . shift
@last_section = @section if @section
@last_course = @course if @course
# reset the cached course/section if they don't match this row
if @course && enrollment_info . course_id . present? && @course . sis_source_id != enrollment_info . course_id
@course = nil
@section = nil
end
if @section && enrollment_info . section_id . present? && @section . sis_source_id != enrollment_info . section_id
@section = nil
end
2011-09-07 02:07:54 +08:00
2018-05-17 13:59:54 +08:00
if enrollment_info . root_account_id . present?
2020-08-05 17:52:27 +08:00
root_account = root_account_from_id ( enrollment_info . root_account_id , enrollment_info )
2018-05-17 13:59:54 +08:00
next unless root_account
else
root_account = @root_account
end
2011-09-07 02:07:54 +08:00
2018-05-17 13:59:54 +08:00
pseudo = if enrollment_info . user_integration_id . blank?
root_account . pseudonyms . where ( sis_user_id : enrollment_info . user_id ) . take
2021-11-20 22:33:31 +08:00
else
2018-05-17 13:59:54 +08:00
root_account . pseudonyms . where ( integration_id : enrollment_info . user_integration_id ) . take
end
2015-06-17 10:10:51 +08:00
2018-05-17 13:59:54 +08:00
unless pseudo
2020-10-27 00:50:13 +08:00
err = + " User not found for enrollment "
2018-05-17 13:59:54 +08:00
err << " (User ID: #{ enrollment_info . user_id } , Course ID: #{ enrollment_info . course_id } , Section ID: #{ enrollment_info . section_id } ) "
2018-11-06 04:22:43 +08:00
@messages << SisBatch . build_error ( enrollment_info . csv , err , sis_batch : @batch , row : enrollment_info . lineno , row_info : enrollment_info . row_info )
2018-05-17 13:59:54 +08:00
next
end
2014-03-19 23:57:19 +08:00
2018-05-17 13:59:54 +08:00
user = pseudo . user
if root_account != @root_account && ! SisPseudonym . for ( user , @root_account , type : :implicit , require_sis : false )
err = " User #{ enrollment_info . root_account_id } : #{ enrollment_info . user_id } does not have a usable login for this account "
2018-11-06 04:22:43 +08:00
@messages << SisBatch . build_error ( enrollment_info . csv , err , sis_batch : @batch , row : enrollment_info . lineno , row_info : enrollment_info . row_info )
2014-03-19 23:57:19 +08:00
next
2018-05-17 13:59:54 +08:00
end
2014-03-19 23:57:19 +08:00
2018-05-17 13:59:54 +08:00
@course || = @root_account . all_courses . where ( sis_source_id : enrollment_info . course_id ) . take unless enrollment_info . course_id . blank?
@section || = @root_account . course_sections . where ( sis_source_id : enrollment_info . section_id ) . take unless enrollment_info . section_id . blank?
if @course . nil? && @section . nil?
2020-10-27 00:50:13 +08:00
message = " Neither course nor section existed for user enrollment " \
" (Course ID: #{ enrollment_info . course_id } , Section ID: #{ enrollment_info . section_id } , User ID: #{ enrollment_info . user_id } ) "
2018-11-06 04:22:43 +08:00
@messages << SisBatch . build_error ( enrollment_info . csv , message , sis_batch : @batch , row : enrollment_info . lineno , row_info : enrollment_info . row_info )
2018-05-17 13:59:54 +08:00
next
end
2011-09-07 02:07:54 +08:00
2018-05-17 13:59:54 +08:00
if enrollment_info . section_id . present? && ! @section
@course = nil
message = " An enrollment referenced a non-existent section #{ enrollment_info . section_id } "
2018-11-06 04:22:43 +08:00
@messages << SisBatch . build_error ( enrollment_info . csv , message , sis_batch : @batch , row : enrollment_info . lineno , row_info : enrollment_info . row_info )
2018-05-17 13:59:54 +08:00
next
end
if enrollment_info . course_id . present? && ! @course
@section = nil
message = " An enrollment referenced a non-existent course #{ enrollment_info . course_id } "
2018-11-06 04:22:43 +08:00
@messages << SisBatch . build_error ( enrollment_info . csv , message , sis_batch : @batch , row : enrollment_info . lineno , row_info : enrollment_info . row_info )
2018-05-17 13:59:54 +08:00
next
end
2011-09-07 02:07:54 +08:00
2018-05-17 13:59:54 +08:00
# reset cached/inferred course and section if they don't match with the opposite piece that was
# explicitly provided
2021-09-27 23:58:39 +08:00
@section = @course . default_section ( include_xlists : true ) if @section . nil? || ( enrollment_info . section_id . blank? && ! @section . default_section )
2018-05-17 13:59:54 +08:00
@course = @section . course if @course . nil? ||
( enrollment_info . course_id . blank? && @course . id != @section . course_id ) ||
( @course . id != @section . course_id && @section . nonxlist_course_id == @course . id )
if @course . id != @section . course_id
2020-10-27 00:50:13 +08:00
message = " An enrollment listed a section ( #{ enrollment_info . section_id } ) " \
" and a course ( #{ enrollment_info . course_id } ) that are unrelated " \
" for user ( #{ enrollment_info . user_id } ) "
2018-11-06 04:22:43 +08:00
@messages << SisBatch . build_error ( enrollment_info . csv , message , sis_batch : @batch , row : enrollment_info . lineno , row_info : enrollment_info . row_info )
2018-05-17 13:59:54 +08:00
next
end
2011-09-07 02:07:54 +08:00
2018-05-17 13:59:54 +08:00
# preload the course object to avoid later queries for it
@section . course = @course
2011-09-07 02:07:54 +08:00
2018-05-17 13:59:54 +08:00
# cache available course roles for this account
@course_roles_by_account_id [ @course . account_id ] || = @course . account . available_course_roles
2015-02-11 04:03:52 +08:00
2018-05-17 13:59:54 +08:00
# commit pending incremental account associations
incrementally_update_account_associations if @section != @last_section && ! @incrementally_update_account_associations_user_ids . empty?
2012-12-08 03:28:30 +08:00
2018-05-17 13:59:54 +08:00
associated_user_id = nil
2011-09-07 02:07:54 +08:00
2018-05-17 13:59:54 +08:00
role = nil
if enrollment_info . role_id
role = @course_roles_by_account_id [ @course . account_id ] . detect { | r | r . global_id == Shard . global_id_for ( enrollment_info . role_id , @course . shard ) }
end
role || = @course_roles_by_account_id [ @course . account_id ] . detect { | r | r . name == enrollment_info . role }
type = if role
role . base_role_type
else
2021-11-12 01:20:36 +08:00
case enrollment_info . role
when / \ Ateacher \ z /i
2018-05-17 13:59:54 +08:00
" TeacherEnrollment "
2021-11-12 01:20:36 +08:00
when / \ Astudent /i
2018-05-17 13:59:54 +08:00
" StudentEnrollment "
2021-11-12 01:20:36 +08:00
when / \ Ata \ z /i
2018-05-17 13:59:54 +08:00
" TaEnrollment "
2021-11-12 01:20:36 +08:00
when / \ Aobserver \ z /i
2018-05-17 13:59:54 +08:00
" ObserverEnrollment "
2021-11-12 01:20:36 +08:00
when / \ Adesigner \ z /i
2018-05-17 13:59:54 +08:00
" DesignerEnrollment "
end
end
unless type
message = " Improper role \" #{ enrollment_info . role } \" for an enrollment "
2018-11-06 04:22:43 +08:00
@messages << SisBatch . build_error ( enrollment_info . csv , message , sis_batch : @batch , row : enrollment_info . lineno , row_info : enrollment_info . row_info )
2018-05-17 13:59:54 +08:00
next
end
2015-02-11 04:03:52 +08:00
2022-04-02 02:00:04 +08:00
if %w[ StudentEnrollment ObserverEnrollment ] . include? ( type ) && MasterCourses :: MasterTemplate . is_master_course? ( @course )
message = " #{ ( type == " StudentEnrollment " ) ? " Student " : " Observer " } enrollment for \" #{ enrollment_info . user_id } \" not allowed in blueprint course \" #{ @course . sis_course_id } \" "
2021-08-21 05:13:28 +08:00
@messages << SisBatch . build_error ( enrollment_info . csv , message , sis_batch : @batch , row : enrollment_info . lineno , row_info : enrollment_info . row_info )
next
end
2020-07-31 04:24:21 +08:00
role || = Role . get_built_in_role ( type , root_account_id : @root_account . id )
2015-02-11 04:03:52 +08:00
2018-05-17 13:59:54 +08:00
if enrollment_info . associated_user_id && type == " ObserverEnrollment "
a_pseudo = root_account . pseudonyms . where ( sis_user_id : enrollment_info . associated_user_id ) . take
if a_pseudo
associated_user_id = a_pseudo . user_id
2012-12-08 03:28:30 +08:00
else
2018-05-17 13:59:54 +08:00
message = " An enrollment referenced a non-existent associated user #{ enrollment_info . associated_user_id } "
2018-11-06 04:22:43 +08:00
@messages << SisBatch . build_error ( enrollment_info . csv , message , sis_batch : @batch , row : enrollment_info . lineno , row_info : enrollment_info . row_info )
2012-12-08 03:28:30 +08:00
next
end
2018-05-17 13:59:54 +08:00
end
enrollment = @section . all_enrollments . where ( user_id : user ,
type : type ,
associated_user_id : associated_user_id ,
2020-09-11 00:56:56 +08:00
role_id : role ) . take
2014-09-08 20:48:45 +08:00
2018-05-17 13:59:54 +08:00
enrollment || = Enrollment . typed_enrollment ( type ) . new
enrollment . root_account = @root_account
enrollment . user = user
enrollment . type = type
enrollment . associated_user_id = associated_user_id
enrollment . role = role
enrollment . course = @course
enrollment . course_section = @section
if enrollment_info . limit_section_privileges
enrollment . limit_privileges_to_course_section = Canvas :: Plugin . value_to_boolean ( enrollment_info . limit_section_privileges )
end
2011-09-07 02:07:54 +08:00
2019-02-14 09:46:47 +08:00
next if enrollment_status ( associated_user_id , enrollment , enrollment_info , pseudo , role , user )
2011-09-07 02:07:54 +08:00
2018-05-17 13:59:54 +08:00
if ( enrollment . stuck_sis_fields & [ :start_at , :end_at ] ) . empty?
enrollment . start_at = enrollment_info . start_date
enrollment . end_at = enrollment_info . end_date
end
2011-09-07 02:07:54 +08:00
2018-05-17 13:59:54 +08:00
@courses_to_touch_ids . add ( enrollment . course_id )
if enrollment . should_update_user_account_association? && ! %w[ creation_pending deleted ] . include? ( user . workflow_state )
if enrollment . new_record? && ! @update_account_association_user_ids . include? ( user . id )
@incrementally_update_account_associations_user_ids . add ( user . id )
else
@update_account_association_user_ids . add ( user . id )
2011-09-07 02:07:54 +08:00
end
2018-05-17 13:59:54 +08:00
end
enrollment . sis_pseudonym_id = pseudo . id
if enrollment . changed?
@users_to_touch_ids . add ( user . id )
if enrollment . workflow_state_changed?
if enrollment_needs_due_date_recaching? ( enrollment )
courses_to_recache_due_dates [ enrollment . course_id ] || = [ ]
courses_to_recache_due_dates [ enrollment . course_id ] << enrollment . user_id
2018-03-02 00:45:11 +08:00
end
2018-05-17 13:59:54 +08:00
if enrollment . workflow_state == " active "
enrollments_to_add_to_favorites << enrollment
end
end
enrollment . sis_batch_id = enrollment_info . sis_batch_id if enrollment_info . sis_batch_id
enrollment . sis_batch_id = @batch . id
enrollment . skip_touch_user = true
begin
2020-06-29 07:34:35 +08:00
if Canvas :: Plugin . value_to_boolean ( enrollment_info . notify )
enrollment . save!
else
enrollment . save_without_broadcasting!
end
2018-05-17 13:59:54 +08:00
rescue ActiveRecord :: RecordInvalid
msg = " An enrollment did not pass validation "
msg += " ( " + " course: #{ enrollment_info . course_id } , section: #{ enrollment_info . section_id } , "
msg += " user: #{ enrollment_info . user_id } , role: #{ enrollment_info . role } , error: " +
2013-03-05 08:00:01 +08:00
msg += enrollment . errors . full_messages . join ( " , " ) + " ) "
2018-11-06 04:22:43 +08:00
@messages << SisBatch . build_error ( enrollment_info . csv , msg , sis_batch : @batch , row : enrollment_info . lineno , row_info : enrollment_info . row_info )
2018-05-17 13:59:54 +08:00
next
rescue ActiveRecord :: RecordNotUnique
if @retry == true
msg = " An enrollment failed to save "
msg += " (course: #{ enrollment_info . course_id } , section: #{ enrollment_info . section_id } , "
msg += " user: #{ enrollment_info . user_id } , role: #{ enrollment_info . role } , error: " +
msg += enrollment . errors . full_messages . join ( " , " ) + " ) "
2018-11-06 04:22:43 +08:00
@messages << SisBatch . build_error ( enrollment_info . csv , msg , sis_batch : @batch , row : enrollment_info . lineno , row_info : enrollment_info . row_info )
2018-05-17 13:59:54 +08:00
@retry = false
else
@enrollment_batch . unshift ( enrollment_info )
@retry = true
2013-03-05 08:00:01 +08:00
end
2018-05-17 13:59:54 +08:00
next
2011-09-07 02:07:54 +08:00
end
2018-05-17 13:59:54 +08:00
data = SisBatchRollBackData . build_data ( sis_batch : @batch , context : enrollment )
@roll_back_data << data if data
else
@enrollments_to_update_sis_batch_ids << enrollment . id
2011-09-07 02:07:54 +08:00
end
2018-05-17 13:59:54 +08:00
@success_count += 1
2011-09-07 02:07:54 +08:00
end
end
2020-08-05 17:52:27 +08:00
def root_account_from_id ( _root_account_id , _enrollment_info )
2014-03-19 23:57:19 +08:00
nil
end
2011-09-07 02:07:54 +08:00
def incrementally_update_account_associations
if @incrementally_update_account_associations_user_ids . length < 10
@update_account_association_user_ids . merge ( @incrementally_update_account_associations_user_ids )
else
User . update_account_associations ( @incrementally_update_account_associations_user_ids . to_a ,
2018-05-17 13:59:54 +08:00
incremental : true ,
precalculated_associations : User . calculate_account_associations_from_accounts (
[ @last_course . account_id , @last_section . nonxlist_course . try ( :account_id ) ] . compact . uniq , @account_chain_cache
) )
2011-09-07 02:07:54 +08:00
end
@incrementally_update_account_associations_user_ids = Set . new
2011-08-18 03:38:36 +08:00
end
2018-04-19 03:38:46 +08:00
private
2019-02-14 09:46:47 +08:00
def enrollment_status ( associated_user_id , enrollment , enrollment_info , pseudo , role , user )
all_done = false
2020-08-05 14:42:48 +08:00
return true if enrollment . workflow_state == " deleted " && pseudo . workflow_state == " deleted "
2021-09-23 00:25:11 +08:00
2021-11-12 01:20:36 +08:00
case enrollment_info . status
when / \ Aactive /i
2019-02-14 09:46:47 +08:00
message = set_enrollment_workflow_state ( enrollment , enrollment_info , pseudo , user )
@messages << SisBatch . build_error ( enrollment_info . csv , message , sis_batch : @batch , row : enrollment_info . lineno , row_info : enrollment_info . row_info ) if message
2021-11-12 01:20:36 +08:00
when / \ Acompleted /i
2019-02-14 09:46:47 +08:00
completed_status ( enrollment )
2021-11-12 01:20:36 +08:00
when / \ Ainactive /i
2019-02-14 09:46:47 +08:00
enrollment . workflow_state = " inactive "
2021-11-12 01:20:36 +08:00
when / \ Adeleted_last_completed /i
2019-02-14 09:46:47 +08:00
# if any matching enrollment for the same user in the same course
# exists, we will mark the enrollment as deleted, but if it is the
# last enrollment it gets marked as completed
if @course . enrollments . active . where ( user : user , associated_user_id : associated_user_id , role : role ) . where . not ( id : enrollment . id ) . exists?
all_done = deleted_status ( enrollment )
else
completed_status ( enrollment )
end
2021-11-12 01:20:36 +08:00
when / \ Adeleted /i
2019-02-14 09:46:47 +08:00
# we support creating deleted enrollments, but we want to preserve
# the state for roll_back_data so only set workflow_state for new
# objects otherwise delete them in a batch at the end unless it is
# already deleted.
all_done = deleted_status ( enrollment )
end
all_done
end
def completed_status ( enrollment )
enrollment . workflow_state = " completed "
2023-01-28 04:13:35 +08:00
enrollment . completed_at = Time . zone . now
2019-02-14 09:46:47 +08:00
end
def deleted_status ( enrollment )
if enrollment . id . nil?
enrollment . workflow_state = " deleted "
# this will allow the enrollment to continue to be created
false
else
if enrollment . workflow_state == " deleted "
2019-05-09 05:34:32 +08:00
@enrollments_to_update_sis_batch_ids << enrollment . id
2019-02-14 09:46:47 +08:00
@success_count += 1
2021-11-20 22:33:31 +08:00
else
2019-02-14 09:46:47 +08:00
@enrollments_to_delete << enrollment
end
# we are done and we con go to the next enrollment
true
end
end
2019-01-17 00:24:34 +08:00
def set_enrollment_workflow_state ( enrollment , enrollment_info , pseudo , user )
message = nil
# the user is active, and the pseudonym is active
if user . workflow_state != " deleted " && pseudo . workflow_state != " deleted "
enrollment . workflow_state = " active "
# the user is active, but the pseudonym is deleted, check for other active pseudonym
elsif user . workflow_state != " deleted " && pseudo . workflow_state == " deleted "
if @root_account . pseudonyms . active . where ( user_id : user ) . where ( " sis_user_id != ? OR sis_user_id IS NULL " , enrollment_info . user_id ) . exists?
enrollment . workflow_state = " active "
message = " Enrolled a user #{ enrollment_info . user_id } in course #{ enrollment_info . course_id } , but referenced a deleted sis login "
else
message = invalid_active_enrollment ( enrollment , enrollment_info )
end
else # the user is deleted
message = invalid_active_enrollment ( enrollment , enrollment_info )
end
message
end
def invalid_active_enrollment ( enrollment , enrollment_info )
enrollment . workflow_state = " deleted "
" Attempted enrolling of deleted user #{ enrollment_info . user_id } in course #{ enrollment_info . course_id } "
end
2018-04-19 03:38:46 +08:00
def enrollment_needs_due_date_recaching? ( enrollment )
unless %w[ active inactive ] . include? enrollment . workflow_state_before_last_save
return %w[ active inactive ] . include? enrollment . workflow_state
end
2021-09-23 00:25:11 +08:00
2018-04-19 03:38:46 +08:00
false
end
2011-02-01 09:57:29 +08:00
end
end
end