class TournamentBroadcastInvitation < ApplicationRecord SCOPE_KINDS = %w[matches court_day].freeze belongs_to :tournament belongs_to :accepted_by, class_name: "User", optional: true has_many :assignments, class_name: "TournamentBroadcastAssignment", foreign_key: :invitation_id, dependent: :destroy validates :email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP } validates :token_digest, presence: true, uniqueness: true validates :scope_kind, inclusion: { in: SCOPE_KINDS } validates :court, presence: true, if: -> { scope_kind == "court_day" } validates :on_date, presence: true, if: -> { scope_kind == "court_day" } validates :note, length: { maximum: 2000 }, allow_blank: true scope :pending, -> { where(accepted_at: nil).where("expires_at > ?", Time.current) } scope :accepted, -> { where.not(accepted_at: nil) } def self.generate_token SecureRandom.urlsafe_base64(32) end def expired? expires_at.past? end def covers_match?(match) return false if match.blank? || match.tournament_id != tournament_id case scope_kind when "court_day" return false if court.blank? || on_date.blank? || match.scheduled_at.blank? court.to_s == match.court.to_s && on_date == match.scheduled_at.in_time_zone.to_date else Array(match_ids).map(&:to_s).include?(match.id.to_s) end end def accept!(user) transaction do update!(accepted_at: Time.current, accepted_by: user) Tournaments::GrantBroadcastAccess.call(invitation: self, user: user) Tournaments::SyncAssignments.call(invitation: self) end end def scope_label if scope_kind == "court_day" "#{court} ยท #{I18n.l(on_date)}" else "#{Array(match_ids).size} partite" end end end