# frozen_string_literal: true
class UsageController < ApplicationController
after_action :verify_authorized
# GET /usage
def index
authorize :usage
args = default_query_args
user_data(args: args, as_json: true)
plan_data(args: args, as_json: true)
total_plans(args: min_max_dates(args: args))
total_users(args: min_max_dates(args: args))
#TODO: pull this in from branding.yml
@separators = [",", "|", "#"]
@funder = current_user.org.funder?
end
# POST /usage_plans_by_template
def plans_by_template
# This action is triggered when a user changes the timeframe for the
# plans by template chart
authorize :usage
args = default_query_args
if usage_params["template_plans_range"].present?
args[:start_date] = usage_params["template_plans_range"]
end
plan_data(args: args, as_json: true)
end
# GET
def global_statistics
# This action is triggered when a user clicks on the 'download csv' button
# for global usage
authorize :usage
data = Org::TotalCountStatService.call
sep = sep_param
data_csvified = Csvable.from_array_of_hashes(data, true, sep)
send_data(data_csvified, filename: "totals.csv")
end
# GET
def org_statistics
authorize :usage
data = Org::MonthlyUsageService.call(current_user)
sep = sep_param
data_csvified = Csvable.from_array_of_hashes(data, true, sep)
send_data(data_csvified, filename: "totals.csv")
end
# POST /usage_filter
# rubocop:disable Metrics/MethodLength
def filter
# This action is triggered when a user specifies a date range
authorize :usage
args = args_from_params
plan_data(args: args)
user_data(args: args)
total_plans(args: min_max_dates(args: args))
total_users(args: min_max_dates(args: args))
@topic = usage_params[:topic]
case @topic
when "plans"
@total = @total_org_plans
@ranged = @plans_per_month.sum(:count)
else
@total = @total_org_users
@ranged = @users_per_month.sum(:count)
end
end
# rubocop:enable Metrics/MethodLength
# GET /usage_yearly_users
def yearly_users
# This action is triggered when a user clicks on the 'download csv' button
# for the annual users chart
authorize :usage
user_data(args: default_query_args)
sep = sep_param
send_data(CSV.generate({:col_sep => sep}) do |csv|
csv << [_("Month"), _("No. Users joined")]
total = 0
@users_per_month.each do |data|
csv << [data.date.strftime("%b-%y"), data.count]
total += data.count
end
csv << [_("Total"), total]
end, filename: "users_joined.csv")
end
# GET /usage_yearly_plans
def yearly_plans
# This action is triggered when a user clicks on the 'download csv' button
# for the annual plans chart
authorize :usage
plan_data(args: default_query_args)
sep = sep_param
send_data(CSV.generate({:col_sep => sep}) do |csv|
csv << [_("Month"), _("No. Completed Plans")]
total = 0
@plans_per_month.each do |data|
csv << [data.date.strftime("%b-%y"), data.count]
total += data.count
end
csv << [_("Total"), total]
end, filename: "completed_plans.csv")
end
# GET /usage_all_plans_by_template
def all_plans_by_template
# This action is triggered when a user clicks on the 'download csv' button
# for the plans by template chart
authorize :usage
args = default_query_args
args[:start_date] = first_plan_date
sep = sep_param
{:col_sep => sep}
plan_data(args: args, sort: :desc)
data_csvified = StatCreatedPlan.to_csv(@plans_per_month, details: { by_template: true, sep: sep })
send_data(data_csvified, filename: "created_plan_by_template.csv")
end
private
def usage_params
params.require(:usage).permit(:template_plans_range, :org_id, :start_date,
:end_date, :topic)
end
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
# rubocop:disable Metrics/MethodLength
def args_from_params
org = current_user.org
if current_user.can_super_admin? && usage_params[:org_id].present?
org = Org.find_by(id: usage_params[:org_id])
end
start_date = usage_params[:start_date] if usage_params[:start_date].present?
end_date = usage_params[:end_date] if usage_params[:end_date].present?
{
org: org,
start_date: start_date.present? ? start_date : first_plan_date.strftime("%Y-%m-%d"),
end_date: end_date.present? ? end_date : Date.today.strftime("%Y-%m-%d")
}
end
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
# rubocop:enable Metrics/MethodLength
def default_query_args
# Stats are generated at the beginning of each month, so our reference
# point would be the end of the prior month. For example if it is December
# 15th 2019 then the most recent stats would be for the month of November 2019.
# That means we want our date range to be 11/30/2018 to 11/30/2019
{
org: current_user.org,
start_date: Date.today.months_ago(12).end_of_month.strftime("%Y-%m-%d"),
end_date: Date.today.last_month.end_of_month.strftime("%Y-%m-%d")
}
end
# set the csv separator or default to comma
def sep_param
params["sep"] || ','
end
def min_max_dates(args:)
args[:start_date] = first_plan_date.strftime("%Y-%m-%d")
args[:end_date] = Date.today.strftime("%Y-%m-%d")
args
end
def user_data(args:, as_json: false, sort: :asc)
@users_per_month = StatJoinedUser.monthly_range(args)
.order(date: sort)
@users_per_month = @users_per_month.map { |rec| rec.to_json } if as_json
end
def plan_data(args:, as_json: false, sort: :asc)
@plans_per_month = StatCreatedPlan.monthly_range(args)
.where.not(details: "{\"by_template\":[]}")
.order(date: sort)
@plans_per_month = @plans_per_month.map { |rec| rec.to_json } if as_json
end
def total_plans(args:)
@total_org_plans = StatCreatedPlan.monthly_range(args).sum(:count)
end
def total_users(args:)
@total_org_users = StatJoinedUser.monthly_range(args).sum(:count)
end
def first_plan_date
StatCreatedPlan.all.order(:date).limit(1).pluck(:date).first \
|| Date.today.last_month.end_of_month
end
end