Class: Workarea::Order

Inherits:
Object
  • Object
show all
Includes:
ApplicationDocument, Commentable, DiscountIds, Lockable, NormalizeEmail, Queries, UrlToken
Defined in:
app/models/workarea/order.rb,
app/models/workarea/order/status.rb,
app/models/workarea/order/queries.rb,
app/models/workarea/order/items_extension.rb

Defined Under Namespace

Modules: ItemsExtension, Queries, Status Classes: Item

Instance Method Summary collapse

Methods included from Lockable

#default_lock_value, #lock!, #lock_key, #locked?, #unlock!

Methods included from Commentable

#add_subscription, #remove_subscription

Methods included from DiscountIds

#discount_ids

Methods included from ApplicationDocument

#releasable?

Methods included from Sidekiq::Callbacks

assert_valid_config!, async, disable, enable, inline, #run_callbacks

Instance Method Details

#abandoned?Boolean

Whether this order is considered abandoned. This means not canceled or placed and not checking out within the active period.

Returns:

  • (Boolean)


289
290
291
292
# File 'app/models/workarea/order.rb', line 289

def abandoned?
  !canceled? && !placed? && !checking_out? &&
    created_at + Workarea.config.order_active_period < Time.current
end

#add_item(attributes) ⇒ Boolean

Adds an item to the order. Increases quantity if the SKU is already in the order.

Parameters:

  • attributes (Hash)

Returns:

  • (Boolean)

    success



218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'app/models/workarea/order.rb', line 218

def add_item(attributes)
  quantity = attributes.fetch(:quantity, 1).to_i
  sku = attributes[:sku]
  customizations = attributes[:customizations]

  if existing_item = items.find_existing(sku, customizations)
    update_item(existing_item.id, quantity: existing_item.quantity + quantity)
  else
    items.build(attributes)
  end

  save
end

#add_promo_code(code) ⇒ self

Adds a promo code to the order. Ensures only unique promo codes remain in the order promo code list.

Parameters:

Returns:

  • (self)


266
267
268
269
270
271
272
# File 'app/models/workarea/order.rb', line 266

def add_promo_code(code)
  promo_codes << code
  promo_codes.map!(&:upcase)
  promo_codes.uniq!
  save
  self
end

#cancelObject

Cancel this order.



319
320
321
# File 'app/models/workarea/order.rb', line 319

def cancel
  update_attribute(:canceled_at, Time.current)
end

#canceled?Boolean

Whether this order has been canceled.

Returns:

  • (Boolean)


308
309
310
# File 'app/models/workarea/order.rb', line 308

def canceled?
  !!canceled_at
end

#checking_out?Boolean

Whether this order is currently checking out, defined as whether they’ve touched checkout within Workarea.config.checkout_expiration

Returns:

  • (Boolean)


147
148
149
150
151
152
153
154
# File 'app/models/workarea/order.rb', line 147

def checking_out?
  return false unless checkout_started_at.present?

  checkout_expires_at = checkout_started_at +
                          Workarea.config.checkout_expiration

  checkout_expires_at > Time.current
end

#copied?Boolean

Whether this order was copied from another

Returns:

  • (Boolean)


313
314
315
# File 'app/models/workarea/order.rb', line 313

def copied?
  copied_from.present?
end

#has_sku?(sku) ⇒ Boolean

Whether an item of this SKU is in this order

Parameters:

Returns:

  • (Boolean)


279
280
281
# File 'app/models/workarea/order.rb', line 279

def has_sku?(sku)
  items.any? { |i| i.sku == sku }
end

#mark_as_reminded!Boolean

Mark this order as having been reminded. Used in the reminding worker to ensure an Order doesn’t get reminded twice.

Returns:

  • (Boolean)


129
130
131
132
# File 'app/models/workarea/order.rb', line 129

def mark_as_reminded!
  self.reminded_at = Time.current
  save!(validate: false)
end

#metrics_saved!Object

Mark the metrics for the order saved.



331
332
333
# File 'app/models/workarea/order.rb', line 331

def metrics_saved!
  set(metrics_saved_at: Time.current)
end

#metrics_saved?Boolean

Check whether metrics were saved for this order. Used to ensure this doesn’t happen more than once due to Sidekiq’s semantics (run at least once).

Returns:

  • (Boolean)


326
327
328
# File 'app/models/workarea/order.rb', line 326

def metrics_saved?
  !!metrics_saved_at
end

#nameString

The user-friendly name for the order

Returns:



76
77
78
# File 'app/models/workarea/order.rb', line 76

def name
  I18n.t('workarea.order.name', id: id)
end

#no_items?Boolean

Whether this order is empty.

Returns:

  • (Boolean)


100
101
102
# File 'app/models/workarea/order.rb', line 100

def no_items?
  quantity == 0
end

#placeBoolean

Place the order.

Returns:

  • (Boolean)

    whether the order was placed



204
205
206
207
208
209
210
211
# File 'app/models/workarea/order.rb', line 204

def place
  return false unless purchasable?

  run_callbacks :place do
    self.placed_at = Time.current
    with(write: { w: "majority", j: true }) { save }
  end
end

#placed?Boolean

Whether this order was placed.

Returns:

  • (Boolean)


195
196
197
# File 'app/models/workarea/order.rb', line 195

def placed?
  !!placed_at
end

#price_adjustmentsPriceAdjustmentSet

All price adjustments on this order.

Returns:



92
93
94
# File 'app/models/workarea/order.rb', line 92

def price_adjustments
  PriceAdjustmentSet.new(items.map(&:price_adjustments).flatten)
end

#purchasable?Boolean

Whether this order can be purchased, which is defined here as the order having items and an email address.

Returns:

  • (Boolean)


187
188
189
# File 'app/models/workarea/order.rb', line 187

def purchasable?
  items.present? && valid?(:purchasable)
end

#quantityInteger

The number of units in this order.

Returns:

  • (Integer)


84
85
86
# File 'app/models/workarea/order.rb', line 84

def quantity
  items.select(&:valid?).sum(&:quantity)
end

#remove_item(id) ⇒ self

Removes an item from the order

Parameters:

Returns:

  • (self)


255
256
257
258
# File 'app/models/workarea/order.rb', line 255

def remove_item(id)
  items.find(id).destroy
  self
end

#requires_shipping?Boolean

Whether this order needs to be shipped

Returns:

  • (Boolean)


178
179
180
# File 'app/models/workarea/order.rb', line 178

def requires_shipping?
  items.present? && items.any? { |i| !i.digital? }
end

#reset_checkout!Boolean

Clears out order checkout details, effectively placing the order back into a cart state.

Explicitly does not reset email or shipping service since these can be carried in and out of checkout.

Email can be set by being logged in or not, shipping method can be set by estimation on the cart page.

Returns:

  • (Boolean)


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

def reset_checkout!
  self.user_id = nil
  self.checkout_started_at = nil
  self.token = nil
  save!
end

#started_checkout?Boolean

Whether this order has ever started checkout

Returns:

  • (Boolean)


138
139
140
# File 'app/models/workarea/order.rb', line 138

def started_checkout?
  checkout_started_at.present?
end

#statusSymbol

Get the status of this order. Does NOT include fulfillment statuses like shipped, partially shipped, etc.

Returns:

  • (Symbol)


299
300
301
302
# File 'app/models/workarea/order.rb', line 299

def status
  calculators = Workarea.config.order_status_calculators.map(&:constantize)
  StatusCalculator.new(calculators, self).result
end

#touch_checkout!(attributes = {}) ⇒ Boolean

Update the checkout timestamp to indicate the last time this checkout was active and optionally set checkout user data

Returns:

  • (Boolean)


109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'app/models/workarea/order.rb', line 109

def touch_checkout!(attributes = {})
  update_attribute(:checkout_started_at, Time.current)
  assign_attributes(
    attributes.slice(
      :ip_address,
      :user_activity_id,
      :checkout_by_id,
      :source,
      :traffic_referrer,
      :user_agent
    )
  )
end

#update_item(id, attributes) ⇒ Boolean

Updates an items attributes

Parameters:

  • id (String)
  • attributes (Hash)

    new item attributes

Returns:

  • (Boolean)

    whether the item was successfully updated



239
240
241
242
243
244
245
246
247
248
# File 'app/models/workarea/order.rb', line 239

def update_item(id, attributes)
  existing_item = items.find_existing(attributes[:sku], attributes[:customizations])
  if existing_item.present? && existing_item.id.to_s != id.to_s
    item = items.find(id)
    existing_item.update_attributes(quantity: existing_item.quantity + (attributes[:quantity] || item.quantity))
    item.delete
  else
    items.find(id).update_attributes(attributes)
  end
end