diff --git a/app/models/course.rb b/app/models/course.rb index 348891dac19..65d2fc90f9c 100644 --- a/app/models/course.rb +++ b/app/models/course.rb @@ -846,14 +846,25 @@ class Course < ActiveRecord::Base self.shard.activate do if self.workflow_state_changed? if self.completed? - Enrollment.where(:course_id => self, :workflow_state => ['active', 'invited']).update_all(:workflow_state => 'completed', :completed_at => Time.now.utc) + enrollment_ids = Enrollment.where(:course_id => self, :workflow_state => ['active', 'invited']).pluck(:id) + if enrollment_ids.any? + Enrollment.where(:id => enrollment_ids).update_all(:workflow_state => 'completed', :completed_at => Time.now.utc) + EnrollmentState.where(:enrollment_id => enrollment_ids).update_all(:state => 'completed', :state_is_current => true, :access_is_current => false) + EnrollmentState.send_later_if_production(:process_states_for_ids, enrollment_ids) # recalculate access + end + appointment_participants.active.current.update_all(:workflow_state => 'deleted') appointment_groups.each(&:clear_cached_available_slots!) elsif self.deleted? enroll_scope = Enrollment.where("course_id=? AND workflow_state<>'deleted'", self) + user_ids = enroll_scope.group(:user_id).pluck(:user_id).uniq if user_ids.any? - enroll_scope.update_all(:workflow_state => 'deleted') + enrollment_ids = enroll_scope.pluck(:id) + if enrollment_ids.any? + Enrollment.where(:id => enrollment_ids).update_all(:workflow_state => 'deleted') + EnrollmentState.where(:enrollment_id => enrollment_ids).update_all(:state => 'deleted', :state_is_current => true) + end User.send_later_if_production(:update_account_associations, user_ids) end end diff --git a/app/models/enrollment_state.rb b/app/models/enrollment_state.rb index 404f44275ff..3920c77025d 100644 --- a/app/models/enrollment_state.rb +++ b/app/models/enrollment_state.rb @@ -199,6 +199,13 @@ class EnrollmentState < ActiveRecord::Base EnrollmentState.where(:enrollment_id => enrollment_scope, :state_is_current => true, :state => INVALIDATEABLE_STATES).update_all(:state_is_current => false, :state_invalidated_at => Time.now.utc) end + def self.force_recalculation(enrollment_ids) + if enrollment_ids.any? + EnrollmentState.where(:enrollment_id => enrollment_ids, :state_is_current => true).update_all(:state_is_current => false) + EnrollmentState.send_later_if_production(:process_states_for_ids, enrollment_ids) + end + end + def self.invalidate_access(enrollment_scope, states_to_update) EnrollmentState.where(:enrollment_id => enrollment_scope, :access_is_current => true, :state => states_to_update).update_all(:access_is_current => false, :access_invalidated_at => Time.now.utc) end diff --git a/db/migrate/20160818202512_recompute_merged_enrollments.rb b/db/migrate/20160818202512_recompute_merged_enrollments.rb index 43d428d16fa..a5defbf6597 100644 --- a/db/migrate/20160818202512_recompute_merged_enrollments.rb +++ b/db/migrate/20160818202512_recompute_merged_enrollments.rb @@ -9,8 +9,7 @@ class RecomputeMergedEnrollments < ActiveRecord::Migration if merged_enrollment_ids.any? Shard.partition_by_shard(merged_enrollment_ids) do |sliced_ids| - EnrollmentState.invalidate_states(Enrollment.where(:id => sliced_ids)) - EnrollmentState.send_later_if_production(:process_states_for_ids, sliced_ids) + EnrollmentState.force_recalculation(sliced_ids) end end end diff --git a/db/migrate/20160819193534_fix_deleted_enrollment_states.rb b/db/migrate/20160819193534_fix_deleted_enrollment_states.rb new file mode 100644 index 00000000000..b01aaeebac0 --- /dev/null +++ b/db/migrate/20160819193534_fix_deleted_enrollment_states.rb @@ -0,0 +1,10 @@ +class FixDeletedEnrollmentStates < ActiveRecord::Migration + tag :postdeploy + + def up + DataFixup::FixDeletedEnrollmentStates.send_later_if_production(:run) + end + + def down + end +end \ No newline at end of file diff --git a/lib/data_fixup/fix_deleted_enrollment_states.rb b/lib/data_fixup/fix_deleted_enrollment_states.rb new file mode 100644 index 00000000000..e369d530d26 --- /dev/null +++ b/lib/data_fixup/fix_deleted_enrollment_states.rb @@ -0,0 +1,14 @@ +module DataFixup + module FixDeletedEnrollmentStates + def self.run + Enrollment.find_ids_in_ranges(:batch_size => 20000) do |min_id, max_id| + # find deleted enrollments with states that haven't been properly synced + ids = Enrollment.where(:id => min_id..max_id). + where(:workflow_state => 'deleted'). + joins(:enrollment_state).where("enrollment_states.state <> 'deleted'").pluck(:id) + + EnrollmentState.force_recalculation(ids) + end + end + end +end diff --git a/lib/sis/user_importer.rb b/lib/sis/user_importer.rb index 5f920b476aa..6b2f00d03e4 100644 --- a/lib/sis/user_importer.rb +++ b/lib/sis/user_importer.rb @@ -140,7 +140,13 @@ module SIS if !status_is_active && !user.new_record? # if this user is deleted, we're just going to make sure the user isn't enrolled in anything in this root account and # delete the pseudonym. - d = @root_account.enrollments.active.where(user_id: user).update_all(workflow_state: 'deleted') + enrollment_ids = @root_account.enrollments.active.where(user_id: user).where.not(:workflow_state => 'deleted').pluck(:id) + if enrollment_ids.any? + Enrollment.where(:id => enrollment_ids).update_all(workflow_state: 'deleted') + EnrollmentState.where(:enrollment_id => enrollment_ids).update_all(:state => 'deleted', :state_is_current => true) + end + + d = enrollment_ids.count d += @root_account.all_group_memberships.active.where(user_id: user).update_all(workflow_state: 'deleted') d += user.account_users.shard(@root_account).where(account_id: @root_account.all_accounts).delete_all d += user.account_users.shard(@root_account).where(account_id: @root_account).delete_all diff --git a/lib/user_merge.rb b/lib/user_merge.rb index c0b43bc534a..7c5cc1f1419 100644 --- a/lib/user_merge.rb +++ b/lib/user_merge.rb @@ -309,8 +309,7 @@ class UserMerge enrollment_ids = Enrollment.where(id: scope).where.not(id: keeper).pluck(:id) Enrollment.where(:id => enrollment_ids).update_all(workflow_state: keeper.workflow_state) - EnrollmentState.invalidate_states(Enrollment.where(:id => enrollment_ids)) - EnrollmentState.send_later_if_production(:process_states_for_ids, enrollment_ids) + EnrollmentState.force_recalculation(enrollment_ids) # mark the would be keeper from the from_user as deleted so it will not be moved later keeper.destroy