diff --git a/app/models/champ.rb b/app/models/champ.rb index 7fa02202b..7c98eebcf 100644 --- a/app/models/champ.rb +++ b/app/models/champ.rb @@ -109,24 +109,29 @@ class Champ < ApplicationRecord [to_s] end - def to_s - value.present? ? value.to_s : '' - end - - def for_export(path = :value) - path == :value ? value.presence : nil - end - - def for_api + def valid_value + return unless valid_champ_value? value end + def to_s + TypeDeChamp.champ_value(type_champ, self) + end + + def for_api + TypeDeChamp.champ_value_for_api(type_champ, self, 1) + end + def for_api_v2 - to_s + TypeDeChamp.champ_value_for_api(type_champ, self, 2) + end + + def for_export(path = :value) + TypeDeChamp.champ_value_for_export(type_champ, self, path) end def for_tag(path = :value) - path == :value && value.present? ? value.to_s : '' + TypeDeChamp.champ_value_for_tag(type_champ, self, path) end def main_value_name diff --git a/app/models/champs/address_champ.rb b/app/models/champs/address_champ.rb index 751b9844a..1c4d9e78f 100644 --- a/app/models/champs/address_champ.rb +++ b/app/models/champs/address_champ.rb @@ -38,36 +38,6 @@ class Champs::AddressChamp < Champs::TextChamp end end - def to_s - address_label.presence || '' - end - - def for_tag(path = :value) - case path - when :value - address_label - when :departement - departement_code_and_name || '' - when :commune - commune_name || '' - end - end - - def for_export(path = :value) - case path - when :value - value.present? ? address_label : nil - when :departement - departement_code_and_name - when :commune - commune_name - end - end - - def for_api - address_label - end - def code_departement if full_address? address.fetch('department_code') diff --git a/app/models/champs/boolean_champ.rb b/app/models/champs/boolean_champ.rb index 745a3536d..7d8a8d502 100644 --- a/app/models/champs/boolean_champ.rb +++ b/app/models/champs/boolean_champ.rb @@ -17,28 +17,8 @@ class Champs::BooleanChamp < Champ end end - def to_s - processed_value - end - - def for_tag(path = :value) - processed_value - end - - def for_export(path = :value) - processed_value - end - - def for_api_v2 - true? ? 'true' : 'false' - end - private - def processed_value - true? ? 'Oui' : 'Non' - end - def set_value_to_nil self.value = nil end diff --git a/app/models/champs/carte_champ.rb b/app/models/champs/carte_champ.rb index c19d2d913..ff2f3252a 100644 --- a/app/models/champs/carte_champ.rb +++ b/app/models/champs/carte_champ.rb @@ -83,14 +83,6 @@ class Champs::CarteChamp < Champ end end - def for_api - nil - end - - def for_export(path = :value) - geo_areas.map(&:label).join("\n") - end - def blank? geo_areas.blank? end diff --git a/app/models/champs/checkbox_champ.rb b/app/models/champs/checkbox_champ.rb index f58bc76d0..0032c0d05 100644 --- a/app/models/champs/checkbox_champ.rb +++ b/app/models/champs/checkbox_champ.rb @@ -1,8 +1,4 @@ class Champs::CheckboxChamp < Champs::BooleanChamp - def for_export(path = :value) - true? ? 'on' : 'off' - end - def mandatory_blank? mandatory? && (blank? || !true?) end diff --git a/app/models/champs/cojo_champ.rb b/app/models/champs/cojo_champ.rb index be2ab2311..514db2a8e 100644 --- a/app/models/champs/cojo_champ.rb +++ b/app/models/champs/cojo_champ.rb @@ -34,10 +34,6 @@ class Champs::COJOChamp < Champ COJOService.new.(accreditation_number:, accreditation_birthdate:) end - def to_s - "#{accreditation_number} – #{accreditation_birthdate}" - end - def accreditation_number_input_id "#{input_id}-accreditation_number" end diff --git a/app/models/champs/commune_champ.rb b/app/models/champs/commune_champ.rb index 8dc7c9903..be62ce968 100644 --- a/app/models/champs/commune_champ.rb +++ b/app/models/champs/commune_champ.rb @@ -2,28 +2,6 @@ class Champs::CommuneChamp < Champs::TextChamp store_accessor :value_json, :code_departement, :code_postal, :code_region before_save :on_codes_change, if: :should_refresh_after_code_change? - def for_export(path = :value) - case path - when :value - to_s - when :departement - departement_code_and_name || '' - when :code - code || '' - end - end - - def for_tag(path = :value) - case path - when :value - to_s - when :departement - departement_code_and_name || '' - when :code - code || '' - end - end - def departement_name APIGeoService.departement_name(code_departement) end @@ -60,10 +38,6 @@ class Champs::CommuneChamp < Champs::TextChamp APIGeoService.safely_normalize_city_name(code_departement, code, safe_to_s) end - def to_s - code_postal? ? "#{name} (#{code_postal})" : name - end - def code external_id end diff --git a/app/models/champs/date_champ.rb b/app/models/champs/date_champ.rb index 4a9d1a215..2e2d5fdf4 100644 --- a/app/models/champs/date_champ.rb +++ b/app/models/champs/date_champ.rb @@ -6,16 +6,6 @@ class Champs::DateChamp < Champ # Text search is pretty useless for dates so we’re not including these champs end - def to_s - value.present? ? I18n.l(Time.zone.parse(value), format: '%d %B %Y') : "" - rescue ArgumentError - value.presence || "" # old dossiers can have not parseable dates - end - - def for_tag(path = :value) - to_s if path == :value - end - private def convert_to_iso8601 diff --git a/app/models/champs/datetime_champ.rb b/app/models/champs/datetime_champ.rb index 93983b5dd..c2517acce 100644 --- a/app/models/champs/datetime_champ.rb +++ b/app/models/champs/datetime_champ.rb @@ -6,14 +6,6 @@ class Champs::DatetimeChamp < Champ # Text search is pretty useless for datetimes so we’re not including these champs end - def to_s - value.present? ? I18n.l(Time.zone.parse(value)) : "" - end - - def for_tag(path = :value) - value.present? ? I18n.l(Time.zone.parse(value)) : "" - end - private def convert_to_iso8601 diff --git a/app/models/champs/decimal_number_champ.rb b/app/models/champs/decimal_number_champ.rb index 856c92a4c..57091da53 100644 --- a/app/models/champs/decimal_number_champ.rb +++ b/app/models/champs/decimal_number_champ.rb @@ -17,14 +17,6 @@ class Champs::DecimalNumberChamp < Champ } }, if: :validate_champ_value_or_prefill? - def for_export(path = :value) - processed_value - end - - def for_api - processed_value - end - private def format_value @@ -32,10 +24,4 @@ class Champs::DecimalNumberChamp < Champ self.value = value.tr(",", ".") end - - def processed_value - return unless valid_champ_value? - - value&.to_f - end end diff --git a/app/models/champs/departement_champ.rb b/app/models/champs/departement_champ.rb index d599e6249..12a1becdc 100644 --- a/app/models/champs/departement_champ.rb +++ b/app/models/champs/departement_champ.rb @@ -5,36 +5,6 @@ class Champs::DepartementChamp < Champs::TextChamp validate :external_id_in_departement_codes, if: -> { validate_champ_value_or_prefill? && !external_id.nil? } before_save :store_code_region - def for_export(path = :value) - case path - when :code - code - when :value - name - end - end - - def to_s - formatted_value - end - - def for_tag(path = :value) - case path - when :code - code - when :value - formatted_value - end - end - - def for_api - formatted_value - end - - def for_api_v2 - formatted_value.tr('–', '-') - end - def selected code end @@ -71,10 +41,6 @@ class Champs::DepartementChamp < Champs::TextChamp private - def formatted_value - blank? ? "" : "#{code} – #{name}" - end - def value_in_departement_names return if value.in?(APIGeoService.departements.pluck(:name)) diff --git a/app/models/champs/epci_champ.rb b/app/models/champs/epci_champ.rb index 6f11b462a..7168e0682 100644 --- a/app/models/champs/epci_champ.rb +++ b/app/models/champs/epci_champ.rb @@ -7,28 +7,6 @@ class Champs::EpciChamp < Champs::TextChamp validate :external_id_in_departement_epci_codes, if: -> { !(code_departement.nil? || external_id.nil?) && validate_champ_value_or_prefill? } validate :value_in_departement_epci_names, if: -> { !(code_departement.nil? || external_id.nil? || value.nil?) && validate_champ_value_or_prefill? } - def for_export(path = :value) - case path - when :value - value - when :code - code - when :departement - departement_code_and_name - end - end - - def for_tag(path = :value) - case path - when :value - value - when :code - code - when :departement - departement_code_and_name - end - end - def departement_name APIGeoService.departement_name(code_departement) end diff --git a/app/models/champs/integer_number_champ.rb b/app/models/champs/integer_number_champ.rb index 69f95adc4..39adbb5fc 100644 --- a/app/models/champs/integer_number_champ.rb +++ b/app/models/champs/integer_number_champ.rb @@ -8,20 +8,4 @@ class Champs::IntegerNumberChamp < Champ object.errors.generate_message(:value, :not_an_integer) } }, if: :validate_champ_value_or_prefill? - - def for_export(path = :value) - processed_value - end - - def for_api - processed_value - end - - private - - def processed_value - return unless valid_champ_value? - - value&.to_i - end end diff --git a/app/models/champs/linked_drop_down_list_champ.rb b/app/models/champs/linked_drop_down_list_champ.rb index 6a1edcaef..169a7aa33 100644 --- a/app/models/champs/linked_drop_down_list_champ.rb +++ b/app/models/champs/linked_drop_down_list_champ.rb @@ -37,36 +37,6 @@ class Champs::LinkedDropDownListChamp < Champ :primary_value end - def to_s - value.present? ? [primary_value, secondary_value].filter(&:present?).join(' / ') : "" - end - - def for_tag(path = :value) - case path - when :primary - primary_value - when :secondary - secondary_value - when :value - value.present? ? [primary_value, secondary_value].filter(&:present?).join(' / ') : "" - end - end - - def for_export(path = :value) - case path - when :primary - primary_value - when :secondary - secondary_value - when :value - value.present? ? "#{primary_value || ''};#{secondary_value || ''}" : nil - end - end - - def for_api - value.present? ? { primary: primary_value, secondary: secondary_value } : nil - end - def blank? primary_value.blank? || (has_secondary_options_for_primary? && secondary_value.blank?) diff --git a/app/models/champs/multiple_drop_down_list_champ.rb b/app/models/champs/multiple_drop_down_list_champ.rb index 60e8be104..cd55dbc0c 100644 --- a/app/models/champs/multiple_drop_down_list_champ.rb +++ b/app/models/champs/multiple_drop_down_list_champ.rb @@ -19,18 +19,6 @@ class Champs::MultipleDropDownListChamp < Champ value.blank? ? [] : JSON.parse(value) end - def to_s - selected_options.join(', ') - end - - def for_tag(path = :value) - selected_options.join(', ') - end - - def for_export(path = :value) - value.present? ? selected_options.join(', ') : nil - end - def render_as_checkboxes? enabled_non_empty_options.size <= THRESHOLD_NB_OPTIONS_AS_CHECKBOX end diff --git a/app/models/champs/pays_champ.rb b/app/models/champs/pays_champ.rb index 4dc5c0a6d..bd88da4b8 100644 --- a/app/models/champs/pays_champ.rb +++ b/app/models/champs/pays_champ.rb @@ -11,28 +11,6 @@ class Champs::PaysChamp < Champs::TextChamp validates :value, inclusion: APIGeoService.countries.pluck(:name), allow_nil: false, allow_blank: false end - def for_export(path = :value) - case path - when :code - code - when :value - name - end - end - - def to_s - name - end - - def for_tag(path = :value) - case path - when :code - code - when :value - name - end - end - def selected code || value end @@ -55,6 +33,10 @@ class Champs::PaysChamp < Champs::TextChamp end end + def blank? + value.blank? && external_id.blank? + end + def code external_id || APIGeoService.country_code(value) end diff --git a/app/models/champs/phone_champ.rb b/app/models/champs/phone_champ.rb index e22e70682..acb603152 100644 --- a/app/models/champs/phone_champ.rb +++ b/app/models/champs/phone_champ.rb @@ -1,41 +1,9 @@ class Champs::PhoneChamp < Champs::TextChamp - # 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 validates :value, phone: { possible: true, allow_blank: true, message: I18n.t(:not_a_phone, scope: 'activerecord.errors.messages') }, - if: -> { !Phonelib.valid_for_countries?(value, DEFAULT_COUNTRY_CODES) && validate_champ_value_or_prefill? } - - def to_s - return '' if value.blank? - - if Phonelib.valid_for_countries?(value, DEFAULT_COUNTRY_CODES) - Phonelib.parse_for_countries(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. - value - end - end + if: -> { !Phonelib.valid_for_countries?(value, TypesDeChamp::PhoneTypeDeChamp::DEFAULT_COUNTRY_CODES) && validate_champ_value_or_prefill? } end diff --git a/app/models/champs/piece_justificative_champ.rb b/app/models/champs/piece_justificative_champ.rb index 0708460e2..37f50d888 100644 --- a/app/models/champs/piece_justificative_champ.rb +++ b/app/models/champs/piece_justificative_champ.rb @@ -25,20 +25,4 @@ class Champs::PieceJustificativeChamp < Champ def blank? piece_justificative_file.blank? end - - def for_export(path = :value) - piece_justificative_file.map { _1.filename.to_s }.join(', ') - end - - def for_api - return nil unless piece_justificative_file.attached? - - # API v1 don't support multiple PJ - attachment = piece_justificative_file.first - return nil if attachment.nil? - - if attachment.virus_scanner.safe? || attachment.virus_scanner.pending? - attachment.url - end - end end diff --git a/app/models/champs/region_champ.rb b/app/models/champs/region_champ.rb index 04fab515c..60e791c47 100644 --- a/app/models/champs/region_champ.rb +++ b/app/models/champs/region_champ.rb @@ -2,24 +2,6 @@ class Champs::RegionChamp < Champs::TextChamp validate :value_in_region_names, if: -> { !value.nil? && validate_champ_value_or_prefill? } validate :external_id_in_region_codes, if: -> { !external_id.nil? && validate_champ_value_or_prefill? } - def for_export(path = :value) - case path - when :value - name - when :code - code - end - end - - def for_tag(path = :value) - case path - when :value - name - when :code - code - end - end - def selected code end diff --git a/app/models/champs/rna_champ.rb b/app/models/champs/rna_champ.rb index 5905d35fa..b1e3397c9 100644 --- a/app/models/champs/rna_champ.rb +++ b/app/models/champs/rna_champ.rb @@ -15,10 +15,6 @@ class Champs::RNAChamp < Champ title.present? ? "#{value} (#{title})" : value end - def for_export(path = :value) - identifier - end - def search_terms etablissement.present? ? etablissement.search_terms : [value] end diff --git a/app/models/champs/rnf_champ.rb b/app/models/champs/rnf_champ.rb index cb0de4e8d..e9ca751ea 100644 --- a/app/models/champs/rnf_champ.rb +++ b/app/models/champs/rnf_champ.rb @@ -25,36 +25,6 @@ class Champs::RNFChamp < Champ rnf_id.blank? end - def for_export(path = :value) - case path - when :value - rnf_id - when :departement - departement_code_and_name - when :code_insee - commune&.fetch(:code) - when :address - full_address - when :nom - title - end - end - - def for_tag(path = :value) - case path - when :value - rnf_id - when :departement - departement_code_and_name || '' - when :code_insee - commune&.fetch(:code) || '' - when :address - full_address || '' - when :nom - title || '' - end - end - def code_departement address.present? && address['departmentCode'] end diff --git a/app/models/champs/textarea_champ.rb b/app/models/champs/textarea_champ.rb index abcb2644e..44c67ece8 100644 --- a/app/models/champs/textarea_champ.rb +++ b/app/models/champs/textarea_champ.rb @@ -1,8 +1,4 @@ class Champs::TextareaChamp < Champs::TextChamp - def for_export(path = :value) - value.present? ? ActionView::Base.full_sanitizer.sanitize(value) : nil - end - def remaining_characters character_limit_base - character_count if character_count >= character_limit_threshold_75 end diff --git a/app/models/champs/titre_identite_champ.rb b/app/models/champs/titre_identite_champ.rb index ae57491bd..86df81ee3 100644 --- a/app/models/champs/titre_identite_champ.rb +++ b/app/models/champs/titre_identite_champ.rb @@ -19,12 +19,4 @@ class Champs::TitreIdentiteChamp < Champ def blank? piece_justificative_file.blank? end - - def for_export(path = :value) - piece_justificative_file.attached? ? "présent" : "absent" - end - - def for_api - nil - end end diff --git a/app/models/concerns/dossier_champs_concern.rb b/app/models/concerns/dossier_champs_concern.rb index ab5a7545e..1e5f2bc3e 100644 --- a/app/models/concerns/dossier_champs_concern.rb +++ b/app/models/concerns/dossier_champs_concern.rb @@ -25,7 +25,7 @@ module DossierChampsConcern types_de_champ.flat_map do |type_de_champ| champ = champ_for_export(type_de_champ, row_id) type_de_champ.libelles_for_export.map do |(libelle, path)| - [libelle, champ&.for_export(path)] + [libelle, TypeDeChamp.champ_value_for_export(type_de_champ.type_champ, champ, path)] end end end diff --git a/app/models/type_de_champ.rb b/app/models/type_de_champ.rb index b4ff3ac51..78f5f6bac 100644 --- a/app/models/type_de_champ.rb +++ b/app/models/type_de_champ.rb @@ -250,7 +250,7 @@ class TypeDeChamp < ApplicationRecord def params_for_champ { private: private?, - type: "Champs::#{type_champ.classify}Champ", + type: self.class.type_champ_to_champ_class_name(type_champ), stable_id:, stream: 'main' } @@ -463,10 +463,6 @@ class TypeDeChamp < ApplicationRecord !private? end - def self.type_champ_to_class_name(type_champ) - "TypesDeChamp::#{type_champ.classify}TypeDeChamp" - end - def filename_for_attachement(attachment_sym) attachment = send(attachment_sym) if attachment.attached? @@ -687,6 +683,56 @@ class TypeDeChamp < ApplicationRecord end end + class << self + def champ_value(type_champ, champ) + dynamic_type_class = type_champ_to_class_name(type_champ).constantize + # special case for linked drop down champ – it's blank implementation is not what you think + if champ.blank? && (type_champ != TypeDeChamp.type_champs.fetch(:linked_drop_down_list) || champ.nil? || champ.value.blank?) + dynamic_type_class.champ_default_value + else + dynamic_type_class.champ_value(champ) + end + end + + def champ_value_for_api(type_champ, champ, version = 2) + dynamic_type_class = type_champ_to_class_name(type_champ).constantize + # special case for linked drop down champ – it's blank implementation is not what you think + if champ.blank? && (type_champ != TypeDeChamp.type_champs.fetch(:linked_drop_down_list) || champ.nil? || champ.value.blank?) + dynamic_type_class.champ_default_api_value(version) + else + dynamic_type_class.champ_value_for_api(champ, version) + end + end + + def champ_value_for_export(type_champ, champ, path = :value) + dynamic_type_class = type_champ_to_class_name(type_champ).constantize + # special case for linked drop down champ – it's blank implementation is not what you think + if champ.blank? && (type_champ != TypeDeChamp.type_champs.fetch(:linked_drop_down_list) || champ.nil? || champ.value.blank?) + dynamic_type_class.champ_default_export_value(path) + else + dynamic_type_class.champ_value_for_export(champ, path) + end + end + + def champ_value_for_tag(type_champ, champ, path = :value) + dynamic_type_class = type_champ_to_class_name(type_champ).constantize + # special case for linked drop down champ – it's blank implementation is not what you think + if champ.blank? && (type_champ != TypeDeChamp.type_champs.fetch(:linked_drop_down_list) || champ.nil? || champ.value.blank?) + '' + else + dynamic_type_class.champ_value_for_tag(champ, path) + end + end + + def type_champ_to_champ_class_name(type_champ) + "Champs::#{type_champ.classify}Champ" + end + + def type_champ_to_class_name(type_champ) + "TypesDeChamp::#{type_champ.classify}TypeDeChamp" + end + end + private DEFAULT_EMPTY = [''] 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/type_de_champ_base.rb b/app/models/types_de_champ/type_de_champ_base.rb index db0d38d9b..81217caa2 100644 --- a/app/models/types_de_champ/type_de_champ_base.rb +++ b/app/models/types_de_champ/type_de_champ_base.rb @@ -56,6 +56,46 @@ class TypesDeChamp::TypeDeChampBase human_value end + class << self + def champ_value(champ) + champ.value.present? ? champ.value.to_s : champ_default_value + end + + def champ_value_for_api(champ, version = 2) + case version + when 2 + champ_value(champ) + else + champ.valid_value.presence || champ_default_api_value(version) + end + end + + def champ_value_for_export(champ, path = :value) + path == :value ? champ.valid_value.presence : champ_default_export_value(path) + end + + def champ_value_for_tag(champ, path = :value) + path == :value ? champ_value(champ) : nil + end + + def champ_default_value + '' + end + + def champ_default_export_value(path = :value) + nil + end + + def champ_default_api_value(version = 2) + case version + when 2 + '' + else + nil + end + end + end + private def paths 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 diff --git a/app/services/dossier_projection_service.rb b/app/services/dossier_projection_service.rb index 6a87f0515..85521f70f 100644 --- a/app/services/dossier_projection_service.rb +++ b/app/services/dossier_projection_service.rb @@ -49,6 +49,7 @@ class DossierProjectionService individual_last_name = { TABLE => 'individual', COLUMN => 'nom' } sva_svr_decision_on_field = { TABLE => 'self', COLUMN => 'sva_svr_decision_on' } dossier_corrections = { TABLE => 'dossier_corrections', COLUMN => 'resolved_at' } + champ_value = champ_value_formatter(dossiers_ids, fields) ([state_field, archived_field, sva_svr_decision_on_field, hidden_by_user_at_field, hidden_by_administration_at_field, for_tiers_field, individual_first_name, individual_last_name, batch_operation_field, dossier_corrections] + fields) # the view needs state and archived dossier attributes .each { |f| f[:id_value_h] = {} } .group_by { |f| f[TABLE] } # one query per table @@ -64,7 +65,7 @@ class DossierProjectionService .group_by(&:stable_id) # the champs are redispatched to their respective fields .map do |stable_id, champs| field = fields.find { |f| f[COLUMN] == stable_id.to_s } - field[:id_value_h] = champs.to_h { |c| [c.dossier_id, c.to_s] } + field[:id_value_h] = champs.to_h { |c| [c.dossier_id, champ_value.(c)] } end when 'self' Dossier @@ -159,4 +160,27 @@ class DossierProjectionService ) end end + + class << self + private + + def champ_value_formatter(dossiers_ids, fields) + stable_ids = fields.filter { _1[TABLE].in?(['type_de_champ', 'type_de_champ_private']) }.map { _1[COLUMN] } + revision_ids_by_dossier_ids = Dossier.where(id: dossiers_ids).pluck(:id, :revision_id).to_h + stable_ids_and_types_champ_by_revision_ids = ProcedureRevisionTypeDeChamp.includes(:type_de_champ) + .where(revision_id: revision_ids_by_dossier_ids.values.uniq, type_de_champ: { stable_id: stable_ids }) + .pluck(:revision_id, 'type_de_champ.stable_id', 'type_de_champ.type_champ') + .group_by(&:first) + .transform_values { _1.map { |_, stable_id, type_champ| [stable_id, type_champ] }.to_h } + stable_ids_and_types_champ_by_dossier_ids = revision_ids_by_dossier_ids.transform_values { stable_ids_and_types_champ_by_revision_ids[_1] }.compact + -> (champ) { + type_champ = stable_ids_and_types_champ_by_dossier_ids.fetch(champ.dossier_id, {})[champ.stable_id] + if type_champ.present? && TypeDeChamp.type_champ_to_champ_class_name(type_champ) == champ.type + TypeDeChamp.champ_value(type_champ, champ) + else + '' + end + } + end + end end diff --git a/spec/models/champ_spec.rb b/spec/models/champ_spec.rb index bf22d18dc..1501b3fe7 100644 --- a/spec/models/champ_spec.rb +++ b/spec/models/champ_spec.rb @@ -142,10 +142,7 @@ describe Champ do end describe 'for_export' do - let(:type_de_champ) { create(:type_de_champ) } - let(:champ) { type_de_champ.champ.build(value: value) } - - before { champ.save } + let(:champ) { create(:champ_text, value: value) } context 'when type_de_champ is text' do let(:value) { '123' } @@ -154,14 +151,14 @@ describe Champ do end context 'when type_de_champ is textarea' do - let(:type_de_champ) { create(:type_de_champ_textarea) } + let(:champ) { create(:champ_textarea, value: value) } let(:value) { 'gras' } it { expect(champ.for_export).to eq('gras') } end context 'when type_de_champ is yes_no' do - let(:type_de_champ) { create(:type_de_champ_yes_no) } + let(:champ) { create(:champ_yes_no, value: value) } context 'if yes' do let(:value) { 'true' } @@ -182,249 +179,242 @@ describe Champ do end end - describe '#search_terms' do - let(:champ) { type_de_champ.champ.build(value: value) } - subject { champ.search_terms } - - context 'for adresse champ' do - let(:type_de_champ) { build(:type_de_champ_address) } - let(:value) { "10 rue du Pinson qui Piaille" } - - it { is_expected.to eq([value]) } - end - - context 'for checkbox champ' do - let(:libelle) { 'majeur' } - let(:type_de_champ) { build(:type_de_champ_checkbox, libelle: libelle) } - - context 'when the box is checked' do - let(:value) { 'true' } - - it { is_expected.to eq([libelle]) } - end - - context 'when the box is unchecked' do - let(:value) { 'false' } - - it { is_expected.to be_nil } - end - end - - context 'for civilite champ' do - let(:type_de_champ) { build(:type_de_champ_civilite) } - let(:value) { "M." } - - it { is_expected.to eq([value]) } - end - - context 'for date champ' do - let(:type_de_champ) { build(:type_de_champ_date) } - let(:value) { "2018-07-30" } - - it { is_expected.to be_nil } - end - - context 'for date time champ' do - let(:type_de_champ) { build(:type_de_champ_datetime) } - let(:value) { "2018-04-29 09:00" } - - it { is_expected.to be_nil } - end - - context 'for département champ' do - let(:type_de_champ) { build(:type_de_champ_departements) } - let(:value) { "69" } - - it { is_expected.to eq(['69 – Rhône']) } - end - - context 'for dossier link champ' do - let(:type_de_champ) { build(:type_de_champ_dossier_link) } - let(:value) { "9103132886" } - - it { is_expected.to eq([value]) } - end - - context 'for drop down list champ' do - let(:type_de_champ) { build(:type_de_champ_dossier_link) } - let(:value) { "HLM" } - - it { is_expected.to eq([value]) } - end - - context 'for email champ' do - let(:type_de_champ) { build(:type_de_champ_email) } - let(:value) { "machin@example.com" } - - it { is_expected.to eq([value]) } - end - - context 'for explication champ' do - let(:type_de_champ) { build(:type_de_champ_explication) } - let(:value) { nil } - - it { is_expected.to be_nil } - end - - context 'for header section champ' do - let(:type_de_champ) { build(:type_de_champ_header_section) } - let(:value) { nil } - - it { is_expected.to be_nil } - end - - context 'for linked drop down list champ' do - let(:type_de_champ) { build(:type_de_champ_linked_drop_down_list) } - let(:champ) { type_de_champ.champ.build(primary_value: "hello", secondary_value: "world") } - - it { is_expected.to eq(["hello", "world"]) } - end - - context 'for multiple drop down list champ' do - let(:type_de_champ) { build(:type_de_champ_multiple_drop_down_list) } - - context 'when there are multiple values selected' do - let(:value) { JSON.generate(['goodbye', 'cruel', 'world']) } - - it { is_expected.to eq(["goodbye", "cruel", "world"]) } - end - - context 'when there is no value selected' do - let(:value) { nil } - - it { is_expected.to eq([]) } - end - end - - context 'for number champ' do - let(:type_de_champ) { build(:type_de_champ_number) } - let(:value) { "1234" } - - it { is_expected.to eq([value]) } - end - - context 'for pays champ' do - let(:type_de_champ) { build(:type_de_champ_pays) } - let(:value) { "FR" } - - it { is_expected.to eq(['France']) } - end - - context 'for phone champ' do - let(:type_de_champ) { build(:type_de_champ_phone) } - let(:value) { "06 06 06 06 06" } - - it { is_expected.to eq([value]) } - end - - context 'for pièce justificative champ' do - let(:type_de_champ) { build(:type_de_champ_piece_justificative) } - let(:value) { nil } - - it { is_expected.to be_nil } - end - - context 'for region champ' do - let(:type_de_champ) { build(:type_de_champ_regions) } - let(:value) { "11" } - - it { is_expected.to eq(['Île-de-France']) } - end - - context 'for siret champ' do - let(:type_de_champ) { build(:type_de_champ_siret) } - - context 'when there is an etablissement' do - let(:etablissement) do - build( - :etablissement, - siret: "35130347400024", - siege_social: true, - naf: "9004Z", - libelle_naf: "Gestion de salles de spectacles", - adresse: "MAISON JEUNES CULTURE FABRIQUE\r\n98 RUE DE PARIS\r\n59200 TOURCOING\r\nFRANCE\r\n", - numero_voie: "98", - type_voie: "RUE", - nom_voie: "DE PARIS", - code_postal: "59200", - localite: "TOURCOING", - code_insee_localite: "59599", - entreprise_siren: "351303474", - entreprise_numero_tva_intracommunautaire: "FR02351303474", - entreprise_forme_juridique: "Association déclarée ", - entreprise_forme_juridique_code: "9220", - entreprise_nom_commercial: "", - entreprise_raison_sociale: "MAISON DES JEUNES ET DE LA CULTURE DE LA FABRIQUE", - entreprise_siret_siege_social: "35130347400024", - entreprise_nom: 'Martin', - entreprise_prenom: 'Guillaume', - entreprise_code_effectif_entreprise: "12", - entreprise_date_creation: "1989-07-09", - association_rna: "W595004053", - association_titre: "MAISON DES JEUNES ET DE LA CULTURE DE LA FABRIQUE", - association_objet: "Création, gestion et animation de la Maison des Jeunes et de la Culture de la Fabrique, qui constitue un élément essentiel de la vie sociale et culturelle d'un territoire de vie : pays, agglomération, ville, communauté de communes, village, quartier ...", - association_date_creation: "1962-05-23", - association_date_declaration: "2016-12-02", - association_date_publication: "1962-05-31" - ) - end - let(:champ) { type_de_champ.champ.build(value: etablissement.siret, etablissement: etablissement) } - - it { is_expected.to eq([etablissement.entreprise_siren, etablissement.entreprise_numero_tva_intracommunautaire, etablissement.entreprise_forme_juridique, etablissement.entreprise_forme_juridique_code, etablissement.entreprise_nom_commercial, etablissement.entreprise_raison_sociale, etablissement.entreprise_siret_siege_social, etablissement.entreprise_nom, etablissement.entreprise_prenom, etablissement.association_rna, etablissement.association_titre, etablissement.association_objet, etablissement.siret, etablissement.enseigne, etablissement.naf, etablissement.libelle_naf, etablissement.adresse, etablissement.code_postal, etablissement.localite, etablissement.code_insee_localite]) } - end - - context 'when there is no etablissement' do - let(:siret) { "35130347400024" } - let(:champ) { type_de_champ.champ.build(value: siret) } - - it { is_expected.to eq([siret]) } - end - end - - context 'for text champ' do - let(:type_de_champ) { build(:type_de_champ_text) } - let(:value) { "Blah" } - - it { is_expected.to eq([value]) } - end - - context 'for text area champ' do - let(:type_de_champ) { build(:type_de_champ_textarea) } - let(:value) { "Bla\nBlah de bla." } - - it { is_expected.to eq([value]) } - end - - context 'for yes/no champ' do - let(:type_de_champ) { build(:type_de_champ_yes_no, libelle: libelle) } - let(:libelle) { 'avec enfant à charge' } - - context 'when the box is checked' do - let(:value) { "true" } - - it { is_expected.to eq([libelle]) } - end - - context 'when the box is unchecked' do - let(:value) { "false" } - - it { is_expected.to be_nil } - end - end - end - context 'when type_de_champ is multiple_drop_down_list' do - let(:type_de_champ) { create(:type_de_champ_multiple_drop_down_list) } + let(:champ) { create(:champ_multiple_drop_down_list, value:) } let(:value) { '["Crétinier", "Mousserie"]' } it { expect(champ.for_export).to eq('Crétinier, Mousserie') } end end + describe '#search_terms' do + subject { champ.search_terms } + + context 'for adresse champ' do + let(:champ) { create(:champ_address, value:) } + let(:value) { "10 rue du Pinson qui Piaille" } + + it { is_expected.to eq([value]) } + end + + context 'for checkbox champ' do + let(:libelle) { champ.libelle } + let(:champ) { create(:champ_checkbox, value:) } + + context 'when the box is checked' do + let(:value) { 'true' } + + it { is_expected.to eq([libelle]) } + end + + context 'when the box is unchecked' do + let(:value) { 'false' } + + it { is_expected.to be_nil } + end + end + + context 'for civilite champ' do + let(:champ) { create(:champ_civilite, value:) } + let(:value) { "M." } + + it { is_expected.to eq([value]) } + end + + context 'for date champ' do + let(:champ) { create(:champ_date, value:) } + let(:value) { "2018-07-30" } + + it { is_expected.to be_nil } + end + + context 'for date time champ' do + let(:champ) { create(:champ_datetime, value:) } + let(:value) { "2018-04-29 09:00" } + + it { is_expected.to be_nil } + end + + context 'for département champ' do + let(:champ) { create(:champ_departements, value:) } + let(:value) { "69" } + + it { is_expected.to eq(['69 – Rhône']) } + end + + context 'for dossier link champ' do + let(:champ) { create(:champ_dossier_link, value:) } + let(:value) { "9103132886" } + + it { is_expected.to eq([value]) } + end + + context 'for drop down list champ' do + let(:champ) { create(:champ_dossier_link, value:) } + let(:value) { "HLM" } + + it { is_expected.to eq([value]) } + end + + context 'for email champ' do + let(:champ) { build(:champ_email, value:) } + let(:value) { "machin@example.com" } + + it { is_expected.to eq([value]) } + end + + context 'for explication champ' do + let(:champ) { build(:champ_explication) } + + it { is_expected.to be_nil } + end + + context 'for header section champ' do + let(:champ) { build(:champ_header_section) } + + it { is_expected.to be_nil } + end + + context 'for linked drop down list champ' do + let(:champ) { create(:champ_linked_drop_down_list, primary_value: "hello", secondary_value: "world") } + + it { is_expected.to eq(["hello", "world"]) } + end + + context 'for multiple drop down list champ' do + let(:champ) { build(:champ_multiple_drop_down_list, value:) } + + context 'when there are multiple values selected' do + let(:value) { JSON.generate(['goodbye', 'cruel', 'world']) } + + it { is_expected.to eq(["goodbye", "cruel", "world"]) } + end + + context 'when there is no value selected' do + let(:value) { nil } + + it { is_expected.to eq([]) } + end + end + + context 'for number champ' do + let(:champ) { build(:champ_number, value:) } + let(:value) { "1234" } + + it { is_expected.to eq([value]) } + end + + context 'for pays champ' do + let(:champ) { build(:champ_pays, value:) } + let(:value) { "FR" } + + it { is_expected.to eq(['France']) } + end + + context 'for phone champ' do + let(:champ) { build(:champ_phone, value:) } + let(:value) { "06 06 06 06 06" } + + it { is_expected.to eq([value]) } + end + + context 'for pièce justificative champ' do + let(:champ) { build(:champ_piece_justificative, value:) } + let(:value) { nil } + + it { is_expected.to be_nil } + end + + context 'for region champ' do + let(:champ) { build(:champ_regions, value:) } + let(:value) { "11" } + + it { is_expected.to eq(['Île-de-France']) } + end + + context 'for siret champ' do + context 'when there is an etablissement' do + let(:etablissement) do + build( + :etablissement, + siret: "35130347400024", + siege_social: true, + naf: "9004Z", + libelle_naf: "Gestion de salles de spectacles", + adresse: "MAISON JEUNES CULTURE FABRIQUE\r\n98 RUE DE PARIS\r\n59200 TOURCOING\r\nFRANCE\r\n", + numero_voie: "98", + type_voie: "RUE", + nom_voie: "DE PARIS", + code_postal: "59200", + localite: "TOURCOING", + code_insee_localite: "59599", + entreprise_siren: "351303474", + entreprise_numero_tva_intracommunautaire: "FR02351303474", + entreprise_forme_juridique: "Association déclarée ", + entreprise_forme_juridique_code: "9220", + entreprise_nom_commercial: "", + entreprise_raison_sociale: "MAISON DES JEUNES ET DE LA CULTURE DE LA FABRIQUE", + entreprise_siret_siege_social: "35130347400024", + entreprise_nom: 'Martin', + entreprise_prenom: 'Guillaume', + entreprise_code_effectif_entreprise: "12", + entreprise_date_creation: "1989-07-09", + association_rna: "W595004053", + association_titre: "MAISON DES JEUNES ET DE LA CULTURE DE LA FABRIQUE", + association_objet: "Création, gestion et animation de la Maison des Jeunes et de la Culture de la Fabrique, qui constitue un élément essentiel de la vie sociale et culturelle d'un territoire de vie : pays, agglomération, ville, communauté de communes, village, quartier ...", + association_date_creation: "1962-05-23", + association_date_declaration: "2016-12-02", + association_date_publication: "1962-05-31" + ) + end + let(:champ) { create(:champ_siret, value: etablissement.siret, etablissement:) } + + it { is_expected.to eq([etablissement.entreprise_siren, etablissement.entreprise_numero_tva_intracommunautaire, etablissement.entreprise_forme_juridique, etablissement.entreprise_forme_juridique_code, etablissement.entreprise_nom_commercial, etablissement.entreprise_raison_sociale, etablissement.entreprise_siret_siege_social, etablissement.entreprise_nom, etablissement.entreprise_prenom, etablissement.association_rna, etablissement.association_titre, etablissement.association_objet, etablissement.siret, etablissement.enseigne, etablissement.naf, etablissement.libelle_naf, etablissement.adresse, etablissement.code_postal, etablissement.localite, etablissement.code_insee_localite]) } + end + + context 'when there is no etablissement' do + let(:champ) { create(:champ_siret, value:, etablissement: nil) } + let(:value) { "35130347400024" } + + it { is_expected.to eq([value]) } + end + end + + context 'for text champ' do + let(:champ) { build(:champ_text, value:) } + let(:value) { "Blah" } + + it { is_expected.to eq([value]) } + end + + context 'for text area champ' do + let(:champ) { build(:champ_textarea, value:) } + let(:value) { "Bla\nBlah de bla." } + + it { is_expected.to eq([value]) } + end + + context 'for yes/no champ' do + let(:champ) { build(:champ_yes_no, value:) } + let(:libelle) { champ.libelle } + + context 'when the box is checked' do + let(:value) { "true" } + + it { is_expected.to eq([libelle]) } + end + + context 'when the box is unchecked' do + let(:value) { "false" } + + it { is_expected.to be_nil } + end + end + end + describe '#enqueue_virus_scan' do context 'when type_champ is type_de_champ_piece_justificative' do - let(:type_de_champ) { create(:type_de_champ_piece_justificative) } - let(:champ) { build(:champ_piece_justificative, type_de_champ: type_de_champ) } + let(:champ) { build(:champ_piece_justificative) } context 'and there is a blob' do before do diff --git a/spec/models/champs/address_champ_spec.rb b/spec/models/champs/address_champ_spec.rb index 21b8c458c..7cc27997d 100644 --- a/spec/models/champs/address_champ_spec.rb +++ b/spec/models/champs/address_champ_spec.rb @@ -1,5 +1,5 @@ describe Champs::AddressChamp do - let(:champ) { Champs::AddressChamp.new(value: value, data: data, type_de_champ: create(:type_de_champ_address)) } + let(:champ) { build(:champ_address, value:, data:) } let(:value) { '' } let(:data) { nil } diff --git a/spec/models/champs/carte_champ_spec.rb b/spec/models/champs/carte_champ_spec.rb index 71c2c3ff8..37bdadb02 100644 --- a/spec/models/champs/carte_champ_spec.rb +++ b/spec/models/champs/carte_champ_spec.rb @@ -1,5 +1,5 @@ describe Champs::CarteChamp do - let(:champ) { Champs::CarteChamp.new(geo_areas: geo_areas, type_de_champ: create(:type_de_champ_carte)) } + let(:champ) { build(:champ_carte, geo_areas:) } let(:value) { '' } let(:coordinates) { [[[2.3859214782714844, 48.87442541960633], [2.3850631713867183, 48.87273183590832], [2.3809432983398438, 48.87081237174292], [2.3859214782714844, 48.87442541960633]]] } let(:geo_json) do diff --git a/spec/models/champs/departement_champ_spec.rb b/spec/models/champs/departement_champ_spec.rb index c3cb405e6..38cbe67a8 100644 --- a/spec/models/champs/departement_champ_spec.rb +++ b/spec/models/champs/departement_champ_spec.rb @@ -61,7 +61,7 @@ describe Champs::DepartementChamp, type: :model do end describe 'value' do - let(:champ) { described_class.new } + let(:champ) { build(:champ_departements, value: nil) } it 'with code having 2 chars' do champ.value = '01' diff --git a/spec/models/champs/epci_champ_spec.rb b/spec/models/champs/epci_champ_spec.rb index b81195e86..759e07558 100644 --- a/spec/models/champs/epci_champ_spec.rb +++ b/spec/models/champs/epci_champ_spec.rb @@ -144,16 +144,19 @@ describe Champs::EpciChamp, type: :model do end describe 'value' do - let(:champ) { described_class.new } + let(:champ) { build(:champ_epci, external_id: nil, value: nil) } + let(:epci) { APIGeoService.epcis('01').first } + it 'with departement and code' do champ.code_departement = '01' - champ.value = '200042935' - expect(champ.external_id).to eq('200042935') - expect(champ.value).to eq('CA Haut - Bugey Agglomération') - expect(champ.selected).to eq('200042935') - expect(champ.code).to eq('200042935') + champ.value = epci[:code] + expect(champ.blank?).to be_falsey + expect(champ.external_id).to eq(epci[:code]) + expect(champ.value).to eq(epci[:name]) + expect(champ.selected).to eq(epci[:code]) + expect(champ.code).to eq(epci[:code]) expect(champ.departement?).to be_truthy - expect(champ.to_s).to eq('CA Haut - Bugey Agglomération') + expect(champ.to_s).to eq(epci[:name]) end end end diff --git a/spec/models/champs/linked_drop_down_list_champ_spec.rb b/spec/models/champs/linked_drop_down_list_champ_spec.rb index 75a668647..88fcd9ccb 100644 --- a/spec/models/champs/linked_drop_down_list_champ_spec.rb +++ b/spec/models/champs/linked_drop_down_list_champ_spec.rb @@ -1,13 +1,13 @@ describe Champs::LinkedDropDownListChamp do describe '#unpack_value' do - let(:champ) { described_class.new(value: '["tata", "tutu"]') } + let(:champ) { build(:champ_linked_drop_down_list, value: '["tata", "tutu"]') } it { expect(champ.primary_value).to eq('tata') } it { expect(champ.secondary_value).to eq('tutu') } end describe '#pack_value' do - let(:champ) { described_class.new(primary_value: 'tata', secondary_value: 'tutu') } + let(:champ) { build(:champ_linked_drop_down_list, primary_value: 'tata', secondary_value: 'tutu') } before { champ.save } @@ -15,7 +15,7 @@ describe Champs::LinkedDropDownListChamp do end describe '#primary_value=' do - let!(:champ) { described_class.new(primary_value: 'tata', secondary_value: 'tutu') } + let!(:champ) { build(:champ_linked_drop_down_list, primary_value: 'tata', secondary_value: 'tutu') } before { champ.primary_value = '' } @@ -23,7 +23,7 @@ describe Champs::LinkedDropDownListChamp do end describe '#to_s' do - let(:champ) { described_class.new(primary_value: primary_value, secondary_value: secondary_value) } + let(:champ) { build(:champ_linked_drop_down_list, value: [primary_value, secondary_value].to_json) } let(:primary_value) { nil } let(:secondary_value) { nil } @@ -48,22 +48,28 @@ describe Champs::LinkedDropDownListChamp do end describe 'for_export' do + let(:champ) { build(:champ_linked_drop_down_list, value:) } + let(:value) { [primary_value, secondary_value].to_json } + let(:primary_value) { nil } + let(:secondary_value) { nil } + subject { champ.for_export } context 'with no value' do - let(:champ) { described_class.new } + let(:value) { nil } it { is_expected.to be_nil } end context 'with primary value' do - let(:champ) { described_class.new(primary_value: 'primary') } + let(:primary_value) { 'primary' } it { is_expected.to eq('primary;') } end context 'with secondary value' do - let(:champ) { described_class.new(primary_value: 'primary', secondary_value: 'secondary') } + let(:primary_value) { 'primary' } + let(:secondary_value) { 'secondary' } it { is_expected.to eq('primary;secondary') } end diff --git a/spec/models/champs/pays_champ_spec.rb b/spec/models/champs/pays_champ_spec.rb index 2110261e0..4c0da34d1 100644 --- a/spec/models/champs/pays_champ_spec.rb +++ b/spec/models/champs/pays_champ_spec.rb @@ -1,5 +1,5 @@ describe Champs::PaysChamp, type: :model do - let(:champ) { described_class.new } + let(:champ) { build(:champ_pays, value: nil) } describe 'value' do it 'with code' do diff --git a/spec/models/champs/piece_justificative_champ_spec.rb b/spec/models/champs/piece_justificative_champ_spec.rb index d3462235d..36f7a663e 100644 --- a/spec/models/champs/piece_justificative_champ_spec.rb +++ b/spec/models/champs/piece_justificative_champ_spec.rb @@ -47,7 +47,7 @@ describe Champs::PieceJustificativeChamp do context 'without attached file' do before { champ_pj.piece_justificative_file.purge } - it { is_expected.to eq('') } + it { is_expected.to eq(nil) } end end diff --git a/spec/models/champs/pole_emploi_champ_spec.rb b/spec/models/champs/pole_emploi_champ_spec.rb index baf248152..be30dcb25 100644 --- a/spec/models/champs/pole_emploi_champ_spec.rb +++ b/spec/models/champs/pole_emploi_champ_spec.rb @@ -1,5 +1,5 @@ describe Champs::PoleEmploiChamp, type: :model do - let(:champ) { described_class.new } + let(:champ) { build(:champ_pole_emploi) } describe 'identifiant' do before do diff --git a/spec/models/champs/region_champ_spec.rb b/spec/models/champs/region_champ_spec.rb index 970c50613..1d012c68b 100644 --- a/spec/models/champs/region_champ_spec.rb +++ b/spec/models/champs/region_champ_spec.rb @@ -1,7 +1,7 @@ describe Champs::RegionChamp, type: :model do describe 'validations' do describe 'external link' do - let(:champ) { build(:champ_regions, external_id: external_id) } + let(:champ) { build(:champ_regions, value: nil, external_id: external_id) } subject { champ.validate(:champs_public_value) } context 'when nil' do let(:external_id) { nil } @@ -29,7 +29,7 @@ describe Champs::RegionChamp, type: :model do end describe 'value' do - let(:champ) { create(:champ_regions) } + let(:champ) { create(:champ_regions, value: nil) } subject { champ.validate(:champs_public_value) } before { champ.update_columns(value: value) } @@ -61,7 +61,7 @@ describe Champs::RegionChamp, type: :model do end describe 'value' do - let(:champ) { described_class.new } + let(:champ) { build(:champ_regions, value: nil) } it 'with code' do champ.value = '01' diff --git a/spec/serializers/champ_serializer_spec.rb b/spec/serializers/champ_serializer_spec.rb index 68710ea58..651fe6d38 100644 --- a/spec/serializers/champ_serializer_spec.rb +++ b/spec/serializers/champ_serializer_spec.rb @@ -104,7 +104,7 @@ describe ChampSerializer do context 'when type champ is siret' do let(:etablissement) { create(:etablissement) } - let(:champ) { create(:type_de_champ_siret).champ.create(etablissement: etablissement, value: etablissement.siret) } + let(:champ) { create(:champ_siret, etablissement:, value: etablissement.siret) } it { is_expected.to include(value: etablissement.siret) diff --git a/spec/services/dossier_projection_service_spec.rb b/spec/services/dossier_projection_service_spec.rb index 4d5f03667..14865a971 100644 --- a/spec/services/dossier_projection_service_spec.rb +++ b/spec/services/dossier_projection_service_spec.rb @@ -214,7 +214,7 @@ describe DossierProjectionService do let(:dossier) { create(:dossier, procedure: procedure) } let(:column) { dossier.procedure.active_revision.types_de_champ_public.first.stable_id.to_s } - before { dossier.champs_public.first.update(data: { 'label' => '18 a la bonne rue', 'departement' => 'd' }) } + before { dossier.champs_public.first.update(value: '18 a la bonne rue', data: { 'label' => '18 a la bonne rue', 'departement' => 'd' }) } it { is_expected.to eq('18 a la bonne rue') } end