From 99834e0cf5804e2c42460c062015a6a3fc5ebb1a Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Tue, 23 Apr 2024 10:02:07 +0200 Subject: [PATCH] refactor(export): move formatting logic to type de champ --- .../types_de_champ/address_type_de_champ.rb | 32 +++++++++++++ .../types_de_champ/carte_type_de_champ.rb | 10 ++++ .../types_de_champ/checkbox_type_de_champ.rb | 40 ++++++++++++++++ .../types_de_champ/cojo_type_de_champ.rb | 5 ++ .../types_de_champ/commune_type_de_champ.rb | 28 +++++++++++ .../types_de_champ/date_type_de_champ.rb | 7 +++ .../types_de_champ/datetime_type_de_champ.rb | 5 ++ .../decimal_number_type_de_champ.rb | 24 ++++++++++ .../departement_type_de_champ.rb | 33 +++++++++++++ .../types_de_champ/epci_type_de_champ.rb | 24 ++++++++++ .../integer_number_type_de_champ.rb | 24 ++++++++++ .../linked_drop_down_list_type_de_champ.rb | 37 +++++++++++++++ .../multiple_drop_down_list_type_de_champ.rb | 13 ++++++ .../types_de_champ/pays_type_de_champ.rb | 24 ++++++++++ .../types_de_champ/phone_type_de_champ.rb | 32 +++++++++++++ .../piece_justificative_type_de_champ.rb | 18 ++++++++ .../types_de_champ/region_type_de_champ.rb | 24 ++++++++++ .../types_de_champ/rna_type_de_champ.rb | 6 +++ .../types_de_champ/rnf_type_de_champ.rb | 32 +++++++++++++ .../types_de_champ/textarea_type_de_champ.rb | 6 +++ .../titre_identite_type_de_champ.rb | 14 ++++++ .../types_de_champ/yes_no_type_de_champ.rb | 46 +++++++++++++++++++ 22 files changed, 484 insertions(+) diff --git a/app/models/types_de_champ/address_type_de_champ.rb b/app/models/types_de_champ/address_type_de_champ.rb index 710ca5f96..82203d035 100644 --- a/app/models/types_de_champ/address_type_de_champ.rb +++ b/app/models/types_de_champ/address_type_de_champ.rb @@ -4,6 +4,38 @@ class TypesDeChamp::AddressTypeDeChamp < TypesDeChamp::TextTypeDeChamp [[path[:libelle], path[:path]]] end + class << self + def champ_value(champ) + champ.address_label.presence || '' + end + + def champ_value_for_api(champ, version = 2) + champ_value(champ) + end + + def champ_value_for_tag(champ, path = :value) + case path + when :value + champ_value(champ) + when :departement + champ.departement_code_and_name || '' + when :commune + champ.commune_name || '' + end + end + + def champ_value_for_export(champ, path = :value) + case path + when :value + champ_value(champ) + when :departement + champ.departement_code_and_name + when :commune + champ.commune_name + end + end + end + private def paths diff --git a/app/models/types_de_champ/carte_type_de_champ.rb b/app/models/types_de_champ/carte_type_de_champ.rb index 054914bcf..d1ca43d49 100644 --- a/app/models/types_de_champ/carte_type_de_champ.rb +++ b/app/models/types_de_champ/carte_type_de_champ.rb @@ -17,4 +17,14 @@ class TypesDeChamp::CarteTypeDeChamp < TypesDeChamp::TypeDeChampBase end def tags_for_template = [].freeze + + class << self + def champ_value_for_api(champ, version = 2) + nil + end + + def champ_value_for_export(champ, path = :value) + champ.geo_areas.map(&:label).join("\n") + end + end end diff --git a/app/models/types_de_champ/checkbox_type_de_champ.rb b/app/models/types_de_champ/checkbox_type_de_champ.rb index aa60db19d..e0bdd0701 100644 --- a/app/models/types_de_champ/checkbox_type_de_champ.rb +++ b/app/models/types_de_champ/checkbox_type_de_champ.rb @@ -8,4 +8,44 @@ class TypesDeChamp::CheckboxTypeDeChamp < TypesDeChamp::TypeDeChampBase filter_value end end + + class << self + def champ_value(champ) + champ.true? ? 'Oui' : 'Non' + end + + def champ_value_for_tag(champ, path = :value) + champ_value(champ) + end + + def champ_value_for_export(champ, path = :value) + champ.true? ? 'on' : 'off' + end + + def champ_value_for_api(champ, version = 2) + case version + when 2 + champ.true? ? 'true' : 'false' + else + super + end + end + + def champ_default_value + 'Non' + end + + def champ_default_export_value(path = :value) + 'off' + end + + def champ_default_api_value(version = 2) + case version + when 2 + 'false' + else + nil + end + end + end end diff --git a/app/models/types_de_champ/cojo_type_de_champ.rb b/app/models/types_de_champ/cojo_type_de_champ.rb index 2747a34c7..eb6c07787 100644 --- a/app/models/types_de_champ/cojo_type_de_champ.rb +++ b/app/models/types_de_champ/cojo_type_de_champ.rb @@ -1,2 +1,7 @@ class TypesDeChamp::COJOTypeDeChamp < TypesDeChamp::TextTypeDeChamp + class << self + def champ_value(champ) + "#{champ.accreditation_number} – #{champ.accreditation_birthdate}" + end + end end diff --git a/app/models/types_de_champ/commune_type_de_champ.rb b/app/models/types_de_champ/commune_type_de_champ.rb index 69be05959..da7e53e65 100644 --- a/app/models/types_de_champ/commune_type_de_champ.rb +++ b/app/models/types_de_champ/commune_type_de_champ.rb @@ -1,4 +1,32 @@ class TypesDeChamp::CommuneTypeDeChamp < TypesDeChamp::TypeDeChampBase + class << self + def champ_value_for_export(champ, path = :value) + case path + when :value + champ_value(champ) + when :departement + champ.departement_code_and_name || '' + when :code + champ.code || '' + end + end + + def champ_value_for_tag(champ, path = :value) + case path + when :value + champ_value(champ) + when :departement + champ.departement_code_and_name || '' + when :code + champ.code || '' + end + end + + def champ_value(champ) + champ.code_postal? ? "#{champ.name} (#{champ.code_postal})" : champ.name + end + end + private def paths diff --git a/app/models/types_de_champ/date_type_de_champ.rb b/app/models/types_de_champ/date_type_de_champ.rb index 65b0d5fc7..890cba7c2 100644 --- a/app/models/types_de_champ/date_type_de_champ.rb +++ b/app/models/types_de_champ/date_type_de_champ.rb @@ -1,2 +1,9 @@ class TypesDeChamp::DateTypeDeChamp < TypesDeChamp::TypeDeChampBase + class << self + def champ_value(champ) + I18n.l(Time.zone.parse(champ.value), format: '%d %B %Y') + rescue ArgumentError + champ.value.presence || "" # old dossiers can have not parseable dates + end + end end diff --git a/app/models/types_de_champ/datetime_type_de_champ.rb b/app/models/types_de_champ/datetime_type_de_champ.rb index 2ccfec18f..6ed9ff56c 100644 --- a/app/models/types_de_champ/datetime_type_de_champ.rb +++ b/app/models/types_de_champ/datetime_type_de_champ.rb @@ -1,2 +1,7 @@ class TypesDeChamp::DatetimeTypeDeChamp < TypesDeChamp::TypeDeChampBase + class << self + def champ_value(champ) + I18n.l(Time.zone.parse(champ.value)) + end + end end diff --git a/app/models/types_de_champ/decimal_number_type_de_champ.rb b/app/models/types_de_champ/decimal_number_type_de_champ.rb index 9a1363317..9455283f5 100644 --- a/app/models/types_de_champ/decimal_number_type_de_champ.rb +++ b/app/models/types_de_champ/decimal_number_type_de_champ.rb @@ -1,2 +1,26 @@ class TypesDeChamp::DecimalNumberTypeDeChamp < TypesDeChamp::TypeDeChampBase + class << self + def champ_value_for_export(champ, path = :value) + champ_formatted_value(champ) + end + + def champ_value_for_api(champ, version = 2) + case version + when 1 + champ_formatted_value(champ) + else + super + end + end + + def champ_default_export_value(path = :value) + 0 + end + + private + + def champ_formatted_value(champ) + champ.valid_value&.to_f + end + end end diff --git a/app/models/types_de_champ/departement_type_de_champ.rb b/app/models/types_de_champ/departement_type_de_champ.rb index 334286f78..24ab7c490 100644 --- a/app/models/types_de_champ/departement_type_de_champ.rb +++ b/app/models/types_de_champ/departement_type_de_champ.rb @@ -3,6 +3,39 @@ class TypesDeChamp::DepartementTypeDeChamp < TypesDeChamp::TextTypeDeChamp APIGeoService.departement_name(filter_value).presence || filter_value end + class << self + def champ_value(champ) + "#{champ.code} – #{champ.name}" + end + + def champ_value_for_export(champ, path = :value) + case path + when :code + champ.code + when :value + champ.name + end + end + + def champ_value_for_tag(path = :value) + case path + when :code + champ.code + when :value + champ_value(champ) + end + end + + def champ_value_for_api(champ, version = 2) + case version + when 2 + champ_value(champ).tr('–', '-') + else + champ_value(champ) + end + end + end + private def paths diff --git a/app/models/types_de_champ/epci_type_de_champ.rb b/app/models/types_de_champ/epci_type_de_champ.rb index 1ef14d66e..ab7b8c0ba 100644 --- a/app/models/types_de_champ/epci_type_de_champ.rb +++ b/app/models/types_de_champ/epci_type_de_champ.rb @@ -1,4 +1,28 @@ class TypesDeChamp::EpciTypeDeChamp < TypesDeChamp::TextTypeDeChamp + class << self + def champ_value_for_export(champ, path = :value) + case path + when :value + champ_value(champ) + when :code + champ.code + when :departement + champ.departement_code_and_name + end + end + + def champ_value_for_tag(champ, path = :value) + case path + when :value + champ_value(champ) + when :code + champ.code + when :departement + champ.departement_code_and_name + end + end + end + private def paths diff --git a/app/models/types_de_champ/integer_number_type_de_champ.rb b/app/models/types_de_champ/integer_number_type_de_champ.rb index 0eda2c3d5..7c2d3ef58 100644 --- a/app/models/types_de_champ/integer_number_type_de_champ.rb +++ b/app/models/types_de_champ/integer_number_type_de_champ.rb @@ -1,2 +1,26 @@ class TypesDeChamp::IntegerNumberTypeDeChamp < TypesDeChamp::TypeDeChampBase + class << self + def champ_value_for_export(champ, path = :value) + champ_formatted_value(champ) + end + + def champ_value_for_api(champ, version = 2) + case version + when 1 + champ_formatted_value(champ) + else + super + end + end + + def champ_default_export_value(path = :value) + 0 + end + + private + + def champ_formatted_value(champ) + champ.valid_value&.to_i + end + end end diff --git a/app/models/types_de_champ/linked_drop_down_list_type_de_champ.rb b/app/models/types_de_champ/linked_drop_down_list_type_de_champ.rb index e5b0b56a3..7fb51647e 100644 --- a/app/models/types_de_champ/linked_drop_down_list_type_de_champ.rb +++ b/app/models/types_de_champ/linked_drop_down_list_type_de_champ.rb @@ -30,6 +30,43 @@ class TypesDeChamp::LinkedDropDownListTypeDeChamp < TypesDeChamp::TypeDeChampBas secondary_options end + class << self + def champ_value(champ) + [champ.primary_value, champ.secondary_value].filter(&:present?).join(' / ') + end + + def champ_value_for_tag(champ, path = :value) + case path + when :primary + champ.primary_value + when :secondary + champ.secondary_value + when :value + champ_value(champ) + end + end + + def champ_value_for_export(champ, path = :value) + case path + when :primary + champ.primary_value + when :secondary + champ.secondary_value + when :value + "#{champ.primary_value || ''};#{champ.secondary_value || ''}" + end + end + + def champ_value_for_api(champ, version = 2) + case version + when 1 + { primary: champ.primary_value, secondary: champ.secondary_value } + else + super + end + end + end + private def paths diff --git a/app/models/types_de_champ/multiple_drop_down_list_type_de_champ.rb b/app/models/types_de_champ/multiple_drop_down_list_type_de_champ.rb index f5028c302..4056bb81a 100644 --- a/app/models/types_de_champ/multiple_drop_down_list_type_de_champ.rb +++ b/app/models/types_de_champ/multiple_drop_down_list_type_de_champ.rb @@ -1,2 +1,15 @@ class TypesDeChamp::MultipleDropDownListTypeDeChamp < TypesDeChamp::TypeDeChampBase + class << self + def champ_value(champ) + champ.selected_options.join(', ') + end + + def champ_value_for_tag(champ, path = :value) + champ.selected_options.join(', ') + end + + def champ_value_for_export(champ, path = :value) + champ.selected_options.join(', ') + end + end end diff --git a/app/models/types_de_champ/pays_type_de_champ.rb b/app/models/types_de_champ/pays_type_de_champ.rb index 43a041e76..5d35ba049 100644 --- a/app/models/types_de_champ/pays_type_de_champ.rb +++ b/app/models/types_de_champ/pays_type_de_champ.rb @@ -1,4 +1,28 @@ class TypesDeChamp::PaysTypeDeChamp < TypesDeChamp::TextTypeDeChamp + class << self + def champ_value(champ) + champ.name + end + + def champ_value_for_export(champ, path = :value) + case path + when :value + champ_value(champ) + when :code + champ.code + end + end + + def champ_value_for_tag(champ, path = :value) + case path + when :value + champ_value(champ) + when :code + champ.code + end + end + end + private def paths diff --git a/app/models/types_de_champ/phone_type_de_champ.rb b/app/models/types_de_champ/phone_type_de_champ.rb index 6cd42ac46..c78047239 100644 --- a/app/models/types_de_champ/phone_type_de_champ.rb +++ b/app/models/types_de_champ/phone_type_de_champ.rb @@ -1,2 +1,34 @@ class TypesDeChamp::PhoneTypeDeChamp < TypesDeChamp::TextTypeDeChamp + # We want to allow: + # * international (e164) phone numbers + # * “french format” (ten digits with a leading 0) + # * DROM numbers + # + # However, we need to special-case some ten-digit numbers, + # because the ARCEP assigns some blocks of "O6 XX XX XX XX" numbers to DROM operators. + # Guadeloupe | GP | +590 | 0690XXXXXX, 0691XXXXXX + # Guyane | GF | +594 | 0694XXXXXX + # Martinique | MQ | +596 | 0696XXXXXX, 0697XXXXXX + # Réunion | RE | +262 | 0692XXXXXX, 0693XXXXXX + # Mayotte | YT | +262 | 0692XXXXXX, 0693XXXXXX + # Nouvelle-Calédonie | NC | +687 | + # Polynésie française | PF | +689 | 40XXXXXX, 45XXXXXX, 87XXXXXX, 88XXXXXX, 89XXXXXX + # + # Cf: Plan national de numérotation téléphonique, + # https://www.arcep.fr/uploads/tx_gsavis/05-1085.pdf “Numéros mobiles à 10 chiffres”, page 6 + # + # See issue #6996. + DEFAULT_COUNTRY_CODES = [:FR, :GP, :GF, :MQ, :RE, :YT, :NC, :PF].freeze + + class << self + def champ_value(champ) + if Phonelib.valid_for_countries?(champ.value, DEFAULT_COUNTRY_CODES) + Phonelib.parse_for_countries(champ.value, DEFAULT_COUNTRY_CODES).full_national + else + # When he phone number is possible for the default countries, but not strictly valid, + # `full_national` could mess up the formatting. In this case just return the original. + champ.value + end + end + end end diff --git a/app/models/types_de_champ/piece_justificative_type_de_champ.rb b/app/models/types_de_champ/piece_justificative_type_de_champ.rb index b10a261b7..69d482b7d 100644 --- a/app/models/types_de_champ/piece_justificative_type_de_champ.rb +++ b/app/models/types_de_champ/piece_justificative_type_de_champ.rb @@ -4,4 +4,22 @@ class TypesDeChamp::PieceJustificativeTypeDeChamp < TypesDeChamp::TypeDeChampBas end def tags_for_template = [].freeze + + class << self + def champ_value_for_export(champ, path = :value) + champ.piece_justificative_file.map { _1.filename.to_s }.join(', ') + end + + def champ_value_for_api(champ, version = 2) + return if version == 2 + + # API v1 don't support multiple PJ + attachment = champ.piece_justificative_file.first + return if attachment.nil? + + if attachment.virus_scanner.safe? || attachment.virus_scanner.pending? + attachment.url + end + end + end end diff --git a/app/models/types_de_champ/region_type_de_champ.rb b/app/models/types_de_champ/region_type_de_champ.rb index 015614aa9..638ab4b28 100644 --- a/app/models/types_de_champ/region_type_de_champ.rb +++ b/app/models/types_de_champ/region_type_de_champ.rb @@ -3,6 +3,30 @@ class TypesDeChamp::RegionTypeDeChamp < TypesDeChamp::TextTypeDeChamp APIGeoService.region_name(filter_value).presence || filter_value end + class << self + def champ_value(champ) + champ.name + end + + def champ_value_for_export(champ, path = :value) + case path + when :value + champ_value(champ) + when :code + champ.code + end + end + + def champ_value_for_tag(champ, path = :value) + case path + when :value + champ_value(champ) + when :code + champ.code + end + end + end + private def paths diff --git a/app/models/types_de_champ/rna_type_de_champ.rb b/app/models/types_de_champ/rna_type_de_champ.rb index 01bf96815..a36bb3405 100644 --- a/app/models/types_de_champ/rna_type_de_champ.rb +++ b/app/models/types_de_champ/rna_type_de_champ.rb @@ -2,4 +2,10 @@ class TypesDeChamp::RNATypeDeChamp < TypesDeChamp::TypeDeChampBase def estimated_fill_duration(revision) FILL_DURATION_MEDIUM end + + class << self + def champ_value_for_export(champ, path = :value) + champ.identifier + end + end end diff --git a/app/models/types_de_champ/rnf_type_de_champ.rb b/app/models/types_de_champ/rnf_type_de_champ.rb index d25e02a46..0497cd382 100644 --- a/app/models/types_de_champ/rnf_type_de_champ.rb +++ b/app/models/types_de_champ/rnf_type_de_champ.rb @@ -1,4 +1,36 @@ class TypesDeChamp::RNFTypeDeChamp < TypesDeChamp::TextTypeDeChamp + class << self + def champ_value_for_export(champ, path = :value) + case path + when :value + champ.rnf_id + when :departement + champ.departement_code_and_name + when :code_insee + champ.commune&.fetch(:code) + when :address + champ.full_address + when :nom + champ.title + end + end + + def champ_value_for_tag(champ, path = :value) + case path + when :value + champ.rnf_id + when :departement + champ.departement_code_and_name || '' + when :code_insee + champ.commune&.fetch(:code) || '' + when :address + champ.full_address || '' + when :nom + champ.title || '' + end + end + end + private def paths diff --git a/app/models/types_de_champ/textarea_type_de_champ.rb b/app/models/types_de_champ/textarea_type_de_champ.rb index 3c92afb1e..2cf976343 100644 --- a/app/models/types_de_champ/textarea_type_de_champ.rb +++ b/app/models/types_de_champ/textarea_type_de_champ.rb @@ -2,4 +2,10 @@ class TypesDeChamp::TextareaTypeDeChamp < TypesDeChamp::TextTypeDeChamp def estimated_fill_duration(revision) FILL_DURATION_MEDIUM end + + class << self + def champ_value_for_export(champ, path = :value) + ActionView::Base.full_sanitizer.sanitize(champ.value) + end + end end diff --git a/app/models/types_de_champ/titre_identite_type_de_champ.rb b/app/models/types_de_champ/titre_identite_type_de_champ.rb index 36ff0cd52..69c2dcb1c 100644 --- a/app/models/types_de_champ/titre_identite_type_de_champ.rb +++ b/app/models/types_de_champ/titre_identite_type_de_champ.rb @@ -7,4 +7,18 @@ class TypesDeChamp::TitreIdentiteTypeDeChamp < TypesDeChamp::TypeDeChampBase end def tags_for_template = [].freeze + + class << self + def champ_value_for_export(champ, path = :value) + champ.piece_justificative_file.attached? ? "présent" : "absent" + end + + def champ_value_for_api(champ, version = 2) + nil + end + + def champ_default_export_value(path = :value) + "absent" + end + end end 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 25dae97bc..e924efafd 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 @@ -19,4 +19,50 @@ class TypesDeChamp::YesNoTypeDeChamp < TypesDeChamp::CheckboxTypeDeChamp human_value end end + + class << self + def champ_value(champ) + champ_formatted_value(champ) + end + + def champ_value_for_tag(champ, path = :value) + champ_formatted_value(champ) + end + + def champ_value_for_export(champ, path = :value) + champ_formatted_value(champ) + end + + def champ_value_for_api(champ, version = 2) + case version + when 2 + champ.true? ? 'true' : 'false' + else + super + end + end + + def champ_default_value + 'Non' + end + + def champ_default_export_value(path = :value) + 'Non' + end + + def champ_default_api_value(version = 2) + case version + when 2 + 'false' + else + nil + end + end + + private + + def champ_formatted_value(champ) + champ.true? ? 'Oui' : 'Non' + end + end end