app/models/programme_type.rb
# == Schema Information
#
# Table name: programme_types
#
# active :boolean default(FALSE)
# bonus_score :integer default(0)
# created_at :datetime default(Wed, 06 Jul 2022 12:00:00.000000000 UTC +00:00), not null
# default :boolean default(FALSE)
# document_link :string
# id :bigint(8) not null, primary key
# short_description :text
# title :text
# updated_at :datetime default(Wed, 06 Jul 2022 12:00:00.000000000 UTC +00:00), not null
#
class ProgrammeType < ApplicationRecord
extend Mobility
include TransifexSerialisable
include TranslatableAttachment
translates :title, type: :string, fallbacks: { cy: :en }
translates :short_description, type: :string, fallbacks: { cy: :en }
translates :description, backend: :action_text
translates :document_link, type: :string, fallbacks: { cy: :en }
t_has_one_attached :image
has_many :programme_type_activity_types
has_many :activity_types, through: :programme_type_activity_types
has_many :programmes
scope :active, -> { where(active: true) }
scope :default, -> { where(default: true) }
scope :by_title, -> { i18n.order(title: :asc) }
scope :default_first, -> { order(default: :desc) }
scope :featured, -> { active.default_first.by_title }
scope :with_school_activity_type_count, ->(school) {
joins(activity_types: :activities)
.where(activity_types: { activities: { school: school } })
.select('programme_types.*, COUNT(distinct activity_types.id) activity_type_count')
.group('programme_types.id').order(activity_type_count: :desc)
}
scope :not_in, ->(programme_types) { where.not(id: programme_types) }
validates_presence_of :title
validates :bonus_score, numericality: { greater_than_or_equal_to: 0 }
validates_uniqueness_of :default, if: :default
accepts_nested_attributes_for :programme_type_activity_types, reject_if: proc {|attributes| attributes['position'].blank? }
def activity_types_by_position
programme_type_activity_types.order(:position).map(&:activity_type)
end
def programme_for_school(school)
programmes.where(school: school).last
end
def activity_of_type_for_school(school, activity_type)
if (programme = programme_for_school(school))
programme.activity_of_type(activity_type)
end
end
def update_activity_type_positions!(position_attributes)
transaction do
programme_type_activity_types.destroy_all
update!(programme_type_activity_types_attributes: position_attributes)
end
end
def activity_types_and_school_activity(school)
programme_type_activity_types.order(:position).map do |programme_type_activity_type|
activity = school.activities.find_by(activity_type_id: programme_type_activity_type.activity_type_id)
[programme_type_activity_type.activity_type, activity]
end
end
# Provide a list of activity types a school has already completed this year for this programme type
# regardless of having signed up to the programme
def activity_type_ids_for_school(school)
activity_types.pluck(:id) & school.activity_types_in_academic_year.pluck(:id)
end
# Has the provided school already completed all activity types this year?
# regardless of having signed up to the programme
def all_activity_types_completed_for_school?(school)
(activity_types.pluck(:id) - school.activity_types_in_academic_year.pluck(:id)).empty?
end
def self.tx_resources
active.order(:id)
end
end