demarches-normaliennes/app/controllers/stats_controller.rb

162 lines
4.5 KiB
Ruby

class StatsController < ApplicationController
before_action :authenticate_super_admin!, only: [:download]
MEAN_NUMBER_OF_CHAMPS_IN_A_FORM = 24.0
def index
stat = Stat.first
procedures = Procedure.publiees_ou_closes
@procedures_numbers = procedures_numbers(procedures)
@dossiers_numbers = dossiers_numbers(
stat.dossiers_not_brouillon,
stat.dossiers_depose_avant_30_jours,
stat.dossiers_deposes_entre_60_et_30_jours
)
@contact_percentage = Rails.cache.fetch("stats.contact_percentage", expires_in: 1.day) do
contact_percentage
end
@dossiers_states_for_pie = {
"Brouillon" => stat.dossiers_brouillon,
"En construction" => stat.dossiers_en_construction,
"En instruction" => stat.dossiers_en_instruction,
"Terminé" => stat.dossiers_termines
}
@procedures_cumulative = cumulative_hash(procedures, :published_at)
@procedures_in_the_last_4_months = last_four_months_hash(procedures, :published_at)
@dossiers_cumulative = stat.dossiers_cumulative
@dossiers_in_the_last_4_months = stat.dossiers_in_the_last_4_months
end
def download
headers = [
'ID du dossier',
'ID de la démarche',
'Nom de la démarche',
'ID utilisateur',
'Etat du fichier',
'Durée en brouillon',
'Durée en construction',
'Durée en instruction'
]
data = Dossier
.includes(:procedure, :user)
.in_batches
.flat_map do |dossiers|
dossiers
.pluck(
"dossiers.id",
"procedures.id",
"procedures.libelle",
"users.id",
"dossiers.state",
"dossiers.depose_at - dossiers.created_at",
"dossiers.en_instruction_at - dossiers.depose_at",
"dossiers.processed_at - dossiers.en_instruction_at"
)
end
respond_to do |format|
format.csv { send_data(SpreadsheetArchitect.to_xlsx(headers: headers, data: data), filename: "statistiques.csv") }
end
end
private
def procedures_numbers(procedures)
total = procedures.count
last_30_days_count = procedures.where(published_at: 1.month.ago..Time.zone.now).count
previous_count = procedures.where(published_at: 2.months.ago..1.month.ago).count
if previous_count != 0
evolution = (((last_30_days_count.to_f / previous_count) - 1) * 100).round(0)
else
evolution = 0
end
formatted_evolution = format("%+d", evolution)
{
total: total.to_s,
last_30_days_count: last_30_days_count.to_s,
evolution: formatted_evolution
}
end
def dossiers_numbers(total, last_30_days_count, previous_count)
if previous_count != 0
evolution = (((last_30_days_count.to_f / previous_count) - 1) * 100).round(0)
else
evolution = 0
end
formatted_evolution = format("%+d", evolution)
{
total: total.to_s,
last_30_days_count: last_30_days_count.to_s,
evolution: formatted_evolution
}
end
def contact_percentage
number_of_months = 13
from = Time.zone.today.prev_month(number_of_months)
to = Time.zone.today.prev_month
adapter = Helpscout::UserConversationsAdapter.new(from, to)
if !adapter.can_fetch_reports?
return nil
end
adapter
.reports
.map do |monthly_report|
start_date = monthly_report[:start_date].to_time.localtime
end_date = monthly_report[:end_date].to_time.localtime
replies_count = monthly_report[:replies_sent]
dossiers_count = Dossier.where(depose_at: start_date..end_date).count
monthly_contact_percentage = replies_count.fdiv(dossiers_count || 1) * 100
[I18n.l(start_date, format: '%b %y'), monthly_contact_percentage.round(1)]
end
end
def max_date
if super_admin_signed_in?
Time.zone.now
else
Time.zone.now.beginning_of_month - 1.second
end
end
def last_four_months_hash(association, date_attribute)
min_date = 3.months.ago.beginning_of_month.to_date
association
.where(date_attribute => min_date..max_date)
.group("DATE_TRUNC('month', #{date_attribute})")
.count
.to_a
.sort_by { |a| a[0] }
.map { |e| [I18n.l(e.first, format: "%B %Y"), e.last] }
end
def cumulative_hash(association, date_attribute)
sum = 0
association
.where("#{date_attribute} < ?", max_date)
.group("DATE_TRUNC('month', #{date_attribute})")
.count
.to_a
.sort_by { |a| a[0] }
.map { |x, y| { x => (sum += y) } }
.reduce({}, :merge)
end
end