Class: Workarea::Metrics::User

Inherits:
Object
  • Object
show all
Includes:
Mongoid::Document, Mongoid::Document::Taggable, Mongoid::Timestamps
Defined in:
app/models/workarea/metrics/user.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Mongoid::Document::Taggable

included

Methods included from Mongoid::Document

#embedded_children

Class Method Details

.bestObject



96
97
98
99
100
101
102
# File 'app/models/workarea/metrics/user.rb', line 96

def best
  scoped
    .with_purchases
    .by_frequency_percentile(81..100)
    .by_revenue_percentile(81..100)
    .order_by(revenue: :desc, orders: :desc, last_order_at: :desc, id: :asc)
end

.save_affinity(id:, action:, **data) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'app/models/workarea/metrics/user.rb', line 78

def save_affinity(id:, action:, **data)
  return if data.blank? || data.values.all?(&:blank?)

  collection.update_one(
    { _id: id },
    {
      '$set' => { updated_at: Time.current.utc },
      '$push' => data.each_with_object({}) do |(field, values), update|
        update["#{action}.#{field}"] = {
          '$each' => Array.wrap(values),
          '$slice' => Workarea.config.max_affinity_items
        }
      end
    },
    upsert: true
  )
end

.save_cancellation(email:, refund:, at: Time.current) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'app/models/workarea/metrics/user.rb', line 63

def save_cancellation(email:, refund:, at: Time.current)
  refund_in_default_currency = refund.to_m.exchange_to(Money.default_currency).to_f

  collection.update_one(
    { _id: email },
    {
      '$inc' => {
        cancellations: 1,
        refund: refund_in_default_currency,
        revenue: refund_in_default_currency
      }
    }
  )
end

.save_order(email:, revenue:, discounts: 0, at: Time.current) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'app/models/workarea/metrics/user.rb', line 47

def save_order(email:, revenue:, discounts: 0, at: Time.current)
  revenue_in_default_currency = revenue.to_m.exchange_to(Money.default_currency).to_f
  discounts_in_default_currency = discounts.to_m.exchange_to(Money.default_currency).to_f

  metrics = find_or_create_by(id: email)
  first_order_at = [at, metrics.first_order_at].compact.min
  last_order_at = [at, metrics.last_order_at].compact.max

  metrics.update!(first_order_at: first_order_at, last_order_at: last_order_at)
  metrics.inc(
    orders: 1,
    revenue: revenue_in_default_currency,
    discounts: discounts_in_default_currency
  )
end

Instance Method Details

#average_order_valueObject

Use calculated value for real-time display, the aggregated value used in insights we be recalculated weekly.



107
108
109
110
# File 'app/models/workarea/metrics/user.rb', line 107

def average_order_value
  return nil if orders.zero?
  revenue / orders.to_f
end

#merge!(other) ⇒ Object



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
# File 'app/models/workarea/metrics/user.rb', line 112

def merge!(other)
  %w(orders revenue discounts cancellations refund).each do |field|
    self.send("#{field}=", send(field) + other.send(field))
  end

  self.first_order_at = [first_order_at, other.first_order_at].compact.min
  self.last_order_at = [last_order_at, other.last_order_at].compact.max
  self.average_order_value = average_order_value
  save!

  self.class.save_affinity(
    id: id,
    action: 'viewed',
    product_ids: other.viewed.product_ids,
    category_ids: other.viewed.category_ids,
    search_ids: other.viewed.search_ids
  )
  self.class.save_affinity(
    id: id,
    action: 'purchased',
    product_ids: other.purchased.product_ids,
    category_ids: other.purchased.category_ids,
    search_ids: other.purchased.search_ids
  )
end