Module: SpreeCmCommissioner::TaxonDecorator

Defined in:
app/models/spree_cm_commissioner/taxon_decorator.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.prepended(base) ⇒ Object

rubocop:disable Metrics/AbcSize,Metrics/MethodLength



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'app/models/spree_cm_commissioner/taxon_decorator.rb', line 3

def self.prepended(base) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
  base.include SpreeCmCommissioner::StoreMetadata
  base.include SpreeCmCommissioner::TaxonKind
  base.include SpreeCmCommissioner::ParticipationTypeBitwise
  base.include SpreeCmCommissioner::EventMetadata
  base.include SpreeCmCommissioner::Integrations::IntegrationMappable
  base.include SpreeCmCommissioner::HomepageSectionRelatableConcern

  base.has_many :taxon_vendors, class_name: 'SpreeCmCommissioner::TaxonVendor'
  base.has_many :vendors, through: :taxon_vendors

  base.has_many :guest_card_classes, class_name: 'SpreeCmCommissioner::GuestCardClass'

  base.has_many :user_events, class_name: 'SpreeCmCommissioner::UserEvent'
  base.has_many :users, through: :user_events, class_name: Spree.user_class.to_s
  base.has_many :products, through: :classifications, class_name: 'Spree::Product'
  base.has_many :guests, foreign_key: :event_id, class_name: 'SpreeCmCommissioner::Guest', dependent: :nullify
  base.has_many :check_ins, as: :checkinable, class_name: 'SpreeCmCommissioner::CheckIn', dependent: :nullify
  # Check-in groups for this event (Spree::Role, role_type :check_in). Scoped by event_id (indexed),
  base.has_many :check_in_groups, -> { filter_check_in }, class_name: 'Spree::Role', foreign_key: :event_id
  base.has_many :customer_taxons, class_name: 'SpreeCmCommissioner::CustomerTaxon'

  base.has_many :seat_layouts, as: :layoutable, class_name: 'SpreeCmCommissioner::SeatLayout', dependent: :destroy
  base.has_one :category_icon, as: :viewable, dependent: :destroy, class_name: 'SpreeCmCommissioner::TaxonCategoryIcon'

  base.has_one :web_banner, as: :viewable, dependent: :destroy, class_name: 'SpreeCmCommissioner::TaxonWebBanner'
  base.has_one :app_banner, as: :viewable, dependent: :destroy, class_name: 'SpreeCmCommissioner::TaxonAppBanner'
  base.has_one :home_banner, as: :viewable, dependent: :destroy, class_name: 'SpreeCmCommissioner::TaxonHomeBanner'
  base.has_one :ad_banner, as: :viewable, dependent: :destroy, class_name: 'SpreeCmCommissioner::TaxonAdBanner'
  base.has_one :video_banner, as: :viewable, dependent: :destroy, class_name: 'SpreeCmCommissioner::TaxonVideoBanner'

  # Update children association to work with nested set (lft, rgt)
  base.has_many :children, -> { order(:lft) }, class_name: 'Spree::Taxon', foreign_key: :parent_id, dependent: :destroy
  base.has_many :children_classifications, through: :children, source: :classifications, class_name: 'Spree::Classification'
  base.has_many :children_products, through: :children_classifications, class_name: 'Spree::Product', source: :product

  base.has_many :notification_taxons, class_name: 'SpreeCmCommissioner::NotificationTaxon'
  base.has_many :customer_notifications, through: :notification_taxons, class_name: 'SpreeCmCommissioner::CustomerNotification'

  base.has_many :visible_classifications, -> { where(visible: true).order(:position) }, class_name: 'Spree::Classification'
  base.has_many :visible_products, through: :visible_classifications, class_name: 'Spree::Product', source: :product

  base.has_many :exports, -> { order(created_at: :desc) }, class_name: 'SpreeCmCommissioner::Export', as: :exportable

  base.belongs_to :vendor, class_name: 'Spree::Vendor'

  base.validates_associated :category_icon
  base.validate :validate_event_dates, if: -> { from_date.present? && to_date.present? }

  base. :live_stock_path, :string

  base.before_save :set_kind
  base.before_save :set_slug
  base.before_save :normalize_custom_redirect_url
  # Written once, the first time an organizer sets both live-stock bounds — never rewritten on
  # later edits (guarded by live_stock_path.blank?) so it stays a stable reference the app can
  # read instead of building "events/#{id}" itself. `id` is guaranteed present here since these
  # fields are only ever set via an update (the create flow never touches them).
  base.before_save :set_live_stock_path,
                   if: -> { id.present? && live_stock_starts_at.present? && live_stock_ends_at.present? && live_stock_path.blank? }

  base.after_update :sync_event_dates_to_line_items, if: -> { saved_change_to_from_date? || saved_change_to_to_date? }

  base.whitelisted_ransackable_associations |= %w[vendor]
  base.whitelisted_ransackable_attributes |= %w[kind from_date to_date]

  base.enum purchasable_on: { both: 0, web: 1, app: 2 }
  base.has_many :crew_invites, class_name: 'SpreeCmCommissioner::CrewInvite', dependent: :destroy
  base.has_many :invite_user_events, through: :user_events, class_name: 'SpreeCmCommissioner::InviteUserEvent'

  base.has_many :crew_invite_links, class_name: 'SpreeCmCommissioner::CrewInviteLink', dependent: :destroy

  base.has_many :invite_guests, class_name: 'SpreeCmCommissioner::InviteGuest', foreign_key: :event_id
  base.has_many :invite_guest_groups, class_name: 'SpreeCmCommissioner::InviteGuestGroup', foreign_key: :event_id

  base.has_many :line_items, through: :products
  base.has_many :event_line_items, class_name: 'Spree::LineItem', foreign_key: :event_id
  base.has_many :event_products, class_name: 'Spree::Product', foreign_key: :event_id
  base.has_many :event_variants, through: :event_products, class_name: 'Spree::Variant', source: :variants

  base.has_many :event_blazer_queries, as: :queryable, class_name: 'SpreeCmCommissioner::BlazerQueryable'
  base.has_many :blazer_queries, through: :event_blazer_queries, source: :blazer_query, class_name: 'Blazer::Query'

  base.has_many :taxon_option_types, class_name: 'SpreeCmCommissioner::TaxonOptionType'
  base.has_many :taxon_option_values, class_name: 'SpreeCmCommissioner::TaxonOptionValue'

  base.after_commit :send_transaction_email_to_organizers, on: :create
  base.after_commit :send_event_creation_telegram_alert, on: :create

  base.has_many :taxon_places, class_name: 'SpreeCmCommissioner::TaxonPlace', dependent: :destroy
  base.has_many :places, through: :taxon_places
  base.has_many :check_in_sessions, class_name: 'SpreeCmCommissioner::CheckInSession', foreign_key: :event_id, dependent: :destroy
  base.has_many :active_check_in_sessions, -> { active }, class_name: 'SpreeCmCommissioner::CheckInSession', foreign_key: :event_id

  base.has_many :import_orders, as: :importable, class_name: 'SpreeCmCommissioner::Imports::ImportOrder', dependent: :destroy

  base.scope :shows, -> { where(taxonomy_id: Spree::Taxonomy.shows.id, depth: 1) }
  base.scope :events,     -> { where(taxonomy_id: Spree::Taxonomy.events.id, depth: 1) }
  base.scope :ad_campaigns, -> { where(taxonomy_id: Spree::Taxonomy.ads.id, depth: 1) }

  # Event taxons currently inside their live-stock sale window — see
  # SpreeCmCommissioner::StockStatusConsolidationJob, which only publishes to Firestore for events
  # matched by this scope. `live_stock_starts_at`/`live_stock_ends_at` are only meaningful for
  # `kind: :event` taxons (same convention as `from_date`/`to_date`) — a null on either side
  # naturally excludes the row here, since SQL's <=/>= against NULL is never true.
  base.scope :live_stock_active, lambda {
    where(kind: :event).where('live_stock_starts_at <= ? AND live_stock_ends_at >= ?', Time.current, Time.current)
  }

  base.has_many :advertisements,
                -> { where(product_type: :advertisement, deleted_at: nil) },
                through: :classifications,
                class_name: 'Spree::Product',
                source: :product

  base.has_many :agencies, class_name: 'SpreeCmCommissioner::Agency', foreign_key: :agency_category_id
  base.has_many :preview_roles, class_name: 'SpreeCmCommissioner::PreviewRole', as: :previewable

  base.scope :visible_to, lambda { |user|
    publicly_available = where(preview: false)

    if user
      allowed_ids = user.preview_roles.where(previewable_type: polymorphic_name).select(:previewable_id)
      publicly_available.or(where(preview: true, id: allowed_ids))
    else
      publicly_available
    end
  }

  # Create maintaining task to purge taxon related caches
  base.after_save { SpreeCmCommissioner::MaintenanceTasks::CacheInvalidation.pending.create_or_find_by(maintainable: self) }

  def base.active_homepage_events
    joins(:homepage_section_relatables)
      .joins("INNER JOIN spree_taxons taxon ON taxon.id = cm_homepage_section_relatables.relatable_id
              AND cm_homepage_section_relatables.relatable_type = 'Spree::Taxon'"
            )
      .joins('INNER JOIN cm_homepage_sections ON cm_homepage_section_relatables.homepage_section_id = cm_homepage_sections.id')
      .where(cm_homepage_sections: { tenant_id: nil, active: true })
      .where(kind: :event)
      .where(preview: false)
  end

  def base.find_event(id)
    find_by(slug: "events-#{id}")
  end
end

Instance Method Details

#ended?Boolean

Returns:

  • (Boolean)


186
187
188
# File 'app/models/spree_cm_commissioner/taxon_decorator.rb', line 186

def ended?
  to_date.present? && to_date <= Time.current
end

#event_slugObject



163
164
165
# File 'app/models/spree_cm_commissioner/taxon_decorator.rb', line 163

def event_slug
  slug.sub(/^events-/, '')
end

#event_urlObject



182
183
184
# File 'app/models/spree_cm_commissioner/taxon_decorator.rb', line 182

def event_url
  "https://#{Spree::Store.default.url}/t/#{permalink}"
end

#products_option_type_namesObject



167
168
169
170
171
172
# File 'app/models/spree_cm_commissioner/taxon_decorator.rb', line 167

def products_option_type_names
  Spree::OptionType.joins(products: :taxons)
                   .where(spree_taxons: { id: child_ids })
                   .pluck('spree_option_types.name')
                   .uniq
end

#selected_option_typesObject



174
175
176
# File 'app/models/spree_cm_commissioner/taxon_decorator.rb', line 174

def selected_option_types
  taxon_option_types.pluck(:option_type_id)
end

#selected_option_valuesObject



178
179
180
# File 'app/models/spree_cm_commissioner/taxon_decorator.rb', line 178

def selected_option_values
  taxon_option_values.pluck(:option_value_id)
end

#send_event_creation_telegram_alertObject



196
197
198
199
200
# File 'app/models/spree_cm_commissioner/taxon_decorator.rb', line 196

def send_event_creation_telegram_alert
  return unless kind == 'event' && depth == 1

  SpreeCmCommissioner::EventCreationTelegramAlertSenderJob.perform_later(event_id: id)
end

#send_transaction_email_to_organizersObject



190
191
192
193
194
# File 'app/models/spree_cm_commissioner/taxon_decorator.rb', line 190

def send_transaction_email_to_organizers
  return unless kind == 'event' && level == 1

  SpreeCmCommissioner::OrganizersTransactionalEmailNotifier.call(event_id: id)
end

#set_kindObject



151
152
153
# File 'app/models/spree_cm_commissioner/taxon_decorator.rb', line 151

def set_kind
  self.kind = taxonomy.kind
end

#set_live_stock_pathObject



155
156
157
# File 'app/models/spree_cm_commissioner/taxon_decorator.rb', line 155

def set_live_stock_path
  self.live_stock_path = "events/#{id}"
end

#set_slugObject



159
160
161
# File 'app/models/spree_cm_commissioner/taxon_decorator.rb', line 159

def set_slug
  self.slug = permalink&.parameterize
end

#sync_event_dates_to_line_itemsObject



202
203
204
205
206
# File 'app/models/spree_cm_commissioner/taxon_decorator.rb', line 202

def sync_event_dates_to_line_items
  return unless event? && depth == 1

  ::SpreeCmCommissioner::LineItems::SyncEventDateJob.perform_later(event_id: id)
end