From 3e2985b3057ceda7377e6e485402f9cf9922b928 Mon Sep 17 00:00:00 2001 From: Nicolas Bouilleaud Date: Tue, 30 Jul 2019 14:37:00 +0200 Subject: [PATCH 1/3] First attempt at procedure stats fixes #3945, #3946, #3948 --- .../new_design/procedure_show.scss | 12 ++++--- app/assets/stylesheets/new_design/stats.scss | 2 +- .../instructeurs/procedures_controller.rb | 18 +++++++++++ .../instructeurs/procedures/show.html.haml | 4 ++- .../instructeurs/procedures/stats.html.haml | 32 +++++++++++++++++++ config/routes.rb | 1 + 6 files changed, 62 insertions(+), 7 deletions(-) create mode 100644 app/views/instructeurs/procedures/stats.html.haml diff --git a/app/assets/stylesheets/new_design/procedure_show.scss b/app/assets/stylesheets/new_design/procedure_show.scss index c329189f9..5f9c31bb9 100644 --- a/app/assets/stylesheets/new_design/procedure_show.scss +++ b/app/assets/stylesheets/new_design/procedure_show.scss @@ -2,6 +2,13 @@ @import "common"; @import "constants"; +.procedure-header { + a.header-link { + display: inline-block; + margin-bottom: 1 * $default-padding; + } +} + #procedure-show { h1 { color: $black; @@ -9,11 +16,6 @@ margin-bottom: 1 * $default-padding; } - a.notifications { - display: inline-block; - margin-bottom: 1 * $default-padding; - } - .dossiers-table { margin-top: $default-spacer; margin-bottom: 3 * $default-spacer; diff --git a/app/assets/stylesheets/new_design/stats.scss b/app/assets/stylesheets/new_design/stats.scss index 9eb1e5d2d..4b9b8b58e 100644 --- a/app/assets/stylesheets/new_design/stats.scss +++ b/app/assets/stylesheets/new_design/stats.scss @@ -53,7 +53,7 @@ $stat-card-half-horizontal-spacing: 4 * $default-space; .stat-card-half { width: calc((100% - #{$stat-card-half-horizontal-spacing}) / 2); - margin-right: 3 * $default-space; + margin-right: $stat-card-half-horizontal-spacing; } .stat-card-title { diff --git a/app/controllers/instructeurs/procedures_controller.rb b/app/controllers/instructeurs/procedures_controller.rb index fe323dee4..5f2304c55 100644 --- a/app/controllers/instructeurs/procedures_controller.rb +++ b/app/controllers/instructeurs/procedures_controller.rb @@ -205,6 +205,24 @@ module Instructeurs redirect_to instructeur_procedure_path(procedure) end + def stats + @procedure = procedure + @usual_traitement_time = procedure.usual_traitement_time + + @dossiers_funnel = [ + ['Démarrés', procedure.dossiers.count], + ['Déposés', procedure.dossiers.state_not_brouillon.count], + ['Instruction débutée', procedure.dossiers.state_instruction_commencee.count], + ['Traités', procedure.dossiers.state_termine.count] + ] + + @termines_states = [ + ['Acceptés', procedure.dossiers.where(state: :accepte).count], + ['Refusés', procedure.dossiers.where(state: :refuse).count], + ['Classés sans suite', procedure.dossiers.where(state: :sans_suite).count] + ] + end + private def find_field(table, column) diff --git a/app/views/instructeurs/procedures/show.html.haml b/app/views/instructeurs/procedures/show.html.haml index 6dc7f9292..6ae142f29 100644 --- a/app/views/instructeurs/procedures/show.html.haml +++ b/app/views/instructeurs/procedures/show.html.haml @@ -9,7 +9,9 @@ .procedure-header %h1= procedure_libelle @procedure - = link_to 'configurez vos notifications', email_notifications_instructeur_procedure_path(@procedure), class: 'notifications' + = link_to 'gestion des notifications', email_notifications_instructeur_procedure_path(@procedure), class: 'header-link' + | + = link_to 'statistiques', stats_instructeur_procedure_path(@procedure), class: 'header-link' %ul.tabs diff --git a/app/views/instructeurs/procedures/stats.html.haml b/app/views/instructeurs/procedures/stats.html.haml new file mode 100644 index 000000000..4346d99ff --- /dev/null +++ b/app/views/instructeurs/procedures/stats.html.haml @@ -0,0 +1,32 @@ +- title = "Statistiques · #{@procedure.libelle}" +- content_for(:title, title) + += render partial: 'new_administrateur/breadcrumbs', + locals: { steps: [link_to(@procedure.libelle, procedure_path(@procedure)), + 'Statistiques'] } + +.statistiques + %h1.new-h1= title + .stat-cards + - if @usual_traitement_time.present? + .stat-card.big-number-card + %span.big-number-card-title TEMPS DE TRAITEMENT USUEL + %span.big-number-card-number + = distance_of_time_in_words(@usual_traitement_time) + %span.big-number-card-detail + 90% des demandes du mois dernier ont été traitées en moins de #{distance_of_time_in_words(@usual_traitement_time)}. + + .stat-cards + .stat-card.stat-card-half.pull-left + %span.stat-card-title AVANCÉE DES DOSSIERS + .chart-container + .chart + = area_chart @dossiers_funnel + + .stat-card.stat-card-half.pull-left + %span.stat-card-title TAUX D’ACCEPTATION + .chart-container + .chart + - colors = %w(#C3D9FF #0069CC #1C7EC9) # from _colors.scss + = pie_chart @termines_states, colors: colors + diff --git a/config/routes.rb b/config/routes.rb index e48f85db9..bf0542172 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -285,6 +285,7 @@ Rails.application.routes.draw do post 'add_filter' get 'remove_filter' => 'procedures#remove_filter', as: 'remove_filter' get 'download_dossiers' + get 'stats' get 'email_notifications' patch 'update_email_notifications' From 06d60cd9434236fef279e341f362fd253a101f18 Mon Sep 17 00:00:00 2001 From: Nicolas Bouilleaud Date: Mon, 16 Sep 2019 16:30:45 +0200 Subject: [PATCH 2/3] Cache requests in procedures/stats --- .../instructeurs/procedures_controller.rb | 43 +++++++++++++------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/app/controllers/instructeurs/procedures_controller.rb b/app/controllers/instructeurs/procedures_controller.rb index 5f2304c55..8e431ca19 100644 --- a/app/controllers/instructeurs/procedures_controller.rb +++ b/app/controllers/instructeurs/procedures_controller.rb @@ -207,20 +207,9 @@ module Instructeurs def stats @procedure = procedure - @usual_traitement_time = procedure.usual_traitement_time - - @dossiers_funnel = [ - ['Démarrés', procedure.dossiers.count], - ['Déposés', procedure.dossiers.state_not_brouillon.count], - ['Instruction débutée', procedure.dossiers.state_instruction_commencee.count], - ['Traités', procedure.dossiers.state_termine.count] - ] - - @termines_states = [ - ['Acceptés', procedure.dossiers.where(state: :accepte).count], - ['Refusés', procedure.dossiers.where(state: :refuse).count], - ['Classés sans suite', procedure.dossiers.where(state: :sans_suite).count] - ] + @usual_traitement_time = stats_usual_traitement_time(@procedure) + @dossiers_funnel = stats_dossiers_funnel(@procedure) + @termines_states = stats_termines_states(@procedure) end private @@ -301,5 +290,31 @@ module Instructeurs end EVAL end + + def stats_usual_traitement_time(procedure) + Rails.cache.fetch("#{procedure.cache_key_with_version}/stats_usual_traitement_time", expires_in: 12.hours) do + procedure.usual_traitement_time + end + end + def stats_dossiers_funnel(procedure) + Rails.cache.fetch("#{procedure.cache_key_with_version}/stats_dossiers_funnel", expires_in: 12.hours) do + [ + ['Démarrés', procedure.dossiers.count], + ['Déposés', procedure.dossiers.state_not_brouillon.count], + ['Instruction débutée', procedure.dossiers.state_instruction_commencee.count], + ['Traités', procedure.dossiers.state_termine.count] + ] + end + end + + def stats_termines_states(procedure) + Rails.cache.fetch("#{procedure.cache_key_with_version}/stats_termines_states", expires_in: 12.hours) do + [ + ['Acceptés', procedure.dossiers.where(state: :accepte).count], + ['Refusés', procedure.dossiers.where(state: :refuse).count], + ['Classés sans suite', procedure.dossiers.where(state: :sans_suite).count] + ] + end + end end end From 0c98f29d59b7def344d27c55f674dbf12b974ba8 Mon Sep 17 00:00:00 2001 From: Nicolas Bouilleaud Date: Tue, 17 Sep 2019 15:52:38 +0200 Subject: [PATCH 3/3] Move the cached procedure stats queries to a ProcedureStatsConcern --- .../instructeurs/procedures_controller.rb | 32 ++----------------- .../concerns/procedure_stats_concern.rb | 30 +++++++++++++++++ app/models/procedure.rb | 2 ++ 3 files changed, 35 insertions(+), 29 deletions(-) create mode 100644 app/models/concerns/procedure_stats_concern.rb diff --git a/app/controllers/instructeurs/procedures_controller.rb b/app/controllers/instructeurs/procedures_controller.rb index 8e431ca19..ffc646152 100644 --- a/app/controllers/instructeurs/procedures_controller.rb +++ b/app/controllers/instructeurs/procedures_controller.rb @@ -207,9 +207,9 @@ module Instructeurs def stats @procedure = procedure - @usual_traitement_time = stats_usual_traitement_time(@procedure) - @dossiers_funnel = stats_dossiers_funnel(@procedure) - @termines_states = stats_termines_states(@procedure) + @usual_traitement_time = @procedure.stats_usual_traitement_time + @dossiers_funnel = @procedure.stats_dossiers_funnel + @termines_states = @procedure.stats_termines_states end private @@ -290,31 +290,5 @@ module Instructeurs end EVAL end - - def stats_usual_traitement_time(procedure) - Rails.cache.fetch("#{procedure.cache_key_with_version}/stats_usual_traitement_time", expires_in: 12.hours) do - procedure.usual_traitement_time - end - end - def stats_dossiers_funnel(procedure) - Rails.cache.fetch("#{procedure.cache_key_with_version}/stats_dossiers_funnel", expires_in: 12.hours) do - [ - ['Démarrés', procedure.dossiers.count], - ['Déposés', procedure.dossiers.state_not_brouillon.count], - ['Instruction débutée', procedure.dossiers.state_instruction_commencee.count], - ['Traités', procedure.dossiers.state_termine.count] - ] - end - end - - def stats_termines_states(procedure) - Rails.cache.fetch("#{procedure.cache_key_with_version}/stats_termines_states", expires_in: 12.hours) do - [ - ['Acceptés', procedure.dossiers.where(state: :accepte).count], - ['Refusés', procedure.dossiers.where(state: :refuse).count], - ['Classés sans suite', procedure.dossiers.where(state: :sans_suite).count] - ] - end - end end end diff --git a/app/models/concerns/procedure_stats_concern.rb b/app/models/concerns/procedure_stats_concern.rb new file mode 100644 index 000000000..7e487c6a4 --- /dev/null +++ b/app/models/concerns/procedure_stats_concern.rb @@ -0,0 +1,30 @@ +module ProcedureStatsConcern + extend ActiveSupport::Concern + + def stats_usual_traitement_time + Rails.cache.fetch("#{cache_key_with_version}/stats_usual_traitement_time", expires_in: 12.hours) do + usual_traitement_time + end + end + + def stats_dossiers_funnel + Rails.cache.fetch("#{cache_key_with_version}/stats_dossiers_funnel", expires_in: 12.hours) do + [ + ['Démarrés', dossiers.count], + ['Déposés', dossiers.state_not_brouillon.count], + ['Instruction débutée', dossiers.state_instruction_commencee.count], + ['Traités', dossiers.state_termine.count] + ] + end + end + + def stats_termines_states + Rails.cache.fetch("#{cache_key_with_version}/stats_termines_states", expires_in: 12.hours) do + [ + ['Acceptés', dossiers.where(state: :accepte).count], + ['Refusés', dossiers.where(state: :refuse).count], + ['Classés sans suite', dossiers.where(state: :sans_suite).count] + ] + end + end +end diff --git a/app/models/procedure.rb b/app/models/procedure.rb index 16ff6a9ee..6fcd57717 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -3,6 +3,8 @@ require Rails.root.join('lib', 'percentile') class Procedure < ApplicationRecord self.ignored_columns = ['logo', 'logo_secure_token'] + include ProcedureStatsConcern + MAX_DUREE_CONSERVATION = 36 has_many :types_de_champ, -> { root.public_only.ordered }, inverse_of: :procedure, dependent: :destroy