#
# Copyright (C) 2020 - present Instructure, Inc.
#
# 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/>.
class AdjustGradeChangeTablesForOverrideGrades < CanvasPartman::Migration
  include MigrationHelpers::AddColumnAndFk

  disable_ddl_transaction!
  tag :postdeploy
  self.base_class = Auditors::ActiveRecord::GradeChangeRecord

  GRADE_CHANGE_BASE_TABLE = :auditor_grade_change_records
  COLUMNS = %i[assignment_id submission_id submission_version_number].freeze

  def self.up
    COLUMNS.each { |column| change_column_null(GRADE_CHANGE_BASE_TABLE, column, true) }

    add_column_and_fk GRADE_CHANGE_BASE_TABLE, :grading_period_id, :grading_periods, if_not_exists: true

    # The new column propagates to the partitioned tables, but the foreign key
    # constraint does not, so add it manually
    with_each_partition do |partition|
      unless connection.foreign_key_exists?(partition, column: :grading_period_id)
        foreign_key = connection.send(:foreign_key_name, partition, column: :grading_period_id)
        execute("ALTER TABLE #{connection.quote_table_name(partition)} ADD CONSTRAINT #{foreign_key} FOREIGN KEY (grading_period_id) REFERENCES #{connection.quote_table_name('grading_periods')} (id)")
      end
    end
  end

  def self.down
    remove_records_with_null_values

    remove_column GRADE_CHANGE_BASE_TABLE, :grading_period_id
    COLUMNS.each { |column| change_column_null(GRADE_CHANGE_BASE_TABLE, column, false) }
  end

  def self.remove_records_with_null_values
    null_record_scope = base_class.where("assignment_id IS NULL OR submission_id IS NULL")
    null_record_scope.order(created_at: :asc).find_ids_in_batches(batch_size: 10_000) do |ids|
      base_class.where(id: ids).delete_all
    end
  end
end

Update grade change tables for override grades
Update grade change tables for override grades

flag=none
closes EVAL-1065

Test plan:
- "up" migration:
  - Ensure migrations run properly
  - After the migration finishes, check that the assignment_id,
    submission_id and submission_version_number columns in the
    auditor_grade_change_records_* tables do *not* have not-null
    constraints
  - Check that the grading_period_id column exists on said tables, along
    with an accompanying foreign key
- "down" migration:
  - Check that the assignment_id, submission_id and
    submission_version_number column once again have a not-null
    constraint
  - Check that the grading_period_id column no longer exists

Change-Id: I82d0325ea88f88138e78901415ed8fbe0d7d2814
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/243691
Tested-by: Service Cloud Jenkins <9144042a601061f88f1e1d7a1753ea3e2972119d@instructure.com>
Reviewed-by: Jacob Burroughs <8ecea6e385af5cf9f53123f5ca17fb5fd6a6d4b2@instructure.com>
Reviewed-by: Spencer Olson <7cc0890d6f1f70810a023e7173eca5724d6c8e49@instructure.com>
QA-Review: Adrian Packel <9c6a39807293376f29cba17542b4cb1b663ecc4a@instructure.com>
Product-Review: Syed Hussain <1379c89cd1d253d3c5a299cc4d8f6002ada9d6b5@instructure.com>
