Class: Workarea::Metrics::User

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

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.bestObject



57
58
59
60
61
62
63
# File 'app/models/workarea/metrics/user.rb', line 57

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_order(email:, revenue:, discounts: 0, at: Time.current) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'app/models/workarea/metrics/user.rb', line 38

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

  collection.update_one(
    { _id: email },
    {
      '$set' => { last_order_at: at.utc },
      '$setOnInsert' => { first_order_at: at.utc },
      '$inc' => {
        orders: 1,
        revenue: revenue_in_default_currency,
        discounts: discounts_in_default_currency
      }
    },
    upsert: true
  )
end

.update_aggregations!Object



65
66
67
68
# File 'app/models/workarea/metrics/user.rb', line 65

def update_aggregations!
  update_calculated_fields!
  update_percentiles!
end

.update_calculated_fields!Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'app/models/workarea/metrics/user.rb', line 70

def update_calculated_fields!
  collection.aggregate([
    {
      '$addFields' => {
        'frequency' => {
          '$divide' => [
            '$orders',
            { '$subtract' => [Time.current.utc, '$first_order_at'] }
          ]
        },
        'average_order_value' => {
          '$divide' => ['$revenue', '$orders']
        }
      }
    },
    { '$out' => collection.name }
  ]).first
end

.update_percentiles!Object



89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'app/models/workarea/metrics/user.rb', line 89

def update_percentiles!
  collection.aggregate([
    {
      '$addFields' => {
        'orders_percentile' => update_percentiles_expression(:orders),
        'frequency_percentile' => update_percentiles_expression(:frequency),
        'revenue_percentile' => update_percentiles_expression(:revenue),
        'average_order_value_percentile' => update_percentiles_expression(:average_order_value)
      }
    },
    { '$out' => collection.name }
  ]).first
end

.update_percentiles_expression(field) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'app/models/workarea/metrics/user.rb', line 103

def update_percentiles_expression(field)
  percentiles = CalculatePercentiles.new(collection, field)

  {
    '$switch' => {
      'branches' => 99.downto(1).map do |percentile|
        {
          'case' => {  '$gte' => ["$#{field}", percentiles[percentile.to_s]] },
          'then' => percentile + 1
        }
      end,
      'default' => 1
    }
  }
end

Instance Method Details

#average_order_valueObject

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



122
123
124
125
# File 'app/models/workarea/metrics/user.rb', line 122

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