Class: Coupon
Overview
== Schema Information
Table name: coupons
Database name: primary
id :integer not null, primary key
allow_non_domestic_shipping :boolean
allow_oversized_items :boolean default(FALSE), not null
amount_goods :decimal(10, 2)
amount_services :decimal(10, 2)
amount_services_ar :float is an Array
amount_shipping :decimal(10, 2)
auto_apply :boolean default(FALSE), not null
auto_buying_group_exclude :boolean
buying_group_ids_exclude :boolean default(FALSE), not null
calculation_type_goods :string(5)
calculation_type_services :string(5)
calculation_type_shipping :string(5)
code :string(255)
description :text
details :text
effective_date :date
exclude_opportunity_reception_types_filters :boolean default(FALSE), not null
exclude_opportunity_types_filters :boolean default(FALSE), not null
exclude_order_reception_types_filters :boolean default(FALSE), not null
exclude_order_types_filters :boolean default(FALSE), not null
exclude_state_codes :boolean default(FALSE), not null
exclusion_level :integer default("not_exclusive"), not null
expiration_date :date
first_time_customers_only :boolean default(FALSE), not null
is_inactive :boolean default(FALSE), not null
last_used_at :datetime
legacy_amount_goods :string(100)
legacy_amount_services :string(100)
legacy_amount_shipping :string(100)
opportunity_reception_types_filter :string default([]), is an Array
opportunity_types_filter :string default([]), is an Array
order_reception_types_filter :string(255) default([]), is an Array
order_types_filter :string(255) default([]), is an Array
p5 :string(100)
p6 :string(100)
position :integer
profile_ids_exclude :boolean
promo_page_content_html :text
promo_tracking :boolean default(FALSE), not null
role_ids_restriction :integer default([]), is an Array
sale_page_position :integer default(0), not null
serial_numbers_only :boolean default(FALSE), not null
ships_economy_only :boolean default(FALSE), not null
single_use_per_customer :boolean default(FALSE), not null
state_codes :string(255) default([]), is an Array
store_id_restriction :integer
tier :integer default(3), not null
title :text
type :string(50)
created_at :datetime
updated_at :datetime
auto_apply_customer_filter_id :integer
creator_id :integer
customer_filter_id :integer
image_id :integer
publication_id :integer
source_id :integer
updater_id :integer
Indexes
by_auto_ap_st_codes (auto_apply,state_codes)
idx_code (code)
idx_type_is_inactive (type,is_inactive)
index_coupons_on_auto_apply_customer_filter_id (auto_apply_customer_filter_id)
index_coupons_on_customer_filter_id (customer_filter_id)
index_coupons_on_image_id (image_id)
index_coupons_on_position (position)
index_coupons_on_single_use_per_customer (single_use_per_customer)
index_coupons_on_type_and_id (type,id)
Foreign Keys
coupons_auto_apply_customer_filter_id_fk (auto_apply_customer_filter_id => customer_filters.id)
coupons_customer_filter_id_fk (customer_filter_id => customer_filters.id)
fk_rails_... (image_id => digital_assets.id)
Defined Under Namespace
Classes: ApplyCoupon, CatalogItemPricing, DeleteDiscount, ItemizableDiscountCalculator, LineItemDiscountAllocator, MsrpAllocator, OverlappingPromoValidator, PromoItemSync, Qualifier, QueryBuilder, Tier1BaseItemPricing, Tier2ProgramPricing, Tier3PromotionalPricing
Constant Summary
collapse
- INSTRUCTIONS =
'Placeholder'
- VALID_PRICE_MATRIX_CALCULATIONS =
['%', '$', 'DP', 'MP']
- FIXED_DOLLAR_CALCULATIONS =
{
'Flat Amount Off' => '$',
'Adjustable (+ or -)' => '?',
'Adjustable (Discount Only)' => '-?',
'Adjustable (Charge Only)' => '+?'
}
- FIXED_DOLLAR_CALCULATIONS_TYPES =
FIXED_DOLLAR_CALCULATIONS.map { |_k, v| v }
- CORE_CALCULATIONS =
FIXED_DOLLAR_CALCULATIONS.merge({
'Percentage Off' => '%',
'Flat Amount Off Per Unit' => '$1',
'Percentage Off MSRP' => '%M',
'Percentage Off Catalog Price with VAT' => '%V',
'Percentage Off per Min Qty Met' => '%1',
'Force Discount Unit Price' => 'DP',
'Force MSRP' => 'MP',
'Promo Matrix' => 'MX'
})
- CALCULATION_TYPES_GOODS =
CORE_CALCULATIONS.merge({
'Sq.Ft Multiplier for MSRP' => 'SF',
'Linear Ft Multiplier for MSRP' => 'LF',
'Sq.Ft Multiplier after base discount' => 'SD',
'Linear Ft Multiplier after base discount' => 'LD'
})
- CALCULATION_TYPES_SERVICES =
CORE_CALCULATIONS
- CALCULATION_TYPES_SHIPPING =
{ 'Percentage Off' => '%', 'Flat Amount Off' => '$',
'Flat Rate Shipping' => '_R', 'Adjustable (Discount or Charge)' => '?',
'Adjustable (Discount Only)' => '-?', 'Adjustable (Charge Only)' => '+?' }
- ADJUSTABLE_CALCULATIONS =
['?', '-?', '+?']
- FREE_ONLINE_SHIPPING_COUPON_CODES =
%w[FREEGNDONLINE FREEGNDONLINECA FREE_ECONOMY_ONLINE_USA FREE_ECONOMY_ONLINE_CAN]
- FREE_ECONOMY_SHIPPING_ONLINE_COUPON_CODES_BY_COUNTRY =
{ USA: 'FREE_ECONOMY_ONLINE_USA', CAN: 'FREE_ECONOMY_ONLINE_CAN' }
- ECONOMY_SHIPPING_MATCH_CRM_COUPON_CODE =
'ECONOMY_SHIPPING_MATCH_CRM'
- SKIP_BLACKLISTING_COUPON_CODES =
this blacklisting just breaks things when holding/release. Just skip for these codes!
[ECONOMY_SHIPPING_MATCH_CRM_COUPON_CODE] + FREE_ECONOMY_SHIPPING_ONLINE_COUPON_CODES_BY_COUNTRY.values
Models::Auditable::ALWAYS_IGNORED
Instance Attribute Summary collapse
#creator, #updater
Delegated Instance Attributes
collapse
Class Method Summary
collapse
Instance Method Summary
collapse
#sanitize_html_fragment
#all_skipped_columns, #audit_reference_data, #should_not_save_version, #stamp_record
ransackable_associations, ransackable_attributes, ransackable_scopes, ransortable_attributes, #to_relation
#publish_event
Instance Attribute Details
#amount_goods_override ⇒ Object
Returns the value of attribute amount_goods_override.
132
133
134
|
# File 'app/models/coupon.rb', line 132
def amount_goods_override
@amount_goods_override
end
|
#amount_services_override ⇒ Object
Returns the value of attribute amount_services_override.
132
133
134
|
# File 'app/models/coupon.rb', line 132
def amount_services_override
@amount_services_override
end
|
#amount_shipping_override ⇒ Object
Returns the value of attribute amount_shipping_override.
132
133
134
|
# File 'app/models/coupon.rb', line 132
def amount_shipping_override
@amount_shipping_override
end
|
#serial_number ⇒ Object
Returns the value of attribute serial_number.
132
133
134
|
# File 'app/models/coupon.rb', line 132
def serial_number
@serial_number
end
|
#ship_to_continental_regions ⇒ Object
Returns the value of attribute ship_to_continental_regions.
132
133
134
|
# File 'app/models/coupon.rb', line 132
def ship_to_continental_regions
@ship_to_continental_regions
end
|
Class Method Details
.active ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are active. Active Record Scope
171
|
# File 'app/models/coupon.rb', line 171
scope :active, -> { where.not(is_inactive: true) }
|
.active_and_future ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are active and future. Active Record Scope
189
|
# File 'app/models/coupon.rb', line 189
scope :active_and_future, -> { active.where.not(effective_date: nil).where(Coupon[:effective_date].gt(Date.current)) }
|
.affect_goods ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are affect goods. Active Record Scope
193
|
# File 'app/models/coupon.rb', line 193
scope :affect_goods, -> { where.not(calculation_type_goods: nil) }
|
.affect_services ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are affect services. Active Record Scope
194
|
# File 'app/models/coupon.rb', line 194
scope :affect_services, -> { where.not(calculation_type_services: nil) }
|
.affect_shipping ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are affect shipping. Active Record Scope
195
|
# File 'app/models/coupon.rb', line 195
scope :affect_shipping, -> { where.not(calculation_type_shipping: nil) }
|
.auto_applied ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are auto applied. Active Record Scope
173
|
# File 'app/models/coupon.rb', line 173
scope :auto_applied, -> { where(auto_apply: true) }
|
.by_code ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are by code. Active Record Scope
170
|
# File 'app/models/coupon.rb', line 170
scope :by_code, -> { order(:code) }
|
.calculation_types_for_goods_select ⇒ Object
293
294
295
|
# File 'app/models/coupon.rb', line 293
def self.calculation_types_for_goods_select
CALCULATION_TYPES_GOODS.to_a.sort
end
|
.calculation_types_for_services_select ⇒ Object
297
298
299
|
# File 'app/models/coupon.rb', line 297
def self.calculation_types_for_services_select
CALCULATION_TYPES_SERVICES.to_a.sort
end
|
.calculation_types_for_shipping_select ⇒ Object
301
302
303
|
# File 'app/models/coupon.rb', line 301
def self.calculation_types_for_shipping_select
CALCULATION_TYPES_SHIPPING.to_a.sort
end
|
.coupon_type_for_select ⇒ Object
274
275
276
|
# File 'app/models/coupon.rb', line 274
def self.coupon_type_for_select
coupon_types.invert
end
|
.coupon_types ⇒ Object
270
271
272
|
# File 'app/models/coupon.rb', line 270
def self.coupon_types
['Coupon::Tier1BaseItemPricing', 'Coupon::Tier2ProgramPricing', 'Coupon::Tier3PromotionalPricing'].index_with { |t| t.constantize.friendly_type_name }
end
|
.customer_accessible ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are customer accessible. Active Record Scope
188
|
# File 'app/models/coupon.rb', line 188
scope :customer_accessible, -> { tier3.active.non_auto_applied }
|
.customer_filters_for_select ⇒ Object
313
314
315
|
# File 'app/models/coupon.rb', line 313
def self.customer_filters_for_select
CustomerFilter.joins(:coupons).order(CustomerFilter[:name]).distinct.pluck(:name, :id)
end
|
.discounted_price ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are discounted price. Active Record Scope
176
|
# File 'app/models/coupon.rb', line 176
scope :discounted_price, -> { where(amount_goods: 'DP') }
|
.exclude_ships_economy_only ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are exclude ships economy only. Active Record Scope
199
|
# File 'app/models/coupon.rb', line 199
scope :exclude_ships_economy_only, -> { where.not(ships_economy_only: true) }
|
.exclusion_level_for_select ⇒ Object
278
279
280
|
# File 'app/models/coupon.rb', line 278
def self.exclusion_level_for_select
exclusion_levels.map { |k, _v| [k.humanize, k] }
end
|
.expired ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are expired. Active Record Scope
180
|
# File 'app/models/coupon.rb', line 180
scope :expired, ->(date = Date.current) { where.not(expiration_date: nil).where(Coupon[:expiration_date].lteq(date)) }
|
.fixed_dollar ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are fixed dollar. Active Record Scope
.for_public ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are for public. Active Record Scope
182
|
# File 'app/models/coupon.rb', line 182
scope :for_public, -> { tier3.where(Coupon[:role_ids_restriction].contains([Role.find_by(name: 'customer').id]).or(Coupon[:role_ids_restriction].eq([])).or(Coupon[:role_ids_restriction].eq(nil))) }
|
.free_online_shipping ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are free online shipping. Active Record Scope
.friendly_calculation_name(calculation_type) ⇒ Object
.friendly_price_matrix_calculation_names ⇒ Object
.in_effect_on ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are in effect on. Active Record Scope
178
|
# File 'app/models/coupon.rb', line 178
scope :in_effect_on, ->(date = Date.current) { active.where(Coupon[:effective_date].eq(nil).or(Coupon[:effective_date].lteq(date))).where(Coupon[:expiration_date].eq(nil).or(Coupon[:expiration_date].gteq(date))) }
|
.inactive ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are inactive. Active Record Scope
172
|
# File 'app/models/coupon.rb', line 172
scope :inactive, -> { where(is_inactive: true) }
|
.instantiate_by_type(type) ⇒ Object
262
263
264
|
# File 'app/models/coupon.rb', line 262
def self.instantiate_by_type(type)
(coupon_types.keys & [type])[0].constantize
end
|
.msrp_price ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are msrp price. Active Record Scope
177
|
# File 'app/models/coupon.rb', line 177
scope :msrp_price, -> { where(amount_goods: %w[MP SF LF]) }
|
.non_auto_applied ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are non auto applied. Active Record Scope
174
|
# File 'app/models/coupon.rb', line 174
scope :non_auto_applied, -> { where(auto_apply: false) }
|
.not_expired ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are not expired. Active Record Scope
181
|
# File 'app/models/coupon.rb', line 181
scope :not_expired, ->(date = Date.current) { where.not(expiration_date: nil).where(Coupon[:expiration_date].gt(date)) }
|
.not_in_effect_on ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are not in effect on. Active Record Scope
179
|
# File 'app/models/coupon.rb', line 179
scope :not_in_effect_on, ->(date = Date.current) { where(Coupon[:effective_date].eq(nil).or(Coupon[:effective_date].gt(date))).where(Coupon[:expiration_date].eq(nil).or(Coupon[:expiration_date].lt(date))) }
|
.order_types_for_select ⇒ Object
266
267
268
|
# File 'app/models/coupon.rb', line 266
def self.order_types_for_select
%w[SO CO ST]
end
|
A relation of Coupons that are promo. Active Record Scope
200
|
# File 'app/models/coupon.rb', line 200
scope :promo, -> { where(promo_tracking: true) }
|
.promo_for_sale_page ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are promo for sale page. Active Record Scope
201
202
203
204
205
206
207
|
# File 'app/models/coupon.rb', line 201
scope :promo_for_sale_page, -> {
excluded_codes = []
excluded_codes << 'FREE_ECONOMY_ONLINE_USA' unless I18n.locale == :'en-US'
excluded_codes << 'FREE_ECONOMY_ONLINE_CAN' unless I18n.locale.in?(%i[en-CA fr-CA])
active.in_effect_on.where.not(code: excluded_codes).where(Coupon[:sale_page_position].gt(0)).order(sale_page_position: :asc, created_at: :desc)
}
|
A relation of Coupons that are promo matrix. Active Record Scope
186
|
# File 'app/models/coupon.rb', line 186
scope :promo_matrix, -> { where(calculation_type_goods: 'MX').or(where(calculation_type_services: 'MX')).or(where(calculation_type_shipping: 'MX')) }
|
.select_options ⇒ Object
305
306
307
|
# File 'app/models/coupon.rb', line 305
def self.select_options
all.order(:code).pluck(:code, :id)
end
|
.ships_economy_only ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are ships economy only. Active Record Scope
198
|
# File 'app/models/coupon.rb', line 198
scope :ships_economy_only, -> { where(ships_economy_only: true) }
|
.sorted ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are sorted. Active Record Scope
169
|
# File 'app/models/coupon.rb', line 169
scope :sorted, -> { order(Coupon[:type], Coupon[:position]) }
|
.tier1 ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are tier1. Active Record Scope
183
|
# File 'app/models/coupon.rb', line 183
scope :tier1, -> { where(type: 'Coupon::Tier1BaseItemPricing') }
|
.tier1and3 ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are tier1and3. Active Record Scope
187
|
# File 'app/models/coupon.rb', line 187
scope :tier1and3, -> { where(type: ['Coupon::Tier1BaseItemPricing', 'Coupon::Tier3PromotionalPricing']) }
|
.tier2 ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are tier2. Active Record Scope
184
|
# File 'app/models/coupon.rb', line 184
scope :tier2, -> { where(type: 'Coupon::Tier2ProgramPricing') }
|
.tier2_select_options ⇒ Object
309
310
311
|
# File 'app/models/coupon.rb', line 309
def self.tier2_select_options
tier2.order(:title).pluck(:title, :id)
end
|
.tier3 ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are tier3. Active Record Scope
185
|
# File 'app/models/coupon.rb', line 185
scope :tier3, -> { where(type: 'Coupon::Tier3PromotionalPricing') }
|
.with_economy_shipping_match_crm ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are with economy shipping match crm. Active Record Scope
.with_publication ⇒ ActiveRecord::Relation<Coupon>
A relation of Coupons that are with publication. Active Record Scope
175
|
# File 'app/models/coupon.rb', line 175
scope :with_publication, -> { where.not(publication_id: nil) }
|
Instance Method Details
#adjustable ⇒ Object
419
420
421
|
# File 'app/models/coupon.rb', line 419
def adjustable
goods_adjustable or services_adjustable or shipping_adjustable
end
|
#all_applicable_catalog_items ⇒ Object
450
451
452
453
454
455
456
457
|
# File 'app/models/coupon.rb', line 450
def all_applicable_catalog_items
item_ids = all_applicable_item_ids
catalog_ids = all_catalog_ids || []
CatalogItem.joins(:item).where(items: { id: item_ids }, catalog_id: catalog_ids).available_for_edi_feeds
end
|
#all_applicable_item_ids ⇒ Object
Returns all applicable item IDs using real-time ltree queries.
No caching needed - ltree queries are fast (~1-2ms per filter).
437
438
439
|
# File 'app/models/coupon.rb', line 437
def all_applicable_item_ids
product_filters.where(apply_discount: true).flat_map { |pf| pf.applicable_item_ids_set.to_a }.uniq
end
|
#all_catalog_ids ⇒ Object
Alias for Customer_filter#all_catalog_ids
244
|
# File 'app/models/coupon.rb', line 244
delegate :all_catalog_ids, to: :customer_filter, allow_nil: true
|
#apply_source_to_customer(customer) ⇒ Object
577
578
579
580
581
582
|
# File 'app/models/coupon.rb', line 577
def apply_source_to_customer(customer)
return unless source
customer.update_attribute(:source_id, source_id)
end
|
#apply_source_to_opportunity(opportunity) ⇒ Object
594
595
596
597
598
|
# File 'app/models/coupon.rb', line 594
def apply_source_to_opportunity(opportunity)
return unless source && opportunity.sales_opportunity?
opportunity.update_column(:source_id, source_id)
end
|
#apply_source_to_order(order) ⇒ Object
584
585
586
587
588
589
590
591
592
|
# File 'app/models/coupon.rb', line 584
def apply_source_to_order(order)
return unless source && order && order.is_sales_order?
if order.persisted?
order.update_column(:source_id, source_id)
else
order.source_id = source_id
end
end
|
#auto_apply_customer_filter ⇒ CustomerFilter
140
|
# File 'app/models/coupon.rb', line 140
belongs_to :auto_apply_customer_filter, inverse_of: :auto_apply_coupons, class_name: 'CustomerFilter', optional: true
|
#blacklistable? ⇒ Boolean
Every coupon by default is blacklistable if they are auto apply
This behavior can be overriden in each class of coupon
e.g. tier2 coupon is always true
411
412
413
414
415
416
417
|
# File 'app/models/coupon.rb', line 411
def blacklistable?
if SKIP_BLACKLISTING_COUPON_CODES.include?(code)
false
else
auto_apply
end
end
|
#coupon_active? ⇒ Boolean
353
354
355
|
# File 'app/models/coupon.rb', line 353
def coupon_active?
status == :active
end
|
#coupon_expired? ⇒ Boolean
345
346
347
|
# File 'app/models/coupon.rb', line 345
def coupon_expired?
status == :expired
end
|
#coupon_inactive? ⇒ Boolean
341
342
343
|
# File 'app/models/coupon.rb', line 341
def coupon_inactive?
status == :inactive
end
|
#coupon_not_yet_in_effect? ⇒ Boolean
349
350
351
|
# File 'app/models/coupon.rb', line 349
def coupon_not_yet_in_effect?
status == :not_yet_in_effect
end
|
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
|
# File 'app/models/coupon.rb', line 357
def coupon_promo_sync_alert
msg = nil
if coupon_active? || coupon_not_yet_in_effect?
if (missing_catalog_items = missing_catalog_items_not_in_promotion_product_filter).present?
msg = %(There are potentially #{missing_catalog_items.size} catalog items in your product filter that need to be synchronized,
run Synchronize Promo Items to correct)
elsif (missing_items = promotional_item_ids_not_in_product_filter).present?
msg = %(There are #{missing_items.size} items in your promotional catalog that are not part of your filter,
run Synchronize Promo Items to correct)
end
elsif (coupon_expired? || coupon_inactive?) && promotional_view_product_catalog_items.present?
msg = %(Coupon is inactive or expired, synchronize promo items to cleanup catalog item references)
end
msg
end
|
#coupon_serial_numbers ⇒ ActiveRecord::Relation<CouponSerialNumber>
147
|
# File 'app/models/coupon.rb', line 147
has_many :coupon_serial_numbers, dependent: :destroy, inverse_of: :coupon
|
#customer_can_apply? ⇒ Boolean
573
574
575
|
# File 'app/models/coupon.rb', line 573
def customer_can_apply?
(is_inactive != true) and (auto_apply != true) and public? and tier3?
end
|
139
|
# File 'app/models/coupon.rb', line 139
belongs_to :customer_filter, inverse_of: :coupons, optional: true
|
#customer_ids_txt ⇒ Object
565
566
567
|
# File 'app/models/coupon.rb', line 565
def customer_ids_txt
(customer_ids || []).join(',')
end
|
#customer_ids_txt=(val) ⇒ Object
561
562
563
|
# File 'app/models/coupon.rb', line 561
def customer_ids_txt=(val)
self.customer_ids = val end
|
#deactivate ⇒ Object
487
488
489
|
# File 'app/models/coupon.rb', line 487
def deactivate
update({ is_inactive: true })
end
|
#deep_dup ⇒ Object
250
251
252
253
254
255
256
257
258
259
260
|
# File 'app/models/coupon.rb', line 250
def deep_dup
deep_clone(
include: :product_filters,
except: %i[effective_date expiration_date]
) do |_original, copy|
if copy.is_a?(Coupon)
copy.code = "#{code}_COPY"
copy.is_inactive = true
end
end
end
|
#discounts ⇒ ActiveRecord::Relation<Discount>
144
|
# File 'app/models/coupon.rb', line 144
has_many :discounts, inverse_of: :coupon
|
#exclusive? ⇒ Boolean
246
247
248
|
# File 'app/models/coupon.rb', line 246
def exclusive?
!not_exclusive?
end
|
#flat_amount_goods ⇒ Object
537
538
539
|
# File 'app/models/coupon.rb', line 537
def flat_amount_goods
(amount_goods_override || amount_goods).to_f.round(2)
end
|
#flat_amount_services ⇒ Object
545
546
547
|
# File 'app/models/coupon.rb', line 545
def flat_amount_services
(amount_services_override || amount_services).to_f.round(2)
end
|
#flat_amount_shipping ⇒ Object
541
542
543
|
# File 'app/models/coupon.rb', line 541
def flat_amount_shipping
(amount_shipping_override || amount_shipping).to_f.round(2)
end
|
149
|
# File 'app/models/coupon.rb', line 149
has_many :future_promotional_catalog_items, class_name: 'CatalogItem', foreign_key: :new_coupon_id, dependent: :nullify, inverse_of: :new_coupon
|
#goods_adjustable ⇒ Object
423
424
425
|
# File 'app/models/coupon.rb', line 423
def goods_adjustable
ADJUSTABLE_CALCULATIONS.include? calculation_type_goods
end
|
142
|
# File 'app/models/coupon.rb', line 142
belongs_to :image, optional: true
|
#instructions ⇒ Object
483
484
485
|
# File 'app/models/coupon.rb', line 483
def instructions
self.class::INSTRUCTIONS
end
|
#is_goods_price_forcing? ⇒ Boolean
525
526
527
|
# File 'app/models/coupon.rb', line 525
def is_goods_price_forcing?
%w[DP MP].include? calculation_type_goods
end
|
#is_msrp_goods_based? ⇒ Boolean
533
534
535
|
# File 'app/models/coupon.rb', line 533
def is_msrp_goods_based?
%w[SF LF].include? calculation_type_goods
end
|
#is_price_forcing? ⇒ Boolean
521
522
523
|
# File 'app/models/coupon.rb', line 521
def is_price_forcing?
is_goods_price_forcing? or is_services_price_forcing?
end
|
#is_services_price_forcing? ⇒ Boolean
529
530
531
|
# File 'app/models/coupon.rb', line 529
def is_services_price_forcing?
%w[DP MP].include? calculation_type_services
end
|
#label_for(n) ⇒ Object
477
478
479
480
481
|
# File 'app/models/coupon.rb', line 477
def label_for(n)
eval("self.class::LABEL_P#{n}")
rescue StandardError
nil
end
|
#line_discounts ⇒ ActiveRecord::Relation<LineDiscount>
145
|
# File 'app/models/coupon.rb', line 145
has_many :line_discounts, inverse_of: :coupon
|
#localized_promo_page_content_html(locale = nil, preview_mode: false) ⇒ Object
385
386
387
388
389
390
391
392
393
394
395
|
# File 'app/models/coupon.rb', line 385
def localized_promo_page_content_html(locale = nil, preview_mode: false)
return unless promo_page_content_html.present?
locale ||= I18n.locale
Liquid::ParseEnvironment.parse(promo_page_content_html).render(
'preview_mode' => preview_mode,
'locale' => locale.to_s,
'canada' => %i[en-CA fr-CA].include?(locale.to_sym),
'usa' => locale.to_sym == :'en-US'
)
end
|
459
460
461
|
# File 'app/models/coupon.rb', line 459
def missing_catalog_items_not_in_promotion_product_filter
all_applicable_catalog_items.where.not(id: promotional_view_product_catalog_items.pluck(:id))
end
|
#percentage_off_goods ⇒ Object
549
550
551
|
# File 'app/models/coupon.rb', line 549
def percentage_off_goods
(amount_goods_override || amount_goods).to_f / 100
end
|
#percentage_off_services ⇒ Object
557
558
559
|
# File 'app/models/coupon.rb', line 557
def percentage_off_services
(amount_services_override || amount_services).to_f / 100
end
|
#percentage_off_shipping ⇒ Object
553
554
555
|
# File 'app/models/coupon.rb', line 553
def percentage_off_shipping
(amount_shipping_override || amount_shipping).to_f / 100
end
|
#product_filter_item_ids_not_in_catalog_items ⇒ Object
463
464
465
|
# File 'app/models/coupon.rb', line 463
def product_filter_item_ids_not_in_catalog_items
all_applicable_item_ids - promotional_view_product_catalog_items.pluck(:item_id)
end
|
#product_filters ⇒ ActiveRecord::Relation<ProductFilter>
146
|
# File 'app/models/coupon.rb', line 146
has_many :product_filters, as: :resource
|
517
518
519
|
# File 'app/models/coupon.rb', line 517
def promotion_matrix_calculation?
[calculation_type_goods, calculation_type_services, calculation_type_shipping].include?('MX')
end
|
148
|
# File 'app/models/coupon.rb', line 148
has_many :promotional_catalog_items, class_name: 'CatalogItem', dependent: :nullify, inverse_of: :coupon
|
467
468
469
|
# File 'app/models/coupon.rb', line 467
def promotional_item_ids_not_in_product_filter
promotional_view_product_catalog_items.pluck(:item_id) - all_applicable_item_ids
end
|
Returns the view product catalog items applicable for this coupon
#public? ⇒ Boolean
569
570
571
|
# File 'app/models/coupon.rb', line 569
def public?
role_ids_restriction.empty? or role_ids_restriction.include?(Role.find_by(name: 'customer').id)
end
|
#publication ⇒ Item
138
|
# File 'app/models/coupon.rb', line 138
belongs_to :publication, class_name: 'Item', optional: true
|
#qualifying_line_items?(itemizable) ⇒ Boolean
500
501
502
503
504
505
506
507
508
509
510
511
|
# File 'app/models/coupon.rb', line 500
def qualifying_line_items?(itemizable)
lines = itemizable.line_items.with_discount_preloads.active_parent_lines
ProductFilter::LineQualifier.new(lines, product_filters,
{
code:,
coupon_tier: tier,
allow_non_domestic_shipping: allow_non_domestic_shipping?,
exclusion_level:
}).qualifying_line_items?
end
|
#reactivate ⇒ Object
491
492
493
|
# File 'app/models/coupon.rb', line 491
def reactivate
update({ is_inactive: false })
end
|
#require_amount_goods? ⇒ Boolean
600
601
602
|
# File 'app/models/coupon.rb', line 600
def require_amount_goods?
calculation_type_goods.present? && !goods_adjustable && !calculation_type_goods == 'MX'
end
|
#require_amount_services? ⇒ Boolean
604
605
606
|
# File 'app/models/coupon.rb', line 604
def require_amount_services?
calculation_type_services.present? && !services_adjustable && !calculation_type_services == 'MX'
end
|
#require_amount_shipping? ⇒ Boolean
608
609
610
|
# File 'app/models/coupon.rb', line 608
def require_amount_shipping?
calculation_type_shipping.present? && !shipping_adjustable && !calculation_type_shipping == 'MX'
end
|
#require_product_filter? ⇒ Boolean
513
514
515
|
# File 'app/models/coupon.rb', line 513
def require_product_filter?
is_price_forcing? and !(code == 'SMARTPRESETFREEBG')
end
|
#select_options_for(n) ⇒ Object
471
472
473
474
475
|
# File 'app/models/coupon.rb', line 471
def select_options_for(n)
eval("self.class::OPTIONS_P#{n}")
rescue StandardError
nil
end
|
#services_adjustable ⇒ Object
427
428
429
|
# File 'app/models/coupon.rb', line 427
def services_adjustable
ADJUSTABLE_CALCULATIONS.include? calculation_type_services
end
|
#shipping_adjustable ⇒ Object
431
432
433
|
# File 'app/models/coupon.rb', line 431
def shipping_adjustable
ADJUSTABLE_CALCULATIONS.include? calculation_type_shipping
end
|
141
|
# File 'app/models/coupon.rb', line 141
belongs_to :source, optional: true
|
#status ⇒ Object
329
330
331
332
333
334
335
336
337
338
339
|
# File 'app/models/coupon.rb', line 329
def status
if is_inactive
:inactive
elsif expiration_date && Date.current > expiration_date
:expired
elsif effective_date && Date.current < effective_date
:not_yet_in_effect
else
:active
end
end
|
#sticky? ⇒ Boolean
Sticky coupons remain even when $0
496
497
498
|
# File 'app/models/coupon.rb', line 496
def sticky?
is_price_forcing?
end
|
#tier1? ⇒ Boolean
317
318
319
|
# File 'app/models/coupon.rb', line 317
def tier1?
type == 'Coupon::Tier1BaseItemPricing'
end
|
#tier2? ⇒ Boolean
321
322
323
|
# File 'app/models/coupon.rb', line 321
def tier2?
type == 'Coupon::Tier2ProgramPricing'
end
|
#tier3? ⇒ Boolean
325
326
327
|
# File 'app/models/coupon.rb', line 325
def tier3?
type == 'Coupon::Tier3PromotionalPricing'
end
|
#to_s ⇒ Object
373
374
375
376
377
378
379
380
381
382
383
|
# File 'app/models/coupon.rb', line 373
def to_s
[
code,
("G(#{amount_goods}#{calculation_type_goods})" if calculation_type_goods),
("SV(#{amount_services}#{calculation_type_services})" if calculation_type_services),
("SH(#{amount_shipping}#{calculation_type_shipping})" if calculation_type_shipping),
("From #{effective_date || 'Anytime'}" if effective_date),
("Until #{expiration_date}" if expiration_date),
title
].compact.join(' - ')
end
|
#versions_for_audit_trail(_params = {}) ⇒ Object
397
398
399
400
401
402
403
404
405
406
|
# File 'app/models/coupon.rb', line 397
def versions_for_audit_trail(_params = {})
query_sql = %q{
(item_type = 'Coupon' and item_id = :id)
OR
(item_type = 'ProductFilter'
AND reference_data @> '{"resource_type": "Coupon"}'
AND reference_data @> '{"resource_id": :id}')
}
RecordVersion.where(query_sql, id:)
end
|