172 lines
4.9 KiB
Ruby
172 lines
4.9 KiB
Ruby
class StatisticsController < ApplicationController
|
|
before_action :authenticate_user!
|
|
|
|
def global_activity
|
|
members = current_organization.members
|
|
@active_members = members.active
|
|
|
|
@total_hours = num_movements = 0
|
|
members.each do |m|
|
|
num_movements += m.account.movements.count
|
|
@total_hours += m.account.movements.map do
|
|
|a| (a.amount > 0) ? a.amount : 0
|
|
end.inject(0, :+)
|
|
end
|
|
@total_hours += current_organization.account.movements.
|
|
map { |a| (a.amount > 0) ? a.amount : 0 }.inject(0, :+)
|
|
|
|
@num_swaps = (num_movements + current_organization.account.movements.count) / 2
|
|
|
|
from = params[:from].presence.try(:to_date) || DateTime.now.to_date - 5.month
|
|
to = params[:to].presence.try(:to_date) || DateTime.now.to_date
|
|
num_months = (to.year * 12 + to.month) - (from.year * 12 + from.month) + 1
|
|
date = from
|
|
|
|
@months_names = []
|
|
@user_reg_months = []
|
|
@num_swaps_months = []
|
|
@hours_swaps_months = []
|
|
|
|
num_months.times do
|
|
@months_names << l(date, format: "%B %Y")
|
|
@user_reg_months << members.by_month(date).count
|
|
|
|
swaps_members = members.map { |a| a.account.movements.by_month(date) }
|
|
swaps_organization = current_organization.account.movements.by_month(date)
|
|
sum_swaps = (swaps_members.flatten.count + swaps_organization.count) / 2
|
|
@num_swaps_months << sum_swaps
|
|
|
|
sum_hours = 0
|
|
swaps_members.flatten.each do |s|
|
|
sum_hours += (s.amount > 0) ? s.amount : 0
|
|
end
|
|
sum_hours += swaps_organization.map do
|
|
|a| (a.amount > 0) ? a.amount : 0
|
|
end.inject(0, :+)
|
|
sum_hours = sum_hours / 3600.0 if sum_hours > 0
|
|
@hours_swaps_months << sum_hours
|
|
|
|
date = date.next_month
|
|
end
|
|
end
|
|
|
|
def inactive_users
|
|
@members = current_organization.members.active
|
|
end
|
|
|
|
def demographics
|
|
members = current_organization.members
|
|
@age_counts = age_counts(members)
|
|
@gender_counts = gender_counts(members)
|
|
end
|
|
|
|
def last_login
|
|
@members = current_organization.members.active.joins(:user).
|
|
order("users.current_sign_in_at ASC NULLS FIRST")
|
|
end
|
|
|
|
def without_offers
|
|
@members = current_organization.members.active
|
|
end
|
|
|
|
def type_swaps
|
|
offers = current_organization.posts.
|
|
where(type: "Offer").joins(:transfers, transfers: :movements).
|
|
select("posts.tags, posts.category_id, SUM(movements.amount) as
|
|
sum_of_transfers, COUNT(transfers.id) as
|
|
count_of_transfers").
|
|
where("movements.amount > 0").
|
|
group("posts.tags, posts.category_id, posts.updated_at")
|
|
|
|
@offers = count_offers_by_label(offers).to_a.each { |a| a.flatten!(1) }.
|
|
sort_by(&:last).reverse
|
|
end
|
|
|
|
def all_transfers
|
|
@transfers = current_organization.
|
|
all_transfers_with_accounts.
|
|
page(params[:page]).
|
|
per(20)
|
|
end
|
|
|
|
protected
|
|
|
|
def count_offers_by_label(offers)
|
|
# Cannot use Hash.new([0, 0]) because then counters[key][0] += n
|
|
# will modify directly the "global default" instead of
|
|
# first assigning a new array with the zeroed counters.
|
|
counters = Hash.new { |h, k| h[k] = [0, 0] }
|
|
|
|
offers.each do |offer|
|
|
labels_for_offer(offer).each do |labels|
|
|
counters[labels][0] += offer.sum_of_transfers
|
|
counters[labels][1] += offer.count_of_transfers
|
|
end
|
|
end
|
|
add_ratios(counters)
|
|
|
|
counters
|
|
end
|
|
|
|
def add_ratios(counters)
|
|
total_count = counters.values.map { |_, counts| counts }.sum
|
|
|
|
counters.each do |_, v|
|
|
v << v[1].to_f / total_count
|
|
end
|
|
end
|
|
|
|
def labels_for_offer(offer)
|
|
tag_labels = offer.tags.presence ||
|
|
[t("statistics.type_swaps.without_tags")]
|
|
|
|
category_label = offer.category.try(:name) ||
|
|
t("statistics.type_swaps.without_category")
|
|
|
|
[category_label].product(tag_labels)
|
|
end
|
|
|
|
def age_counts(members)
|
|
members.each_with_object(Hash.new(0)) do |member, counts|
|
|
age = compute_age(member.user_date_of_birth)
|
|
|
|
age_label = age_group_labels.detect do |range, _|
|
|
range.include? age
|
|
end.try(:last) || t("statistics.demographics.unknown")
|
|
|
|
counts[age_label] += 1
|
|
end
|
|
end
|
|
|
|
def compute_age(date_of_birth)
|
|
return unless date_of_birth
|
|
|
|
age_in_days = Date.today - date_of_birth
|
|
(age_in_days / 365.26).to_i
|
|
end
|
|
|
|
def age_group_labels
|
|
{
|
|
0..17 => "-17",
|
|
18..24 => "18-24",
|
|
25..34 => "25-34",
|
|
35..44 => "35-44",
|
|
45..54 => "45-54",
|
|
55..64 => "55-64",
|
|
65..100 => "65+"
|
|
}
|
|
end
|
|
|
|
def gender_counts(members)
|
|
members.each_with_object(Hash.new(0)) do |member, counts|
|
|
gender = member.user_gender
|
|
gender_label = if gender.present?
|
|
t("simple_form.options.user.gender.#{gender}")
|
|
else
|
|
t("statistics.demographics.unknown")
|
|
end
|
|
counts[gender_label] += 1
|
|
end
|
|
end
|
|
end
|