Merge pull request #11026 from demarches-simplifiees/inject_options_in_column

Tech: injecte les options des colonnes de type `enum`, retire scope et value_column du new
This commit is contained in:
LeSim 2024-11-08 09:06:58 +00:00 committed by GitHub
commit 5c3b8f1e1c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 213 additions and 239 deletions

View file

@ -10,7 +10,7 @@ class EditableChamp::DepartementsComponent < EditableChamp::EditableChampBaseCom
end
def options
APIGeoService.departements.map { ["#{_1[:code]} #{_1[:name]}", _1[:code]] }
APIGeoService.departement_options
end
def select_options

View file

@ -10,7 +10,7 @@ class EditableChamp::RegionsComponent < EditableChamp::EditableChampBaseComponen
private
def options
APIGeoService.regions.map { [_1[:name], _1[:code]] }
APIGeoService.region_options
end
def select_options

View file

@ -7,25 +7,23 @@ class Instructeurs::ColumnFilterValueComponent < ApplicationComponent
@column = column
end
def column_type = column.present? ? column.type : :text
def call
if column_type.in?([:enum, :enums, :boolean])
select_tag :filter,
options_for_select(options_for_select_of_column),
if column.nil?
tag.input(id: 'value', class: 'fr-input', disabled: true)
elsif column.type.in?([:enum, :enums, :boolean])
select_tag 'filters[][filter]',
options_for_select(column.options_for_select),
id: 'value',
name: "filters[][filter]",
class: 'fr-select',
data: { no_autosubmit: true },
required: true
else
tag.input(
class: 'fr-input',
id: 'value',
type:,
name: "filters[][filter]",
id: 'value',
class: 'fr-input',
type:,
maxlength: FilteredColumn::FILTERS_VALUE_MAX_LENGTH,
disabled: column.nil? ? true : false,
data: { no_autosubmit: true },
required: true
)
@ -35,7 +33,7 @@ class Instructeurs::ColumnFilterValueComponent < ApplicationComponent
private
def type
case column_type
case column.type
when :datetime, :date
'date'
when :integer, :decimal
@ -44,32 +42,4 @@ class Instructeurs::ColumnFilterValueComponent < ApplicationComponent
'text'
end
end
def options_for_select_of_column
if column.scope.present?
I18n.t(column.scope).map(&:to_a).map(&:reverse)
elsif column.table == 'groupe_instructeur'
current_instructeur.groupe_instructeurs.filter_map do
if _1.procedure_id == procedure_id
[_1.label, _1.id]
end
end
elsif column.table == 'dossier_labels'
Procedure.find(procedure_id).labels.filter_map do
[_1.name, _1.id]
end
else
find_type_de_champ(column.stable_id).options_for_select(column)
end
end
def find_type_de_champ(stable_id)
TypeDeChamp
.joins(:revision_types_de_champ)
.where(revision_types_de_champ: { revision_id: ProcedureRevision.where(procedure_id:) })
.order(created_at: :desc)
.find_by(stable_id:)
end
def procedure_id = @column.h_id[:procedure_id]
end

View file

@ -49,16 +49,16 @@ module Administrateurs
case tdc.type_champ
when TypeDeChamp.type_champs.fetch(:departements)
tdc_options = APIGeoService.departements.map { ["#{_1[:code]} #{_1[:name]}", _1[:code]] }
tdc_options = APIGeoService.departement_options
rule_operator = :ds_eq
create_groups_from_territorial_tdc(tdc_options, stable_id, rule_operator)
when TypeDeChamp.type_champs.fetch(:communes), TypeDeChamp.type_champs.fetch(:epci), TypeDeChamp.type_champs.fetch(:address)
tdc_options = APIGeoService.departements.map { ["#{_1[:code]} #{_1[:name]}", _1[:code]] }
tdc_options = APIGeoService.departement_options
rule_operator = :ds_in_departement
create_groups_from_territorial_tdc(tdc_options, stable_id, rule_operator)
when TypeDeChamp.type_champs.fetch(:regions)
rule_operator = :ds_eq
tdc_options = APIGeoService.regions.map { ["#{_1[:code]} #{_1[:name]}", _1[:code]] }
tdc_options = APIGeoService.region_options
create_groups_from_territorial_tdc(tdc_options, stable_id, rule_operator)
when TypeDeChamp.type_champs.fetch(:pays)
rule_operator = :ds_eq

View file

@ -17,6 +17,11 @@ module Instructeurs
def refresh_column_filter
# According to the html, the selected filters is the last one
column = ColumnType.new.cast(params['filters'].last['id'])
if column.groupe_instructeur?
column.options_for_select = instructeur_groupes(procedure_id: column.h_id[:procedure_id])
end
component = Instructeurs::ColumnFilterValueComponent.new(column:)
render turbo_stream: turbo_stream.replace('value', component)
@ -48,5 +53,10 @@ module Instructeurs
.includes(:assign_to)
.find_by!(id: params[:id], assign_to: { instructeur: current_instructeur })
end
def instructeur_groupes(procedure_id:)
current_instructeur.groupe_instructeurs
.filter_map { [_1.label, _1.id] if _1.procedure_id == procedure_id }
end
end
end

View file

@ -8,18 +8,18 @@ class Column
TYPE_DE_CHAMP_TABLE = 'type_de_champ'
attr_reader :table, :column, :label, :type, :scope, :value_column, :filterable, :displayable
attr_reader :table, :column, :label, :type, :filterable, :displayable
attr_accessor :options_for_select
def initialize(procedure_id:, table:, column:, label: nil, type: :text, value_column: :value, filterable: true, displayable: true, scope: '')
def initialize(procedure_id:, table:, column:, label: nil, type: :text, filterable: true, displayable: true, options_for_select: [])
@procedure_id = procedure_id
@table = table
@column = column
@label = label || I18n.t(column, scope: [:activerecord, :attributes, :procedure_presentation, :fields, table])
@type = type
@scope = scope
@value_column = value_column
@filterable = filterable
@displayable = displayable
@options_for_select = options_for_select
end
# the id is a String to be used in forms
@ -31,12 +31,6 @@ class Column
def ==(other) = h_id == other.h_id # using h_id instead of id to avoid inversion of keys
def to_json
{
table:, column:, label:, type:, scope:, value_column:, filterable:, displayable:
}
end
def notifications? = [table, column] == ['notifications', 'notifications']
def dossier_state? = [table, column] == ['self', 'state']
def groupe_instructeur? = [table, column] == ['groupe_instructeur', 'id']

View file

@ -3,19 +3,20 @@
class Columns::ChampColumn < Column
attr_reader :stable_id
def initialize(procedure_id:, label:, stable_id:, tdc_type:, displayable: true, filterable: true, type: :text, value_column: :value)
def initialize(procedure_id:, label:, stable_id:, tdc_type:, displayable: true, filterable: true, type: :text, options_for_select: [])
@stable_id = stable_id
@tdc_type = tdc_type
column = tdc_type.in?(['departements', 'regions']) ? :external_id : :value
super(
procedure_id:,
table: 'type_de_champ',
column: stable_id.to_s,
column:,
label:,
type:,
value_column:,
displayable:,
filterable:
filterable:,
options_for_select:
)
end
@ -30,11 +31,24 @@ class Columns::ChampColumn < Column
end
end
def filtered_ids(dossiers, search_terms)
if type == :enum
dossiers.with_type_de_champ(stable_id)
.filter_enum(:champs, column, search_terms).ids
elsif type == :enums
dossiers.with_type_de_champ(stable_id)
.filter_array_enum(:champs, column, search_terms).ids
else
dossiers.with_type_de_champ(stable_id)
.filter_ilike(:champs, column, search_terms).ids
end
end
private
def column_id = "type_de_champ/#{stable_id}"
def string_value(champ) = champ.public_send(value_column)
def string_value(champ) = champ.public_send(column)
def typed_value(champ)
value = string_value(champ)

View file

@ -3,7 +3,7 @@
class Columns::JSONPathColumn < Columns::ChampColumn
attr_reader :jsonpath
def initialize(procedure_id:, label:, stable_id:, tdc_type:, jsonpath:, displayable:, type: :text)
def initialize(procedure_id:, label:, stable_id:, tdc_type:, jsonpath:, options_for_select: [], displayable:, type: :text)
@jsonpath = quote_string(jsonpath)
super(
@ -12,7 +12,8 @@ class Columns::JSONPathColumn < Columns::ChampColumn
stable_id:,
tdc_type:,
displayable:,
type:
type:,
options_for_select:
)
end
@ -26,17 +27,6 @@ class Columns::JSONPathColumn < Columns::ChampColumn
.ids
end
def options_for_select
case jsonpath.split('.').last
when 'departement_code'
APIGeoService.departements.map { ["#{_1[:code]} #{_1[:name]}", _1[:code]] }
when 'region_name'
APIGeoService.regions.map { [_1[:name], _1[:name]] }
else
[]
end
end
private
def column_id = "type_de_champ/#{stable_id}-#{jsonpath}"

View file

@ -3,7 +3,7 @@
class Columns::LinkedDropDownColumn < Columns::ChampColumn
attr_reader :path
def initialize(procedure_id:, label:, stable_id:, tdc_type:, path:, displayable:, type: :text)
def initialize(procedure_id:, label:, stable_id:, tdc_type:, path:, options_for_select: [], displayable:, type: :text)
@path = path
super(
@ -12,7 +12,8 @@ class Columns::LinkedDropDownColumn < Columns::ChampColumn
stable_id:,
tdc_type:,
displayable:,
type:
type:,
options_for_select:
)
end

View file

@ -5,12 +5,12 @@ module AddressableColumnConcern
included do
def columns(procedure:, displayable: true, prefix: nil)
super.concat([
["code postal (5 chiffres)", '$.postal_code', :text],
["commune", '$.city_name', :text],
["département", '$.departement_code', :enum],
["region", '$.region_name', :enum]
].map do |(label, jsonpath, type)|
addressable_columns = [
["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]
].map do |(label, jsonpath, type, options_for_select)|
Columns::JSONPathColumn.new(
procedure_id: procedure.id,
stable_id:,
@ -18,9 +18,12 @@ module AddressableColumnConcern
label: "#{libelle_with_prefix(prefix)} #{label}",
jsonpath:,
displayable:,
options_for_select:,
type:
)
end)
end
super.concat(addressable_columns)
end
end
end

View file

@ -51,21 +51,25 @@ module ColumnsConcern
columns.filter { _1.id.in?(self.columns.map(&:id)) }
end
def dossier_id_column = Columns::DossierColumn.new(procedure_id: id, table: 'self', column: 'id', type: :number)
def dossier_id_column = dossier_col(table: 'self', column: 'id', type: :number)
def dossier_state_column = Columns::DossierColumn.new(procedure_id: id, table: 'self', column: 'state', type: :enum, scope: 'instructeurs.dossiers.filterable_state', displayable: false)
def dossier_state_column
options_for_select = I18n.t('instructeurs.dossiers.filterable_state').map(&:to_a).map(&:reverse)
def notifications_column = Columns::DossierColumn.new(procedure_id: id, table: 'notifications', column: 'notifications', label: "notifications", filterable: false)
dossier_col(table: 'self', column: 'state', type: :enum, options_for_select:, displayable: false)
end
def notifications_column = dossier_col(table: 'notifications', column: 'notifications', label: "notifications", filterable: false)
def sva_svr_columns(for_export: false)
scope = [:activerecord, :attributes, :procedure_presentation, :fields, :self]
columns = [
Columns::DossierColumn.new(procedure_id: id, table: 'self', column: 'sva_svr_decision_on', type: :date,
dossier_col(table: 'self', column: 'sva_svr_decision_on', type: :date,
label: I18n.t("#{sva_svr_decision}_decision_on", scope:, type: sva_svr_configuration.human_decision))
]
if !for_export
columns << Columns::DossierColumn.new(procedure_id: id, table: 'self', column: 'sva_svr_decision_before', type: :date, displayable: false,
columns << dossier_col(table: 'self', column: 'sva_svr_decision_before', type: :date, displayable: false,
label: I18n.t("#{sva_svr_decision}_decision_before", scope:))
end
columns
@ -79,37 +83,37 @@ module ColumnsConcern
private
def groupe_instructeurs_id_column = Columns::DossierColumn.new(procedure_id: id, table: 'groupe_instructeur', column: 'id', type: :enum)
def groupe_instructeurs_id_column = dossier_col(table: 'groupe_instructeur', column: 'id', type: :enum)
def followers_instructeurs_email_column = Columns::DossierColumn.new(procedure_id: id, table: 'followers_instructeurs', column: 'email')
def followers_instructeurs_email_column = dossier_col(table: 'followers_instructeurs', column: 'email')
def dossier_archived_column = Columns::DossierColumn.new(procedure_id: id, table: 'self', column: 'archived', type: :text, displayable: false, filterable: false);
def dossier_archived_column = dossier_col(table: 'self', column: 'archived', type: :text, displayable: false, filterable: false);
def dossier_motivation_column = Columns::DossierColumn.new(procedure_id: id, table: 'self', column: 'motivation', type: :text, displayable: false, filterable: false);
def dossier_motivation_column = dossier_col(table: 'self', column: 'motivation', type: :text, displayable: false, filterable: false);
def user_email_for_display_column = Columns::DossierColumn.new(procedure_id: id, table: 'self', column: 'user_email_for_display', filterable: false, displayable: false)
def user_email_for_display_column = dossier_col(table: 'self', column: 'user_email_for_display', filterable: false, displayable: false)
def user_france_connected_column = Columns::DossierColumn.new(procedure_id: id, table: 'self', column: 'user_from_france_connect?', filterable: false, displayable: false)
def user_france_connected_column = dossier_col(table: 'self', column: 'user_from_france_connect?', filterable: false, displayable: false)
def dossier_labels_column = Columns::DossierColumn.new(procedure_id: id, table: 'dossier_labels', column: 'label_id', type: :enum)
def dossier_labels_column = dossier_col(table: 'dossier_labels', column: 'label_id', type: :enum, options_for_select: labels.map { [_1.name, _1.id] })
def procedure_chorus_columns
['domaine_fonctionnel', 'referentiel_prog', 'centre_de_cout']
.map { |column| Columns::DossierColumn.new(procedure_id: id, table: 'procedure', column:, displayable: false, filterable: false) }
.map { |column| dossier_col(table: 'procedure', column:, displayable: false, filterable: false) }
end
def dossier_non_displayable_dates_columns
['updated_since', 'depose_since', 'en_construction_since', 'en_instruction_since', 'processed_since']
.map { |column| Columns::DossierColumn.new(procedure_id: id, table: 'self', column:, type: :date, displayable: false) }
.map { |column| dossier_col(table: 'self', column:, type: :date, displayable: false) }
end
def dossier_dates_columns
['created_at', 'updated_at', 'last_champ_updated_at', 'depose_at', 'en_construction_at', 'en_instruction_at', 'processed_at']
.map { |column| Columns::DossierColumn.new(procedure_id: id, table: 'self', column:, type: :date) }
.map { |column| dossier_col(table: 'self', column:, type: :date) }
end
def email_column
Columns::DossierColumn.new(procedure_id: id, table: 'user', column: 'email')
dossier_col(table: 'user', column: 'email')
end
def dossier_columns
@ -128,27 +132,27 @@ module ColumnsConcern
user_email_for_display_column,
followers_instructeurs_email_column,
groupe_instructeurs_id_column,
Columns::DossierColumn.new(procedure_id: id, table: 'avis', column: 'question_answer', filterable: false),
dossier_col(table: 'avis', column: 'question_answer', filterable: false),
user_france_connected_column,
dossier_labels_column
]
end
def individual_columns
['gender', 'nom', 'prenom'].map { |column| Columns::DossierColumn.new(procedure_id: id, table: 'individual', column:) }
.concat ['for_tiers', 'mandataire_last_name', 'mandataire_first_name'].map { |column| Columns::DossierColumn.new(procedure_id: id, table: 'self', column:) }
['gender', 'nom', 'prenom'].map { |column| dossier_col(table: 'individual', column:) }
.concat ['for_tiers', 'mandataire_last_name', 'mandataire_first_name'].map { |column| dossier_col(table: 'self', column:) }
end
def moral_columns
etablissements = ['entreprise_forme_juridique', 'entreprise_siren', 'entreprise_nom_commercial', 'entreprise_raison_sociale', 'entreprise_siret_siege_social']
.map { |column| Columns::DossierColumn.new(procedure_id: id, table: 'etablissement', column:) }
.map { |column| dossier_col(table: 'etablissement', column:) }
etablissement_dates = ['entreprise_date_creation'].map { |column| Columns::DossierColumn.new(procedure_id: id, table: 'etablissement', column:, type: :date) }
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"]
.map { |column| Columns::DossierColumn.new(procedure_id: id, table: 'etablissement', column:, displayable: false, filterable: false) }
.map { |column| dossier_col(table: 'etablissement', column:, displayable: false, filterable: false) }
other = ['siret', 'libelle_naf', 'code_postal'].map { |column| Columns::DossierColumn.new(procedure_id: id, table: 'etablissement', column:) }
other = ['siret', 'libelle_naf', 'code_postal'].map { |column| dossier_col(table: 'etablissement', column:) }
[etablissements, etablissement_dates, other, for_export].flatten
end
@ -156,5 +160,7 @@ module ColumnsConcern
def types_de_champ_columns
all_revisions_types_de_champ.flat_map { _1.columns(procedure: self) }
end
def dossier_col(**args) = Columns::DossierColumn.new(**(args.merge(procedure_id: id)))
end
end

View file

@ -131,9 +131,9 @@ class Logic::ChampValue < Logic::Term
tdc = type_de_champ(type_de_champs)
if operator_name.in?([Logic::InRegionOperator.name, Logic::NotInRegionOperator.name]) || tdc.type_champ == MANAGED_TYPE_DE_CHAMP.fetch(:regions)
APIGeoService.regions.map { ["#{_1[:code]} #{_1[:name]}", _1[:code]] }
APIGeoService.region_options
elsif operator_name.in?([Logic::InDepartementOperator.name, Logic::NotInDepartementOperator.name]) || tdc.type_champ.in?([MANAGED_TYPE_DE_CHAMP.fetch(:communes), MANAGED_TYPE_DE_CHAMP.fetch(:epci), MANAGED_TYPE_DE_CHAMP.fetch(:departements), MANAGED_TYPE_DE_CHAMP.fetch(:address)])
APIGeoService.departements.map { ["#{_1[:code]} #{_1[:name]}", _1[:code]] }
APIGeoService.departement_options
elsif tdc.type_champ == MANAGED_TYPE_DE_CHAMP.fetch(:pays)
APIGeoService.countries.map { ["#{_1[:name]} #{_1[:code]}", _1[:code]] }
else

View file

@ -545,35 +545,17 @@ class TypeDeChamp < ApplicationRecord
end
end
def self.value_column(type_champ)
if type_champ.in?([type_champs.fetch(:departements), type_champs.fetch(:regions)])
:external_id
else
:value
end
end
def options_for_select(column)
def options_for_select
if departement?
APIGeoService.departements.map { ["#{_1[:code]} #{_1[:name]}", _1[:code]] }
APIGeoService.departement_options
elsif region?
APIGeoService.regions.map { [_1[:name], _1[:code]] }
elsif linked_drop_down_list?
if column.path == :primary
primary_options
else
secondary_options.values.flatten
end
elsif choice_type?
if drop_down_list?
drop_down_options
elsif yes_no?
Champs::YesNoChamp.options
elsif checkbox?
Champs::CheckboxChamp.options
end
elsif siret? || rna? || rnf?
column.options_for_select
APIGeoService.region_options
elsif drop_down_list?
drop_down_options
elsif yes_no?
Champs::YesNoChamp.options
elsif checkbox?
Champs::CheckboxChamp.options
end
end

View file

@ -89,7 +89,8 @@ class TypesDeChamp::LinkedDropDownListTypeDeChamp < TypesDeChamp::TypeDeChampBas
label: "#{libelle_with_prefix(prefix)} (Primaire)",
type: :enum,
path: :primary,
displayable: false
displayable: false,
options_for_select: primary_options
),
Columns::LinkedDropDownColumn.new(
procedure_id: procedure.id,
@ -98,7 +99,8 @@ class TypesDeChamp::LinkedDropDownListTypeDeChamp < TypesDeChamp::TypeDeChampBas
label: "#{libelle_with_prefix(prefix)} (Secondaire)",
type: :enum,
path: :secondary,
displayable: false
displayable: false,
options_for_select: secondary_options.values.flatten.uniq.sort
)
]
end

View file

@ -33,7 +33,6 @@ class TypesDeChamp::PieceJustificativeTypeDeChamp < TypesDeChamp::TypeDeChampBas
tdc_type: type_champ,
label: libelle_with_prefix(prefix),
type: TypeDeChamp.column_type(type_champ),
value_column: TypeDeChamp.value_column(type_champ),
displayable: false,
filterable: false
)

View file

@ -32,7 +32,6 @@ class TypesDeChamp::TitreIdentiteTypeDeChamp < TypesDeChamp::TypeDeChampBase
tdc_type: type_champ,
label: libelle_with_prefix(prefix),
type: TypeDeChamp.column_type(type_champ),
value_column: TypeDeChamp.value_column(type_champ),
displayable: false,
filterable: false
)

View file

@ -3,7 +3,7 @@
class TypesDeChamp::TypeDeChampBase
include ActiveModel::Validations
delegate :description, :libelle, :mandatory, :mandatory?, :stable_id, :fillable?, :public?, :type_champ, to: :@type_de_champ
delegate :description, :libelle, :mandatory, :mandatory?, :stable_id, :fillable?, :public?, :type_champ, :options_for_select, to: :@type_de_champ
FILL_DURATION_SHORT = 10.seconds
FILL_DURATION_MEDIUM = 1.minute
@ -104,8 +104,8 @@ class TypesDeChamp::TypeDeChampBase
tdc_type: type_champ,
label: libelle_with_prefix(prefix),
type: TypeDeChamp.column_type(type_champ),
value_column: TypeDeChamp.value_column(type_champ),
displayable:
displayable:,
options_for_select:
)
]
else

View file

@ -27,6 +27,8 @@ class APIGeoService
get_from_api_geo(:regions).sort_by { I18n.transliterate(_1[:name]) }
end
def region_options = regions.map { [_1[:name], _1[:code]] }
def region_name(code)
regions.find { _1[:code] == code }&.dig(:name)
end
@ -42,7 +44,11 @@ class APIGeoService
end
def departements
[{ code: '99', name: 'Etranger' }] + get_from_api_geo(:departements).sort_by { _1[:code] }
([{ code: '99', name: 'Etranger' }] + get_from_api_geo(:departements)).sort_by { _1[:code] }
end
def departement_options
departements.map { ["#{_1[:code]} #{_1[:name]}", _1[:code]] }
end
def departement_name(code)

View file

@ -32,8 +32,9 @@ class DossierFilterService
dossiers_id_with_notification
end
when TYPE_DE_CHAMP
stable_id = sorted_column.column.stable_id
ids = dossiers
.with_type_de_champ(column)
.with_type_de_champ(stable_id)
.order("champs.value #{order}")
.pluck(:id)
if ids.size != count
@ -74,7 +75,6 @@ class DossierFilterService
.map do |(table, column), filters_for_column|
values = filters_for_column.map(&:filter)
filtered_column = filters_for_column.first.column
value_column = filtered_column.value_column
if filtered_column.respond_to?(:filtered_ids)
filtered_column.filtered_ids(dossiers, values)
@ -93,17 +93,6 @@ class DossierFilterService
else
dossiers.where("dossiers.#{column} IN (?)", values)
end
when TYPE_DE_CHAMP
if filtered_column.type == :enum
dossiers.with_type_de_champ(column)
.filter_enum(:champs, value_column, values)
elsif filtered_column.type == :enums
dossiers.with_type_de_champ(column)
.filter_array_enum(:champs, value_column, values)
else
dossiers.with_type_de_champ(column)
.filter_ilike(:champs, value_column, values)
end
when 'etablissement'
if column == 'entreprise_date_creation'
dates = values

View file

@ -85,7 +85,7 @@
.fr-ml-1w.hidden{ 'data-expand-target': 'content' }
%div
= f.select :service_departement,
APIGeoService.departements.map { ["#{_1[:code]} #{_1[:name]}", _1[:code]] },
APIGeoService.departement_options,
{ selected: @filter.service_departement, include_blank: ''},
id: "service_dep_select",
class: 'fr-select'

View file

@ -123,7 +123,7 @@ describe Conditions::ChampsConditionsComponent, type: :component do
let(:regions) { create(:type_de_champ_regions) }
let(:upper_tdcs) { [regions] }
let(:condition) { empty_operator(champ_value(regions.stable_id), constant(true)) }
let(:region_options) { APIGeoService.regions.map { "#{_1[:code]} #{_1[:name]}" } }
let(:region_options) { APIGeoService.regions.map { _1[:name] } }
it do
expect(page).to have_select('type_de_champ[condition_form][rows][][operator_name]', with_options: ['Est'])

View file

@ -2,34 +2,25 @@
describe Instructeurs::ColumnFilterValueComponent, type: :component do
let(:component) { described_class.new(column:) }
let(:instructeur) { create(:instructeur) }
let(:procedure) { create(:procedure, instructeurs: [instructeur]) }
let(:procedure_id) { procedure.id }
before do
allow(component).to receive(:current_instructeur).and_return(instructeur)
before { render_inline(component) }
describe 'the select case' do
let(:column) { double("Column", type: :enum, options_for_select:) }
let(:options_for_select) { ['option1', 'option2'] }
it { expect(page).to have_select('filters[][filter]', options: options_for_select) }
end
describe '.options_for_select_of_column' do
subject { component.send(:options_for_select_of_column) }
describe 'the input case' do
let(:column) { double("Column", type: :datetime) }
context "column is groupe_instructeur" do
let(:column) { double("Column", scope: nil, table: 'groupe_instructeur', h_id: { procedure_id: }) }
let!(:gi_2) { instructeur.groupe_instructeurs.create(label: 'gi2', procedure:) }
let!(:gi_3) { instructeur.groupe_instructeurs.create(label: 'gi3', procedure: create(:procedure)) }
it { expect(page).to have_selector('input[name="filters[][filter]"][type="date"]') }
end
it { is_expected.to eq([['défaut', procedure.defaut_groupe_instructeur.id], ['gi2', gi_2.id]]) }
end
describe 'the column empty case' do
let(:column) { nil }
context 'when column is dropdown' do
let(:types_de_champ_public) { [{ type: :drop_down_list, libelle: 'Votre ville', options: ['Paris', 'Lyon', 'Marseille'] }] }
let(:procedure) { create(:procedure, :published, types_de_champ_public:) }
let(:drop_down_stable_id) { procedure.active_revision.types_de_champ.first.stable_id }
let(:column) { procedure.find_column(label: 'Votre ville') }
it 'find most recent tdc' do
is_expected.to eq(['Paris', 'Lyon', 'Marseille'])
end
end
it { expect(page).to have_selector('input[disabled]') }
end
end

View file

@ -959,8 +959,8 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do
it do
expect(response).to redirect_to(admin_procedure_groupe_instructeurs_path(procedure3))
expect(flash.notice).to eq 'Les groupes instructeurs ont été ajoutés'
expect(procedure3.groupe_instructeurs.pluck(:label)).to include("01 Guadeloupe")
expect(procedure3.reload.defaut_groupe_instructeur.routing_rule).to eq(ds_eq(champ_value(regions_tdc.stable_id), constant('01')))
expect(procedure3.groupe_instructeurs.pluck(:label)).to include("Guadeloupe")
expect(procedure3.reload.defaut_groupe_instructeur.routing_rule).to eq(ds_eq(champ_value(regions_tdc.stable_id), constant('84')))
expect(procedure3.routing_enabled).to be_truthy
end
end

View file

@ -83,4 +83,28 @@ describe Instructeurs::ProcedurePresentationController, type: :controller do
end
end
end
describe '#refresh_column_filter' do
subject { get :refresh_column_filter, params: { id: procedure_presentation.id, filters: [{ id: column.id }] } }
let(:procedure) { create(:procedure, :routee) }
let(:instructeur) { create(:instructeur) }
let(:column) { procedure.find_column(label: "Groupe instructeur") }
let(:procedure_presentation) do
procedure.groupe_instructeurs.each { _1.add(instructeur) }
instructeur.reload.assign_to.first.procedure_presentation_or_default_and_errors.first
end
before { sign_in(instructeur.user) }
it 'refreshes the column filter' do
subject
expect(response).to be_successful
procedure.groupe_instructeurs.each do |gi|
expect(response.body).to include(gi.label)
end
end
end
end

View file

@ -16,7 +16,7 @@ describe 're_routing_dossiers' do
tdc = procedure.active_revision.simple_routable_types_de_champ.first
tdc_options = APIGeoService.departements.map { ["#{_1[:code]} #{_1[:name]}", _1[:code]] }
tdc_options = APIGeoService.departement_options
rule_operator = :ds_eq

View file

@ -1,6 +1,8 @@
# frozen_string_literal: true
describe ColumnsConcern do
let(:procedure_id) { procedure.id }
describe '#find_column' do
let(:procedure) { build(:procedure) }
let(:notifications_column) { procedure.notifications_column }
@ -22,49 +24,48 @@ describe ColumnsConcern do
context 'when the procedure can have a SIRET number' do
let(:procedure) { create(:procedure, types_de_champ_public:, types_de_champ_private:) }
let(:procedure_id) { procedure.id }
let(:tdc_1) { procedure.active_revision.types_de_champ_public[0] }
let(:tdc_2) { procedure.active_revision.types_de_champ_public[1] }
let(:tdc_private_1) { procedure.active_revision.types_de_champ_private[0] }
let(:tdc_private_2) { procedure.active_revision.types_de_champ_private[1] }
let(:expected) {
[
{ label: 'Dossier ID', table: 'self', column: 'id', displayable: true, type: :number, scope: '', value_column: :value, filterable: true },
{ label: 'notifications', table: 'notifications', column: 'notifications', displayable: true, type: :text, scope: '', value_column: :value, filterable: false },
{ label: 'Date de création', table: 'self', column: 'created_at', displayable: true, type: :date, scope: '', value_column: :value, filterable: true },
{ label: 'Mis à jour le', table: 'self', column: 'updated_at', displayable: true, type: :date, scope: '', value_column: :value, filterable: true },
{ label: 'Date de dépot', table: 'self', column: 'depose_at', displayable: true, type: :date, scope: '', value_column: :value, filterable: true },
{ label: 'En construction le', table: 'self', column: 'en_construction_at', displayable: true, type: :date, scope: '', value_column: :value, filterable: true },
{ label: 'En instruction le', table: 'self', column: 'en_instruction_at', displayable: true, type: :date, scope: '', value_column: :value, filterable: true },
{ label: 'Terminé le', table: 'self', column: 'processed_at', displayable: true, type: :date, scope: '', value_column: :value, filterable: true },
{ label: "Dernier évènement depuis", table: "self", column: "updated_since", displayable: false, type: :date, scope: '', value_column: :value, filterable: true },
{ label: "Déposé depuis", table: "self", column: "depose_since", displayable: false, type: :date, scope: '', value_column: :value, filterable: true },
{ label: "En construction depuis", table: "self", column: "en_construction_since", displayable: false, type: :date, scope: '', value_column: :value, filterable: true },
{ label: "En instruction depuis", table: "self", column: "en_instruction_since", displayable: false, type: :date, scope: '', value_column: :value, filterable: true },
{ label: "Traité depuis", table: "self", column: "processed_since", displayable: false, type: :date, scope: '', value_column: :value, filterable: true },
{ label: "Statut", table: "self", column: "state", displayable: false, scope: 'instructeurs.dossiers.filterable_state', type: :enum, value_column: :value, filterable: true },
{ label: "Archivé", table: "self", column: "archived", displayable: false, scope: '', type: :text, value_column: :value, filterable: false },
{ label: "Motivation de la décision", table: "self", column: "motivation", displayable: false, scope: '', type: :text, value_column: :value, filterable: false },
{ label: "Date de dernière modification (usager)", table: "self", column: "last_champ_updated_at", displayable: false, scope: '', type: :text, value_column: :value, filterable: false },
{ label: 'Demandeur', table: 'user', column: 'email', displayable: true, type: :text, scope: '', value_column: :value, filterable: true },
{ label: 'Email instructeur', table: 'followers_instructeurs', column: 'email', displayable: true, type: :text, scope: '', value_column: :value, filterable: true },
{ label: 'Groupe instructeur', table: 'groupe_instructeur', column: 'id', displayable: true, type: :enum, scope: '', value_column: :value, filterable: true },
{ label: 'Avis oui/non', table: 'avis', column: 'question_answer', displayable: true, type: :text, scope: '', value_column: :value, filterable: false },
{ label: 'France connecté ?', table: 'self', column: 'user_from_france_connect?', displayable: false, type: :text, scope: '', value_column: :value, filterable: false },
{ label: "Labels", table: "dossier_labels", column: "label_id", displayable: true, scope: '', value_column: :value, filterable: true },
{ label: 'SIREN', table: 'etablissement', column: 'entreprise_siren', displayable: true, type: :text, scope: '', value_column: :value, filterable: true },
{ label: 'Forme juridique', table: 'etablissement', column: 'entreprise_forme_juridique', displayable: true, type: :text, scope: '', value_column: :value, filterable: true },
{ label: 'Nom commercial', table: 'etablissement', column: 'entreprise_nom_commercial', displayable: true, type: :text, scope: '', value_column: :value, filterable: true },
{ label: 'Raison sociale', table: 'etablissement', column: 'entreprise_raison_sociale', displayable: true, type: :text, scope: '', value_column: :value, filterable: true },
{ label: 'SIRET siège social', table: 'etablissement', column: 'entreprise_siret_siege_social', displayable: true, type: :text, scope: '', value_column: :value, filterable: true },
{ label: 'Date de création', table: 'etablissement', column: 'entreprise_date_creation', displayable: true, type: :date, scope: '', value_column: :value, filterable: true },
{ label: 'SIRET', table: 'etablissement', column: 'siret', displayable: true, type: :text, scope: '', value_column: :value, filterable: true },
{ label: 'Libellé NAF', table: 'etablissement', column: 'libelle_naf', displayable: true, type: :text, scope: '', value_column: :value, filterable: true },
{ label: 'Code postal', table: 'etablissement', column: 'code_postal', displayable: true, type: :text, scope: '', value_column: :value, filterable: true },
{ label: tdc_1.libelle, table: 'type_de_champ', column: tdc_1.stable_id.to_s, displayable: true, type: :text, scope: '', value_column: :value, filterable: true },
{ label: tdc_2.libelle, table: 'type_de_champ', column: tdc_2.stable_id.to_s, displayable: true, type: :text, scope: '', value_column: :value, filterable: true },
{ label: tdc_private_1.libelle, table: 'type_de_champ', column: tdc_private_1.stable_id.to_s, displayable: true, type: :text, scope: '', value_column: :value, filterable: true },
{ label: tdc_private_2.libelle, table: 'type_de_champ', column: tdc_private_2.stable_id.to_s, displayable: true, type: :text, scope: '', value_column: :value, filterable: true }
{ label: 'Dossier ID', table: 'self', column: 'id', displayable: true, type: :number, filterable: true },
{ label: 'notifications', table: 'notifications', column: 'notifications', displayable: true, type: :text, filterable: false },
{ label: 'Date de création', table: 'self', column: 'created_at', displayable: true, type: :date, filterable: true },
{ label: 'Mis à jour le', table: 'self', column: 'updated_at', displayable: true, type: :date, filterable: true },
{ label: 'Date de dépot', table: 'self', column: 'depose_at', displayable: true, type: :date, filterable: true },
{ label: 'En construction le', table: 'self', column: 'en_construction_at', displayable: true, type: :date, filterable: true },
{ label: 'En instruction le', table: 'self', column: 'en_instruction_at', displayable: true, type: :date, filterable: true },
{ label: 'Terminé le', table: 'self', column: 'processed_at', displayable: true, type: :date, filterable: true },
{ label: "Dernier évènement depuis", table: "self", column: "updated_since", displayable: false, type: :date, filterable: true },
{ label: "Déposé depuis", table: "self", column: "depose_since", displayable: false, type: :date, filterable: true },
{ label: "En construction depuis", table: "self", column: "en_construction_since", displayable: false, type: :date, filterable: true },
{ label: "En instruction depuis", table: "self", column: "en_instruction_since", displayable: false, type: :date, filterable: true },
{ label: "Traité depuis", table: "self", column: "processed_since", displayable: false, type: :date, filterable: true },
{ label: "Statut", table: "self", column: "state", displayable: false, type: :enum, filterable: true },
{ label: "Archivé", table: "self", column: "archived", displayable: false, type: :text, filterable: false },
{ label: "Motivation de la décision", table: "self", column: "motivation", displayable: false, type: :text, filterable: false },
{ label: "Date de dernière modification (usager)", table: "self", column: "last_champ_updated_at", displayable: false, type: :text, filterable: false },
{ label: 'Demandeur', table: 'user', column: 'email', displayable: true, type: :text, filterable: true },
{ label: 'Email instructeur', table: 'followers_instructeurs', column: 'email', displayable: true, type: :text, filterable: true },
{ label: 'Groupe instructeur', table: 'groupe_instructeur', column: 'id', displayable: true, type: :enum, filterable: true },
{ label: 'Avis oui/non', table: 'avis', column: 'question_answer', displayable: true, type: :text, filterable: false },
{ label: 'France connecté ?', table: 'self', column: 'user_from_france_connect?', displayable: false, type: :text, filterable: false },
{ label: "Labels", table: "dossier_labels", column: "label_id", displayable: true, filterable: true },
{ label: 'SIREN', table: 'etablissement', column: 'entreprise_siren', displayable: true, type: :text, filterable: true },
{ label: 'Forme juridique', table: 'etablissement', column: 'entreprise_forme_juridique', displayable: true, type: :text, filterable: true },
{ label: 'Nom commercial', table: 'etablissement', column: 'entreprise_nom_commercial', displayable: true, type: :text, filterable: true },
{ label: 'Raison sociale', table: 'etablissement', column: 'entreprise_raison_sociale', displayable: true, type: :text, filterable: true },
{ label: 'SIRET siège social', table: 'etablissement', column: 'entreprise_siret_siege_social', displayable: true, type: :text, filterable: true },
{ label: 'Date de création', table: 'etablissement', column: 'entreprise_date_creation', displayable: true, type: :date, filterable: true },
{ label: 'SIRET', table: 'etablissement', column: 'siret', displayable: true, type: :text, filterable: true },
{ label: 'Libellé NAF', table: 'etablissement', column: 'libelle_naf', displayable: true, type: :text, filterable: true },
{ label: 'Code postal', table: 'etablissement', column: 'code_postal', displayable: true, type: :text, filterable: true },
{ label: tdc_1.libelle, table: 'type_de_champ', column: tdc_1.stable_id.to_s, displayable: true, type: :text, filterable: true },
{ label: tdc_2.libelle, table: 'type_de_champ', column: tdc_2.stable_id.to_s, displayable: true, type: :text, filterable: true },
{ label: tdc_private_1.libelle, table: 'type_de_champ', column: tdc_private_1.stable_id.to_s, displayable: true, type: :text, filterable: true },
{ label: tdc_private_2.libelle, table: 'type_de_champ', column: tdc_private_2.stable_id.to_s, displayable: true, type: :text, filterable: true }
].map { Column.new(**_1.merge(procedure_id:)) }
}
@ -102,34 +103,28 @@ describe ColumnsConcern do
end
context 'when the procedure is for individuals' do
let(:name_field) { Column.new(procedure_id:, label: "Prénom", table: "individual", column: "prenom", displayable: true, type: :text, scope: '', value_column: :value, filterable: true) }
let(:surname_field) { Column.new(procedure_id:, label: "Nom", table: "individual", column: "nom", displayable: true, type: :text, scope: '', value_column: :value, filterable: true) }
let(:gender_field) { Column.new(procedure_id:, label: "Civilité", table: "individual", column: "gender", displayable: true, type: :text, scope: '', value_column: :value, filterable: true) }
let(:name_field) { Column.new(procedure_id:, label: "Prénom", table: "individual", column: "prenom", displayable: true, type: :text, filterable: true) }
let(:surname_field) { Column.new(procedure_id:, label: "Nom", table: "individual", column: "nom", displayable: true, type: :text, filterable: true) }
let(:gender_field) { Column.new(procedure_id:, label: "Civilité", table: "individual", column: "gender", displayable: true, type: :text, filterable: true) }
let(:procedure) { create(:procedure, :for_individual) }
let(:procedure_id) { procedure.id }
let(:procedure_presentation) { create(:procedure_presentation, assign_to: assign_to) }
it { is_expected.to include(name_field, surname_field, gender_field) }
end
context 'when the procedure is sva' do
let(:procedure) { create(:procedure, :for_individual, :sva) }
let(:procedure_id) { procedure.id }
let(:procedure_presentation) { create(:procedure_presentation, assign_to: assign_to) }
let(:procedure) { create(:procedure, :sva) }
let(:decision_on) { Column.new(procedure_id:, label: "Date décision SVA", table: "self", column: "sva_svr_decision_on", displayable: true, type: :date, scope: '', value_column: :value, filterable: true) }
let(:decision_before_field) { Column.new(procedure_id:, label: "Date décision SVA avant", table: "self", column: "sva_svr_decision_before", displayable: false, type: :date, scope: '', value_column: :value, filterable: true) }
let(:decision_on) { Column.new(procedure_id:, label: "Date décision SVA", table: "self", column: "sva_svr_decision_on", displayable: true, type: :date, filterable: true) }
let(:decision_before_field) { Column.new(procedure_id:, label: "Date décision SVA avant", table: "self", column: "sva_svr_decision_before", displayable: false, type: :date, filterable: true) }
it { is_expected.to include(decision_on, decision_before_field) }
end
context 'when the procedure is svr' do
let(:procedure) { create(:procedure, :for_individual, :svr) }
let(:procedure_id) { procedure.id }
let(:procedure_presentation) { create(:procedure_presentation, assign_to: assign_to) }
let(:procedure) { create(:procedure, :svr) }
let(:decision_on) { Column.new(procedure_id:, label: "Date décision SVR", table: "self", column: "sva_svr_decision_on", displayable: true, type: :date, scope: '', value_column: :value, filterable: true) }
let(:decision_before_field) { Column.new(procedure_id:, label: "Date décision SVR avant", table: "self", column: "sva_svr_decision_before", displayable: false, type: :date, scope: '', value_column: :value, filterable: true) }
let(:decision_on) { Column.new(procedure_id:, label: "Date décision SVR", table: "self", column: "sva_svr_decision_on", displayable: true, type: :date, filterable: true) }
let(:decision_before_field) { Column.new(procedure_id:, label: "Date décision SVR avant", table: "self", column: "sva_svr_decision_before", displayable: false, type: :date, filterable: true) }
it { is_expected.to include(decision_on, decision_before_field) }
end

View file

@ -32,9 +32,8 @@ describe APIGeoService do
describe 'departements' do
it 'return sorted results' do
expect(APIGeoService.departements.size).to eq(110)
expect(APIGeoService.departements.first).to eq(code: '99', name: 'Etranger')
expect(APIGeoService.departements.second).to eq(code: '01', name: 'Ain', region_code: "84")
expect(APIGeoService.departements.last).to eq(code: '989', name: 'Île de Clipperton', region_code: "989")
expect(APIGeoService.departements.first).to eq(code: '01', name: 'Ain', region_code: "84")
expect(APIGeoService.departements.last).to eq(code: '99', name: 'Etranger')
end
end

View file

@ -556,7 +556,7 @@ describe DossierFilterService do
it 'describes column' do
expect(column.type).to eq(:enum)
expect(column.options_for_select.first).to eq(["99 Etranger", "99"])
expect(column.options_for_select.first).to eq(["01 Ain", "01"])
end
end
@ -573,7 +573,7 @@ describe DossierFilterService do
it 'describes column' do
expect(column.type).to eq(:enum)
expect(column.options_for_select.first).to eq(["Auvergne-Rhône-Alpes", "Auvergne-Rhône-Alpes"])
expect(column.options_for_select.first).to eq(["Auvergne-Rhône-Alpes", "84"])
end
end
end