2018-01-23 17:15:42 +01:00
|
|
|
FactoryBot.define do
|
2016-06-24 16:41:44 +02:00
|
|
|
sequence(:published_path) { |n| "fake_path#{n}" }
|
2021-11-19 13:48:52 +01:00
|
|
|
|
2015-09-21 17:59:03 +02:00
|
|
|
factory :procedure do
|
2017-04-12 11:18:28 +02:00
|
|
|
sequence(:libelle) { |n| "Procedure #{n}" }
|
2018-09-04 16:46:48 +02:00
|
|
|
description { "Demande de subvention à l'intention des associations" }
|
2020-02-10 12:52:06 +01:00
|
|
|
organisation { "Orga DINUM" }
|
2018-09-04 16:46:48 +02:00
|
|
|
cadre_juridique { "un cadre juridique important" }
|
|
|
|
published_at { nil }
|
|
|
|
duree_conservation_dossiers_dans_ds { 3 }
|
2022-10-06 15:04:59 +02:00
|
|
|
max_duree_conservation_dossiers_dans_ds { Procedure::OLD_MAX_DUREE_CONSERVATION }
|
2023-01-31 18:23:49 +01:00
|
|
|
estimated_duration_visible { true }
|
2019-01-07 12:17:11 +01:00
|
|
|
ask_birthday { false }
|
2019-07-11 16:07:00 +02:00
|
|
|
lien_site_web { "https://mon-site.gouv" }
|
2019-09-17 15:55:35 +02:00
|
|
|
path { SecureRandom.uuid }
|
2023-06-26 17:34:54 +02:00
|
|
|
declarative_with_state { nil }
|
2023-05-30 18:33:57 +02:00
|
|
|
sva_svr { {} }
|
2015-09-21 17:59:03 +02:00
|
|
|
|
2021-11-19 16:14:40 +01:00
|
|
|
groupe_instructeurs { [association(:groupe_instructeur, :default, procedure: instance, strategy: :build)] }
|
2021-11-19 15:41:47 +01:00
|
|
|
administrateurs { administrateur.present? ? [administrateur] : [association(:administrateur)] }
|
|
|
|
|
2019-02-26 16:57:04 +01:00
|
|
|
transient do
|
2022-01-05 15:48:42 +01:00
|
|
|
administrateur {}
|
2019-08-21 14:25:21 +02:00
|
|
|
instructeurs { [] }
|
2022-07-23 12:29:18 +02:00
|
|
|
types_de_champ_public { [] }
|
2020-08-27 19:55:37 +02:00
|
|
|
types_de_champ_private { [] }
|
|
|
|
updated_at { nil }
|
2022-02-04 14:40:16 +01:00
|
|
|
dossier_submitted_message { nil }
|
2019-02-26 16:57:04 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
after(:build) do |procedure, evaluator|
|
2023-04-18 15:14:43 +02:00
|
|
|
procedure.defaut_groupe_instructeur = procedure.groupe_instructeurs.first
|
2022-11-09 12:09:24 +01:00
|
|
|
initial_revision = build(:procedure_revision, procedure: procedure, dossier_submitted_message: evaluator.dossier_submitted_message)
|
2022-07-23 12:29:18 +02:00
|
|
|
|
|
|
|
if evaluator.types_de_champ_public.present?
|
2022-08-04 11:39:30 +02:00
|
|
|
if !evaluator.types_de_champ_public.first.is_a?(Hash)
|
|
|
|
raise "types_de_champ_public must be an array of hashes"
|
|
|
|
end
|
2022-07-23 12:29:18 +02:00
|
|
|
build_types_de_champ(evaluator.types_de_champ_public, revision: initial_revision, scope: :public)
|
|
|
|
end
|
2022-08-04 11:39:30 +02:00
|
|
|
|
2022-07-23 12:29:18 +02:00
|
|
|
if evaluator.types_de_champ_private.present?
|
2022-08-04 11:39:30 +02:00
|
|
|
if !evaluator.types_de_champ_private.first.is_a?(Hash)
|
|
|
|
raise "types_de_champ_private must be an array of hashes"
|
2022-07-23 12:29:18 +02:00
|
|
|
end
|
2022-08-04 11:39:30 +02:00
|
|
|
build_types_de_champ(evaluator.types_de_champ_private, revision: initial_revision, scope: :private)
|
2022-07-23 12:29:18 +02:00
|
|
|
end
|
2020-08-27 19:55:37 +02:00
|
|
|
|
2021-11-19 13:48:52 +01:00
|
|
|
if procedure.brouillon?
|
|
|
|
procedure.draft_revision = initial_revision
|
|
|
|
else
|
|
|
|
procedure.published_revision = initial_revision
|
|
|
|
procedure.published_revision.published_at = Time.zone.now
|
|
|
|
procedure.draft_revision = build(:procedure_revision, from_original: initial_revision)
|
2020-08-27 19:55:37 +02:00
|
|
|
end
|
2019-01-29 11:49:28 +01:00
|
|
|
end
|
|
|
|
|
2022-07-23 12:29:18 +02:00
|
|
|
before(:create) do |procedure, _evaluator|
|
|
|
|
procedure.revisions.each do |revision|
|
|
|
|
revision.association(:types_de_champ).reset
|
|
|
|
revision.association(:types_de_champ_public).reset
|
|
|
|
revision.association(:types_de_champ_private).reset
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-08-21 14:25:21 +02:00
|
|
|
after(:create) do |procedure, evaluator|
|
|
|
|
evaluator.instructeurs.each { |i| i.assign_to_procedure(procedure) }
|
2020-08-27 19:55:37 +02:00
|
|
|
|
|
|
|
if evaluator.updated_at
|
|
|
|
procedure.update_column(:updated_at, evaluator.updated_at)
|
|
|
|
end
|
|
|
|
|
|
|
|
procedure.reload
|
2019-08-21 14:25:21 +02:00
|
|
|
end
|
|
|
|
|
2018-07-03 20:18:06 +02:00
|
|
|
factory :procedure_with_dossiers do
|
|
|
|
transient do
|
2018-09-04 16:46:48 +02:00
|
|
|
dossiers_count { 1 }
|
2018-07-03 20:18:06 +02:00
|
|
|
end
|
|
|
|
|
2019-08-26 15:31:44 +02:00
|
|
|
after(:create) do |procedure, evaluator|
|
|
|
|
user = create(:user)
|
|
|
|
evaluator.dossiers_count.times do
|
2020-08-27 19:55:37 +02:00
|
|
|
create(:dossier, procedure: procedure, user: user)
|
2019-08-26 15:31:44 +02:00
|
|
|
end
|
2018-07-03 20:18:06 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-09-24 15:54:46 +02:00
|
|
|
factory :simple_procedure do
|
2021-11-19 13:48:52 +01:00
|
|
|
published
|
|
|
|
|
|
|
|
for_individual { true }
|
2024-01-23 09:52:20 +01:00
|
|
|
types_de_champ_public { [{ type: :text, libelle: 'Texte obligatoire', mandatory: true }] }
|
2018-09-24 15:54:46 +02:00
|
|
|
end
|
|
|
|
|
2021-12-09 12:20:22 +01:00
|
|
|
trait :with_bulk_message do
|
|
|
|
groupe_instructeurs { [association(:groupe_instructeur, :default, :with_bulk_message, procedure: instance, strategy: :build)] }
|
|
|
|
end
|
|
|
|
|
2019-03-27 12:32:38 +01:00
|
|
|
trait :with_logo do
|
2020-06-30 17:53:54 +02:00
|
|
|
logo { Rack::Test::UploadedFile.new('spec/fixtures/files/logo_test_procedure.png', 'image/png') }
|
2019-08-22 11:12:35 +02:00
|
|
|
end
|
2022-03-09 10:29:16 +01:00
|
|
|
trait :expirable do
|
|
|
|
procedure_expires_when_termine_enabled { true }
|
|
|
|
end
|
2018-08-13 17:49:15 +02:00
|
|
|
trait :with_path do
|
2018-10-25 17:40:23 +02:00
|
|
|
path { generate(:published_path) }
|
2018-08-13 17:49:15 +02:00
|
|
|
end
|
|
|
|
|
2018-06-19 16:23:43 +02:00
|
|
|
trait :with_service do
|
2021-11-19 17:25:32 +01:00
|
|
|
service { association :service, administrateur: administrateurs.first }
|
2018-06-19 16:23:43 +02:00
|
|
|
end
|
|
|
|
|
2019-08-06 11:02:54 +02:00
|
|
|
trait :with_instructeur do
|
2019-08-21 14:09:56 +02:00
|
|
|
after(:create) do |procedure, _evaluator|
|
2020-07-20 17:22:44 +02:00
|
|
|
procedure.defaut_groupe_instructeur.instructeurs << build(:instructeur)
|
2018-11-26 21:25:50 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-12-20 17:22:19 +01:00
|
|
|
trait :with_zone do
|
|
|
|
zones {
|
|
|
|
[
|
|
|
|
create(:zone, labels:
|
|
|
|
[{ designated_on: Time.zone.now, name: "Ministère 1" }])
|
|
|
|
]
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2019-10-15 10:29:07 +02:00
|
|
|
trait :routee do
|
|
|
|
after(:create) do |procedure, _evaluator|
|
2023-06-29 11:45:20 +02:00
|
|
|
create(:groupe_instructeur, label: 'deuxième groupe', procedure: procedure)
|
2019-10-15 10:29:07 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-12-19 17:15:59 +01:00
|
|
|
trait :for_individual do
|
2021-11-19 17:25:32 +01:00
|
|
|
for_individual { true }
|
2016-12-19 17:15:59 +01:00
|
|
|
end
|
|
|
|
|
2020-05-20 16:50:48 +02:00
|
|
|
trait :with_auto_archive do
|
|
|
|
auto_archive_on { Time.zone.today + 20 }
|
|
|
|
end
|
|
|
|
|
2015-11-05 11:21:44 +01:00
|
|
|
trait :with_type_de_champ do
|
2024-01-23 09:52:20 +01:00
|
|
|
types_de_champ_public { [{ type: :text }] }
|
2015-10-27 17:31:08 +01:00
|
|
|
end
|
|
|
|
|
2016-08-03 18:19:56 +02:00
|
|
|
trait :with_type_de_champ_private do
|
2024-01-23 09:52:20 +01:00
|
|
|
types_de_champ_private { [{ type: :text }] }
|
2022-11-07 18:09:06 +01:00
|
|
|
end
|
2021-03-23 09:55:37 +01:00
|
|
|
|
2022-12-19 12:32:09 +01:00
|
|
|
trait :draft do
|
|
|
|
aasm_state { :brouillon }
|
|
|
|
end
|
|
|
|
|
2016-06-09 17:49:38 +02:00
|
|
|
trait :published do
|
2021-11-19 13:48:52 +01:00
|
|
|
aasm_state { :publiee }
|
|
|
|
path { generate(:published_path) }
|
|
|
|
published_at { Time.zone.now }
|
|
|
|
unpublished_at { nil }
|
|
|
|
closed_at { nil }
|
2022-09-27 19:22:42 +02:00
|
|
|
zones { [association(:zone, strategy: :build)] }
|
2023-07-24 19:01:31 +02:00
|
|
|
service { association :service, administrateur: administrateurs.first }
|
2016-06-09 17:49:38 +02:00
|
|
|
end
|
2017-07-04 13:52:08 +02:00
|
|
|
|
2019-11-14 09:43:45 +01:00
|
|
|
trait :closed do
|
2021-11-19 13:48:52 +01:00
|
|
|
published
|
|
|
|
|
|
|
|
aasm_state { :close }
|
2023-04-19 11:05:30 +02:00
|
|
|
published_at { 1.second.ago }
|
2021-11-19 13:48:52 +01:00
|
|
|
closed_at { Time.zone.now }
|
2018-12-03 13:57:59 +01:00
|
|
|
end
|
|
|
|
|
2019-12-04 15:45:06 +01:00
|
|
|
trait :unpublished do
|
2021-11-19 13:48:52 +01:00
|
|
|
published
|
|
|
|
|
|
|
|
aasm_state { :depubliee }
|
2023-04-19 11:05:30 +02:00
|
|
|
published_at { 1.second.ago }
|
2021-11-19 13:48:52 +01:00
|
|
|
unpublished_at { Time.zone.now }
|
2019-12-04 15:45:06 +01:00
|
|
|
end
|
|
|
|
|
2020-02-05 16:09:03 +01:00
|
|
|
trait :discarded do
|
2020-03-26 09:08:52 +01:00
|
|
|
hidden_at { Time.zone.now }
|
2017-07-04 13:52:08 +02:00
|
|
|
end
|
2018-02-21 18:32:07 +01:00
|
|
|
|
2018-05-30 14:21:17 +02:00
|
|
|
trait :whitelisted do
|
|
|
|
after(:build) do |procedure, _evaluator|
|
2018-10-25 15:07:15 +02:00
|
|
|
procedure.update(whitelisted_at: Time.zone.now)
|
2018-05-30 14:21:17 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-04-26 14:36:27 +02:00
|
|
|
trait :with_notice do
|
|
|
|
after(:create) do |procedure, _evaluator|
|
|
|
|
procedure.notice.attach(
|
|
|
|
io: StringIO.new('Hello World'),
|
2021-09-02 12:26:57 +02:00
|
|
|
filename: 'hello.txt',
|
|
|
|
# we don't want to run virus scanner on this file
|
|
|
|
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
2018-05-31 11:00:22 +02:00
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
trait :with_deliberation do
|
|
|
|
after(:create) do |procedure, _evaluator|
|
|
|
|
procedure.deliberation.attach(
|
|
|
|
io: StringIO.new('Hello World'),
|
2021-09-02 12:26:57 +02:00
|
|
|
filename: 'hello.txt',
|
|
|
|
# we don't want to run virus scanner on this file
|
|
|
|
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
2018-04-26 14:36:27 +02:00
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-02-21 18:32:07 +01:00
|
|
|
trait :with_all_champs_mandatory do
|
|
|
|
after(:build) do |procedure, _evaluator|
|
2020-08-27 19:55:37 +02:00
|
|
|
TypeDeChamp.type_champs.map.with_index do |(libelle, type_champ), index|
|
2018-11-22 00:14:16 +01:00
|
|
|
if libelle == 'drop_down_list'
|
|
|
|
libelle = 'simple_drop_down_list'
|
|
|
|
end
|
2022-11-30 12:05:27 +01:00
|
|
|
if type_champ == 'repetition'
|
|
|
|
build(:type_de_champ_repetition, :with_types_de_champ, procedure: procedure, mandatory: true, libelle: libelle, position: index)
|
|
|
|
else
|
|
|
|
build(:"type_de_champ_#{type_champ}", procedure: procedure, mandatory: true, libelle: libelle, position: index)
|
|
|
|
end
|
2018-11-22 00:14:16 +01:00
|
|
|
end
|
2020-08-27 19:55:37 +02:00
|
|
|
build(:type_de_champ_drop_down_list, :long, procedure: procedure, mandatory: true, libelle: 'simple_choice_drop_down_list_long', position: TypeDeChamp.type_champs.size)
|
|
|
|
build(:type_de_champ_multiple_drop_down_list, :long, procedure: procedure, mandatory: true, libelle: 'multiple_choice_drop_down_list_long', position: TypeDeChamp.type_champs.size + 1)
|
2018-11-22 00:14:16 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
trait :with_all_champs do
|
|
|
|
after(:build) do |procedure, _evaluator|
|
2020-08-27 19:55:37 +02:00
|
|
|
TypeDeChamp.type_champs.map.with_index do |(libelle, type_champ), index|
|
2018-11-22 00:14:16 +01:00
|
|
|
if libelle == 'drop_down_list'
|
|
|
|
libelle = 'simple_drop_down_list'
|
|
|
|
end
|
2022-11-30 12:05:27 +01:00
|
|
|
if type_champ == 'repetition'
|
|
|
|
build(:type_de_champ_repetition, :with_types_de_champ, procedure: procedure, libelle: libelle, position: index)
|
|
|
|
else
|
|
|
|
build(:"type_de_champ_#{type_champ}", procedure: procedure, libelle: libelle, position: index)
|
|
|
|
end
|
2018-11-22 00:14:16 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-01-23 09:52:20 +01:00
|
|
|
# TODO: rewrite with types_de_champ_private
|
2018-11-22 00:14:16 +01:00
|
|
|
trait :with_all_annotations do
|
|
|
|
after(:build) do |procedure, _evaluator|
|
2020-08-27 19:55:37 +02:00
|
|
|
TypeDeChamp.type_champs.map.with_index do |(libelle, type_champ), index|
|
2018-11-22 00:14:16 +01:00
|
|
|
if libelle == 'drop_down_list'
|
|
|
|
libelle = 'simple_drop_down_list'
|
|
|
|
end
|
2020-08-27 19:55:37 +02:00
|
|
|
build(:"type_de_champ_#{type_champ}", procedure: procedure, private: true, libelle: libelle, position: index)
|
2018-11-22 00:14:16 +01:00
|
|
|
end
|
2018-02-21 18:32:07 +01:00
|
|
|
end
|
|
|
|
end
|
2022-02-04 14:40:16 +01:00
|
|
|
|
|
|
|
trait :with_dossier_submitted_message do
|
|
|
|
after(:build) do |procedure, _evaluator|
|
2022-02-25 13:59:07 +01:00
|
|
|
build(:dossier_submitted_message, revisions: [procedure.active_revision])
|
2022-02-04 14:40:16 +01:00
|
|
|
end
|
|
|
|
end
|
2023-06-02 17:51:02 +02:00
|
|
|
|
|
|
|
trait :sva do
|
|
|
|
sva_svr { SVASVRConfiguration.new(decision: :sva).attributes }
|
|
|
|
end
|
2023-06-26 16:03:58 +02:00
|
|
|
|
|
|
|
trait :svr do
|
|
|
|
sva_svr { SVASVRConfiguration.new(decision: :svr).attributes }
|
|
|
|
end
|
2023-10-13 13:16:22 +02:00
|
|
|
|
|
|
|
trait :empty_chorus do
|
|
|
|
chorus { ChorusConfiguration.new }
|
|
|
|
end
|
|
|
|
|
|
|
|
trait :partial_chorus do
|
2023-11-09 09:59:04 +01:00
|
|
|
chorus { ChorusConfiguration.new(centre_de_cout: { a: 1 }) }
|
2023-10-13 13:16:22 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
trait :filled_chorus do
|
|
|
|
chorus do
|
2023-11-09 09:59:04 +01:00
|
|
|
ChorusConfiguration.new(centre_de_cout: { a: 1 },
|
2023-10-13 13:16:22 +02:00
|
|
|
domaine_fonctionnel: { b: 2 },
|
|
|
|
referentiel_de_programmation: { c: 3 })
|
|
|
|
end
|
|
|
|
end
|
2015-09-21 17:59:03 +02:00
|
|
|
end
|
|
|
|
end
|
2021-11-19 13:48:52 +01:00
|
|
|
|
2022-07-23 12:29:18 +02:00
|
|
|
def build_types_de_champ(types_de_champ, revision:, scope: :public, parent: nil)
|
|
|
|
types_de_champ.deep_dup.each.with_index do |type_de_champ_attributes, i|
|
2022-08-04 11:37:56 +02:00
|
|
|
type = TypeDeChamp.type_champs.fetch(type_de_champ_attributes.delete(:type) || :text).to_sym
|
2022-07-23 12:29:18 +02:00
|
|
|
position = type_de_champ_attributes.delete(:position) || i
|
|
|
|
children = type_de_champ_attributes.delete(:children)
|
|
|
|
options = type_de_champ_attributes.delete(:options)
|
|
|
|
layers = type_de_champ_attributes.delete(:layers)
|
|
|
|
|
2022-08-04 11:37:56 +02:00
|
|
|
if !options.nil?
|
2022-07-23 12:29:18 +02:00
|
|
|
if type == :drop_down_list
|
|
|
|
type_de_champ_attributes[:drop_down_other] = options.delete(:other).present?
|
|
|
|
end
|
|
|
|
|
|
|
|
if type.in?([:drop_down_list, :multiple_drop_down_list, :linked_drop_down_list])
|
2022-08-04 11:37:56 +02:00
|
|
|
type_de_champ_attributes[:drop_down_list_value] = options.join("\r\n")
|
2022-07-23 12:29:18 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if type == :linked_drop_down_list
|
|
|
|
type_de_champ_attributes[:drop_down_secondary_libelle] = type_de_champ_attributes.delete(:secondary_libelle)
|
|
|
|
type_de_champ_attributes[:drop_down_secondary_description] = type_de_champ_attributes.delete(:secondary_description)
|
|
|
|
end
|
|
|
|
|
|
|
|
if type == :carte && layers.present?
|
|
|
|
type_de_champ_attributes[:editable_options] = layers.index_with { '1' }
|
|
|
|
end
|
|
|
|
|
|
|
|
type_de_champ = if scope == :private
|
|
|
|
build(:"type_de_champ_#{type}", :private, no_coordinate: true, **type_de_champ_attributes)
|
|
|
|
else
|
|
|
|
build(:"type_de_champ_#{type}", no_coordinate: true, **type_de_champ_attributes)
|
|
|
|
end
|
|
|
|
coordinate = build(:procedure_revision_type_de_champ,
|
|
|
|
revision: revision,
|
|
|
|
type_de_champ: type_de_champ,
|
|
|
|
position: position,
|
|
|
|
parent: parent)
|
|
|
|
|
|
|
|
revision.association(:revision_types_de_champ).target << coordinate
|
|
|
|
|
|
|
|
if parent.present?
|
|
|
|
parent.association(:revision_types_de_champ).target << coordinate
|
|
|
|
end
|
|
|
|
|
|
|
|
if type_de_champ.repetition? && children.present?
|
|
|
|
build_types_de_champ(children, revision: revision, scope: scope, parent: coordinate)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if parent.present?
|
|
|
|
parent.association(:revision_types_de_champ).target.sort_by!(&:position)
|
|
|
|
else
|
|
|
|
revision_types_de_champ_private, revision_types_de_champ_public = revision.revision_types_de_champ.partition(&:private?)
|
|
|
|
|
|
|
|
root_revision_types_de_champ_public, child_revision_types_de_champ_public = revision_types_de_champ_public.partition { |coordinate| coordinate.parent.nil? }
|
|
|
|
root_revision_types_de_champ_private, child_revision_types_de_champ_private = revision_types_de_champ_private.partition { |coordinate| coordinate.parent.nil? }
|
|
|
|
revision.association(:revision_types_de_champ_public).target = root_revision_types_de_champ_public.sort_by(&:position)
|
|
|
|
revision.association(:revision_types_de_champ_private).target = root_revision_types_de_champ_private.sort_by(&:position)
|
|
|
|
revision.association(:revision_types_de_champ).target = revision.revision_types_de_champ_public +
|
|
|
|
revision.revision_types_de_champ_private +
|
|
|
|
child_revision_types_de_champ_public.sort_by(&:parent).sort_by(&:position) +
|
|
|
|
child_revision_types_de_champ_private.sort_by(&:parent).sort_by(&:position)
|
|
|
|
|
|
|
|
revision.association(:types_de_champ).target = revision.revision_types_de_champ.map(&:type_de_champ)
|
|
|
|
revision.association(:types_de_champ_public).target = revision.revision_types_de_champ_public.map(&:type_de_champ)
|
|
|
|
revision.association(:types_de_champ_private).target = revision.revision_types_de_champ_private.map(&:type_de_champ)
|
|
|
|
end
|
|
|
|
end
|