# frozen_string_literal: true
class Api::V0::StatisticsController < Api::V0::BaseController
before_action :authenticate
# GET /api/v0/statistics/users_joined?start_date=&end_date=&org_id=
#
# Returns the number of users joined for the user's org.
# If start_date is passed, only counts those with created_at is >= than start_date
# If end_date is passed, only counts those with created_at is <= than end_date are
# If org_id is passed and user has super_admin privileges that counter is performed
# against org_id param instead of user's org
def users_joined
unless Api::V0::StatisticsPolicy.new(@user, :statistics).users_joined?
raise Pundit::NotAuthorizedError
end
if @user.can_super_admin? && params[:org_id].present?
scoped = User.unscoped.where(org_id: params[:org_id])
else
scoped = User.unscoped.where(org_id: @user.org_id)
end
if params[:range_dates].present?
r = {}
params[:range_dates].each_pair do |k, v|
r[k] = scoped.where(created_at: dates_to_range(v)).count
end
# Reverse hash r, so dates in ascending order
r = Hash[r.to_a.reverse]
respond_to do |format|
format.json { render(json: r.to_json) }
format.csv {
send_data(CSV.generate do |csv|
csv << [_("Month"), _("No. Users joined")]
total = 0
r.each_pair { |k, v| csv << [k, v]; total += v }
csv << [_("Total"), total]
end, filename: "#{_('users_joined')}.csv") }
end
else
if params["start_date"].present? || params["end_date"].present?
scoped = scoped.where(created_at: dates_to_range(params))
end
@users_count = scoped.count
respond_with @users_count
end
end
# GET
# Returns the number of completed plans within the user's org for the data
# start_date and end_date specified
def completed_plans
unless Api::V0::StatisticsPolicy.new(@user, :statistics).completed_plans?
raise Pundit::NotAuthorizedError
end
if @user.can_super_admin? && params[:org_id].present?
scoped = Org.find(params[:org_id]).plans.where(complete: true)
else
scoped = @user.org.plans.where(complete: true)
end
if params[:range_dates].present?
r = {}
params[:range_dates].each_pair do |k, v|
r[k] = scoped.where(created_at: dates_to_range(v)).count
end
# Reverse hash r, so dates in ascending order
r = Hash[r.to_a.reverse]
respond_to do |format|
format.json { render(json: r.to_json) }
format.csv {
send_data(CSV.generate do |csv|
csv << [_("Month"), _("No. Completed Plans")]
total = 0
r.each_pair { |k, v| csv << [k, v]; total += v }
csv << [_("Total"), total]
end, filename: "#{_('completed_plans')}.csv") }
end
else
if params["start_date"].present? || params["end_date"].present?
scoped = scoped.where(created_at: dates_to_range(params))
end
render(json: { completed_plans: scoped.count })
end
end
# /api/v0/statistics/created_plans
# Returns the number of created plans within the user's org for the data
# start_date and end_date specified
def created_plans
unless Api::V0::StatisticsPolicy.new(@user, :statistics).plans?
raise Pundit::NotAuthorizedError
end
if @user.can_super_admin? && params[:org_id].present?
scoped = Org.find(params[:org_id]).plans
else
scoped = @user.org.plans
end
if params[:range_dates].present?
r = {}
params[:range_dates].each_pair do |k, v|
r[k] = scoped.where(created_at: dates_to_range(v)).count
end
# Reverse hash r, so dates in ascending order
r = Hash[r.to_a.reverse]
respond_to do |format|
format.json { render(json: r.to_json) }
format.csv {
send_data(CSV.generate do |csv|
csv << [_("Month"), _("No. Plans")]
total = 0
r.each_pair { |k, v| csv << [k, v]; total += v }
csv << [_("Total"), total]
end, filename: "#{_('plans')}.csv") }
end
else
if params["start_date"].present? || params["end_date"].present?
scoped = scoped.where(created_at: dates_to_range(params))
end
render(json: { completed_plans: scoped.count })
end
end
##
# Displays the number of DMPs using templates owned/create by the caller's Org
# between the optional specified dates
def using_template
org_templates = @user.org.templates.where(customization_of: nil)
unless Api::V0::StatisticsPolicy.new(@user, org_templates.first).using_template?
raise Pundit::NotAuthorizedError
end
@templates = {}
org_templates.each do |template|
if @templates[template.title].blank?
@templates[template.title] = {}
@templates[template.title][:title] = template.title
@templates[template.title][:id] = template.family_id
@templates[template.title][:uses] = 0
end
scoped = template.plans
if params["start_date"].present? || params["end_date"].present?
scoped = scoped.where(created_at: dates_to_range(params))
end
@templates[template.title][:uses] += scoped.length
end
respond_with @templates
end
##
# GET
# Renders a list of templates with their titles, ids, and uses between the optional
# specified dates the uses are restricted to DMPs created by users of the same
# organisation as the user who ititiated the call.
def plans_by_template
unless Api::V0::StatisticsPolicy.new(@user, :statistics).plans_by_template?
raise Pundit::NotAuthorizedError
end
@templates = {}
scoped = @user.org.plans
if params["start_date"].present? || params["end_date"].present?
scoped = scoped.where(created_at: dates_to_range(params))
end
scoped.each do |plan|
# if hash exists
if @templates[plan.template.title].blank?
@templates[plan.template.title] = {}
@templates[plan.template.title][:title] = plan.template.title
@templates[plan.template.title][:id] = plan.template.family_id
@templates[plan.template.title][:uses] = 1
else
@templates[plan.template.title][:uses] += 1
end
end
respond_with @templates
end
# GET
#
# Renders a list of DMPs metadata, provided the DMPs were created between the
# optional specified dates DMPs must be owned by a user who's organisation is the
# same as the user who generates the call.
def plans
unless Api::V0::StatisticsPolicy.new(@user, :statistics).plans?
raise Pundit::NotAuthorizedError
end
@org_plans = @user.org.plans
if params["remove_tests"].present? && params["remove_tests"].downcase == "true"
@org_plans = @org_plans.where.not(visibility: Plan.visibilities[:is_test])
end
if params["start_date"].present? || params["end_date"].present?
@org_plans = @org_plans.where(created_at: dates_to_range(params))
end
respond_with @org_plans
end
private
# Convert start/end dates in hash to a range of Dates
def dates_to_range(hash)
today = Date.today
start_date = Date.parse(hash.fetch("start_date", today.prev_month.to_date.to_s))
end_date = Date.parse(hash.fetch("end_date", today.to_date.to_s)) + 1.day
start_date..end_date
end
end