module NewGestionnaire class ProceduresController < GestionnaireController before_action :ensure_ownership!, except: [:index] before_action :redirect_to_avis_if_needed, only: [:index] ITEMS_PER_PAGE = 25 def index @procedures = current_gestionnaire.visible_procedures.order(archived_at: :desc, published_at: :desc) dossiers = current_gestionnaire.dossiers @dossiers_count_per_procedure = dossiers.all_state.group(:procedure_id).reorder(nil).count @dossiers_a_suivre_count_per_procedure = dossiers.without_followers.en_cours.group(:procedure_id).reorder(nil).count @dossiers_archived_count_per_procedure = dossiers.archived.group(:procedure_id).count @dossiers_termines_count_per_procedure = dossiers.termine.group(:procedure_id).reorder(nil).count @followed_dossiers_count_per_procedure = current_gestionnaire .followed_dossiers .en_cours .where(procedure: @procedures) .group(:procedure_id) .reorder(nil) .count end def show @procedure = procedure @current_filters = current_filters @available_fields_to_filters = available_fields_to_filters @displayed_fields = procedure_presentation.displayed_fields @displayed_fields_values = displayed_fields_values @a_suivre_dossiers = procedure .dossiers .includes(:user) .without_followers .en_cours @followed_dossiers = current_gestionnaire .followed_dossiers .includes(:user) .where(procedure: @procedure) .en_cours @followed_dossiers_id = current_gestionnaire .followed_dossiers .where(procedure: @procedure) .pluck(:id) @termines_dossiers = procedure.dossiers.includes(:user).termine @all_state_dossiers = procedure.dossiers.includes(:user).all_state @archived_dossiers = procedure.dossiers.includes(:user).archived @dossiers = case statut when 'a-suivre' @a_suivre_dossiers when 'suivis' @followed_dossiers when 'traites' @termines_dossiers when 'tous' @all_state_dossiers when 'archives' @archived_dossiers end sorted_ids = sorted_ids(@dossiers) if @current_filters.count > 0 filtered_ids = filtered_ids(@dossiers) filtered_sorted_ids = sorted_ids.select { |id| filtered_ids.include?(id) } else filtered_sorted_ids = sorted_ids end page = params[:page].presence || 1 filtered_sorted_paginated_ids = Kaminari .paginate_array(filtered_sorted_ids) .page(page) .per(ITEMS_PER_PAGE) @dossiers = @dossiers.where(id: filtered_sorted_paginated_ids) eager_load_displayed_fields @dossiers = @dossiers.sort_by { |d| filtered_sorted_paginated_ids.index(d.id) } kaminarize(page, filtered_sorted_ids.count) end def update_displayed_fields values = params[:values] if values.nil? values = [] end fields = values.map do |value| table, column = value.split("/") c = procedure.fields.find do |field| field['table'] == table && field['column'] == column end c.to_json end procedure_presentation.update(displayed_fields: fields) current_sort = procedure_presentation.sort if !values.include?("#{current_sort['table']}/#{current_sort['column']}") procedure_presentation.update(sort: Procedure.default_sort) end redirect_back(fallback_location: gestionnaire_procedure_url(procedure)) end def update_sort current_sort = procedure_presentation.sort table = params[:table] column = params[:column] if table == current_sort['table'] && column == current_sort['column'] order = current_sort['order'] == 'asc' ? 'desc' : 'asc' else order = 'asc' end sort = { 'table' => table, 'column' => column, 'order' => order }.to_json procedure_presentation.update(sort: sort) redirect_back(fallback_location: gestionnaire_procedure_url(procedure)) end def add_filter if params[:value].present? filters = procedure_presentation.filters table, column = params[:field].split('/') label = procedure.fields.find { |c| c['table'] == table && c['column'] == column }['label'] filters[statut] << { 'label' => label, 'table' => table, 'column' => column, 'value' => params[:value] } procedure_presentation.update(filters: filters.to_json) end redirect_back(fallback_location: gestionnaire_procedure_url(procedure)) end def remove_filter filters = procedure_presentation.filters filter_to_remove = current_filters.find do |filter| filter['table'] == params[:table] && filter['column'] == params[:column] end filters[statut] = filters[statut] - [filter_to_remove] procedure_presentation.update(filters: filters.to_json) redirect_back(fallback_location: gestionnaire_procedure_url(procedure)) end def download_dossiers export = procedure.generate_export filename = "dossiers_#{procedure.procedure_path.path}_#{Time.now.strftime('%Y-%m-%d_%H-%M')}" respond_to do |format| format.csv { send_data(SpreadsheetArchitect.to_csv(data: export[:data], headers: export[:headers]), filename: "#{filename}.csv") } format.xlsx { send_data(SpreadsheetArchitect.to_xlsx(data: export[:data], headers: export[:headers]), filename: "#{filename}.xlsx") } format.ods { send_data(SpreadsheetArchitect.to_ods(data: export[:data], headers: export[:headers]), filename: "#{filename}.ods") } end end private def statut @statut ||= (params[:statut].presence || 'a-suivre') end def procedure Procedure.find(params[:procedure_id]) end def ensure_ownership! if !procedure.gestionnaires.include?(current_gestionnaire) flash[:alert] = "Vous n'avez pas accès à cette procédure" redirect_to root_path end end def redirect_to_avis_if_needed if current_gestionnaire.visible_procedures.count == 0 && current_gestionnaire.avis.count > 0 redirect_to gestionnaire_avis_index_path end end def procedure_presentation @procedure_presentation ||= current_gestionnaire.procedure_presentation_for_procedure_id(params[:procedure_id]) end def displayed_fields_values procedure_presentation.displayed_fields.map do |field| "#{field['table']}/#{field['column']}" end end def filtered_ids(dossiers) current_filters.map do |filter| case filter['table'] when 'self' dossiers.where("? LIKE ?", filter['column'], "%#{filter['value']}%") when 'france_connect_information' dossiers .includes(user: :france_connect_information) .where("? LIKE ?", "france_connect_informations.#{filter['column']}", "%#{filter['value']}%") when 'type_de_champ', 'type_de_champ_private' relation = filter['table'] == 'type_de_champ' ? :champs : :champs_private dossiers .includes(relation) .where("champs.type_de_champ_id = ?", filter['column'].to_i) .where("champs.value LIKE ?", "%#{filter['value']}%") when 'user', 'etablissement', 'entreprise' if filter['column'] == 'date_creation' dossiers .includes(filter['table']) .where("#{filter['table'].pluralize}.#{filter['column']} = ?", filter['value'].to_date) else dossiers .includes(filter['table']) .where("#{filter['table'].pluralize}.#{filter['column']} LIKE ?", "%#{filter['value']}%") end end.pluck(:id) end.reduce(:&) end def sorted_ids(dossiers) table = procedure_presentation.sort['table'] column = procedure_presentation.sort['column'] order = procedure_presentation.sort['order'] includes = '' where = '' sorted_ids = nil case table when 'notifications' dossiers_id_with_notification = current_gestionnaire.notifications_for_procedure(procedure) if order == 'desc' sorted_ids = dossiers_id_with_notification + (dossiers.order('dossiers.updated_at desc').ids - dossiers_id_with_notification) else sorted_ids = (dossiers.order('dossiers.updated_at asc').ids - dossiers_id_with_notification) + dossiers_id_with_notification end when 'self' order = "dossiers.#{column} #{order}" when 'france_connect_information' includes = { user: :france_connect_information } order = "france_connect_informations.#{column} #{order}" when 'type_de_champ', 'type_de_champ_private' includes = table == 'type_de_champ' ? :champs : :champs_private where = "champs.type_de_champ_id = #{column.to_i}" order = "champs.value #{order}" else includes = table order = "#{table.pluralize}.#{column} #{order}" end if sorted_ids.nil? sorted_ids = dossiers.includes(includes).where(where).order(Dossier.sanitize_for_order(order)).pluck(:id) end sorted_ids end def current_filters @current_filters ||= procedure_presentation.filters[statut] end def available_fields_to_filters current_filters_fields_ids = current_filters.map do |field| "#{field['table']}/#{field['column']}" end procedure.fields_for_select.reject do |field| current_filters_fields_ids.include?(field[1]) end end def eager_load_displayed_fields @displayed_fields .reject { |field| field['table'] == 'self' } .group_by do |field| if ['type_de_champ', 'type_de_champ_private'].include?(field['table']) 'type_de_champ_group' else field['table'] end end.each do |group_key, fields| case group_key when 'france_connect_information' @dossiers = @dossiers.includes({ user: :france_connect_information }) when 'type_de_champ_group' if fields.any? { |field| field['table'] == 'type_de_champ' } @dossiers = @dossiers.includes(:champs).references(:champs) end if fields.any? { |field| field['table'] == 'type_de_champ_private' } @dossiers = @dossiers.includes(:champs_private).references(:champs_private) end where_conditions = fields.map do |field| "champs.type_de_champ_id = #{field['column']}" end.join(" OR ") @dossiers = @dossiers.where(where_conditions) else @dossiers = @dossiers.includes(fields.first['table']) end end end def kaminarize(current_page, total) @dossiers.instance_eval <<-EVAL def current_page #{current_page} end def total_pages (#{total} / #{ITEMS_PER_PAGE}.to_f).ceil end def limit_value #{ITEMS_PER_PAGE} end def first_page? current_page == 1 end def last_page? current_page == total_pages end EVAL end end end