Class: Workarea::Pricing::Discount
- Inherits:
-
Object
- Object
- Workarea::Pricing::Discount
- Defined in:
- app/models/workarea/pricing/discount.rb,
app/models/workarea/pricing/discount/order.rb,
app/models/workarea/pricing/discount/product.rb,
app/models/workarea/pricing/discount/category.rb,
app/models/workarea/pricing/discount/shipping.rb,
app/models/workarea/pricing/discount/code_list.rb,
app/models/workarea/pricing/discount/free_gift.rb,
app/models/workarea/pricing/discount/collection.rb,
app/models/workarea/pricing/discount/redemption.rb,
app/models/workarea/pricing/discount/order_total.rb,
app/models/workarea/pricing/discount/reconcile_total.rb,
app/models/workarea/pricing/discount/amount_calculator.rb,
app/models/workarea/pricing/discount/application_group.rb,
app/models/workarea/pricing/discount/buy_some_get_some.rb,
app/models/workarea/pricing/discount/product_attribute.rb,
app/models/workarea/pricing/discount/flat_or_percent_off.rb,
app/models/workarea/pricing/discount/conditions/user_tags.rb,
app/models/workarea/pricing/discount/generated_promo_code.rb,
app/models/workarea/pricing/discount/quantity_fixed_price.rb,
app/models/workarea/pricing/discount/conditions/order_total.rb,
app/models/workarea/pricing/discount/conditions/promo_codes.rb,
app/models/workarea/pricing/discount/conditions/item_quantity.rb,
app/models/workarea/pricing/discount/product_attribute/item_qualifier.rb,
app/models/workarea/pricing/discount/quantity_fixed_price/item_shares.rb,
app/models/workarea/pricing/discount/buy_some_get_some/item_application.rb,
app/models/workarea/pricing/discount/buy_some_get_some/product_application.rb,
app/models/workarea/pricing/discount/buy_some_get_some/order_items_by_product.rb,
app/models/workarea/pricing/discount/quantity_fixed_price/application_calculator.rb
Overview
This is the base class for representing a discount in the system. Available siscounts must be a customized subclass of Discount.
They must implement the #apply method, this is the method called to add the price adjustments necessary to discount the order.
Direct Known Subclasses
BuySomeGetSome, Category, FreeGift, OrderTotal, Product, ProductAttribute, QuantityFixedPrice, Shipping
Defined Under Namespace
Modules: Conditions, FlatOrPercentOff Classes: AmountCalculator, ApplicationGroup, BuySomeGetSome, Category, CodeList, Collection, FreeGift, GeneratedPromoCode, MissingConfigurationError, Order, OrderTotal, Product, ProductAttribute, QuantityFixedPrice, ReconcileTotal, Redemption, Shipping
Instance Attribute Summary collapse
- #allow_sale_items ⇒ Boolean
-
#auto_deactivated ⇒ Boolean
Whether to allow auto deactivation.
-
#auto_deactivated_at ⇒ Boolean
When the discount was last automatically deactivated.
- #compatible_discount_ids ⇒ Array
-
#excluded_category_ids ⇒ Boolean
Ids of categories that do not qualify for discount.
-
#excluded_product_ids ⇒ Boolean
Ids of products that do not qualify for discount.
- #name ⇒ String
-
#price_level ⇒ String
Used when creating adjustment data, one of: order, shipping, item.
-
#redemptions ⇒ Enumerable
A log entry for each time it was redeemed.
- #single_use ⇒ Boolean
Class Method Summary collapse
-
.add_qualifier(method_name) ⇒ Symbol
This macro adds a method to the list of qualification methods for this discount.
-
.auto_deactivate ⇒ Object
Deactivate the current scope of discounts, and mark as automatically deactivated.
-
.qualifier_methods ⇒ Array<Symbol>
Methods that should be chcked when determining whether this discount qualifies.
Instance Method Summary collapse
-
#<=>(other) ⇒ Integer
Compare two discounts, used for ensuring discount application order is predictable.
-
#apply(order) ⇒ Workarea::Order
Create the price adjustments that reduce the order price.
-
#auto_deactivate! ⇒ Object
Automatically deactivates a discount.
-
#auto_deactivated? ⇒ Boolean
Whether this discount was autodeactivated.
-
#auto_deactivates_at ⇒ Time
Returns the date of auto deactivation if no redemptions occur.
-
#can_be_used_by?(email) ⇒ Boolean
Whether this email has already redeemed this discount, and is not eligible due to single use.
-
#compatible_discounts ⇒ Set<Workarea::Pricing::Discount>
The set of compatible discounts for creating an undirected graph of discount compatibility for finding ApplicationGroups most efficiently.
-
#compatible_with?(discount) ⇒ Boolean
Whether this discount is compatible with the one passed.
-
#excludes_category_id?(category_id) ⇒ Boolean
Whether or not the provided category_id is excluded from the discount.
-
#excludes_product_id?(product_id) ⇒ Boolean
Whether or not the provided product_id is excluded from the discount.
-
#has_been_redeemed?(email) ⇒ Boolean
Whether this discount has been redeemed by a certain email address.
-
#last_redemption ⇒ Workarea::Pricing::Discount::Redemption?
Find the last redemption for the discount.
-
#log_redemption(email) ⇒ Workarea::Pricing::Discount::Redemption
Record the redemption of this discount by an email address for an amount.
-
#qualifies?(order) ⇒ Boolean
Whether this discount qualifies for this order.
-
#remove_from(order) ⇒ Workarea::Order
Removes the adjustments created by this discount.
Methods included from Commentable
#add_subscription, #remove_subscription
Methods included from Releasable
#changesets_with_children, #destroy, #in_release, #release_changes, #release_originals, #save_changeset, #skip_changeset, #without_release
Methods included from Segmentable
#active?, #active_segment_ids_with_children, #segmented?, #segments
Methods included from Release::Activation
#activate_with?, #create_activation_changeset, #save_activate_with, #was_active?
Methods included from Mongoid::Document::Taggable
Methods included from ApplicationDocument
Methods included from Sidekiq::Callbacks
add_worker, assert_valid_config!, async, caching_classes?, disable, enable, inline, #run_callbacks, workers, workers_list
Methods included from Mongoid::Document
Instance Attribute Details
#allow_sale_items ⇒ Boolean
76 |
# File 'app/models/workarea/pricing/discount.rb', line 76 field :allow_sale_items, type: Boolean, default: true |
#auto_deactivated ⇒ Boolean
Returns whether to allow auto deactivation.
81 |
# File 'app/models/workarea/pricing/discount.rb', line 81 field :auto_deactivate, type: Boolean, default: true |
#auto_deactivated_at ⇒ Boolean
Returns when the discount was last automatically deactivated.
86 |
# File 'app/models/workarea/pricing/discount.rb', line 86 field :auto_deactivated_at, type: Time |
#compatible_discount_ids ⇒ Array
56 |
# File 'app/models/workarea/pricing/discount.rb', line 56 field :compatible_discount_ids, type: Array, default: [] |
#excluded_category_ids ⇒ Boolean
Returns ids of categories that do not qualify for discount.
61 |
# File 'app/models/workarea/pricing/discount.rb', line 61 field :excluded_category_ids, type: Array, default: [] |
#excluded_product_ids ⇒ Boolean
Returns ids of products that do not qualify for discount.
66 |
# File 'app/models/workarea/pricing/discount.rb', line 66 field :excluded_product_ids, type: Array, default: [] |
#name ⇒ String
51 |
# File 'app/models/workarea/pricing/discount.rb', line 51 field :name, type: String, localize: true |
#price_level ⇒ String
Returns used when creating adjustment data, one of: order, shipping, item.
46 |
# File 'app/models/workarea/pricing/discount.rb', line 46 class_attribute :price_level |
#redemptions ⇒ Enumerable
Returns a log entry for each time it was redeemed.
91 92 |
# File 'app/models/workarea/pricing/discount.rb', line 91 has_many :redemptions, class_name: 'Workarea::Pricing::Discount::Redemption' |
#single_use ⇒ Boolean
71 |
# File 'app/models/workarea/pricing/discount.rb', line 71 field :single_use, type: Boolean, default: false |
Class Method Details
.add_qualifier(method_name) ⇒ Symbol
This macro adds a method to the list of qualification methods for this discount. This method should be a predicate method.
116 117 118 119 |
# File 'app/models/workarea/pricing/discount.rb', line 116 def self.add_qualifier(method_name) @qualifier_methods ||= [] @qualifier_methods << method_name end |
.auto_deactivate ⇒ Object
Deactivate the current scope of discounts, and mark as automatically deactivated.
134 135 136 137 |
# File 'app/models/workarea/pricing/discount.rb', line 134 def self.auto_deactivate where(auto_deactivate: true, active: true) .each_by(50) { |d| d.auto_deactivate! } end |
.qualifier_methods ⇒ Array<Symbol>
Methods that should be chcked when determining whether this discount qualifies. The result is the return values of each method ANDed together. Used in Discount#qualifies?.
127 128 129 |
# File 'app/models/workarea/pricing/discount.rb', line 127 def self.qualifier_methods @qualifier_methods || [] end |
Instance Method Details
#<=>(other) ⇒ Integer
Compare two discounts, used for ensuring discount application order is predictable. Sorts by class using config value discount_application_order then by the discounts id for discounts of the same class.
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'app/models/workarea/pricing/discount.rb', line 146 def <=>(other) self_order = Workarea.config.discount_application_order.index(self.class.name) other_order = Workarea.config.discount_application_order.index(other.class.name) if self_order.blank? || other_order.blank? missing = self_order.blank? ? self.class : other.class raise( MissingConfigurationError, <<-eos.strip_heredoc Problem: Missing discount application order config for #{missing} Summary: To determine discount application order, custom discounts must be configured so the system knows how to compare discounts in sorting. Resolution: Check Workarea.config.discount_application_order and ensure that all discount class names are added to that list in the desired position so they can be properly ordered for application. eos ) end class_order = self_order <=> other_order case class_order when -1 then -1 when 0 then self.id <=> other.id when 1 then 1 end end |
#apply(order) ⇒ Workarea::Order
Create the price adjustments that reduce the order price. This method must be implemented when subclassing (creating a new type of) discount. It’s effects will vary discount to discount.
279 280 281 282 283 284 |
# File 'app/models/workarea/pricing/discount.rb', line 279 def apply(order) raise( NotImplementedError, "#{self.class} must implement the #apply method" ) end |
#auto_deactivate! ⇒ Object
Automatically deactivates a discount
181 182 183 |
# File 'app/models/workarea/pricing/discount.rb', line 181 def auto_deactivate! update_attributes!(active: false, auto_deactivated_at: Time.current) end |
#auto_deactivated? ⇒ Boolean
Whether this discount was autodeactivated. Used to show the UI in the admin around what you can do if a discount has been autodeactivated.
229 230 231 |
# File 'app/models/workarea/pricing/discount.rb', line 229 def auto_deactivated? !active? && auto_deactivate && auto_deactivated_at.present? end |
#auto_deactivates_at ⇒ Time
Returns the date of auto deactivation if no redemptions occur
245 246 247 248 |
# File 'app/models/workarea/pricing/discount.rb', line 245 def auto_deactivates_at start = last_redemption.try(:created_at) || updated_at start + Workarea.config.discount_staleness_ttl end |
#can_be_used_by?(email) ⇒ Boolean
Whether this email has already redeemed this discount, and is not eligible due to single use.
219 220 221 222 |
# File 'app/models/workarea/pricing/discount.rb', line 219 def can_be_used_by?(email) return true if !single_use? || email.blank? !redemptions.where(email: email.downcase).exists? end |
#compatible_discounts ⇒ Set<Workarea::Pricing::Discount>
The set of compatible discounts for creating an undirected graph of discount compatibility for finding ApplicationGroups most efficiently.
323 324 325 |
# File 'app/models/workarea/pricing/discount.rb', line 323 def compatible_discounts @compatible_discounts ||= Set.new end |
#compatible_with?(discount) ⇒ Boolean
Whether this discount is compatible with the one passed
255 256 257 258 |
# File 'app/models/workarea/pricing/discount.rb', line 255 def compatible_with?(discount) compatible_discount_ids.map(&:to_s).include?(discount.id.to_s) || discount.compatible_discount_ids.map(&:to_s).include?(id.to_s) end |
#excludes_category_id?(category_id) ⇒ Boolean
Whether or not the provided category_id is excluded from the discount
311 312 313 |
# File 'app/models/workarea/pricing/discount.rb', line 311 def excludes_category_id?(category_id) excluded_category_ids.include?(category_id.to_s) end |
#excludes_product_id?(product_id) ⇒ Boolean
Whether or not the provided product_id is excluded from the discount
302 303 304 |
# File 'app/models/workarea/pricing/discount.rb', line 302 def excludes_product_id?(product_id) excluded_product_ids.include?(product_id.to_s) end |
#has_been_redeemed?(email) ⇒ Boolean
Whether this discount has been redeemed by a certain email address. Used for single use qualification.
209 210 211 |
# File 'app/models/workarea/pricing/discount.rb', line 209 def has_been_redeemed?(email) redemptions.where(email: email.downcase).exists? end |
#last_redemption ⇒ Workarea::Pricing::Discount::Redemption?
Find the last redemption for the discount.
237 238 239 |
# File 'app/models/workarea/pricing/discount.rb', line 237 def last_redemption redemptions.desc(:created_at).first end |
#log_redemption(email) ⇒ Workarea::Pricing::Discount::Redemption
Record the redemption of this discount by an email address for an amount. Used for reporting and use tracking.
267 268 269 |
# File 'app/models/workarea/pricing/discount.rb', line 267 def log_redemption(email) redemptions.create!(email: email) end |
#qualifies?(order) ⇒ Boolean
Whether this discount qualifies for this order. It does so by checking each qualifier_methods set on the class. If all qualifier_methods return true, the discount qualifies.
Returns false if there are no qualified methods setup.
193 194 195 196 197 198 199 200 201 |
# File 'app/models/workarea/pricing/discount.rb', line 193 def qualifies?(order) return false unless self.class.qualifier_methods.present? return false unless order.items.present? return false unless can_be_used_by?(order.email) self.class.qualifier_methods.reduce(true) do |result, method| result && send(method, order) end end |
#remove_from(order) ⇒ Workarea::Order
Removes the adjustments created by this discount. Used after this discount has been disqualified at the end of discount application.
293 294 295 |
# File 'app/models/workarea/pricing/discount.rb', line 293 def remove_from(order) remove_from_items(order.items + order.shippings) end |