# EffectiveCpdUser # # Mark your user model with effective_cpd_user to get a few helpers # And user specific point required scores module EffectiveCpdUser extend ActiveSupport::Concern module Base def effective_cpd_user include ::EffectiveCpdUser end end module ClassMethods def effective_cpd_user?; true; end end included do # App Scoped has_many :cpd_statements, -> { order(:cpd_cycle_id) }, inverse_of: :user, dependent: :destroy accepts_nested_attributes_for :cpd_statements, allow_destroy: true has_many :cpd_audits, -> { order(:id) }, inverse_of: :user has_many :cpd_audit_reviews, -> { order(:id) }, inverse_of: :user # Effective scoped has_many :cpd_targets, -> { order(:cpd_cycle_id) }, inverse_of: :user, class_name: 'Effective::CpdTarget', dependent: :delete_all accepts_nested_attributes_for :cpd_targets, reject_if: proc { |atts| atts['score'].blank? && atts['required_to_submit'].blank? } # These two should not be sorted scope :cpd_audit_auditees, -> { without_role(:cpd_audit_reviewer).without_role(:admin) } scope :cpd_audit_reviewers, -> { with_role(:cpd_audit_reviewer) } scope :sorted_by_in_progress_cpd_audit_reviews, -> { left_joins(:cpd_audit_reviews) .where(cpd_audit_reviews: { submitted_at: nil}) .includes(:cpd_audit_reviews) .group(:id) .order('COUNT(cpd_audit_reviews.id) ASC') .order('MAX(cpd_audit_reviews.created_at) ASC') .order('id ASC') } end # Requires for this user def cpd_target_score(cpd_cycle:) target = cpd_target(cpd_cycle: cpd_cycle) return target.score if target&.score.present? default_cpd_target_score(cpd_cycle: cpd_cycle) end # Required for this user category without the targets # Otherwise calculate default by membership category def default_cpd_target_score(cpd_cycle:) if self.class.try(:effective_memberships_user?) category = membership_categories_on(cpd_cycle.start_at)&.first if cpd_cycle.start_at.present? category ||= membership_categories_on(cpd_cycle.end_at)&.first if cpd_cycle.end_at.present? category ||= membership&.categories&.first category&.cpd_target_score(cpd_cycle: cpd_cycle) end end def cpd_target_score_required_to_submit?(cpd_cycle:) target = cpd_target(cpd_cycle: cpd_cycle) return target.required_to_submit? unless target&.required_to_submit.nil? cpd_cycle.required_to_submit? end def cpd_audit_cpd_required? true end def cpd_audit_reviewer? roles.include?(:cpd_audit_reviewer) end def cpd_statement(cpd_cycle:) raise('expected an CpdCycle') unless cpd_cycle.class.respond_to?(:effective_cpd_cpd_cycle?) cpd_statements.find { |cpd_statement| cpd_statement.cpd_cycle_id == cpd_cycle.id } end # Find or build def build_cpd_statement(cpd_cycle:) raise('expected an CpdCycle') unless cpd_cycle.class.respond_to?(:effective_cpd_cpd_cycle?) cpd_statement(cpd_cycle: cpd_cycle) || cpd_statements.build(cpd_cycle: cpd_cycle) end # Dont use IDs here def cpd_target(cpd_cycle:) raise('expected an CpdCycle') unless cpd_cycle.class.respond_to?(:effective_cpd_cpd_cycle?) cpd_targets.find { |cpd_target| cpd_target.cpd_cycle == cpd_cycle } end # Find or build def build_cpd_target(cpd_cycle:) raise('expected an CpdCycle') unless cpd_cycle.class.respond_to?(:effective_cpd_cpd_cycle?) cpd_target(cpd_cycle: cpd_cycle) || cpd_targets.build(cpd_cycle: cpd_cycle) end # For the form def build_cpd_targets Effective::CpdCycle.sorted.all.each { |cpd_cycle| build_cpd_target(cpd_cycle: cpd_cycle) } cpd_targets.sort_by(&:cpd_cycle_id).reverse end end