Skip to content

Commit

Permalink
Use monthly sums for CRM stats, count stale deals
Browse files Browse the repository at this point in the history
  • Loading branch information
severinraez committed Jul 7, 2021
1 parent c8608c7 commit 8542607
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 30 deletions.
73 changes: 47 additions & 26 deletions app/domain/crm/highrise_stats.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,33 @@

module Crm
class HighriseStats < Base
NO_CATEGORY = '(no category)'
NO_CATEGORY = '(no category)'.freeze

def stats
# BIExportJob runs at 1 o'clock in the morning, collect data from last day.
deals = fetch_deals(1.day.ago.utc)
# Job runs at 1 in the morning, collect data from yesterday
month_from = 1.day.ago.beginning_of_month.utc
month_deals = fetch_deals(modified_since: month_from)
pending_deals = fetch_deals(status: 'pending')

count_stats(deals) + volume_stats(deals)
month_stats(month_deals, month_from) + stale_stats(pending_deals)
end

private

def fetch_deals(on)
updated = ::Highrise::Deal.find(:all, params: { since: timestamp(on) })
counted = relevant_change(updated, on)
def fetch_deals(modified_since: nil, status: nil)
# This ignores paging. If we ever get more than 500 deals we'll have to do multiple requests.

counted.group_by(&:status).transform_values do |deals|
params = {}
params[:since] = timestamp(modified_since) unless modified_since.nil?
params[:status] = status unless status.nil?

::Highrise::Deal.find(:all, params: params).yield_self do |deals|
modified_since.nil? ? deals : status_changed(deals, modified_since)
end
end

def group(deals)
deals.group_by(&:status).transform_values do |deals|
deals.group_by { |deal| deal.try(:category).try(:name) || NO_CATEGORY }
end
end
Expand All @@ -31,44 +42,53 @@ def timestamp(time)
time.strftime('%Y%m%d000000')
end

def count_stats(grouped_deals)
def month_stats(deals, month)
build_stats(
group(deals).except('pending'),
month: month.strftime('%Y-%m')
)
end

def stale_stats(deals)
deals.partition { |deal| deal.updated_at <= 3.months.ago.utc }.zip(
[true, false]
)
.flat_map { |deals, stale| build_stats(group(deals), stale: stale) }
end

def build_stats(deals, tags = {})
count_stats(deals, tags) + volume_stats(deals, tags)
end

def count_stats(grouped_deals, tags)
map_deals(grouped_deals) do |status, category, deals|
{
name: 'highrise_deals_yesterday',
name: 'highrise_deals',
fields: { count: deals.count },
tags: { category: category, status: status }
tags: { category: category, status: status }.merge(tags)
}
end
end

def volume_stats(grouped_deals)
def volume_stats(grouped_deals, tags)
map_deals(grouped_deals) do |status, category, deals|
value = deals.map { |deal| volume(deal) }.sum

{
name: 'highrise_volume_yesterday',
name: 'highrise_volume',
fields: { value: value },
tags: { category: category, status: status }
tags: { category: category, status: status }.merge(tags)
}
end
end

def relevant_change(deals, day)
def status_changed(deals, since)
deals.select do |deal|
next true if on?(day, deal.created_at)
next false if deal.status == 'pending'
next false if deal.status_changed_on.nil?
on?(day, deal.status_changed_on)
next deal.created_at >= since if deal.status_changed_on.nil?
deal.status_changed_on >= since
end
end

def on?(day, time)
from = day.beginning_of_day
to = day.end_of_day

time >= from && time <= to
end

def map_deals(grouped_deals)
grouped_deals.flat_map do |status, deals_by_category|
deals_by_category.map do |category, deals|
Expand All @@ -78,6 +98,7 @@ def map_deals(grouped_deals)
end

def volume(deal)
return 0 if deal.price.nil?
deal.price_type == 'fixed' ? deal.price : deal.price * deal.duration
end
end
Expand Down
12 changes: 8 additions & 4 deletions doc/user/influx_metrics.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,16 @@ Tags

Metriken

* `highrise_deals_yesterday` - Deals
* `count` - Anzahl der Deals, welche erstellt wurden oder in einen neuen Status gewechselt haben
* `highrise_volume_yesterday` - Deal-Volumen
* `value [CHF/EUR]` - Gesamtvolumen der Deals (Fixpreise + Stundensätze * Angebotene Stunden), welche erstellt wurden oder in einen neuen Status gewechselt haben
* `highrise_deals` - Deals
* `count` - Anzahl der Deals
* `highrise_volume` - Deal-Volumen
* `value [CHF/EUR]` - Gesamtvolumen der Deals (Fixpreise + Stundensätze * Angebotene Stunden)

Tags

* `status` - Bearbeitungsstatus
* `category` - Deal-Kategorie
* Wenn `status` den Wert `"lost"` oder `"won"` hat:
* `month` - Monat, z.B. "2021-01"
* Wenn `status` den Wert `"pending"` hat:
* `stale [boolean]` - ob die letzte Änderung des Deals mehr als 3 Monate her ist

0 comments on commit 8542607

Please sign in to comment.