126 lines
4.0 KiB
Ruby
126 lines
4.0 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class Classroom < ApplicationRecord
|
|
MIN_GRADE = 5
|
|
MAX_GRADE = 8
|
|
GRADE_RANGE = (MIN_GRADE..MAX_GRADE).to_a.freeze
|
|
|
|
belongs_to :school_year
|
|
has_one :school, through: :school_year
|
|
has_one :year, through: :school_year
|
|
|
|
delegate :name, to: :school, prefix: :school
|
|
delegate :name, to: :year, prefix: :year
|
|
|
|
has_many :users, dependent: :nullify
|
|
has_many :teacher_classrooms, dependent: :destroy
|
|
has_many :teachers, through: :teacher_classrooms
|
|
has_many :classroom_enrollments, dependent: :destroy
|
|
has_many :enrolled_students, through: :classroom_enrollments, source: :student
|
|
has_many :students, -> { kept }, class_name: "Student", inverse_of: :classroom, dependent: :nullify
|
|
has_many :classroom_grades, dependent: :destroy
|
|
has_many :grades, through: :classroom_grades
|
|
has_many :grade_books, dependent: :destroy
|
|
|
|
validates :name, presence: true
|
|
validate :school_year_presence
|
|
validate :grade_level
|
|
|
|
after_create :create_gradebooks_for_quarters
|
|
|
|
scope :active, -> { where(archived: false) }
|
|
scope :archived, -> { where(archived: true) }
|
|
scope :order_by_name, ->(direction = :asc) { reorder(name: direction) }
|
|
scope :order_by_student_count, lambda { |direction = :asc|
|
|
dir = direction.to_s.upcase == "DESC" ? "DESC" : "ASC"
|
|
|
|
joins("LEFT OUTER JOIN users ON users.classroom_id = classrooms.id AND users.type = 'Student'")
|
|
.group(:id)
|
|
.order(Arel.sql("COUNT(users.id) #{dir}"))
|
|
}
|
|
scope :order_by_total_earnings, lambda { |direction = :asc|
|
|
dir = direction.to_s.upcase == "DESC" ? "DESC" : "ASC"
|
|
|
|
joins("LEFT OUTER JOIN users ON users.classroom_id = classrooms.id AND users.type = 'Student'")
|
|
.joins("LEFT OUTER JOIN portfolios ON portfolios.user_id = users.id")
|
|
.joins("LEFT OUTER JOIN portfolio_transactions ON portfolio_transactions.portfolio_id = portfolios.id")
|
|
.group(:id)
|
|
.order(Arel.sql("COALESCE(SUM(portfolio_transactions.amount_cents), 0) #{dir}"))
|
|
}
|
|
|
|
# Apply sorting based on sort column param
|
|
# @param collection [ActiveRecord::Relation] The collection to sort (optional)
|
|
# @param sort_column [String] The column to sort by
|
|
# @param direction [Symbol] :asc or :desc
|
|
# @return [ActiveRecord::Relation] The sorted collection
|
|
def self.apply_sorting(collection = nil, sort_column = nil, direction = :asc)
|
|
base_scope = collection || all
|
|
|
|
case sort_column
|
|
when "name"
|
|
base_scope.order_by_name(direction)
|
|
when "student_count"
|
|
base_scope.order_by_student_count(direction)
|
|
when "total_earnings"
|
|
base_scope.order_by_total_earnings(direction)
|
|
else
|
|
base_scope.order_by_name(:asc)
|
|
end
|
|
end
|
|
|
|
# Get currently enrolled students (students with active enrollments)
|
|
#
|
|
# @return [ActiveRecord::Relation<Student>]
|
|
def current_students
|
|
enrolled_students.joins(:classroom_enrollments)
|
|
.merge(classroom_enrollments.current)
|
|
.distinct
|
|
end
|
|
|
|
# Get historically enrolled students (students with past enrollments)
|
|
#
|
|
# @return [ActiveRecord::Relation<Student>]
|
|
def historical_students
|
|
enrolled_students.joins(:classroom_enrollments)
|
|
.merge(classroom_enrollments.historical)
|
|
.distinct
|
|
end
|
|
|
|
def grades_display
|
|
values = classroom_grades
|
|
.joins(:grade)
|
|
.pluck("grades.level")
|
|
.uniq
|
|
.sort
|
|
return if values.empty?
|
|
|
|
if values.one?
|
|
values.first.ordinalize
|
|
elsif continuous?(values)
|
|
"#{values.first.ordinalize}-#{values.last.ordinalize}"
|
|
else
|
|
values.map(&:ordinalize).join(", ")
|
|
end
|
|
end
|
|
|
|
def continuous?(values)
|
|
values.each_cons(2).all? { |a, b| b == a + 1 }
|
|
end
|
|
|
|
private
|
|
|
|
def create_gradebooks_for_quarters
|
|
school_year.quarters.each do |quarter|
|
|
GradeBook.find_or_create_by!(quarter: quarter, classroom: self)
|
|
end
|
|
end
|
|
|
|
def grade_level
|
|
errors.add(:grades, "must have at least one grade") if grades.empty?
|
|
end
|
|
|
|
def school_year_presence
|
|
errors.add(:school_year_id, :blank) if school_year_id.blank? && school_year.nil?
|
|
end
|
|
end
|