class Subscription < ApplicationRecord include Recentable belongs_to :employer belongs_to :series_successor, class_name: "Subscription", foreign_key: :series_successor_id, optional: true, inverse_of: :series_predecessor has_one :series_predecessor, -> { readonly }, class_name: "Subscription", foreign_key: :series_successor_id, inverse_of: :series_successor, dependent: :nullify validates :name, length: { in: 2..255, allow_nil: true } validates :autorenew_duration, numericality: { greater_than: 0 } validates :starts_at, presence: true validate :ends_at_after_starts_at validate :ends_at_before_successor_starts validate :starts_at_after_predecessor_ends validate :autorenew_voided_at_after_starts_at validate :terminated_at_after_starts_at validate :autorenew_deadline_after_starts_at_and_before_ends_at validates :billing_frequency, presence: true def ends_at_after_starts_at return if ends_at.blank? || starts_at.blank? if ends_at < starts_at errors.add(:ends_at, "must be after the start date") end end def ends_at_before_successor_starts return if series_successor.blank? if ends_at.blank? errors.add(:ends_at, "is required for renewed records") return end if ends_at >= series_successor.starts_at errors.add(:ends_at, "must be before its renewal's start date") end end def starts_at_after_predecessor_ends return if series_predecessor.blank? if starts_at.blank? errors.add(:starts_at, "is required for records with predecessors") return end if starts_at <= series_predecessor.ends_at errors.add(:starts_at, "must be after its predecessor's end date") end end # Either percentage or flat fare discount type must be set if product is in travel vertical def discount_type_set # If product not yet set, can't assume discount type not being set is an error return if !product if has_percentage_discount_type.blank? && has_flat_fare_discount_type.blank? errors.add(:has_percentage_discount_type, "- At least one of has_percentage_discount_type and has_flat_fare_discount_type must be true") end end # HACK: this is a temporary fix to work around the lack of atomic updates # for subscriptions and cycles. # TODO: https://concertiv.atlassian.net/browse/ENG-266 - fix by using Form Objects def sync_effective_at return if self.cycles.empty? if self.cycles.length == 1 self.cycles.first.effective_at = self.starts_at end end def terminated_at_after_starts_at return if terminated_at.blank? || starts_at.blank? if terminated_at < starts_at errors.add(:terminated_at, "must be after the start date") end end def autorenew_voided_at_after_starts_at return if !is_autorenew return if autorenew_voided_at.blank? || starts_at.blank? if autorenew_voided_at < starts_at errors.add(:autorenew_voided_at, "must be after the start date") end end def autorenew_deadline_after_starts_at_and_before_ends_at return if !is_autorenew if autorenew_deadline.blank? errors.add(:autorenew_deadline, "must be a valid date") return end if !starts_at.blank? && autorenew_deadline < starts_at errors.add(:autorenew_deadline, "must be after the start date") end if !ends_at.blank? && autorenew_deadline > ends_at errors.add(:autorenew_deadline, "must be before the end date") end end end