From c6559577f1b837a5861b9147e3d3f0edc2db0895 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 20 Sep 2024 11:16:38 +0200 Subject: [PATCH 01/13] remove old comment --- app/models/column.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/models/column.rb b/app/models/column.rb index 583aa56aa..50ebeab7f 100644 --- a/app/models/column.rb +++ b/app/models/column.rb @@ -14,7 +14,6 @@ class Column @scope = scope @value_column = value_column @filterable = filterable - # We need this for backward compatibility @displayable = displayable end From 3c7521a42849aeae1cf0137951a50f06ee46a292 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Mon, 30 Sep 2024 20:48:54 +0200 Subject: [PATCH 02/13] extract dossier_id_column, notifications_column --- .../notified_toggle_component.html.haml | 2 +- app/models/concerns/columns_concern.rb | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/components/dossiers/notified_toggle_component/notified_toggle_component.html.haml b/app/components/dossiers/notified_toggle_component/notified_toggle_component.html.haml index 0fe1c9b20..84ff21cb9 100644 --- a/app/components/dossiers/notified_toggle_component/notified_toggle_component.html.haml +++ b/app/components/dossiers/notified_toggle_component/notified_toggle_component.html.haml @@ -1,4 +1,4 @@ -= form_tag update_sort_instructeur_procedure_path(procedure_id: @procedure.id, column_id: 'notifications/notifications', order: opposite_order), method: :get, data: { controller: 'autosubmit' } do += form_tag update_sort_instructeur_procedure_path(procedure_id: @procedure.id, column_id: @procedure.notifications_column.id, order: opposite_order), method: :get, data: { controller: 'autosubmit' } do .fr-fieldset__element.fr-m-0 .fr-checkbox-group.fr-checkbox-group--sm = check_box_tag :order, opposite_order, active? diff --git a/app/models/concerns/columns_concern.rb b/app/models/concerns/columns_concern.rb index 3f8e11a52..efafecc18 100644 --- a/app/models/concerns/columns_concern.rb +++ b/app/models/concerns/columns_concern.rb @@ -14,8 +14,16 @@ module ColumnsConcern columns.concat(types_de_champ_columns) end + def dossier_id_column + Column.new(table: 'self', column: 'id', classname: 'number-col', type: :number) + end + + def notifications_column + Column.new(table: 'notifications', column: 'notifications', label: "notifications", filterable: false) + end + def dossier_columns - common = [Column.new(table: 'self', column: 'id', classname: 'number-col', type: :number), Column.new(table: 'notifications', column: 'notifications', label: "notifications", filterable: false)] + common = [dossier_id_column, notifications_column] dates = ['created_at', 'updated_at', 'depose_at', 'en_construction_at', 'en_instruction_at', 'processed_at'] .map { |column| Column.new(table: 'self', column:, type: :date) } From 3740a79219f48b23b4cdae6f1e7c0b994122f41f Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Mon, 7 Oct 2024 21:46:59 +0200 Subject: [PATCH 03/13] add procedure_id to column.id --- .../instructeurs/column_picker_component.rb | 2 +- app/models/column.rb | 3 +- .../concerns/addressable_column_concern.rb | 3 +- app/models/concerns/columns_concern.rb | 32 +++++++++---------- app/models/procedure_presentation.rb | 8 ++--- .../repetition_type_de_champ.rb | 4 +-- .../types_de_champ/type_de_champ_base.rb | 3 +- .../_dossiers_filter_tags.html.haml | 2 +- .../column_filter_component_spec.rb | 9 +++--- .../column_picker_component_spec.rb | 8 +++-- .../procedures_controller_spec.rb | 7 ++-- spec/models/concerns/columns_concern_spec.rb | 20 +++++++----- spec/models/export_spec.rb | 4 +-- spec/models/procedure_presentation_spec.rb | 9 ++++-- 14 files changed, 65 insertions(+), 49 deletions(-) diff --git a/app/components/instructeurs/column_picker_component.rb b/app/components/instructeurs/column_picker_component.rb index 3e27ce7ab..92cc524da 100644 --- a/app/components/instructeurs/column_picker_component.rb +++ b/app/components/instructeurs/column_picker_component.rb @@ -12,7 +12,7 @@ class Instructeurs::ColumnPickerComponent < ApplicationComponent def displayable_columns_for_select [ procedure.columns.filter(&:displayable).map { |column| [column.label, column.id] }, - procedure_presentation.displayed_fields.map { Column.new(**_1.deep_symbolize_keys).id } + procedure_presentation.displayed_fields.map { Column.new(**_1.deep_symbolize_keys.merge(procedure_id: procedure.id)).id } ] end end diff --git a/app/models/column.rb b/app/models/column.rb index 50ebeab7f..0add50b3a 100644 --- a/app/models/column.rb +++ b/app/models/column.rb @@ -5,7 +5,8 @@ class Column attr_reader :table, :column, :label, :classname, :type, :scope, :value_column, :filterable, :displayable - def initialize(table:, column:, label: nil, type: :text, value_column: :value, filterable: true, displayable: true, classname: '', scope: '') + def initialize(procedure_id:, table:, column:, label: nil, type: :text, value_column: :value, filterable: true, displayable: true, classname: '', scope: '') + @procedure_id = procedure_id @table = table @column = column @label = label || I18n.t(column, scope: [:activerecord, :attributes, :procedure_presentation, :fields, table]) diff --git a/app/models/concerns/addressable_column_concern.rb b/app/models/concerns/addressable_column_concern.rb index f6fbbed5d..b439d50bc 100644 --- a/app/models/concerns/addressable_column_concern.rb +++ b/app/models/concerns/addressable_column_concern.rb @@ -4,7 +4,7 @@ module AddressableColumnConcern extend ActiveSupport::Concern included do - def columns(displayable: true, prefix: nil) + def columns(procedure_id:, displayable: true, prefix: nil) super.concat([ ["code postal (5 chiffres)", ['postal_code'], :text], ["commune", ['city_name'], :text], @@ -12,6 +12,7 @@ module AddressableColumnConcern ["region", ['region_name'], :enum] ].map do |(label, value_column, type)| Columns::JSONPathColumn.new( + procedure_id:, table: Column::TYPE_DE_CHAMP_TABLE, column: stable_id, label: "#{libelle_with_prefix(prefix)} – #{label}", diff --git a/app/models/concerns/columns_concern.rb b/app/models/concerns/columns_concern.rb index efafecc18..772f5bc76 100644 --- a/app/models/concerns/columns_concern.rb +++ b/app/models/concerns/columns_concern.rb @@ -15,23 +15,23 @@ module ColumnsConcern end def dossier_id_column - Column.new(table: 'self', column: 'id', classname: 'number-col', type: :number) + Column.new(procedure_id: id, table: 'self', column: 'id', classname: 'number-col', type: :number) end def notifications_column - Column.new(table: 'notifications', column: 'notifications', label: "notifications", filterable: false) + Column.new(procedure_id: id, table: 'notifications', column: 'notifications', label: "notifications", filterable: false) end def dossier_columns common = [dossier_id_column, notifications_column] dates = ['created_at', 'updated_at', 'depose_at', 'en_construction_at', 'en_instruction_at', 'processed_at'] - .map { |column| Column.new(table: 'self', column:, type: :date) } + .map { |column| Column.new(procedure_id: id, table: 'self', column:, type: :date) } non_displayable_dates = ['updated_since', 'depose_since', 'en_construction_since', 'en_instruction_since', 'processed_since'] - .map { |column| Column.new(table: 'self', column:, type: :date, displayable: false) } + .map { |column| Column.new(procedure_id: id, table: 'self', column:, type: :date, displayable: false) } - states = [Column.new(table: 'self', column: 'state', type: :enum, scope: 'instructeurs.dossiers.filterable_state', displayable: false)] + states = [Column.new(procedure_id: id, table: 'self', column: 'state', type: :enum, scope: 'instructeurs.dossiers.filterable_state', displayable: false)] [common, dates, sva_svr_columns(for_filters: true), non_displayable_dates, states].flatten.compact end @@ -42,12 +42,12 @@ module ColumnsConcern scope = [:activerecord, :attributes, :procedure_presentation, :fields, :self] columns = [ - Column.new(table: 'self', column: 'sva_svr_decision_on', type: :date, + Column.new(procedure_id: id, table: 'self', column: 'sva_svr_decision_on', type: :date, label: I18n.t("#{sva_svr_decision}_decision_on", scope:), classname: for_filters ? '' : 'sva-col') ] if for_filters - columns << Column.new(table: 'self', column: 'sva_svr_decision_before', type: :date, displayable: false, + columns << Column.new(procedure_id: id, table: 'self', column: 'sva_svr_decision_before', type: :date, displayable: false, label: I18n.t("#{sva_svr_decision}_decision_before", scope:)) end @@ -58,30 +58,30 @@ module ColumnsConcern def standard_columns [ - Column.new(table: 'user', column: 'email'), - Column.new(table: 'followers_instructeurs', column: 'email'), - Column.new(table: 'groupe_instructeur', column: 'id', type: :enum), - Column.new(table: 'avis', column: 'question_answer', filterable: false) # not filterable ? + Column.new(procedure_id: id, table: 'user', column: 'email'), + Column.new(procedure_id: id, table: 'followers_instructeurs', column: 'email'), + Column.new(procedure_id: id, table: 'groupe_instructeur', column: 'id', type: :enum), + Column.new(procedure_id: id, table: 'avis', column: 'question_answer', filterable: false) # not filterable ? ] end def individual_columns - ['nom', 'prenom', 'gender'].map { |column| Column.new(table: 'individual', column:) } + ['nom', 'prenom', 'gender'].map { |column| Column.new(procedure_id: id, table: 'individual', column:) } end def moral_columns etablissements = ['entreprise_siren', 'entreprise_forme_juridique', 'entreprise_nom_commercial', 'entreprise_raison_sociale', 'entreprise_siret_siege_social'] - .map { |column| Column.new(table: 'etablissement', column:) } + .map { |column| Column.new(procedure_id: id, table: 'etablissement', column:) } - etablissement_dates = ['entreprise_date_creation'].map { |column| Column.new(table: 'etablissement', column:, type: :date) } + etablissement_dates = ['entreprise_date_creation'].map { |column| Column.new(procedure_id: id, table: 'etablissement', column:, type: :date) } - other = ['siret', 'libelle_naf', 'code_postal'].map { |column| Column.new(table: 'etablissement', column:) } + other = ['siret', 'libelle_naf', 'code_postal'].map { |column| Column.new(procedure_id: id, table: 'etablissement', column:) } [etablissements, etablissement_dates, other].flatten end def types_de_champ_columns - all_revisions_types_de_champ.flat_map(&:columns) + all_revisions_types_de_champ.flat_map { _1.columns(procedure_id: id) } end end end diff --git a/app/models/procedure_presentation.rb b/app/models/procedure_presentation.rb index 7ac5e26a1..d271c68ac 100644 --- a/app/models/procedure_presentation.rb +++ b/app/models/procedure_presentation.rb @@ -31,9 +31,9 @@ class ProcedurePresentation < ApplicationRecord def displayed_fields_for_headers [ - Column.new(table: 'self', column: 'id', classname: 'number-col'), - *displayed_fields.map { Column.new(**_1.deep_symbolize_keys) }, - Column.new(table: 'self', column: 'state', classname: 'state-col'), + Column.new(procedure_id: procedure.id, table: 'self', column: 'id', classname: 'number-col'), + *displayed_fields.map { Column.new(**_1.deep_symbolize_keys.merge(procedure_id: procedure.id)) }, + Column.new(procedure_id: procedure.id, table: 'self', column: 'state', classname: 'state-col'), *procedure.sva_svr_columns ] end @@ -201,7 +201,7 @@ class ProcedurePresentation < ApplicationRecord .map do |(table, column), filters| values = filters.pluck('value') value_column = filters.pluck('value_column').compact.first || :value - dossier_column = procedure.find_column(id: Column.make_id(table, column)) # hack to find json path columns + dossier_column = procedure.find_column(id: Column.make_id(procedure.id, table, column)) # hack to find json path columns if dossier_column.is_a?(Columns::JSONPathColumn) dossier_column.filtered_ids(dossiers, values) else diff --git a/app/models/types_de_champ/repetition_type_de_champ.rb b/app/models/types_de_champ/repetition_type_de_champ.rb index 163470308..dea997ad9 100644 --- a/app/models/types_de_champ/repetition_type_de_champ.rb +++ b/app/models/types_de_champ/repetition_type_de_champ.rb @@ -27,9 +27,9 @@ class TypesDeChamp::RepetitionTypeDeChamp < TypesDeChamp::TypeDeChampBase ActiveStorage::Filename.new(str.delete('[]*?')).sanitized end - def columns(displayable: true, prefix: nil) + def columns(procedure_id:, displayable: true, prefix: nil) @type_de_champ.procedure .all_revisions_types_de_champ(parent: @type_de_champ) - .flat_map { _1.columns(displayable: false, prefix: libelle) } + .flat_map { _1.columns(procedure_id:, displayable: false, prefix: libelle) } end end diff --git a/app/models/types_de_champ/type_de_champ_base.rb b/app/models/types_de_champ/type_de_champ_base.rb index 3b75b05da..19d37df0e 100644 --- a/app/models/types_de_champ/type_de_champ_base.rb +++ b/app/models/types_de_champ/type_de_champ_base.rb @@ -98,9 +98,10 @@ class TypesDeChamp::TypeDeChampBase end end - def columns(displayable: true, prefix: nil) + def columns(procedure_id:, displayable: true, prefix: nil) [ Column.new( + procedure_id:, table: Column::TYPE_DE_CHAMP_TABLE, column: stable_id.to_s, label: libelle_with_prefix(prefix), diff --git a/app/views/instructeurs/procedures/_dossiers_filter_tags.html.haml b/app/views/instructeurs/procedures/_dossiers_filter_tags.html.haml index dadfb4478..d6216f80b 100644 --- a/app/views/instructeurs/procedures/_dossiers_filter_tags.html.haml +++ b/app/views/instructeurs/procedures/_dossiers_filter_tags.html.haml @@ -6,6 +6,6 @@ - filters.each_with_index do |filter, i| - if i > 0 = " ou " - = link_to remove_filter_instructeur_procedure_path(procedure, { statut: statut, column: "#{filter['table']}/#{filter['column']}", value: filter['value'] }), + = link_to remove_filter_instructeur_procedure_path(procedure, { statut: statut, column: Column.make_id(procedure.id, filter['table'], filter['column']), value: filter['value'] }), class: "fr-tag fr-tag--dismiss fr-my-1w", aria: { label: "Retirer le filtre #{filter['column']}" } do = "#{filter['label'].truncate(50)} : #{procedure_presentation.human_value_for_filter(filter)}" diff --git a/spec/components/instructeurs/column_filter_component_spec.rb b/spec/components/instructeurs/column_filter_component_spec.rb index b7f736f42..426c52034 100644 --- a/spec/components/instructeurs/column_filter_component_spec.rb +++ b/spec/components/instructeurs/column_filter_component_spec.rb @@ -5,6 +5,7 @@ describe Instructeurs::ColumnFilterComponent, type: :component do let(:instructeur) { create(:instructeur) } let(:procedure) { create(:procedure, instructeurs: [instructeur]) } + let(:procedure_id) { procedure.id } let(:procedure_presentation) { nil } let(:statut) { nil } @@ -17,8 +18,8 @@ describe Instructeurs::ColumnFilterComponent, type: :component do let(:column) { nil } let(:included_displayable_field) do [ - Column.new(label: 'email', table: 'user', column: 'email'), - Column.new(label: "depose_since", table: "self", column: "depose_since", displayable: false) + Column.new(procedure_id:, label: 'email', table: 'user', column: 'email'), + Column.new(procedure_id:, label: "depose_since", table: "self", column: "depose_since", displayable: false) ] end @@ -26,7 +27,7 @@ describe Instructeurs::ColumnFilterComponent, type: :component do subject { component.filterable_columns_options } - it { is_expected.to eq([["email", "user/email"], ["depose_since", "self/depose_since"]]) } + it { is_expected.to eq([["email", Column.make_id(procedure_id, "user", "email")], ["depose_since", Column.make_id(procedure_id, "self", "depose_since")]]) } end end @@ -45,7 +46,7 @@ describe Instructeurs::ColumnFilterComponent, type: :component do let(:types_de_champ_public) { [{ type: :drop_down_list, libelle: 'Votre ville', options: ['Paris', 'Lyon', 'Marseille'] }] } let(:procedure) { create(:procedure, :published, types_de_champ_public:) } let(:drop_down_stable_id) { procedure.active_revision.types_de_champ.first.stable_id } - let(:column) { Column.new(table: 'type_de_champ', scope: nil, column: drop_down_stable_id) } + let(:column) { Column.new(procedure_id:, table: 'type_de_champ', scope: nil, column: drop_down_stable_id) } it 'find most recent tdc' do is_expected.to eq(['Paris', 'Lyon', 'Marseille']) diff --git a/spec/components/instructeurs/column_picker_component_spec.rb b/spec/components/instructeurs/column_picker_component_spec.rb index 13edeb9a4..92cdf4451 100644 --- a/spec/components/instructeurs/column_picker_component_spec.rb +++ b/spec/components/instructeurs/column_picker_component_spec.rb @@ -4,13 +4,15 @@ describe Instructeurs::ColumnPickerComponent, type: :component do let(:component) { described_class.new(procedure:, procedure_presentation:) } let(:procedure) { create(:procedure) } + let(:procedure_id) { procedure.id } let(:instructeur) { create(:instructeur) } let(:assign_to) { create(:assign_to, procedure: procedure, instructeur: instructeur) } let(:procedure_presentation) { create(:procedure_presentation, assign_to: assign_to) } describe "#displayable_columns_for_select" do - let(:default_user_email) { Column.new(label: 'email', table: 'user', column: 'email') } - let(:excluded_displayable_field) { Column.new(label: "label1", table: "table1", column: "column1", displayable: false) } + let(:default_user_email) { Column.new(procedure_id:, label: 'email', table: 'user', column: 'email') } + let(:excluded_displayable_field) { Column.new(procedure_id:, label: "label1", table: "table1", column: "column1", displayable: false) } + let(:email_column_id) { Column.make_id(procedure_id, 'user', 'email') } subject { component.displayable_columns_for_select } @@ -21,6 +23,6 @@ describe Instructeurs::ColumnPickerComponent, type: :component do ]) end - it { is_expected.to eq([[["email", "user/email"]], ["user/email"]]) } + it { is_expected.to eq([[["email", email_column_id]], [email_column_id]]) } end end diff --git a/spec/controllers/instructeurs/procedures_controller_spec.rb b/spec/controllers/instructeurs/procedures_controller_spec.rb index 52f6bbeb3..bab2a299b 100644 --- a/spec/controllers/instructeurs/procedures_controller_spec.rb +++ b/spec/controllers/instructeurs/procedures_controller_spec.rb @@ -886,12 +886,14 @@ describe Instructeurs::ProceduresController, type: :controller do end it 'can change order' do - expect { get :update_sort, params: { procedure_id: procedure.id, column_id: "individual/nom", order: 'asc' } } + column_id = Column.make_id(procedure.id, "individual", "nom") + expect { get :update_sort, params: { procedure_id: procedure.id, column_id:, order: 'asc' } } .to change { procedure_presentation.sort } .from({ "column" => "notifications", "order" => "desc", "table" => "notifications" }) .to({ "column" => "nom", "order" => "asc", "table" => "individual" }) end end + describe '#add_filter' do let(:instructeur) { create(:instructeur) } let(:procedure) { create(:procedure, :for_individual) } @@ -903,7 +905,8 @@ describe Instructeurs::ProceduresController, type: :controller do end subject do - post :add_filter, params: { procedure_id: procedure.id, column: "individual/nom", value: "n" * 110, statut: "a-suivre" } + column = Column.make_id(procedure.id, "individual", "nom") + post :add_filter, params: { procedure_id: procedure.id, column:, value: "n" * 110, statut: "a-suivre" } end it 'should render the error' do diff --git a/spec/models/concerns/columns_concern_spec.rb b/spec/models/concerns/columns_concern_spec.rb index ab13657ce..63ac65622 100644 --- a/spec/models/concerns/columns_concern_spec.rb +++ b/spec/models/concerns/columns_concern_spec.rb @@ -6,6 +6,7 @@ describe ColumnsConcern do context 'when the procedure can have a SIRET number' do let(:procedure) { create(:procedure, types_de_champ_public:, types_de_champ_private:) } + let(:procedure_id) { procedure.id } let(:tdc_1) { procedure.active_revision.types_de_champ_public[0] } let(:tdc_2) { procedure.active_revision.types_de_champ_public[1] } let(:tdc_private_1) { procedure.active_revision.types_de_champ_private[0] } @@ -43,7 +44,7 @@ describe ColumnsConcern do { label: tdc_2.libelle, table: 'type_de_champ', column: tdc_2.stable_id.to_s, classname: '', displayable: true, type: :text, scope: '', value_column: :value, filterable: true }, { label: tdc_private_1.libelle, table: 'type_de_champ', column: tdc_private_1.stable_id.to_s, classname: '', displayable: true, type: :text, scope: '', value_column: :value, filterable: true }, { label: tdc_private_2.libelle, table: 'type_de_champ', column: tdc_private_2.stable_id.to_s, classname: '', displayable: true, type: :text, scope: '', value_column: :value, filterable: true } - ].map { Column.new(**_1) } + ].map { Column.new(**_1.merge(procedure_id:)) } } context 'with explication/header_sections' do @@ -67,10 +68,11 @@ describe ColumnsConcern do end context 'when the procedure is for individuals' do - let(:name_field) { Column.new(label: "Prénom", table: "individual", column: "prenom", classname: '', displayable: true, type: :text, scope: '', value_column: :value, filterable: true) } - let(:surname_field) { Column.new(label: "Nom", table: "individual", column: "nom", classname: '', displayable: true, type: :text, scope: '', value_column: :value, filterable: true) } - let(:gender_field) { Column.new(label: "Civilité", table: "individual", column: "gender", classname: '', displayable: true, type: :text, scope: '', value_column: :value, filterable: true) } + let(:name_field) { Column.new(procedure_id:, label: "Prénom", table: "individual", column: "prenom", classname: '', displayable: true, type: :text, scope: '', value_column: :value, filterable: true) } + let(:surname_field) { Column.new(procedure_id:, label: "Nom", table: "individual", column: "nom", classname: '', displayable: true, type: :text, scope: '', value_column: :value, filterable: true) } + let(:gender_field) { Column.new(procedure_id:, label: "Civilité", table: "individual", column: "gender", classname: '', displayable: true, type: :text, scope: '', value_column: :value, filterable: true) } let(:procedure) { create(:procedure, :for_individual) } + let(:procedure_id) { procedure.id } let(:procedure_presentation) { create(:procedure_presentation, assign_to: assign_to) } it { is_expected.to include(name_field, surname_field, gender_field) } @@ -78,20 +80,22 @@ describe ColumnsConcern do context 'when the procedure is sva' do let(:procedure) { create(:procedure, :for_individual, :sva) } + let(:procedure_id) { procedure.id } let(:procedure_presentation) { create(:procedure_presentation, assign_to: assign_to) } - let(:decision_on) { Column.new(label: "Date décision SVA", table: "self", column: "sva_svr_decision_on", classname: '', displayable: true, type: :date, scope: '', value_column: :value, filterable: true) } - let(:decision_before_field) { Column.new(label: "Date décision SVA avant", table: "self", column: "sva_svr_decision_before", classname: '', displayable: false, type: :date, scope: '', value_column: :value, filterable: true) } + let(:decision_on) { Column.new(procedure_id:, label: "Date décision SVA", table: "self", column: "sva_svr_decision_on", classname: '', displayable: true, type: :date, scope: '', value_column: :value, filterable: true) } + let(:decision_before_field) { Column.new(procedure_id:, label: "Date décision SVA avant", table: "self", column: "sva_svr_decision_before", classname: '', displayable: false, type: :date, scope: '', value_column: :value, filterable: true) } it { is_expected.to include(decision_on, decision_before_field) } end context 'when the procedure is svr' do let(:procedure) { create(:procedure, :for_individual, :svr) } + let(:procedure_id) { procedure.id } let(:procedure_presentation) { create(:procedure_presentation, assign_to: assign_to) } - let(:decision_on) { Column.new(label: "Date décision SVR", table: "self", column: "sva_svr_decision_on", classname: '', displayable: true, type: :date, scope: '', value_column: :value, filterable: true) } - let(:decision_before_field) { Column.new(label: "Date décision SVR avant", table: "self", column: "sva_svr_decision_before", classname: '', displayable: false, type: :date, scope: '', value_column: :value, filterable: true) } + let(:decision_on) { Column.new(procedure_id:, label: "Date décision SVR", table: "self", column: "sva_svr_decision_on", classname: '', displayable: true, type: :date, scope: '', value_column: :value, filterable: true) } + let(:decision_before_field) { Column.new(procedure_id:, label: "Date décision SVR avant", table: "self", column: "sva_svr_decision_before", classname: '', displayable: false, type: :date, scope: '', value_column: :value, filterable: true) } it { is_expected.to include(decision_on, decision_before_field) } end diff --git a/spec/models/export_spec.rb b/spec/models/export_spec.rb index c1316dfe7..f9e34a47b 100644 --- a/spec/models/export_spec.rb +++ b/spec/models/export_spec.rb @@ -94,7 +94,7 @@ RSpec.describe Export, type: :model do let(:instructeur) { create(:instructeur) } let!(:gi_1) { create(:groupe_instructeur, procedure: procedure, instructeurs: [instructeur]) } let!(:pp) { gi_1.instructeurs.first.procedure_presentation_and_errors_for_procedure_id(procedure.id).first } - before { pp.add_filter('tous', 'self/created_at', '10/12/2021') } + before { pp.add_filter('tous', Column.make_id(procedure.id, 'self', 'created_at'), '10/12/2021') } context 'with procedure_presentation having different filters' do it 'works once' do @@ -105,7 +105,7 @@ RSpec.describe Export, type: :model do it 'works once, changes procedure_presentation, recreate a new' do expect { Export.find_or_create_fresh_export(:zip, [gi_1], instructeur, time_span_type: Export.time_span_types.fetch(:everything), statut: Export.statuts.fetch(:tous), procedure_presentation: pp) } .to change { Export.count }.by(1) - pp.add_filter('tous', 'self/updated_at', '10/12/2021') + pp.add_filter('tous', Column.make_id(procedure.id, 'self', 'updated_at'), '10/12/2021') expect { Export.find_or_create_fresh_export(:zip, [gi_1], instructeur, time_span_type: Export.time_span_types.fetch(:everything), statut: Export.statuts.fetch(:tous), procedure_presentation: pp) } .to change { Export.count }.by(1) end diff --git a/spec/models/procedure_presentation_spec.rb b/spec/models/procedure_presentation_spec.rb index 0ae5de859..f1f640a64 100644 --- a/spec/models/procedure_presentation_spec.rb +++ b/spec/models/procedure_presentation_spec.rb @@ -582,7 +582,7 @@ describe ProcedurePresentation do context 'for type_de_champ using AddressableColumnConcern' do let(:types_de_champ_public) { [{ type: :rna, stable_id: 1 }] } let(:type_de_champ) { procedure.active_revision.types_de_champ.first } - let(:available_columns) { type_de_champ.columns } + let(:available_columns) { type_de_champ.columns(procedure_id: procedure.id) } let(:column) { available_columns.find { _1.value_column == value_column_searched } } let(:filter) { [column.to_json.merge({ "value" => value })] } let(:kept_dossier) { create(:dossier, procedure: procedure) } @@ -611,6 +611,7 @@ describe ProcedurePresentation do create(:dossier, procedure: procedure).project_champs_public.find { _1.stable_id == 1 }.update(value_json: { "departement_code" => "unknown" }) end it { is_expected.to contain_exactly(kept_dossier.id) } + it 'describes column' do expect(column.type).to eq(:enum) expect(column.options_for_select.first).to eq(["99 – Etranger", "99"]) @@ -865,9 +866,10 @@ describe ProcedurePresentation do context 'when type_de_champ text' do let(:filters) { { "suivis" => [] } } + let(:column_id) { Column.make_id(procedure.id, 'type_de_champ', first_type_de_champ_id) } it 'should passthrough value' do - procedure_presentation.add_filter("suivis", "type_de_champ/#{first_type_de_champ_id}", "Oui") + procedure_presentation.add_filter("suivis", column_id, "Oui") expect(procedure_presentation.filters).to eq({ "suivis" => [ @@ -879,10 +881,11 @@ describe ProcedurePresentation do context 'when type_de_champ departements' do let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :departements }]) } + let(:column_id) { Column.make_id(procedure.id, 'type_de_champ', first_type_de_champ_id) } let(:filters) { { "suivis" => [] } } it 'should set value_column' do - procedure_presentation.add_filter("suivis", "type_de_champ/#{first_type_de_champ_id}", "13") + procedure_presentation.add_filter("suivis", column_id, "13") expect(procedure_presentation.filters).to eq({ "suivis" => [ From a8b41e90cc64f0901277676318f3e57b0ac780d2 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Mon, 7 Oct 2024 16:57:54 +0200 Subject: [PATCH 04/13] remove make_id --- app/models/column.rb | 4 ---- app/models/procedure_presentation.rb | 2 +- .../procedures/_dossiers_filter_tags.html.haml | 2 +- .../instructeurs/column_filter_component_spec.rb | 2 +- .../instructeurs/column_picker_component_spec.rb | 2 +- .../instructeurs/procedures_controller_spec.rb | 4 ++-- spec/models/export_spec.rb | 4 ++-- spec/models/procedure_presentation_spec.rb | 9 +++++---- 8 files changed, 13 insertions(+), 16 deletions(-) diff --git a/app/models/column.rb b/app/models/column.rb index 0add50b3a..240a11937 100644 --- a/app/models/column.rb +++ b/app/models/column.rb @@ -22,10 +22,6 @@ class Column "#{table}/#{column}" end - def self.make_id(table, column) - "#{table}/#{column}" - end - def ==(other) other.to_json == to_json end diff --git a/app/models/procedure_presentation.rb b/app/models/procedure_presentation.rb index d271c68ac..de6d162d4 100644 --- a/app/models/procedure_presentation.rb +++ b/app/models/procedure_presentation.rb @@ -201,7 +201,7 @@ class ProcedurePresentation < ApplicationRecord .map do |(table, column), filters| values = filters.pluck('value') value_column = filters.pluck('value_column').compact.first || :value - dossier_column = procedure.find_column(id: Column.make_id(procedure.id, table, column)) # hack to find json path columns + dossier_column = procedure.find_column(h_id: { procedure_id: procedure.id, column_id: "#{table}/#{column}" }) # hack to find json path columns if dossier_column.is_a?(Columns::JSONPathColumn) dossier_column.filtered_ids(dossiers, values) else diff --git a/app/views/instructeurs/procedures/_dossiers_filter_tags.html.haml b/app/views/instructeurs/procedures/_dossiers_filter_tags.html.haml index d6216f80b..d1b57d57e 100644 --- a/app/views/instructeurs/procedures/_dossiers_filter_tags.html.haml +++ b/app/views/instructeurs/procedures/_dossiers_filter_tags.html.haml @@ -6,6 +6,6 @@ - filters.each_with_index do |filter, i| - if i > 0 = " ou " - = link_to remove_filter_instructeur_procedure_path(procedure, { statut: statut, column: Column.make_id(procedure.id, filter['table'], filter['column']), value: filter['value'] }), + = link_to remove_filter_instructeur_procedure_path(procedure, { statut: statut, column: { procedure_id: procedure.id, column_id: filter['table'] + "/" + filter['column'] }.to_json, value: filter['value'] }), class: "fr-tag fr-tag--dismiss fr-my-1w", aria: { label: "Retirer le filtre #{filter['column']}" } do = "#{filter['label'].truncate(50)} : #{procedure_presentation.human_value_for_filter(filter)}" diff --git a/spec/components/instructeurs/column_filter_component_spec.rb b/spec/components/instructeurs/column_filter_component_spec.rb index 426c52034..8c31094dd 100644 --- a/spec/components/instructeurs/column_filter_component_spec.rb +++ b/spec/components/instructeurs/column_filter_component_spec.rb @@ -27,7 +27,7 @@ describe Instructeurs::ColumnFilterComponent, type: :component do subject { component.filterable_columns_options } - it { is_expected.to eq([["email", Column.make_id(procedure_id, "user", "email")], ["depose_since", Column.make_id(procedure_id, "self", "depose_since")]]) } + it { is_expected.to eq([["email", included_displayable_field.first.id], ["depose_since", included_displayable_field.second.id]]) } end end diff --git a/spec/components/instructeurs/column_picker_component_spec.rb b/spec/components/instructeurs/column_picker_component_spec.rb index 92cdf4451..ac2737f01 100644 --- a/spec/components/instructeurs/column_picker_component_spec.rb +++ b/spec/components/instructeurs/column_picker_component_spec.rb @@ -12,7 +12,7 @@ describe Instructeurs::ColumnPickerComponent, type: :component do describe "#displayable_columns_for_select" do let(:default_user_email) { Column.new(procedure_id:, label: 'email', table: 'user', column: 'email') } let(:excluded_displayable_field) { Column.new(procedure_id:, label: "label1", table: "table1", column: "column1", displayable: false) } - let(:email_column_id) { Column.make_id(procedure_id, 'user', 'email') } + let(:email_column_id) { default_user_email.id } subject { component.displayable_columns_for_select } diff --git a/spec/controllers/instructeurs/procedures_controller_spec.rb b/spec/controllers/instructeurs/procedures_controller_spec.rb index bab2a299b..d24a519ed 100644 --- a/spec/controllers/instructeurs/procedures_controller_spec.rb +++ b/spec/controllers/instructeurs/procedures_controller_spec.rb @@ -886,7 +886,7 @@ describe Instructeurs::ProceduresController, type: :controller do end it 'can change order' do - column_id = Column.make_id(procedure.id, "individual", "nom") + column_id = procedure.find_column(label: "Nom").id expect { get :update_sort, params: { procedure_id: procedure.id, column_id:, order: 'asc' } } .to change { procedure_presentation.sort } .from({ "column" => "notifications", "order" => "desc", "table" => "notifications" }) @@ -905,7 +905,7 @@ describe Instructeurs::ProceduresController, type: :controller do end subject do - column = Column.make_id(procedure.id, "individual", "nom") + column = procedure.find_column(label: "Nom").id post :add_filter, params: { procedure_id: procedure.id, column:, value: "n" * 110, statut: "a-suivre" } end diff --git a/spec/models/export_spec.rb b/spec/models/export_spec.rb index f9e34a47b..e960acb8f 100644 --- a/spec/models/export_spec.rb +++ b/spec/models/export_spec.rb @@ -94,7 +94,7 @@ RSpec.describe Export, type: :model do let(:instructeur) { create(:instructeur) } let!(:gi_1) { create(:groupe_instructeur, procedure: procedure, instructeurs: [instructeur]) } let!(:pp) { gi_1.instructeurs.first.procedure_presentation_and_errors_for_procedure_id(procedure.id).first } - before { pp.add_filter('tous', Column.make_id(procedure.id, 'self', 'created_at'), '10/12/2021') } + before { pp.add_filter('tous', procedure.find_column(label: 'Créé le').id, '10/12/2021') } context 'with procedure_presentation having different filters' do it 'works once' do @@ -105,7 +105,7 @@ RSpec.describe Export, type: :model do it 'works once, changes procedure_presentation, recreate a new' do expect { Export.find_or_create_fresh_export(:zip, [gi_1], instructeur, time_span_type: Export.time_span_types.fetch(:everything), statut: Export.statuts.fetch(:tous), procedure_presentation: pp) } .to change { Export.count }.by(1) - pp.add_filter('tous', Column.make_id(procedure.id, 'self', 'updated_at'), '10/12/2021') + pp.add_filter('tous', procedure.find_column(label: 'Mis à jour le').id, '10/12/2021') expect { Export.find_or_create_fresh_export(:zip, [gi_1], instructeur, time_span_type: Export.time_span_types.fetch(:everything), statut: Export.statuts.fetch(:tous), procedure_presentation: pp) } .to change { Export.count }.by(1) end diff --git a/spec/models/procedure_presentation_spec.rb b/spec/models/procedure_presentation_spec.rb index f1f640a64..3197c2c19 100644 --- a/spec/models/procedure_presentation_spec.rb +++ b/spec/models/procedure_presentation_spec.rb @@ -850,10 +850,11 @@ describe ProcedurePresentation do let(:filters) { { "suivis" => [] } } context 'when type_de_champ yes_no' do - let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :yes_no }]) } + let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :yes_no, libelle: 'oui ou non' }]) } it 'should downcase and transform value' do - procedure_presentation.add_filter("suivis", "type_de_champ/#{first_type_de_champ_id}", +"Oui") + column_id = procedure.find_column(label: 'oui ou non').id + procedure_presentation.add_filter("suivis", column_id, "Oui") expect(procedure_presentation.filters).to eq({ "suivis" => @@ -866,7 +867,7 @@ describe ProcedurePresentation do context 'when type_de_champ text' do let(:filters) { { "suivis" => [] } } - let(:column_id) { Column.make_id(procedure.id, 'type_de_champ', first_type_de_champ_id) } + let(:column_id) { procedure.find_column(label: first_type_de_champ.libelle).id } it 'should passthrough value' do procedure_presentation.add_filter("suivis", column_id, "Oui") @@ -881,7 +882,7 @@ describe ProcedurePresentation do context 'when type_de_champ departements' do let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :departements }]) } - let(:column_id) { Column.make_id(procedure.id, 'type_de_champ', first_type_de_champ_id) } + let(:column_id) { procedure.find_column(label: first_type_de_champ.libelle).id } let(:filters) { { "suivis" => [] } } it 'should set value_column' do From e3697bd9761641e9efe8bfecde68fe652765541e Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Mon, 7 Oct 2024 15:01:40 +0200 Subject: [PATCH 05/13] colonne.id = { procedure_id:, column_id: }.to_json because: - id should be a string as other id - id need procedure_id to allow ColumnType.deserialize(id) -> Column as the columns are built by a procedure --- .../instructeurs/procedures_controller.rb | 2 +- app/models/column.rb | 10 +++------- app/models/concerns/columns_concern.rb | 5 ++++- app/models/procedure_presentation.rb | 14 +++++++++----- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/app/controllers/instructeurs/procedures_controller.rb b/app/controllers/instructeurs/procedures_controller.rb index f8a332189..302bde7b1 100644 --- a/app/controllers/instructeurs/procedures_controller.rb +++ b/app/controllers/instructeurs/procedures_controller.rb @@ -158,7 +158,7 @@ module Instructeurs @statut = statut @procedure = procedure @procedure_presentation = procedure_presentation - @column = procedure.find_column(id: params[:column]) + @column = procedure.find_column(h_id: JSON.parse(params[:column], symbolize_names: true)) end def remove_filter diff --git a/app/models/column.rb b/app/models/column.rb index 240a11937..a7f74fa69 100644 --- a/app/models/column.rb +++ b/app/models/column.rb @@ -18,13 +18,9 @@ class Column @displayable = displayable end - def id - "#{table}/#{column}" - end - - def ==(other) - other.to_json == to_json - end + def id = h_id.to_json + def h_id = { procedure_id: @procedure_id, column_id: "#{table}/#{column}" } + def ==(other) = h_id == other.h_id # using h_id instead of id to avoid inversion of keys def to_json { diff --git a/app/models/concerns/columns_concern.rb b/app/models/concerns/columns_concern.rb index 772f5bc76..ea88cb73a 100644 --- a/app/models/concerns/columns_concern.rb +++ b/app/models/concerns/columns_concern.rb @@ -4,7 +4,10 @@ module ColumnsConcern extend ActiveSupport::Concern included do - def find_column(id:) = columns.find { |f| f.id == id } + def find_column(h_id: nil, label: nil) + return columns.find { _1.h_id == h_id } if h_id.present? + return columns.find { _1.label == label } if label.present? + end def columns columns = dossier_columns diff --git a/app/models/procedure_presentation.rb b/app/models/procedure_presentation.rb index de6d162d4..7cd4e0f48 100644 --- a/app/models/procedure_presentation.rb +++ b/app/models/procedure_presentation.rb @@ -81,8 +81,10 @@ class ProcedurePresentation < ApplicationRecord end def add_filter(statut, column_id, value) + h_id = JSON.parse(column_id, symbolize_names: true) + if value.present? - column = procedure.find_column(id: column_id) + column = procedure.find_column(h_id:) case column.table when TYPE_DE_CHAMP @@ -103,7 +105,8 @@ class ProcedurePresentation < ApplicationRecord end def remove_filter(statut, column_id, value) - column = procedure.find_column(id: column_id) + h_id = JSON.parse(column_id, symbolize_names: true) + column = procedure.find_column(h_id:) updated_filters = filters.dup updated_filters[statut] = filters[statut].reject do |filter| @@ -114,8 +117,8 @@ class ProcedurePresentation < ApplicationRecord end def update_displayed_fields(column_ids) - column_ids = Array.wrap(column_ids) - columns = column_ids.map { |id| procedure.find_column(id:) } + h_ids = Array.wrap(column_ids).map { |id| JSON.parse(id, symbolize_names: true) } + columns = h_ids.map { |h_id| procedure.find_column(h_id:) } update!(displayed_fields: columns) @@ -125,7 +128,8 @@ class ProcedurePresentation < ApplicationRecord end def update_sort(column_id, order) - column = procedure.find_column(id: column_id) + h_id = JSON.parse(column_id, symbolize_names: true) + column = procedure.find_column(h_id:) update!(sort: { TABLE => column.table, From 3d79c6176e143f49132876c616326f8dec44fa12 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 20 Sep 2024 11:12:52 +0200 Subject: [PATCH 06/13] add columns_ids to procedure_presentations table --- app/models/procedure_presentation.rb | 11 +++++++++++ ..._add_column_ids_to_procedure_presentations.rb | 16 ++++++++++++++++ db/schema.rb | 10 ++++++++++ 3 files changed, 37 insertions(+) create mode 100644 db/migrate/20240920090848_add_column_ids_to_procedure_presentations.rb diff --git a/app/models/procedure_presentation.rb b/app/models/procedure_presentation.rb index 7cd4e0f48..5939f68cf 100644 --- a/app/models/procedure_presentation.rb +++ b/app/models/procedure_presentation.rb @@ -29,6 +29,17 @@ class ProcedurePresentation < ApplicationRecord validate :check_filters_max_length validate :check_filters_max_integer + attribute :sorted_column, :jsonb + + attribute :a_suivre_filters, :jsonb, array: true + attribute :suivis_filters, :jsonb, array: true + attribute :traites_filters, :jsonb, array: true + attribute :tous_filters, :jsonb, array: true + attribute :supprimes_filters, :jsonb, array: true + attribute :supprimes_recemment_filters, :jsonb, array: true + attribute :expirant_filters, :jsonb, array: true + attribute :archives_filters, :jsonb, array: true + def displayed_fields_for_headers [ Column.new(procedure_id: procedure.id, table: 'self', column: 'id', classname: 'number-col'), diff --git a/db/migrate/20240920090848_add_column_ids_to_procedure_presentations.rb b/db/migrate/20240920090848_add_column_ids_to_procedure_presentations.rb new file mode 100644 index 000000000..dd2a98142 --- /dev/null +++ b/db/migrate/20240920090848_add_column_ids_to_procedure_presentations.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class AddColumnIdsToProcedurePresentations < ActiveRecord::Migration[7.0] + def change + add_column :procedure_presentations, :displayed_columns, :jsonb, array: true, default: [], null: false + add_column :procedure_presentations, :tous_filters, :jsonb, array: true, default: [], null: false + add_column :procedure_presentations, :suivis_filters, :jsonb, array: true, default: [], null: false + add_column :procedure_presentations, :traites_filters, :jsonb, array: true, default: [], null: false + add_column :procedure_presentations, :a_suivre_filters, :jsonb, array: true, default: [], null: false + add_column :procedure_presentations, :archives_filters, :jsonb, array: true, default: [], null: false + add_column :procedure_presentations, :expirant_filters, :jsonb, array: true, default: [], null: false + add_column :procedure_presentations, :supprimes_filters, :jsonb, array: true, default: [], null: false + add_column :procedure_presentations, :supprimes_recemment_filters, :jsonb, array: true, default: [], null: false + add_column :procedure_presentations, :sorted_column, :jsonb + end +end diff --git a/db/schema.rb b/db/schema.rb index 6998464ea..a628a89ea 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -866,11 +866,21 @@ ActiveRecord::Schema[7.0].define(version: 2024_09_23_125619) do end create_table "procedure_presentations", id: :serial, force: :cascade do |t| + t.jsonb "a_suivre_filters", default: [], null: false, array: true + t.jsonb "archives_filters", default: [], null: false, array: true t.integer "assign_to_id" t.datetime "created_at", precision: nil + t.jsonb "displayed_columns", default: [], null: false, array: true t.jsonb "displayed_fields", default: [{"label"=>"Demandeur", "table"=>"user", "column"=>"email"}], null: false + t.jsonb "expirant_filters", default: [], null: false, array: true t.jsonb "filters", default: {"tous"=>[], "suivis"=>[], "traites"=>[], "a-suivre"=>[], "archives"=>[], "expirant"=>[], "supprimes"=>[]}, null: false t.jsonb "sort", default: {"order"=>"desc", "table"=>"notifications", "column"=>"notifications"}, null: false + t.jsonb "sorted_column" + t.jsonb "suivis_filters", default: [], null: false, array: true + t.jsonb "supprimes_filters", default: [], null: false, array: true + t.jsonb "supprimes_recemment_filters", default: [], null: false, array: true + t.jsonb "tous_filters", default: [], null: false, array: true + t.jsonb "traites_filters", default: [], null: false, array: true t.datetime "updated_at", precision: nil t.index ["assign_to_id"], name: "index_procedure_presentations_on_assign_to_id", unique: true end From 0abee083295bc4c61be915ced19e3548121dc3ec Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Mon, 7 Oct 2024 18:10:08 +0200 Subject: [PATCH 07/13] add filters for --- app/models/procedure_presentation.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/models/procedure_presentation.rb b/app/models/procedure_presentation.rb index 5939f68cf..a14ad5faf 100644 --- a/app/models/procedure_presentation.rb +++ b/app/models/procedure_presentation.rb @@ -40,6 +40,12 @@ class ProcedurePresentation < ApplicationRecord attribute :expirant_filters, :jsonb, array: true attribute :archives_filters, :jsonb, array: true + def filters_for(statut) + send(filters_name_for(statut)) + end + + def filters_name_for(statut) = statut.tr('-', '_').then { "#{_1}_filters" } + def displayed_fields_for_headers [ Column.new(procedure_id: procedure.id, table: 'self', column: 'id', classname: 'number-col'), From a7ebe235040f15d82c510424201fb3515af749f4 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Mon, 7 Oct 2024 15:22:27 +0200 Subject: [PATCH 08/13] migrate procedure_presentation to column --- ...ate_procedure_presentation_to_columns.rake | 49 +++++++++++++++ ...edure_presentation_to_columns.rake_spec.rb | 60 +++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 lib/tasks/deployment/20240920130741_migrate_procedure_presentation_to_columns.rake create mode 100644 spec/lib/tasks/deployment/20240920130741_migrate_procedure_presentation_to_columns.rake_spec.rb diff --git a/lib/tasks/deployment/20240920130741_migrate_procedure_presentation_to_columns.rake b/lib/tasks/deployment/20240920130741_migrate_procedure_presentation_to_columns.rake new file mode 100644 index 000000000..56236afe1 --- /dev/null +++ b/lib/tasks/deployment/20240920130741_migrate_procedure_presentation_to_columns.rake @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +namespace :after_party do + desc 'Deployment task: migrate_procedure_presentation_to_columns' + task migrate_procedure_presentation_to_columns: :environment do + total = ProcedurePresentation.count + + progress = ProgressReport.new(total) + + ProcedurePresentation.find_each do |presentation| + procedure_id = presentation.procedure.id + + presentation.displayed_columns = presentation.displayed_fields + .filter(&:present?) + .map { Column.new(**_1.deep_symbolize_keys.merge(procedure_id:)) } + .map(&:h_id) + + sort = presentation.sort + + presentation.sorted_column = { + 'order' => sort['order'], + 'id' => make_id(procedure_id, sort['table'], sort['column']) + } + + presentation.filters.each do |key, filters| + raw_columns = filters.map do + { + id: make_id(procedure_id, _1['table'], _1['column']), + filter: _1['value'] + } + end + + presentation.send("#{presentation.filters_name_for(key)}=", raw_columns) + end + + presentation.save!(validate: false) + progress.inc + end + + AfterParty::TaskRecord + .create version: AfterParty::TaskRecorder.new(__FILE__).timestamp + end + + private + + def make_id(procedure_id, table, column) + { procedure_id:, column_id: "#{table}/#{column}" } + end +end diff --git a/spec/lib/tasks/deployment/20240920130741_migrate_procedure_presentation_to_columns.rake_spec.rb b/spec/lib/tasks/deployment/20240920130741_migrate_procedure_presentation_to_columns.rake_spec.rb new file mode 100644 index 000000000..6545cf027 --- /dev/null +++ b/spec/lib/tasks/deployment/20240920130741_migrate_procedure_presentation_to_columns.rake_spec.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +describe '20240920130741_migrate_procedure_presentation_to_columns.rake' do + let(:rake_task) { Rake::Task['after_party:migrate_procedure_presentation_to_columns'] } + + let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :text }]) } + let(:instructeur) { create(:instructeur) } + let(:assign_to) { create(:assign_to, procedure: procedure, instructeur: instructeur) } + let(:stable_id) { procedure.active_revision.types_de_champ.first.stable_id } + let!(:procedure_presentation) do + displayed_fields = [ + { "table" => "etablissement", "column" => "entreprise_raison_sociale" }, + { "table" => "type_de_champ", "column" => stable_id.to_s } + ] + + sort = { "order" => "desc", "table" => "self", "column" => "en_construction_at" } + + filters = { + "tous" => [], + "suivis" => [], + "traites" => [{ "label" => "Libellé NAF", "table" => "etablissement", "value" => "Administration publique générale", "column" => "libelle_naf", "value_column" => "value" }], + "a-suivre" => [], + "archives" => [], + "expirant" => [], + "supprimes" => [], + "supprimes_recemment" => [] + } + + create(:procedure_presentation, assign_to:, displayed_fields:, filters:, sort:) + end + + before do + rake_task.invoke + + procedure_presentation.reload + end + + it 'populates the columns' do + procedure_id = procedure.id + + expect(procedure_presentation.displayed_columns).to eq([ + { "procedure_id" => procedure_id, "column_id" => "etablissement/entreprise_raison_sociale" }, + { "procedure_id" => procedure_id, "column_id" => "type_de_champ/#{stable_id}" } + ]) + + order, column_id = procedure_presentation + .sorted_column + .then { |sorted| [sorted['order'], sorted['id']] } + + expect(order).to eq('desc') + expect(column_id).to eq("procedure_id" => procedure_id, "column_id" => "self/en_construction_at") + + expect(procedure_presentation.tous_filters).to eq([]) + + traites = procedure_presentation.traites_filters + .map { [_1['id'], _1['filter']] } + + expect(traites).to eq([[{ "column_id" => "etablissement/libelle_naf", "procedure_id" => procedure_id }, "Administration publique générale"]]) + end +end From 98c2b7e954c21a27f0cd09e91cdc44ab25f9da9c Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Mon, 7 Oct 2024 22:02:43 +0200 Subject: [PATCH 09/13] update_sort double write --- app/models/procedure_presentation.rb | 17 ++++++++++++----- spec/models/procedure_presentation_spec.rb | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/app/models/procedure_presentation.rb b/app/models/procedure_presentation.rb index a14ad5faf..59b7470c6 100644 --- a/app/models/procedure_presentation.rb +++ b/app/models/procedure_presentation.rb @@ -147,12 +147,19 @@ class ProcedurePresentation < ApplicationRecord def update_sort(column_id, order) h_id = JSON.parse(column_id, symbolize_names: true) column = procedure.find_column(h_id:) + order = order.presence || opposite_order_for(column.table, column.column) - update!(sort: { - TABLE => column.table, - COLUMN => column.column, - ORDER => order.presence || opposite_order_for(column.table, column.column) - }) + update!( + sort: { + TABLE => column.table, + COLUMN => column.column, + ORDER => order + }, + sorted_column: { + order:, + id: h_id + } + ) end def opposite_order_for(table, column) diff --git a/spec/models/procedure_presentation_spec.rb b/spec/models/procedure_presentation_spec.rb index 3197c2c19..87892f1aa 100644 --- a/spec/models/procedure_presentation_spec.rb +++ b/spec/models/procedure_presentation_spec.rb @@ -943,4 +943,22 @@ describe ProcedurePresentation do end end end + + describe '#update_sort' do + let(:procedure_presentation) { create(:procedure_presentation, assign_to:) } + + subject do + column_id = procedure.find_column(label: 'En construction le').id + procedure_presentation.update_sort(column_id, 'asc') + end + + it 'should update sort and order' do + expect(procedure_presentation.sorted_column).to be_nil + + subject + + expect(procedure_presentation.sorted_column['id']).to eq("column_id" => "self/en_construction_at", "procedure_id" => procedure.id) + expect(procedure_presentation.sorted_column['order']).to eq('asc') + end + end end From 5f6d8e93ca1053e34ba84f74cb0539aea87d9c32 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Mon, 7 Oct 2024 22:04:44 +0200 Subject: [PATCH 10/13] update_display double write --- app/models/procedure.rb | 8 ------ app/models/procedure_presentation.rb | 8 ++++-- spec/models/procedure_presentation_spec.rb | 29 ++++++++++++++++++++++ spec/models/procedure_spec.rb | 4 --- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/app/models/procedure.rb b/app/models/procedure.rb index 168c486ec..10377d4ff 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -613,14 +613,6 @@ class Procedure < ApplicationRecord end end - def self.default_sort - { - 'table' => 'self', - 'column' => 'id', - 'order' => 'desc' - } - end - def whitelist! touch(:whitelisted_at) end diff --git a/app/models/procedure_presentation.rb b/app/models/procedure_presentation.rb index 59b7470c6..1d2134e9c 100644 --- a/app/models/procedure_presentation.rb +++ b/app/models/procedure_presentation.rb @@ -137,10 +137,14 @@ class ProcedurePresentation < ApplicationRecord h_ids = Array.wrap(column_ids).map { |id| JSON.parse(id, symbolize_names: true) } columns = h_ids.map { |h_id| procedure.find_column(h_id:) } - update!(displayed_fields: columns) + update!( + displayed_fields: columns, + displayed_columns: columns.map(&:h_id) + ) if !sort_to_column_id(sort).in?(column_ids) - update!(sort: Procedure.default_sort) + default_column_id = procedure.dossier_id_column.id + update_sort(default_column_id, "desc") end end diff --git a/spec/models/procedure_presentation_spec.rb b/spec/models/procedure_presentation_spec.rb index 87892f1aa..5754b80da 100644 --- a/spec/models/procedure_presentation_spec.rb +++ b/spec/models/procedure_presentation_spec.rb @@ -944,6 +944,35 @@ describe ProcedurePresentation do end end + describe '#update_displayed_fields' do + let(:procedure_presentation) do + create(:procedure_presentation, assign_to:).tap do |pp| + pp.update_sort(procedure.find_column(label: 'Demandeur').id, 'desc') + end + end + + subject do + procedure_presentation.update_displayed_fields([ + procedure.find_column(label: 'En construction le').id, + procedure.find_column(label: 'Mis à jour le').id + ]) + end + + it 'should update displayed_fields' do + expect(procedure_presentation.displayed_columns).to eq([]) + + subject + + expect(procedure_presentation.displayed_columns).to eq([ + { "column_id" => "self/en_construction_at", "procedure_id" => procedure.id }, + { "column_id" => "self/updated_at", "procedure_id" => procedure.id } + ]) + + expect(procedure_presentation.sorted_column['id']).to eq("column_id" => "self/id", "procedure_id" => procedure.id) + expect(procedure_presentation.sorted_column['order']).to eq('desc') + end + end + describe '#update_sort' do let(:procedure_presentation) { create(:procedure_presentation, assign_to:) } diff --git a/spec/models/procedure_spec.rb b/spec/models/procedure_spec.rb index cda2f8330..4f580d727 100644 --- a/spec/models/procedure_spec.rb +++ b/spec/models/procedure_spec.rb @@ -1450,10 +1450,6 @@ describe Procedure do end end - describe ".default_sort" do - it { expect(Procedure.default_sort).to eq({ "table" => "self", "column" => "id", "order" => "desc" }) } - end - describe "#organisation_name" do subject { procedure.organisation_name } context 'when the procedure has a service (and no organization)' do From 870d67e84436b12c820cab56953de3d49737c4ce Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Mon, 7 Oct 2024 22:05:31 +0200 Subject: [PATCH 11/13] add_filter double write --- app/models/procedure_presentation.rb | 1 + spec/models/procedure_presentation_spec.rb | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/app/models/procedure_presentation.rb b/app/models/procedure_presentation.rb index 1d2134e9c..d606554c8 100644 --- a/app/models/procedure_presentation.rb +++ b/app/models/procedure_presentation.rb @@ -117,6 +117,7 @@ class ProcedurePresentation < ApplicationRecord 'value' => value } + filters_for(statut) << { id: h_id, filter: value } update(filters: updated_filters) end end diff --git a/spec/models/procedure_presentation_spec.rb b/spec/models/procedure_presentation_spec.rb index 5754b80da..f02e8b97c 100644 --- a/spec/models/procedure_presentation_spec.rb +++ b/spec/models/procedure_presentation_spec.rb @@ -862,6 +862,10 @@ describe ProcedurePresentation do { "label" => first_type_de_champ.libelle, "table" => "type_de_champ", "column" => first_type_de_champ_id, "value" => "true", "value_column" => "value" } ] }) + + suivis = procedure_presentation.suivis_filters.map { [_1['id'], _1['filter']] } + + expect(suivis).to eq([[{ "column_id" => "type_de_champ/#{first_type_de_champ_id}", "procedure_id" => procedure.id }, "true"]]) end end From a418cf6632e6e7ff4aefd097ee7d4312afdfe054 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Mon, 7 Oct 2024 21:59:49 +0200 Subject: [PATCH 12/13] remove_filter double_write --- app/models/procedure_presentation.rb | 3 +++ spec/models/procedure_presentation_spec.rb | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/app/models/procedure_presentation.rb b/app/models/procedure_presentation.rb index d606554c8..6607f8adc 100644 --- a/app/models/procedure_presentation.rb +++ b/app/models/procedure_presentation.rb @@ -131,6 +131,9 @@ class ProcedurePresentation < ApplicationRecord filter.values_at(TABLE, COLUMN, 'value') == [column.table, column.column, value] end + collection = filters_for(statut) + collection.delete(collection.find { sym_h = _1.deep_symbolize_keys; sym_h[:id] == h_id && sym_h[:filter] == value }) + update!(filters: updated_filters) end diff --git a/spec/models/procedure_presentation_spec.rb b/spec/models/procedure_presentation_spec.rb index f02e8b97c..6fbdbf9c2 100644 --- a/spec/models/procedure_presentation_spec.rb +++ b/spec/models/procedure_presentation_spec.rb @@ -901,6 +901,26 @@ describe ProcedurePresentation do end end + describe "#remove_filter" do + let(:filters) { { "suivis" => [] } } + let(:email_column_id) { procedure.find_column(label: 'Demandeur').id } + + before do + procedure_presentation.add_filter("suivis", email_column_id, "a@a.com") + end + + it 'should remove filter' do + expect(procedure_presentation.filters).to eq({ "suivis" => [{ "column" => "email", "label" => "Demandeur", "table" => "user", "value" => "a@a.com", "value_column" => "value" }] }) + expect(procedure_presentation.suivis_filters).to eq([{ "filter" => "a@a.com", "id" => { "column_id" => "user/email", "procedure_id" => procedure.id } }]) + + procedure_presentation.remove_filter("suivis", email_column_id, "a@a.com") + procedure_presentation.reload + + expect(procedure_presentation.filters).to eq({ "suivis" => [] }) + expect(procedure_presentation.suivis_filters).to eq([]) + end + end + describe '#filtered_sorted_ids' do let(:procedure_presentation) { create(:procedure_presentation, assign_to:) } let(:dossier_1) { create(:dossier) } From d5a722c1439179abfef554b704b9f4909b33a567 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Wed, 25 Sep 2024 17:55:11 +0200 Subject: [PATCH 13/13] weird frozen_string bug --- app/models/types_de_champ/yes_no_type_de_champ.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/models/types_de_champ/yes_no_type_de_champ.rb b/app/models/types_de_champ/yes_no_type_de_champ.rb index 5c1870195..4e500a6fd 100644 --- a/app/models/types_de_champ/yes_no_type_de_champ.rb +++ b/app/models/types_de_champ/yes_no_type_de_champ.rb @@ -12,13 +12,13 @@ class TypesDeChamp::YesNoTypeDeChamp < TypesDeChamp::CheckboxTypeDeChamp end def human_to_filter(human_value) - human_value.downcase! - if human_value == "oui" + downcased = human_value.downcase + if downcased == "oui" "true" - elsif human_value == "non" + elsif downcased == "non" "false" else - human_value + downcased end end