From 0be93d84eef5af8a6ba5d2d6b8a3ea95330f441a Mon Sep 17 00:00:00 2001 From: Colin Darie Date: Tue, 3 Dec 2024 14:58:50 +0100 Subject: [PATCH 01/13] chore(gitignore): + .zed --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e22760720..7b059a5af 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ storage/ yarn-debug.log* .yarn-integrity /.vscode +/.zed /.idea /public/assets /spec/support/spec_config.local.rb From 45efac16f29e5949dd7fbecf1a58ddab5bbc402b Mon Sep 17 00:00:00 2001 From: Colin Darie Date: Wed, 20 Nov 2024 15:57:42 +0100 Subject: [PATCH 02/13] chore(rubocop): disable Style/WordArray for %w[] transition --- .rubocop.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index c806ff7c1..a2214f9a3 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1497,8 +1497,7 @@ Style/WhileUntilModifier: Enabled: false Style/WordArray: - Enabled: true - EnforcedStyle: brackets + Enabled: false Style/YodaCondition: Enabled: true From 89e202740643288e21273cb19108eb1dc8c6ec8e Mon Sep 17 00:00:00 2001 From: Colin Darie Date: Wed, 20 Nov 2024 15:58:27 +0100 Subject: [PATCH 03/13] style(filters): dynamic & larger width because we now have long column names --- app/assets/stylesheets/buttons.scss | 6 +++++- .../column_filter_component.html.haml | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/buttons.scss b/app/assets/stylesheets/buttons.scss index 1293eb494..53fe0130c 100644 --- a/app/assets/stylesheets/buttons.scss +++ b/app/assets/stylesheets/buttons.scss @@ -374,7 +374,11 @@ ul.dropdown-items { padding: 2 * $default-spacer; &.large { - width: 340px; + width: 90vw; + + @media (min-width: 62em) { + width: 40vw; + } } ul { diff --git a/app/components/instructeurs/column_filter_component/column_filter_component.html.haml b/app/components/instructeurs/column_filter_component/column_filter_component.html.haml index c8b94293f..0558fce58 100644 --- a/app/components/instructeurs/column_filter_component/column_filter_component.html.haml +++ b/app/components/instructeurs/column_filter_component/column_filter_component.html.haml @@ -5,7 +5,7 @@ = current_filter_tags .fr-select-group - = label_tag :column, t('.column'), class: 'fr-label fr-m-0', id: 'instructeur-filter-combo-label', for: 'search-filter' + = label_tag :column, t('.column'), class: 'fr-label fr-mb-1w', id: 'instructeur-filter-combo-label', for: 'search-filter' %react-fragment = render ReactComponent.new "ComboBox/SingleComboBox", **filter_react_props From 5226f67cb3e7ca27e23c16a9a4d7db2c08df76e4 Mon Sep 17 00:00:00 2001 From: Colin Darie Date: Wed, 20 Nov 2024 16:00:36 +0100 Subject: [PATCH 04/13] fix(locale): remove duplicate entreprise keys --- config/locales/models/procedure_presentation/en.yml | 4 ---- config/locales/models/procedure_presentation/fr.yml | 4 ---- 2 files changed, 8 deletions(-) diff --git a/config/locales/models/procedure_presentation/en.yml b/config/locales/models/procedure_presentation/en.yml index 95ff9d0ff..71866feed 100644 --- a/config/locales/models/procedure_presentation/en.yml +++ b/config/locales/models/procedure_presentation/en.yml @@ -47,10 +47,6 @@ en: question_answer: Opinion yes/no etablissement: entreprise_etat_administratif: 'Entreprise état administratif' - entreprise_forme_juridique: Forme juridique - entreprise_nom_commercial: Commercial name - entreprise_raison_sociale: Raison sociale - entreprise_siret_siege_social: SIRET siège social entreprise_date_creation: Entreprise date de création siret: Établissement SIRET libelle_naf: Libellé NAF diff --git a/config/locales/models/procedure_presentation/fr.yml b/config/locales/models/procedure_presentation/fr.yml index a17cc75f8..cf8618233 100644 --- a/config/locales/models/procedure_presentation/fr.yml +++ b/config/locales/models/procedure_presentation/fr.yml @@ -51,10 +51,6 @@ fr: question_answer: Avis oui/non etablissement: entreprise_etat_administratif: 'Entreprise état administratif' - entreprise_forme_juridique: Forme juridique - entreprise_nom_commercial: Nom commercial - entreprise_raison_sociale: Raison sociale - entreprise_siret_siege_social: SIRET siège social entreprise_date_creation: Entreprise date de création siret: Établissement SIRET libelle_naf: Libellé NAF From 90a8888adeb2805ac939411844605b0535e2f9b9 Mon Sep 17 00:00:00 2001 From: Colin Darie Date: Wed, 20 Nov 2024 16:35:42 +0100 Subject: [PATCH 05/13] feat(champ siret): etablissement columns filterable & displayable --- app/models/column.rb | 1 + app/models/columns/json_path_column.rb | 3 +- app/models/etablissement.rb | 11 +++++++ .../types_de_champ/siret_type_de_champ.rb | 23 +++++++++++++- spec/factories/champ.rb | 2 +- spec/models/columns/champ_column_spec.rb | 16 +++++++++- spec/models/export_template_tabular_spec.rb | 13 ++++++-- .../siret_type_de_champ_spec.rb | 30 +++++++++++++++++++ 8 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 spec/models/types_de_champ/siret_type_de_champ_spec.rb diff --git a/app/models/column.rb b/app/models/column.rb index f41ce3cdb..aea80775f 100644 --- a/app/models/column.rb +++ b/app/models/column.rb @@ -50,6 +50,7 @@ class Column def dossier_column? = false def champ_column? = false + def filterable? = filterable def label_for_value(value) if options_for_select.present? diff --git a/app/models/columns/json_path_column.rb b/app/models/columns/json_path_column.rb index a60d5d872..9227a5e3d 100644 --- a/app/models/columns/json_path_column.rb +++ b/app/models/columns/json_path_column.rb @@ -3,7 +3,7 @@ class Columns::JSONPathColumn < Columns::ChampColumn attr_reader :jsonpath - def initialize(procedure_id:, label:, stable_id:, tdc_type:, jsonpath:, options_for_select: [], displayable:, type: :text) + def initialize(procedure_id:, label:, stable_id:, tdc_type:, jsonpath:, options_for_select: [], displayable:, filterable: true, type: :text) @jsonpath = quote_string(jsonpath) super( @@ -12,6 +12,7 @@ class Columns::JSONPathColumn < Columns::ChampColumn stable_id:, tdc_type:, displayable:, + filterable:, type:, options_for_select: ) diff --git a/app/models/etablissement.rb b/app/models/etablissement.rb index ba5232598..54e9c7cb7 100644 --- a/app/models/etablissement.rb +++ b/app/models/etablissement.rb @@ -21,6 +21,17 @@ class Etablissement < ApplicationRecord after_commit -> { dossier&.index_search_terms_later } + # See https://github.com/demarches-simplifiees/demarches-simplifiees.fr/pull/10591#discussion_r1819399688 + # SIRET is already exposed as base column. + DISPLAYABLE_COLUMNS = { + "entreprise_raison_sociale" => { type: :text }, + "entreprise_siren" => { type: :text }, + "entreprise_nom_commercial" => { type: :text }, + "entreprise_forme_juridique" => { type: :text }, + "entreprise_date_creation" => { type: :date, filterable: false }, + "libelle_naf" => { type: :text } + }.freeze + def entreprise_raison_sociale read_attribute(:entreprise_raison_sociale).presence || raison_sociale_for_ei end diff --git a/app/models/types_de_champ/siret_type_de_champ.rb b/app/models/types_de_champ/siret_type_de_champ.rb index 5786a071f..c0d6fe6ef 100644 --- a/app/models/types_de_champ/siret_type_de_champ.rb +++ b/app/models/types_de_champ/siret_type_de_champ.rb @@ -10,6 +10,27 @@ class TypesDeChamp::SiretTypeDeChamp < TypesDeChamp::TypeDeChampBase def champ_blank_or_invalid?(champ) = Siret.new(siret: champ.value).invalid? def columns(procedure:, displayable: true, prefix: nil) - super.concat(addressable_columns(procedure:, displayable:, prefix:)) + super + .concat(etablissement_columns(procedure:, displayable:, prefix:)) + .concat(addressable_columns(procedure:, displayable:, prefix:)) + end + + private + + def etablissement_columns(procedure:, displayable:, prefix:) + i18n_scope = [:activerecord, :attributes, :procedure_presentation, :fields, :etablissement] + + Etablissement::DISPLAYABLE_COLUMNS.map do |(column, attributes)| + Columns::JSONPathColumn.new( + procedure_id: procedure.id, + stable_id:, + tdc_type: type_champ, + label: [prefix, libelle, I18n.t(column, scope: i18n_scope)].compact.join(' – '), + type: attributes[:type], + jsonpath: "$.#{column}", + displayable: true, + filterable: attributes.fetch(:filterable, true) + ) + end end end diff --git a/spec/factories/champ.rb b/spec/factories/champ.rb index b84c93379..ed0fad2a2 100644 --- a/spec/factories/champ.rb +++ b/spec/factories/champ.rb @@ -165,7 +165,7 @@ FactoryBot.define do factory :champ_do_not_use_siret, class: 'Champs::SiretChamp' do association :etablissement, factory: [:etablissement] value { '44011762001530' } - value_json { AddressProxy::ADDRESS_PARTS.index_by(&:itself) } + value_json { etablissement.champ_value_json } end factory :champ_do_not_use_rna, class: 'Champs::RNAChamp' do diff --git a/spec/models/columns/champ_column_spec.rb b/spec/models/columns/champ_column_spec.rb index 4f4ce0b0e..a1bf8b8b9 100644 --- a/spec/models/columns/champ_column_spec.rb +++ b/spec/models/columns/champ_column_spec.rb @@ -19,7 +19,21 @@ describe Columns::ChampColumn do expect_type_de_champ_values('pays', eq(['France'])) expect_type_de_champ_values('epci', eq([nil])) expect_type_de_champ_values('iban', eq([nil])) - expect_type_de_champ_values('siret', eq(["44011762001530", "postal_code", "city_name", "departement_code", "region_name"])) + expect_type_de_champ_values('siret', match_array( + [ + "44011762001530", + "SA à conseil d'administration (s.a.i.)", + "440117620", + "GRTGAZ", + "GRTGAZ", + "1990-04-24", + "Transports par conduites", + "92270", + "Bois-Colombes", + "92", + "Île-de-France" + ] + )) expect_type_de_champ_values('text', eq(['text'])) expect_type_de_champ_values('textarea', eq(['textarea'])) expect_type_de_champ_values('number', eq(['42'])) diff --git a/spec/models/export_template_tabular_spec.rb b/spec/models/export_template_tabular_spec.rb index 4751ffdd2..bcaf35f76 100644 --- a/spec/models/export_template_tabular_spec.rb +++ b/spec/models/export_template_tabular_spec.rb @@ -123,11 +123,20 @@ describe ExportTemplate do context 'when procedure has a TypeDeChamp::Siret' do let(:types_de_champ_public) do [ - { type: :siret, libelle: 'siret', stable_id: 20 } + { type: :siret, libelle: 'SIRET', stable_id: 20 } ] end it 'is able to resolve stable_id' do - expect(export_template.columns_for_stable_id(20).size).to eq(5) + columns = export_template.columns_for_stable_id(20) + + expect(columns.find { _1.libelle == "SIRET" }).to be_present + + %w[ + $.entreprise_nom_commercial + $.entreprise_raison_sociale + ].each do |jsonpath| + expect(columns.find { _1.column.respond_to?(:jsonpath) && _1.column.jsonpath == jsonpath }).to be_present + end end end context 'when procedure has a TypeDeChamp::Text' do diff --git a/spec/models/types_de_champ/siret_type_de_champ_spec.rb b/spec/models/types_de_champ/siret_type_de_champ_spec.rb new file mode 100644 index 000000000..1188c1762 --- /dev/null +++ b/spec/models/types_de_champ/siret_type_de_champ_spec.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +describe TypesDeChamp::SiretTypeDeChamp do + let(:tdc_siret) { build(:type_de_champ_siret, libelle: 'Numéro SIRET') } + let(:procedure) { build(:procedure) } + + describe "#columns" do + subject(:columns) { tdc_siret.columns(procedure: procedure) } + + it "includes required jsonpaths" do + expected_paths = [ + "$.entreprise_raison_sociale", + "$.entreprise_siren" + ] + + json_columns = columns.filter { _1.is_a?(Columns::JSONPathColumn) } + expect(json_columns.map(&:jsonpath)).to include(*expected_paths) + end + + it "includes address columns" do + address_columns = columns.filter { _1.is_a?(Columns::JSONPathColumn) && _1.jsonpath.match?(/adresse|postal_code/) } + + expect(address_columns).not_to be_empty + end + + it "does not include jsonpath SIRET column" do + expect(columns.find { |c| c.is_a?(Columns::JSONPathColumn) && c.jsonpath == "$.siret" }).to be_nil + end + end +end From b71d60dff94c6a1b0f95cfe6a613d8e8966f118b Mon Sep 17 00:00:00 2001 From: Colin Darie Date: Wed, 4 Dec 2024 12:07:12 +0100 Subject: [PATCH 06/13] test(siret): fix after champ factory have been changed to real values --- .../maintenance/populate_siret_value_json_task_spec.rb | 4 ++++ .../dossiers/_normalized_address.html.haml_spec.rb | 9 ++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/spec/tasks/maintenance/populate_siret_value_json_task_spec.rb b/spec/tasks/maintenance/populate_siret_value_json_task_spec.rb index f5e1a29a6..2bb454fe4 100644 --- a/spec/tasks/maintenance/populate_siret_value_json_task_spec.rb +++ b/spec/tasks/maintenance/populate_siret_value_json_task_spec.rb @@ -10,6 +10,10 @@ module Maintenance let(:element) { dossier.champs.first } subject(:process) { described_class.process(element) } + before do + element.update!(value_json: nil) + end + it 'updates value_json' do expect { subject }.to change { element.reload.value_json } .from(anything) diff --git a/spec/views/shared/dossiers/_normalized_address.html.haml_spec.rb b/spec/views/shared/dossiers/_normalized_address.html.haml_spec.rb index 9e1a722e3..37f5cbfa9 100644 --- a/spec/views/shared/dossiers/_normalized_address.html.haml_spec.rb +++ b/spec/views/shared/dossiers/_normalized_address.html.haml_spec.rb @@ -9,9 +9,12 @@ describe 'shared/dossiers/normalized_address', type: :view do let(:address) { AddressProxy.new(dossier.champs.first) } it 'render address' do - AddressProxy::ADDRESS_PARTS.each do |address_part| - expect(subject).to have_text(address_part) - end + expect(subject).to have_text("6 RUE RAOUL NORDLING") + expect(subject).to have_text("Bois-Colombes") + expect(subject).to have_text("92270") + expect(subject).to have_text("92009") + expect(subject).to have_text("Hauts-de-Seine – 92") + expect(subject).to have_text("Île-de-France – 11") end end From 985cf32752dddbc6363b36040f8d32ab9da4d205 Mon Sep 17 00:00:00 2001 From: Colin Darie Date: Wed, 20 Nov 2024 16:36:25 +0100 Subject: [PATCH 07/13] feat(champ siret): improve default base SIRET column wording --- app/models/types_de_champ/type_de_champ_base.rb | 7 ++++++- spec/models/types_de_champ/siret_type_de_champ_spec.rb | 10 ++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) 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 86ab644f5..4df247271 100644 --- a/app/models/types_de_champ/type_de_champ_base.rb +++ b/app/models/types_de_champ/type_de_champ_base.rb @@ -116,7 +116,12 @@ class TypesDeChamp::TypeDeChampBase private def libelle_with_prefix(prefix) - [prefix, libelle].compact.join(' – ') + # SIRET needs to be explicit in listings for better UI readability + if type_champ == "siret" && !libelle.upcase.include?("SIRET") + [prefix, libelle, "SIRET"].compact.join(' – ') + else + [prefix, libelle].compact.join(' – ') + end end def paths diff --git a/spec/models/types_de_champ/siret_type_de_champ_spec.rb b/spec/models/types_de_champ/siret_type_de_champ_spec.rb index 1188c1762..3dc47d20d 100644 --- a/spec/models/types_de_champ/siret_type_de_champ_spec.rb +++ b/spec/models/types_de_champ/siret_type_de_champ_spec.rb @@ -7,6 +7,16 @@ describe TypesDeChamp::SiretTypeDeChamp do describe "#columns" do subject(:columns) { tdc_siret.columns(procedure: procedure) } + it "returns base column without duplicating SIRET when already in libelle" do + expect(columns[0].label).to eq("Numéro SIRET") + end + + it "returns base column with SIRET when libelle doesn't contain SIRET" do + tdc_siret.update(libelle: "Identification de l'entreprise") + + expect(columns[0].label).to eq("Identification de l'entreprise – SIRET") + end + it "includes required jsonpaths" do expected_paths = [ "$.entreprise_raison_sociale", From 2e873254feb62c8ca79463a6df84e361be1d4339 Mon Sep 17 00:00:00 2001 From: Colin Darie Date: Wed, 20 Nov 2024 16:38:08 +0100 Subject: [PATCH 08/13] refactor(columns): normalize (upcase first) address columns wording --- app/models/concerns/addressable_column_concern.rb | 8 ++++---- spec/models/concerns/columns_concern_spec.rb | 4 ++-- spec/services/dossier_filter_service_spec.rb | 6 +++--- spec/services/dossier_projection_service_spec.rb | 4 ++-- spec/system/instructeurs/procedure_filters_spec.rb | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/models/concerns/addressable_column_concern.rb b/app/models/concerns/addressable_column_concern.rb index b3a6edf73..d96300a67 100644 --- a/app/models/concerns/addressable_column_concern.rb +++ b/app/models/concerns/addressable_column_concern.rb @@ -6,10 +6,10 @@ module AddressableColumnConcern included do def addressable_columns(procedure:, displayable: true, prefix: nil) [ - ["code postal (5 chiffres)", '$.postal_code', :text, []], - ["commune", '$.city_name', :text, []], - ["département", '$.departement_code', :enum, APIGeoService.departement_options], - ["region", '$.region_name', :enum, APIGeoService.region_options] + ["Code postal (5 chiffres)", '$.postal_code', :text, []], + ["Commune", '$.city_name', :text, []], + ["Département", '$.departement_code', :enum, APIGeoService.departement_options], + ["Région", '$.region_name', :enum, APIGeoService.region_options] ].map do |(label, jsonpath, type, options_for_select)| Columns::JSONPathColumn.new( procedure_id: procedure.id, diff --git a/spec/models/concerns/columns_concern_spec.rb b/spec/models/concerns/columns_concern_spec.rb index 3cc07308b..4b21061fa 100644 --- a/spec/models/concerns/columns_concern_spec.rb +++ b/spec/models/concerns/columns_concern_spec.rb @@ -99,9 +99,9 @@ describe ColumnsConcern do end context 'with rna' do - let(:types_de_champ_public) { [{ type: :rna, libelle: 'rna' }] } + let(:types_de_champ_public) { [{ type: :rna, libelle: 'RNA' }] } let(:types_de_champ_private) { [] } - it { expect(subject.map(&:label)).to include('rna – commune') } + it { expect(subject.map(&:label)).to include('RNA – Commune') } end context 'with linked drop down list' do diff --git a/spec/services/dossier_filter_service_spec.rb b/spec/services/dossier_filter_service_spec.rb index 7a85e02ac..28d16a283 100644 --- a/spec/services/dossier_filter_service_spec.rb +++ b/spec/services/dossier_filter_service_spec.rb @@ -572,7 +572,7 @@ describe DossierFilterService do context "when searching by postal_code (text)" do let(:value) { "60580" } - let(:filter) { ["rna – code postal (5 chiffres)", value] } + let(:filter) { ["rna – Code postal (5 chiffres)", value] } before do kept_dossier.project_champs_public.find { _1.stable_id == 1 }.update(value_json: { "postal_code" => value }) @@ -589,7 +589,7 @@ describe DossierFilterService do context "when searching by departement_code (enum)" do let(:value) { "99" } - let(:filter) { ["rna – département", value] } + let(:filter) { ["rna – Département", value] } before do kept_dossier.project_champs_public.find { _1.stable_id == 1 }.update(value_json: { "departement_code" => value }) @@ -606,7 +606,7 @@ describe DossierFilterService do context "when searching by region_name" do let(:value) { "60" } - let(:filter) { ["rna – region", value] } + let(:filter) { ["rna – Région", value] } before do kept_dossier.project_champs_public.find { _1.stable_id == 1 }.update(value_json: { "region_name" => value }) diff --git a/spec/services/dossier_projection_service_spec.rb b/spec/services/dossier_projection_service_spec.rb index e55a72734..9029846d0 100644 --- a/spec/services/dossier_projection_service_spec.rb +++ b/spec/services/dossier_projection_service_spec.rb @@ -239,9 +239,9 @@ describe DossierProjectionService do end context 'for a json column' do - let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :siret, libelle: 'siret' }]) } + let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :siret, libelle: 'SIRET' }]) } let(:dossier) { create(:dossier, procedure:) } - let(:label) { "siret – département" } + let(:label) { "SIRET – Département" } before do dossier.project_champs_public.first.update(value_json: { 'departement_code': '38' }) diff --git a/spec/system/instructeurs/procedure_filters_spec.rb b/spec/system/instructeurs/procedure_filters_spec.rb index 2e3f54a0e..dac3aeaac 100644 --- a/spec/system/instructeurs/procedure_filters_spec.rb +++ b/spec/system/instructeurs/procedure_filters_spec.rb @@ -154,7 +154,7 @@ describe "procedure filters" do rna_champ.reload champ_select_value = "37 – Indre-et-Loire" - add_filter("#{rna_champ.libelle} – département", champ_select_value, type: :enum) + add_filter("#{rna_champ.libelle} – Département", champ_select_value, type: :enum) expect(page).to have_link(new_unfollow_dossier.id.to_s) end end From a4000459640c5f330a69bad532aef1cf02370016 Mon Sep 17 00:00:00 2001 From: Colin Darie Date: Fri, 22 Nov 2024 11:37:13 +0100 Subject: [PATCH 09/13] refactor(etablissement): update champ value json address from model --- app/jobs/api_entreprise/entreprise_job.rb | 1 + app/models/etablissement.rb | 10 +++++++ app/services/api_entreprise_service.rb | 10 ++----- .../populate_siret_value_json_task.rb | 2 +- spec/models/etablissement_spec.rb | 29 +++++++++++++++++++ 5 files changed, 43 insertions(+), 9 deletions(-) diff --git a/app/jobs/api_entreprise/entreprise_job.rb b/app/jobs/api_entreprise/entreprise_job.rb index 1fe7c37fa..403e9aaa7 100644 --- a/app/jobs/api_entreprise/entreprise_job.rb +++ b/app/jobs/api_entreprise/entreprise_job.rb @@ -5,5 +5,6 @@ class APIEntreprise::EntrepriseJob < APIEntreprise::Job find_etablissement(etablissement_id) etablissement_params = APIEntreprise::EntrepriseAdapter.new(etablissement.siret, procedure_id).to_params etablissement.update!(etablissement_params) + etablissement.update_champ_value_json! end end diff --git a/app/models/etablissement.rb b/app/models/etablissement.rb index 54e9c7cb7..d348ec530 100644 --- a/app/models/etablissement.rb +++ b/app/models/etablissement.rb @@ -204,6 +204,16 @@ class Etablissement < ApplicationRecord adresse.nil? # TOOD: maybe dedicated column or more robust way end + def update_champ_value_json! + return if champ.nil? + + champ.update!(value_json: champ_value_json) + end + + def champ_value_json + APIGeoService.parse_etablissement_address(self) + end + private def bilans_new_keys diff --git a/app/services/api_entreprise_service.rb b/app/services/api_entreprise_service.rb index f73ccbcb0..276efc3a7 100644 --- a/app/services/api_entreprise_service.rb +++ b/app/services/api_entreprise_service.rb @@ -22,10 +22,7 @@ class APIEntrepriseService etablissement = dossier_or_champ.build_etablissement(etablissement_params) etablissement.save! - - if dossier_or_champ.is_a?(Champ) - dossier_or_champ.update!(value_json: APIGeoService.parse_etablissement_address(etablissement)) - end + etablissement.update_champ_value_json! perform_later_fetch_jobs(etablissement, procedure_id, user_id) @@ -49,10 +46,7 @@ class APIEntrepriseService return nil if etablissement_params.empty? etablissement.update!(etablissement_params) - - if etablissement.champ.present? - etablissement.champ.update!(value_json: APIGeoService.parse_etablissement_address(etablissement)) - end + etablissement.update_champ_value_json! etablissement end diff --git a/app/tasks/maintenance/populate_siret_value_json_task.rb b/app/tasks/maintenance/populate_siret_value_json_task.rb index 3b43ebb73..78a5d8757 100644 --- a/app/tasks/maintenance/populate_siret_value_json_task.rb +++ b/app/tasks/maintenance/populate_siret_value_json_task.rb @@ -12,7 +12,7 @@ module Maintenance def process(champ) return if champ.etablissement.blank? - champ.update!(value_json: APIGeoService.parse_etablissement_address(champ.etablissement)) + champ.update!(value_json: champ.etablissement.champ_value_json) rescue ActiveRecord::RecordInvalid # noop, just a champ without dossier end diff --git a/spec/models/etablissement_spec.rb b/spec/models/etablissement_spec.rb index 58e122167..5cf5cb15a 100644 --- a/spec/models/etablissement_spec.rb +++ b/spec/models/etablissement_spec.rb @@ -130,6 +130,35 @@ describe Etablissement do end end + describe '#update_champ_value_json!' do + let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :siret }]) } + let(:dossier) { create(:dossier, procedure:) } + let(:etablissement) { create(:etablissement) } + let(:champ) { dossier.champs[0] } + let(:address_data) do + { + "street_number" => "6", + "street_name" => "RAOUL NORDLING", + "postal_code" => "92270", + "city_name" => "BOIS COLOMBES" + } + end + + before do + allow(APIGeoService).to receive(:parse_etablissement_address) + .with(etablissement) + .and_return(address_data.dup) + + etablissement.champ = champ + end + + it 'updates the associated champ value_json with geocoded address' do + etablissement.update_champ_value_json! + + expect(champ.reload.value_json).to eq(address_data) + end + end + private def csv_to_array_of_hash(lines) From f1d14bd6afc85090b8d03fb113726595b56a840c Mon Sep 17 00:00:00 2001 From: Colin Darie Date: Tue, 26 Nov 2024 18:19:19 +0100 Subject: [PATCH 10/13] feat(etablissement): save value json data for columns --- app/models/etablissement.rb | 7 ++++++- spec/models/etablissement_spec.rb | 12 ++++++++++-- .../populate_siret_value_json_task_spec.rb | 9 ++++++++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/app/models/etablissement.rb b/app/models/etablissement.rb index d348ec530..94160e2b1 100644 --- a/app/models/etablissement.rb +++ b/app/models/etablissement.rb @@ -211,7 +211,12 @@ class Etablissement < ApplicationRecord end def champ_value_json - APIGeoService.parse_etablissement_address(self) + address_data = APIGeoService.parse_etablissement_address(self) + + DISPLAYABLE_COLUMNS.keys.each_with_object(address_data) do |attr, hash| + value = public_send(attr) + hash[attr.to_sym] = value if value.present? + end end private diff --git a/spec/models/etablissement_spec.rb b/spec/models/etablissement_spec.rb index 5cf5cb15a..f46c2a93b 100644 --- a/spec/models/etablissement_spec.rb +++ b/spec/models/etablissement_spec.rb @@ -152,10 +152,18 @@ describe Etablissement do etablissement.champ = champ end - it 'updates the associated champ value_json with geocoded address' do + subject(:value_json) { etablissement.update_champ_value_json! + champ.reload.value_json + } - expect(champ.reload.value_json).to eq(address_data) + it 'updates the associated champ value_json with geocoded address' do + expect(value_json).to include(address_data.stringify_keys) + end + + it 'includes jsonpathables columns entreprise attributes' do + expect(value_json["entreprise_siren"]).to eq(etablissement.siren) + expect(value_json["entreprise_raison_sociale"]).to eq(etablissement.entreprise_raison_sociale) end end diff --git a/spec/tasks/maintenance/populate_siret_value_json_task_spec.rb b/spec/tasks/maintenance/populate_siret_value_json_task_spec.rb index 2bb454fe4..fbc2600b4 100644 --- a/spec/tasks/maintenance/populate_siret_value_json_task_spec.rb +++ b/spec/tasks/maintenance/populate_siret_value_json_task_spec.rb @@ -29,7 +29,14 @@ module Maintenance "departement_code" => "92", "department_code" => "92", "departement_name" => "Hauts-de-Seine", - "department_name" => "Hauts-de-Seine" + "department_name" => "Hauts-de-Seine", + + "entreprise_date_creation" => "1990-04-24", + "entreprise_forme_juridique" => "SA à conseil d'administration (s.a.i.)", + "entreprise_nom_commercial" => "GRTGAZ", + "entreprise_raison_sociale" => "GRTGAZ", + "entreprise_siren" => "440117620", + "libelle_naf" => "Transports par conduites" }) end end From 9cb547efcfea0fd5689bf83d48d67ca5c425de7e Mon Sep 17 00:00:00 2001 From: Colin Darie Date: Mon, 2 Dec 2024 14:24:35 +0100 Subject: [PATCH 11/13] refactor: rename naf => code_naf --- app/models/concerns/columns_concern.rb | 2 +- app/models/etablissement.rb | 2 ++ app/views/shared/dossiers/_identite_entreprise.html.haml | 2 +- config/locales/models/procedure_presentation/en.yml | 1 + config/locales/models/procedure_presentation/fr.yml | 1 + spec/models/columns/dossier_column_spec.rb | 2 +- spec/models/concerns/columns_concern_spec.rb | 2 +- 7 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/models/concerns/columns_concern.rb b/app/models/concerns/columns_concern.rb index d845bd7d7..69a5871ce 100644 --- a/app/models/concerns/columns_concern.rb +++ b/app/models/concerns/columns_concern.rb @@ -159,7 +159,7 @@ module ColumnsConcern etablissement_dates = ['entreprise_date_creation'].map { |column| dossier_col(table: 'etablissement', column:, type: :date) } - for_export = ["siege_social", "naf", "adresse", "numero_voie", "type_voie", "nom_voie", "complement_adresse", "localite", "code_insee_localite", "entreprise_siren", "entreprise_capital_social", "entreprise_numero_tva_intracommunautaire", "entreprise_forme_juridique_code", "entreprise_code_effectif_entreprise", "entreprise_etat_administratif", "entreprise_nom", "entreprise_prenom", "association_rna", "association_titre", "association_objet", "association_date_creation", "association_date_declaration", "association_date_publication"] + for_export = ["siege_social", "code_naf", "adresse", "numero_voie", "type_voie", "nom_voie", "complement_adresse", "localite", "code_insee_localite", "entreprise_siren", "entreprise_capital_social", "entreprise_numero_tva_intracommunautaire", "entreprise_forme_juridique_code", "entreprise_code_effectif_entreprise", "entreprise_etat_administratif", "entreprise_nom", "entreprise_prenom", "association_rna", "association_titre", "association_objet", "association_date_creation", "association_date_declaration", "association_date_publication"] .map { |column| dossier_col(table: 'etablissement', column:, displayable: false, filterable: false) } other = ['siret', 'libelle_naf', 'code_postal'].map { |column| dossier_col(table: 'etablissement', column:) } diff --git a/app/models/etablissement.rb b/app/models/etablissement.rb index 94160e2b1..132759dcc 100644 --- a/app/models/etablissement.rb +++ b/app/models/etablissement.rb @@ -21,6 +21,8 @@ class Etablissement < ApplicationRecord after_commit -> { dossier&.index_search_terms_later } + alias_attribute :code_naf, :naf + # See https://github.com/demarches-simplifiees/demarches-simplifiees.fr/pull/10591#discussion_r1819399688 # SIRET is already exposed as base column. DISPLAYABLE_COLUMNS = { diff --git a/app/views/shared/dossiers/_identite_entreprise.html.haml b/app/views/shared/dossiers/_identite_entreprise.html.haml index 7d2bd5dbc..71a128370 100644 --- a/app/views/shared/dossiers/_identite_entreprise.html.haml +++ b/app/views/shared/dossiers/_identite_entreprise.html.haml @@ -43,7 +43,7 @@ - c.with_value do %p= etablissement.libelle_naf - = render Dossiers::RowShowComponent.new(label: "Libellé NAF") do |c| + = render Dossiers::RowShowComponent.new(label: "Code NAF") do |c| - c.with_value do %p= etablissement.naf diff --git a/config/locales/models/procedure_presentation/en.yml b/config/locales/models/procedure_presentation/en.yml index 71866feed..7fccc8a8e 100644 --- a/config/locales/models/procedure_presentation/en.yml +++ b/config/locales/models/procedure_presentation/en.yml @@ -50,6 +50,7 @@ en: entreprise_date_creation: Entreprise date de création siret: Établissement SIRET libelle_naf: Libellé NAF + code_naf: Code NAF siege_social: "Établissement siège social" naf: "Établissement NAF" adresse: "Établissement Adresse" diff --git a/config/locales/models/procedure_presentation/fr.yml b/config/locales/models/procedure_presentation/fr.yml index cf8618233..9c82c0731 100644 --- a/config/locales/models/procedure_presentation/fr.yml +++ b/config/locales/models/procedure_presentation/fr.yml @@ -54,6 +54,7 @@ fr: entreprise_date_creation: Entreprise date de création siret: Établissement SIRET libelle_naf: Libellé NAF + code_naf: Code NAF siege_social: "Établissement siège social" naf: "Établissement NAF" adresse: "Établissement Adresse" diff --git a/spec/models/columns/dossier_column_spec.rb b/spec/models/columns/dossier_column_spec.rb index 46d39461a..8937eee72 100644 --- a/spec/models/columns/dossier_column_spec.rb +++ b/spec/models/columns/dossier_column_spec.rb @@ -36,9 +36,9 @@ describe Columns::DossierColumn do expect(procedure.find_column(label: "Date de création").value(dossier)).to be_an_instance_of(ActiveSupport::TimeWithZone) expect(procedure.find_column(label: "Établissement SIRET").value(dossier)).to eq('44011762001530') expect(procedure.find_column(label: "Libellé NAF").value(dossier)).to eq('Transports par conduites') + expect(procedure.find_column(label: "Code NAF").value(dossier)).to eq('4950Z') expect(procedure.find_column(label: "Établissement code postal").value(dossier)).to eq('92270') expect(procedure.find_column(label: "Établissement siège social").value(dossier)).to eq(true) - expect(procedure.find_column(label: "Établissement NAF").value(dossier)).to eq('4950Z') expect(procedure.find_column(label: "Établissement Adresse").value(dossier)).to eq("GRTGAZ\r IMMEUBLE BORA\r 6 RUE RAOUL NORDLING\r 92270 BOIS COLOMBES\r") expect(procedure.find_column(label: "Établissement numero voie").value(dossier)).to eq('6') expect(procedure.find_column(label: "Établissement type voie").value(dossier)).to eq('RUE') diff --git a/spec/models/concerns/columns_concern_spec.rb b/spec/models/concerns/columns_concern_spec.rb index 4b21061fa..c3c185be1 100644 --- a/spec/models/concerns/columns_concern_spec.rb +++ b/spec/models/concerns/columns_concern_spec.rb @@ -187,8 +187,8 @@ describe ColumnsConcern do procedure.find_column(label: "France connecté ?"), procedure.find_column(label: "Établissement SIRET"), procedure.find_column(label: "Établissement siège social"), - procedure.find_column(label: "Établissement NAF"), procedure.find_column(label: "Libellé NAF"), + procedure.find_column(label: "Code NAF"), procedure.find_column(label: "Établissement Adresse"), procedure.find_column(label: "Établissement numero voie"), procedure.find_column(label: "Établissement type voie"), From 33df2029ab63112d9a57015867d64ee3cb9c5beb Mon Sep 17 00:00:00 2001 From: Colin Darie Date: Thu, 28 Nov 2024 12:20:42 +0100 Subject: [PATCH 12/13] chore: re backfill siret champ --- app/tasks/maintenance/populate_siret_value_json_task.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/tasks/maintenance/populate_siret_value_json_task.rb b/app/tasks/maintenance/populate_siret_value_json_task.rb index 78a5d8757..4464cceca 100644 --- a/app/tasks/maintenance/populate_siret_value_json_task.rb +++ b/app/tasks/maintenance/populate_siret_value_json_task.rb @@ -4,8 +4,13 @@ # la normalisation des adresses des champs RNA/RNF/SIRET # le fait de stocker ces données normalisées dans le champs.value_json (un jsonb) # le backfill les anciens champs RNA/RNF/SIRET +# A (re)jouer après déploiement de PR #11013 https://github.com/demarches-simplifiees/demarches-simplifiees.fr/pull/11013 module Maintenance class PopulateSiretValueJSONTask < MaintenanceTasks::Task + include RunnableOnDeployConcern + + run_on_first_deploy + def collection Champs::SiretChamp.where.not(value: nil) end From bab474d46d39c4a889db2efd182a6d3223704c1c Mon Sep 17 00:00:00 2001 From: Colin Darie Date: Tue, 3 Dec 2024 14:57:45 +0100 Subject: [PATCH 13/13] refactor(columns): more readable etablissment columns list --- app/models/concerns/columns_concern.rb | 38 +++++++++++++++++++++----- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/app/models/concerns/columns_concern.rb b/app/models/concerns/columns_concern.rb index 69a5871ce..d849b9438 100644 --- a/app/models/concerns/columns_concern.rb +++ b/app/models/concerns/columns_concern.rb @@ -154,17 +154,41 @@ module ColumnsConcern end def moral_columns - etablissements = ['entreprise_forme_juridique', 'entreprise_siren', 'entreprise_nom_commercial', 'entreprise_raison_sociale', 'entreprise_siret_siege_social'] - .map { |column| dossier_col(table: 'etablissement', column:) } + siret_column = dossier_col(table: 'etablissement', column: :siret) - etablissement_dates = ['entreprise_date_creation'].map { |column| dossier_col(table: 'etablissement', column:, type: :date) } + etablissements = Etablissement::DISPLAYABLE_COLUMNS.map do |(column, attributes)| + dossier_col(table: 'etablissement', column:, type: attributes[:type], filterable: attributes.fetch(:filterable, true)) + end - for_export = ["siege_social", "code_naf", "adresse", "numero_voie", "type_voie", "nom_voie", "complement_adresse", "localite", "code_insee_localite", "entreprise_siren", "entreprise_capital_social", "entreprise_numero_tva_intracommunautaire", "entreprise_forme_juridique_code", "entreprise_code_effectif_entreprise", "entreprise_etat_administratif", "entreprise_nom", "entreprise_prenom", "association_rna", "association_titre", "association_objet", "association_date_creation", "association_date_declaration", "association_date_publication"] - .map { |column| dossier_col(table: 'etablissement', column:, displayable: false, filterable: false) } + others = %w[code_postal].map { |column| dossier_col(table: 'etablissement', column:) } - other = ['siret', 'libelle_naf', 'code_postal'].map { |column| dossier_col(table: 'etablissement', column:) } + for_export = %w[ + siege_social + code_naf + adresse + numero_voie + type_voie + nom_voie + complement_adresse + localite + code_insee_localite + entreprise_capital_social + entreprise_numero_tva_intracommunautaire + entreprise_forme_juridique_code + entreprise_code_effectif_entreprise + entreprise_etat_administratif + entreprise_siret_siege_social + entreprise_nom + entreprise_prenom + association_rna + association_titre + association_objet + association_date_creation + association_date_declaration + association_date_publication + ].map { |column| dossier_col(table: 'etablissement', column:, displayable: false, filterable: false) } - [etablissements, etablissement_dates, other, for_export].flatten + [siret_column, etablissements, others, for_export].flatten end def types_de_champ_columns