Module: ApplicationHelpers

Includes:
Rack::Utils
Included in:
ShopifyDashboardPlus::Report
Defined in:
lib/shopify_dashboard_plus/helpers.rb

Constant Summary collapse

DESIRED_FIELDS =
[
  "total_price",
  "created_at",
  "billing_address",
  "currency",
  "line_items",
  "customer",
  "referring_site",
  "discount_codes"
]

Instance Method Summary collapse

Instance Method Details

#close_connectionObject



29
30
31
# File 'lib/shopify_dashboard_plus/helpers.rb', line 29

def close_connection
  $connected = false
end

#connected?Boolean

Returns:

  • (Boolean)


37
38
39
# File 'lib/shopify_dashboard_plus/helpers.rb', line 37

def connected?
  $connected
end

#date_range_valid?(from, to) ⇒ Boolean

Returns:

  • (Boolean)


64
65
66
67
68
# File 'lib/shopify_dashboard_plus/helpers.rb', line 64

def date_range_valid?(from, to)
  DateTime.parse(from) <= DateTime.parse(to)
rescue ArgumentError
  false
end

#date_todayObject

Generic Helpers



48
49
50
# File 'lib/shopify_dashboard_plus/helpers.rb', line 48

def date_today
  DateTime.now.strftime('%Y-%m-%d')
end

#days(num) ⇒ Object



52
53
54
# File 'lib/shopify_dashboard_plus/helpers.rb', line 52

def days(num)
  num.to_i == 1 ? "#{num} Day" : "#{num} Days"
end

#display_as_currency(value) ⇒ Object

Metrics Helpers



73
74
75
76
77
# File 'lib/shopify_dashboard_plus/helpers.rb', line 73

def display_as_currency(value)
  ShopifyAPI::Shop.current.money_with_currency_format.gsub("{{amount}}", value.to_s)
rescue
  'N/A'
end

#get_average_revenue(total_revenue, duration) ⇒ Object



90
91
92
93
94
# File 'lib/shopify_dashboard_plus/helpers.rb', line 90

def get_average_revenue(total_revenue, duration)
  (total_revenue/duration).round(2)
rescue
  'N/A'
end

#get_daily_revenues(start_date, end_date, orders) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/shopify_dashboard_plus/helpers.rb', line 96

def get_daily_revenues(start_date, end_date, orders)
  # Create hash entry for every day within interval over which to inspect sales
  revenue_per_day = {}
  days = get_date_range(start_date, end_date)
  (0..days).each{ |day| revenue_per_day[(DateTime.parse(end_date) - day).strftime("%Y-%m-%d")] = 0 }

  # Retreive array of ActiveRecord::Collections, each containing orders between the start and end date
  order_details = orders.map{ |order| [order.created_at, order.total_price.to_f] }
  
  # Filter order details into daily totals and return
  order_details.each do |(date, total)|
    day_index = DateTime.parse(date).strftime('%Y-%m-%d')
    revenue_per_day[day_index] = revenue_per_day[day_index].plus(total)
  end
  revenue_per_day
end

#get_date_range(first, last) ⇒ Object



79
80
81
# File 'lib/shopify_dashboard_plus/helpers.rb', line 79

def get_date_range(first, last)
  DateTime.parse(last).mjd - DateTime.parse(first).mjd
end

#get_detailed_revenue_metrics(start_date, end_date = DateTime.now) ⇒ Object



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/shopify_dashboard_plus/helpers.rb', line 175

def get_detailed_revenue_metrics(start_date, end_date = DateTime.now)

  order_list = get_list_of_orders(start_date, end_date)

  # Revenue
  total_revenue = get_total_revenue(order_list)
  duration = get_date_range(start_date, end_date) + 1
  avg_revenue = get_average_revenue(total_revenue, duration)
  daily_revenue = get_daily_revenues(start_date, end_date, order_list)
  max_daily_revenue = daily_revenue.max_by{ |k,v| v }[1]
  
  # Retrieve Metrics
  sales_report = ShopifyDashboardPlus::SalesReport.new(order_list).to_h
  revenue_report = ShopifyDashboardPlus::RevenueReport.new(order_list).to_h
  traffic_report = ShopifyDashboardPlus::TrafficReport.new(order_list).to_h
  discounts_report = ShopifyDashboardPlus::DiscountReport.new(order_list).to_h
  metrics = { 
    :total_revenue => total_revenue,
    :average_revenue => avg_revenue,
    :daily_revenue => daily_revenue,
    :max_daily_revenue => max_daily_revenue,
    :duration => duration
  }

  [sales_report, revenue_report, traffic_report, discounts_report, metrics].inject(&:merge)
end

#get_host(site) ⇒ Object



60
61
62
# File 'lib/shopify_dashboard_plus/helpers.rb', line 60

def get_host(site)
  URI(site).host.downcase.sub(/\Awww\./, "")
end

#get_list_of_orders(start_date, end_date) ⇒ Object

Return array of ActiveRecord::Collections, each containing up to :limit (250) orders Continue to query next page until less than :limit orders are returned, indicating no next pages with orders matching query



159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/shopify_dashboard_plus/helpers.rb', line 159

def get_list_of_orders(start_date, end_date)

  # Get first 250 results matching query
  params = order_parameters_paginate(start_date, end_date, 1)
  revenue_metrics = [ShopifyAPI::Order.find(:all, :params => params)]
  
  # If the amount of results equal to the limit (250) were returned, pass the query on to the next page (orders 251 to 500)
  while revenue_metrics.last.length == 250
    params = order_parameters_paginate(start_date, end_date, revenue_metrics.length + 1)
    revenue_metrics << ShopifyAPI::Order.find(:all, :params => params)
  end

  revenue_metrics.flat_map{ |orders| orders.map{ |order| order }}
end

#get_total_revenue(orders) ⇒ Object



83
84
85
86
87
88
# File 'lib/shopify_dashboard_plus/helpers.rb', line 83

def get_total_revenue(orders)
  totals = orders.map { |order| order.total_price.to_f }
  totals.inject(:+).round(2)
rescue
  0
end

#hash_to_graph_format(sales, merge_results: false) ⇒ Object



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/shopify_dashboard_plus/helpers.rb', line 113

def hash_to_graph_format(sales, merge_results: false)
  
  # ChartKick requires a strange format to build graphs. For instance, an array of
  #   {:name => <item_name>, :data => [[<customer_id>, <item_price>], [<customer_id>, <item_price>]]}
  # places <customer_id> on the independent (x) axis, and stacks each item (item_name) on the y-axis by price (item_price)

  name_hash = sales.map{ |sale| {:name => sale[:name], :data => []} }.uniq
  
  sales.map do |old_hash|
    name_hash.map do |new_hash|
      if old_hash[:name] == new_hash[:name]
        new_hash[:data].push(old_hash[:data])
      end
    end
  end

  # This hash will return repeated values (i.e., :data => [["item 1", 6], ["item 1", 6]])
  # ChartKick will ignore repeated entries, so the totals need to be merged
  # i.e., :data => [["item1", 12]]
  if merge_results
    name_hash.each_with_index do |item, index|
      consolidated_data = Hash.new(0)
      item[:data].each do |purchase_entry|
        consolidated_data[purchase_entry[0]] = consolidated_data[purchase_entry[0]].plus(purchase_entry[1])
      end
      name_hash[index][:data] = consolidated_data.to_a
    end
  end

  name_hash
end

#open_connectionObject



33
34
35
# File 'lib/shopify_dashboard_plus/helpers.rb', line 33

def open_connection
  $connected = true
end

#order_parameters_paginate(start_date, end_date, page) ⇒ Object

Return order query parameters hash



146
147
148
149
150
151
152
153
154
# File 'lib/shopify_dashboard_plus/helpers.rb', line 146

def order_parameters_paginate(start_date, end_date, page)
  {  
    :created_at_min => start_date + " 0:00", 
    :created_at_max => end_date + " 23:59:59", 
    :limit => 250,
    :page => page,
    :fields => DESIRED_FIELDS 
  }
end

#set_connection(key, pwd, name) ⇒ Object

Connection & Setup Helpers



19
20
21
22
23
24
25
26
27
# File 'lib/shopify_dashboard_plus/helpers.rb', line 19

def set_connection(key, pwd, name)
  shop_url = "https://#{key}:#{pwd}@#{name}.myshopify.com/admin"
  ShopifyAPI::Base.site = shop_url
  shop = ShopifyAPI::Shop.current
  $shop_name = name
  open_connection
rescue
  close_connection
end

#shop_nameObject



41
42
43
# File 'lib/shopify_dashboard_plus/helpers.rb', line 41

def shop_name
  $shop_name
end

#strip_protocol(page) ⇒ Object



56
57
58
# File 'lib/shopify_dashboard_plus/helpers.rb', line 56

def strip_protocol(page)
  page.sub(/\Ahttps?:\/\//, "")
end