diff --git a/app/views/shared/_procedure_description.html.haml b/app/views/shared/_procedure_description.html.haml
index 27f4e266f..1ca1d8504 100644
--- a/app/views/shared/_procedure_description.html.haml
+++ b/app/views/shared/_procedure_description.html.haml
@@ -69,12 +69,22 @@
= pj.libelle
= t('utils.no_mandatory') if !pj.mandatory?
- - if procedure.persisted? && procedure.estimated_duration_visible?
+ - if @usual_traitement_time.present?
%section.fr-accordion
%h2.fr-accordion__title
%button.fr-accordion__btn{ "aria-controls" => "accordion-117", "aria-expanded" => "false" }
- = t('shared.procedure_description.estimated_fill_duration_title')
+ = t('shared.procedure_description.usual_traitement_time_title')
+
#accordion-117.fr-collapse
+ = t('shared.procedure_description.usual_traitement_time_detail_html', traitement_time: distance_of_time_in_words(@usual_traitement_time), percentile: ProcedureStatsConcern::USUAL_TRAITEMENT_TIME_PERCENTILE, days: ProcedureStatsConcern::NB_DAYS_RECENT_DOSSIERS, href: statistiques_path(procedure.path) )
+
+
+ - if procedure.persisted? && procedure.estimated_duration_visible?
+ %section.fr-accordion
+ %h2.fr-accordion__title
+ %button.fr-accordion__btn{ "aria-controls" => "accordion-118", "aria-expanded" => "false" }
+ = t('shared.procedure_description.estimated_fill_duration_title')
+ #accordion-118.fr-collapse
= t('shared.procedure_description.estimated_fill_duration_detail', estimated_minutes: estimated_fill_duration_minutes(procedure))
.fr-my-3w
@@ -89,4 +99,3 @@
= t('shared.procedure_description.sva_svr_prevision_date',
delay: t("x_#{procedure.sva_svr_configuration.unit}", count: procedure.sva_svr_configuration.period.to_i, scope: 'datetime.distance_in_words'),
date: l(SVASVRDecisionDateCalculatorService.decision_date_from_today(procedure), format: :long).gsub(' ', " "))
-
diff --git a/app/views/shared/dossiers/_update_champs.turbo_stream.haml b/app/views/shared/dossiers/_update_champs.turbo_stream.haml
new file mode 100644
index 000000000..f3ce3e5f2
--- /dev/null
+++ b/app/views/shared/dossiers/_update_champs.turbo_stream.haml
@@ -0,0 +1,15 @@
+- if to_show.present?
+ = turbo_stream.show_all(to_show)
+- if to_hide.present?
+ = turbo_stream.hide_all(to_hide)
+- to_update.each do |champ|
+ = fields_for champ.input_name, champ do |form|
+ - if champ.refresh_after_update?
+ = turbo_stream.replace champ.input_group_id do
+ = render EditableChamp::EditableChampComponent.new champ:, form:
+ - else
+ = turbo_stream.update champ.labelledby_id do
+ = render EditableChamp::ChampLabelContentComponent.new champ:, form:
+
+= turbo_stream.remove_all(".editable-champ .spinner-removable")
+= turbo_stream.hide_all(".editable-champ .spinner")
diff --git a/app/views/shared/dossiers/messages/_form.html.haml b/app/views/shared/dossiers/messages/_form.html.haml
index 5e616301c..7a26eb66f 100644
--- a/app/views/shared/dossiers/messages/_form.html.haml
+++ b/app/views/shared/dossiers/messages/_form.html.haml
@@ -1,20 +1,15 @@
= render NestedForms::FormOwnerComponent.new
-= form_for(commentaire, url: form_url, html: { multipart: true, data: { controller: 'persisted-form', persisted_form_key_value: @dossier.present? ? dom_id(@dossier) : dom_id(@procedure, :bulk_message) } }) do |f|
+= form_for(commentaire, url: form_url, html: { multipart: true, data: { controller: 'persisted-form', persisted_form_key_value: dom_id(@dossier) } }) do |f|
- dossier = commentaire.dossier
- placeholder = t('views.shared.dossiers.messages.form.write_message_to_administration_placeholder')
- if instructeur_signed_in? || administrateur_signed_in? || expert_signed_in?
- placeholder = t('views.shared.dossiers.messages.form.write_message_placeholder')
%p.mandatory-explanation= t('asterisk_html', scope: [:utils])
- .fr-input-group
- = label_tag :commentaire_body, class: 'fr-label' do
- = t('message', scope: [:utils])
- %span.mandatory *
- = f.text_area :body, rows: 5, placeholder: placeholder, title: placeholder, required: true, class: 'fr-input message-textarea'
- - disable_piece_jointe = defined?(disable_piece_jointe) ? disable_piece_jointe : false
- - if !disable_piece_jointe
- .fr-mt-3w
- = render Attachment::EditComponent.new(attached_file: commentaire.piece_jointe)
+ = render Dsfr::InputComponent.new(form: f, attribute: :body, input_type: :text_area, opts: { rows: 5, placeholder: placeholder, title: placeholder, class: 'fr-input message-textarea'})
+
+ .fr-mt-3w
+ = render Attachment::EditComponent.new(attached_file: commentaire.piece_jointe)
.fr-mt-3w
= f.submit t('views.shared.dossiers.messages.form.send_message'), class: 'fr-btn', data: { disable: true }
diff --git a/app/views/user_mailer/invite_instructeur.html.haml b/app/views/user_mailer/invite_instructeur.html.haml
index 2d597f427..2e5a5ad96 100644
--- a/app/views/user_mailer/invite_instructeur.html.haml
+++ b/app/views/user_mailer/invite_instructeur.html.haml
@@ -7,11 +7,18 @@
Vous venez d’être nommé instructeur sur #{APPLICATION_NAME}.
%p
- Votre compte a été créé pour l'adresse email #{@user.email}. Pour l’activer, je vous invite à cliquer sur le lien suivant :
+ Votre compte a été créé pour l'adresse email
+ %strong #{@user.email}.
+
+%p
+ Pour l’activer, cliquez sur le lien suivant :
= link_to(users_activate_url(token: @reset_password_token), users_activate_url(token: @reset_password_token))
%p
- Par ailleurs, nous vous invitons à prendre quelques minutes pour consulter notre tutoriel à destination des nouveaux instructeurs :
+ Lors de vos prochaines connexions sur #{APPLICATION_NAME} cliquez sur le bouton « Se connecter » positionné sur le haut de page ou bien sur ce lien :
+ = link_to new_user_session_url, new_user_session_url
+%p
+ Nous vous invitons aussi à consulter notre tutoriel à destination des nouveaux instructeurs :
= link_to(INSTRUCTEUR_TUTORIAL_URL, INSTRUCTEUR_TUTORIAL_URL)
= render partial: "layouts/mailers/signature"
diff --git a/app/views/users/activate/new.html.haml b/app/views/users/activate/new.html.haml
index 4089ceec0..8eac6851c 100644
--- a/app/views/users/activate/new.html.haml
+++ b/app/views/users/activate/new.html.haml
@@ -1,7 +1,9 @@
-.container
- = form_for @user, url: { controller: 'users/activate', action: :create }, html: { class: "form" } do |f|
- %br
- %h1= @user.email
- = f.password_field :password, placeholder: 'Mot de passe'
- = f.hidden_field :reset_password_token, value: params[:token]
- = f.submit 'Définir le mot de passe', class: 'button large primary expand'
+= content_for(:page_id, 'activate_account')
+= content_for(:title, t('metas.users.activate.title', application_name: APPLICATION_NAME))
+
+.fr-container.fr-my-5w
+ .fr-grid-row
+ .fr-col-12.fr-col-offset-md-2.fr-col-md-8
+ = render Instructeurs::ActivateAccountFormComponent.new(user: @user)
+
+= render partial: 'users/dossiers/index_footer'
diff --git a/app/views/users/dossiers/_dossiers_list.html.haml b/app/views/users/dossiers/_dossiers_list.html.haml
index 566c2dbd3..057ea81d6 100644
--- a/app/views/users/dossiers/_dossiers_list.html.haml
+++ b/app/views/users/dossiers/_dossiers_list.html.haml
@@ -37,9 +37,9 @@
= dossier.invites.map(&:email).join(', ')
.text-right
- %p.fr-mb-0
+ %p.fr-mb-0.width-max-content
= t('views.users.dossiers.dossiers_list.n_dossier')
- = dossier.id
+ = number_with_html_delimiter(dossier.id)
- if @statut == "dossiers-supprimes-recemment"
%span.fr-badge.fr-badge--sm.fr-badge--warning
diff --git a/app/views/users/dossiers/identite.html.haml b/app/views/users/dossiers/identite.html.haml
index d4019d360..ef60c6fde 100644
--- a/app/views/users/dossiers/identite.html.haml
+++ b/app/views/users/dossiers/identite.html.haml
@@ -34,4 +34,4 @@
= f.label :birthdate
= f.date_field :birthdate, value: @dossier.individual.birthdate, placeholder: 'format : AAAA-MM-JJ', required: true, class: "small"
- = f.submit t('views.users.dossiers.identite.continue'), class: "fr-btn fr-btn--lg"
+ = f.submit t('views.users.dossiers.identite.continue'), class: "fr-btn fr-btn--lg fr-mt-4w"
diff --git a/app/views/users/dossiers/update.turbo_stream.haml b/app/views/users/dossiers/update.turbo_stream.haml
index e998f507c..b7c234b23 100644
--- a/app/views/users/dossiers/update.turbo_stream.haml
+++ b/app/views/users/dossiers/update.turbo_stream.haml
@@ -1,17 +1,4 @@
-- if @to_show.present?
- = turbo_stream.show_all(@to_show)
-- if @to_hide.present?
- = turbo_stream.hide_all(@to_hide)
-- @to_update.each do |champ|
- = fields_for champ.input_name, champ do |form|
- - if champ.refresh_after_update?
- = turbo_stream.replace champ.input_group_id do
- = render EditableChamp::EditableChampComponent.new champ:, form:
- - else
- = turbo_stream.update champ.labelledby_id do
- = render EditableChamp::ChampLabelContentComponent.new champ:, form:
+= render partial: 'shared/dossiers/update_champs', locals: { to_show: @to_show, to_hide: @to_hide, to_update: @to_update, dossier: @dossier, annotation: false }
-= turbo_stream.remove_all(".editable-champ .spinner-removable");
-= turbo_stream.hide_all(".editable-champ .spinner");
= turbo_stream.replace_all '.dossier-edit-sticky-footer' do
= render Dossiers::EditFooterComponent.new(dossier: @dossier, annotation: false)
diff --git a/app/views/users/profil/show.html.haml b/app/views/users/profil/show.html.haml
index 4ced0acba..6aed93abb 100644
--- a/app/views/users/profil/show.html.haml
+++ b/app/views/users/profil/show.html.haml
@@ -39,8 +39,8 @@
application_name: APPLICATION_NAME,
legit_admin_domains: LEGIT_ADMIN_DOMAINS.join(', '))
- = form_for current_user, url: update_email_path, method: :patch, html: { class: 'form' } do |f|
- = f.email_field :email, value: nil, placeholder: t('.new_email_address'), required: true
+ = form_for current_user, url: update_email_path, method: :patch do |f|
+ = render Dsfr::InputComponent.new(form: f, attribute: :email, input_type: :email_field, opts: { value: nil, placeholder: t('.new_email_address') })
= f.submit t('.change_address'), class: 'fr-btn fr-btn--secondary'
- if !instructeur_signed_in?
diff --git a/app/views/users/sessions/link_sent.html.haml b/app/views/users/sessions/link_sent.html.haml
index cc4b44efe..9f8fd76dc 100644
--- a/app/views/users/sessions/link_sent.html.haml
+++ b/app/views/users/sessions/link_sent.html.haml
@@ -3,18 +3,27 @@
- content_for :footer do
= render partial: 'root/footer'
-#link-sent.container
- = image_tag('user/confirmation-email.svg', "aria-hidden": true)
- %h1 Encore une petite étape :)
+.fr-container.fr-my-5w
+ .fr-grid-row
+ .fr-col-12.fr-col-offset-md-1.fr-col-md-7
+ %h1.fr-mt-6w Encore une petite étape !
- %section.link-sent-info
- %p
- Ouvrez votre boite email
#{@email} puis cliquez sur le lien d’activation du message
Connexion sécurisée à #{APPLICATION_NAME}.
- %p
- = t('views.users.shared.email_can_take_a_while_html')
+ %section
+ %p.fr-text--lead
+ Nous venons de vous envoyer un courriel sur votre boite email
#{@email}.
+ Veuillez l’ouvrir et cliquer sur le lien de
connexion sécurisée à #{APPLICATION_NAME}.
- %section.link-sent-help
- %p
- Si vous voyez cette page trop souvent, consultez notre aide : #{link_to t("links.common.faq.confirmer_compte_chaque_connexion_url"), **external_link_attributes}
- %p
- = t('views.users.shared.contact_us_if_any_trouble_html', href: contact_admin_url)
+ %p.fr-text--lead
+ Ce lien est
valide une semaine et peut être réutilisé
plusieurs fois.
+
+ %p.fr-text--sm.fr-text-mention--grey
+ Ce courriel peut mettre jusqu’à
15 minutes pour arriver. Si vous n’avez pas reçu de courriel (n’hésitez pas à vérifier dans les indésirables), cliquez sur le bouton ci-dessous.
+
+ = button_to instructeurs_reset_link_sent_path, class: 'fr-btn fr-btn--secondary fr-btn--icon-left fr-icon-mail-line', method: 'POST' do
+ Renvoyer le courriel
+
+ %section
+ %p.fr-mt-3w
+ Si vous voyez cette page trop souvent, consultez notre aide : #{link_to t("links.common.faq.confirmer_compte_chaque_connexion_url"), **external_link_attributes}
+ %p.fr-mt-3w
+ = t('views.users.shared.contact_us_if_any_trouble_html', href: contact_admin_url)
diff --git a/app/views/users/sessions/new.html.haml b/app/views/users/sessions/new.html.haml
index 2b33d5437..76863f1d5 100644
--- a/app/views/users/sessions/new.html.haml
+++ b/app/views/users/sessions/new.html.haml
@@ -1,7 +1,6 @@
= content_for(:page_id, 'auth')
= content_for(:title, t('metas.signin.title'))
-
#session-new.auth-form.sign-in-form
= form_for resource, url: user_session_path, html: { class: "fr-py-5w" } do |f|
diff --git a/config/initializers/02_urls.rb b/config/initializers/02_urls.rb
index 4c7b1a256..f47dfcfc7 100644
--- a/config/initializers/02_urls.rb
+++ b/config/initializers/02_urls.rb
@@ -8,7 +8,6 @@ API_PARTICULIER_URL = ENV.fetch("API_PARTICULIER_URL", "https://particulier.api.
API_TCHAP_URL = ENV.fetch("API_TCHAP_URL", "https://matrix.agent.tchap.gouv.fr/_matrix/identity/api/v1")
API_COJO_URL = ENV.fetch("API_COJO_URL", nil)
HELPSCOUT_API_URL = ENV.fetch("HELPSCOUT_API_URL", "https://api.helpscout.net/v2")
-PIPEDRIVE_API_URL = ENV.fetch("PIPEDRIVE_API_URL", "https://api.pipedrive.com/v1")
SENDINBLUE_API_URL = ENV.fetch("SENDINBLUE_API_URL", "https://in-automate.sendinblue.com/api/v2")
SENDINBLUE_API_V3_URL = ENV.fetch("SENDINBLUE_API_V3_URL", "https://api.sendinblue.com/v3")
UNIVERSIGN_API_URL = ENV.fetch("UNIVERSIGN_API_URL", "https://ws.universign.eu/tsa/post/")
diff --git a/config/initializers/graphql.rb b/config/initializers/graphql.rb
index e669da38b..28e39e2aa 100644
--- a/config/initializers/graphql.rb
+++ b/config/initializers/graphql.rb
@@ -3,3 +3,15 @@ GraphQL::RailsLogger.configure do |config|
'API::V2::GraphqlController' => ['execute']
}
end
+
+module GraphQL
+ class Schema
+ class Member
+ module BuildType
+ def self.camelize(string)
+ string.camelize(:lower)
+ end
+ end
+ end
+ end
+end
diff --git a/config/initializers/lograge.rb b/config/initializers/lograge.rb
index 40cd8c01a..b5795fde2 100644
--- a/config/initializers/lograge.rb
+++ b/config/initializers/lograge.rb
@@ -18,6 +18,7 @@ Rails.application.configure do
graphql_variables: event.payload[:graphql_variables],
graphql_null_error: event.payload[:graphql_null_error],
graphql_timeout_error: event.payload[:graphql_timeout_error],
+ graphql_mutation: event.payload[:graphql_mutation],
ds_procedure_id: event.payload[:ds_procedure_id],
ds_dossier_id: event.payload[:ds_dossier_id],
browser: event.payload[:browser],
diff --git a/config/initializers/new_framework_defaults_7_0.rb b/config/initializers/new_framework_defaults_7_0.rb
index b90fb14e4..14380b98a 100644
--- a/config/initializers/new_framework_defaults_7_0.rb
+++ b/config/initializers/new_framework_defaults_7_0.rb
@@ -73,7 +73,7 @@ Rails.application.config.action_controller.raise_on_open_redirects = true
# generate variants to use image processing macros and ruby-vips
# operations. See the upgrading guide for detail on the changes required.
# The `:mini_magick` option is not deprecated; it's fine to keep using it.
-Rails.application.config.active_storage.variant_processor = :vips
+Rails.application.config.active_storage.variant_processor = :mini_magick
# Enable parameter wrapping for JSON.
# Previously this was set in an initializer. It's fine to keep using that initializer if you've customized it.
diff --git a/config/locales/en.yml b/config/locales/en.yml
index b26f2de22..616cc3df1 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -515,7 +515,7 @@ en:
check_france_connect_html: Have you once logged in with France Connect? If yes,
try again with France Connect.
check_gpdr: "The account may have been deleted in the event of prolonged inactivity and no current file. In this case you will have to recreate an account from a procedure."
shared:
- email_can_take_a_while_html:
Please note that this message can take up to 15 minutes to arrive.
+ email_can_take_a_while_html:
Please note that this email can take up to 15 minutes to arrive.
contact_us_if_any_trouble_html: 'You can contact us
through this form if a problem still exists.'
modal:
publish:
@@ -849,6 +849,8 @@ en:
estimated_fill_duration: "Estimated fill time: %{estimated_minutes} mn"
estimated_fill_duration_title: What is the procedure estimated fill time ?
estimated_fill_duration_detail: "The fill time is etimated to %{estimated_minutes} min. This period may vary depending on the options you choose"
+ usual_traitement_time_title: What are the processing times for this procedure?
+ usual_traitement_time_detail_html: Usually, files in this procedure are processed within %{traitement_time}. This estimate is calculated automatically from the processing times observed on %{percentile}% of requests that have been processed during the last %{days} days. Actual lead time may vary. For more information, you can
consult the statistics page of this procedure.
pieces_jointes : What are the required attachments ?
pieces_jointes_conditionnal_list_title : Attachments list according to your situation
sva_svr_title: "This procedure applies the « %{rule} »"
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index fea2eceff..58abcf5df 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -309,6 +309,7 @@ fr:
invite_to_edit_line1: Vous pouvez inviter quelqu’un à remplir ce dossier avec vous.
invite_to_edit_line2: Cette personne aura le droit de modifier votre dossier.
email: Adresse mail
+ email_hint: "Exemple : camilya.martin@exemple.fr"
invite_message: Ajouter un message à la personne invitée (optionnel)
send_invitation: Envoyer une invitation
invite_to_participate: "Personnes invitées à participer à ce dossier"
@@ -462,7 +463,7 @@ fr:
index:
dossiers: "Mes dossiers"
dossiers_list:
- n_dossier: "Nº dossier"
+ n_dossier: "dossier Nº "
no_result_title: Aucun dossier
no_result_text_html: "Pour remplir une démarche, contactez votre administration en lui demandant le lien de la démarche.
Celui ci doit ressembler à %{app_base}/commencer/xxx."
no_result_text_with_filter: ne correspond aux filtres sélectionnés
@@ -518,7 +519,7 @@ fr:
open_your_mailbox: "Maintenant ouvrez votre boite email."
title: "Lien de réinitialisation du mot de passe envoyé"
shared:
- email_can_take_a_while_html: "
Attention, ce message peut mettre jusqu’à
15 minutes pour arriver."
+ email_can_take_a_while_html: "
Attention, ce courriel peut mettre jusqu’à
15 minutes pour arriver."
contact_us_if_any_trouble_html: 'En cas de difficultés, nous restons joignables
via ce formulaire.'
modal:
publish:
@@ -737,7 +738,7 @@ fr:
other: demandes de transfert
dossiers_close_to_expiration:
one: expirant
- other: expirant
+ other: expirants
dossier_trouve:
one: "%{count} dossier trouvé"
other: "%{count} dossiers trouvés"
@@ -903,6 +904,8 @@ fr:
estimated_fill_duration: "Temps de remplissage estimé : %{estimated_minutes} mn"
estimated_fill_duration_title: Quelle est la durée de remplissage de la démarche ?
estimated_fill_duration_detail: "La durée de remplissage est estimée à %{estimated_minutes} min. Ce délai peut varier selon les options que vous choisirez."
+ usual_traitement_time_title: Quels sont des délais d'instruction pour cette démarche ?
+ usual_traitement_time_detail_html: Habituellement, les dossiers de cette démarche sont traités dans un délai de %{traitement_time}. Cette estimation est calculée automatiquement à partir des délais d’instruction constatés sur %{percentile}% des demandes qui ont été traitées lors des %{days} derniers jours. Le délai réel peut être différent. Pour plus d'informations, vous pouvez
consulter la page statistiques de cette démarche.
pieces_jointes : Quelles sont les pièces justificatives à fournir ?
pieces_jointes_conditionnal_list_title : Liste des pièces en fonction de votre situation
sva_svr_title: "Cette démarche applique le « %{rule} »"
diff --git a/config/locales/metas.en.yml b/config/locales/metas.en.yml
index adb3709cb..4cbf750ce 100644
--- a/config/locales/metas.en.yml
+++ b/config/locales/metas.en.yml
@@ -17,3 +17,5 @@ en:
title: "Modification of draft nº %{number} (%{procedure_label})"
merci:
title: "File submitted (%{procedure_label})"
+ activate:
+ title: Activate my account on %{application_name}
diff --git a/config/locales/metas.fr.yml b/config/locales/metas.fr.yml
index c7ae048eb..5261f1215 100644
--- a/config/locales/metas.fr.yml
+++ b/config/locales/metas.fr.yml
@@ -17,3 +17,5 @@ fr:
title: "Modification du brouillon nº %{number} (%{procedure_label})"
merci:
title: "Dossier envoyé (%{procedure_label})"
+ activate:
+ title: Activer mon compte sur %{application_name}
diff --git a/config/locales/models/bulk_message/en.yml b/config/locales/models/bulk_message/en.yml
new file mode 100644
index 000000000..c1a59b743
--- /dev/null
+++ b/config/locales/models/bulk_message/en.yml
@@ -0,0 +1,9 @@
+en:
+ activerecord:
+ models:
+ bulk_message:
+ one: "Bulk message to users"
+ other: "Bulk message to users"
+ attributes:
+ bulk_message:
+ body: Content
diff --git a/config/locales/models/bulk_message/fr.yml b/config/locales/models/bulk_message/fr.yml
new file mode 100644
index 000000000..04c830d1f
--- /dev/null
+++ b/config/locales/models/bulk_message/fr.yml
@@ -0,0 +1,9 @@
+fr:
+ activerecord:
+ models:
+ bulk_message:
+ one: "Message aux usagers"
+ other: "Messages aux usagers"
+ attributes:
+ bulk_message:
+ body: "Message envoyé aux destinataires :"
diff --git a/config/locales/models/procedure_presentation/en.yml b/config/locales/models/procedure_presentation/en.yml
index 9d3fbcd7b..3861e1234 100644
--- a/config/locales/models/procedure_presentation/en.yml
+++ b/config/locales/models/procedure_presentation/en.yml
@@ -32,6 +32,7 @@ en:
gender: Title
avis:
answer: Opinion
+ question_answer: Opinion yes/no
etablissement:
entreprise_siren: SIREN
entreprise_forme_juridique: Forme juridique
diff --git a/config/locales/models/procedure_presentation/fr.yml b/config/locales/models/procedure_presentation/fr.yml
index 650ab6afc..6f6fab137 100644
--- a/config/locales/models/procedure_presentation/fr.yml
+++ b/config/locales/models/procedure_presentation/fr.yml
@@ -32,6 +32,7 @@ fr:
gender: Civilité
avis:
answer: Avis
+ question_answer: Avis oui/non
etablissement:
entreprise_siren: SIREN
entreprise_forme_juridique: Forme juridique
diff --git a/config/locales/models/service/fr.yml b/config/locales/models/service/fr.yml
index e7158667e..40b6a2e0b 100644
--- a/config/locales/models/service/fr.yml
+++ b/config/locales/models/service/fr.yml
@@ -9,6 +9,25 @@ fr:
adresse: 'Adresse postale'
email: 'Email de contact'
telephone: 'Téléphone'
+ nom: Nom du service
+ organisme: Organisme(s)
+ hints:
+ nom: |
+ Indiquez le nom et la direction rattachée, séparés par une virgule.
+ Exemple : service jeunesse et prévention, direction des affaires maritimes
+ organisme: |
+ Indiquez les organismes depuis l’échelon territorial jusqu’au ministère séparés par une virgule.
+ Exemple : mairie de Mours, préfecture de l'Oise, ministère de la Culture
+ email: |
+ Indiquez une adresse email valide qui permettra de recevoir et de répondre aux questions des usagers.
+ Exemple : contact@mairie-de-mours.fr
+ telephone: "Indiquez le numéro de téléphone du service valide le plus à même de fournir des réponses pertinentes à vos usagers. Exemple : 01 23 45 67 89"
+ horaires: |
+ Indiquez les jours ouvrables et les horaires où les usagers peuvent vous joindre.
+ Exemple : Du lundi au vendredi de 9h30 à 17h30, le samedi de 9h30 à 12h.
+ adresse: |
+ Indiquez l’adresse à laquelle un usager peut vous contacter, par exemple s’il n’est pas en capacité de compléter son formulaire en ligne.
+
errors:
models:
service:
diff --git a/config/locales/views/instructeurs/procedures/en.yml b/config/locales/views/instructeurs/procedures/en.yml
index dab0dce11..e8d267ca7 100644
--- a/config/locales/views/instructeurs/procedures/en.yml
+++ b/config/locales/views/instructeurs/procedures/en.yml
@@ -12,8 +12,11 @@ en:
copy_link_button: Copy the procedure link to clipboard
email_usagers:
contact_users: Contact users (draft)
- notice: "You will send a message to %{dossiers_count} whose files are in draft, in the instructor groups : %{groupe_instructeurs}."
+ hint:
+ zero: "There is no user with a draft."
+ one: "You will send a message to
1 user."
+ other: "You will send a message to
%{count} users."
administrators_list:
title: "%{procedure_libelle} - n°%{procedure_id} - administrators"
- stats:
+ stats:
title: Statistics
diff --git a/config/locales/views/instructeurs/procedures/fr.yml b/config/locales/views/instructeurs/procedures/fr.yml
index e2d643394..886464b85 100644
--- a/config/locales/views/instructeurs/procedures/fr.yml
+++ b/config/locales/views/instructeurs/procedures/fr.yml
@@ -12,7 +12,10 @@ fr:
copy_link_button: Copier le lien de la démarche dans le presse-papiers
email_usagers:
contact_users: Contacter les usagers (brouillon)
- notice: "Vous allez envoyer un message à %{dossiers_count} dont les dossiers sont en brouillon, dans les groupes instructeurs : %{groupe_instructeurs}."
+ hint:
+ zero: "Aucun usager n'a de dossier en brouillon."
+ one: "Vous allez envoyer un message à
1 usager ayant un dossier en brouillon."
+ other: "Vous allez envoyer un message à
%{count} usagers ayant un dossier en brouillon."
administrators_list:
title: "%{procedure_libelle} - n°%{procedure_id} - administrateurs"
stats:
diff --git a/config/routes.rb b/config/routes.rb
index eb74b18a6..dbe210a06 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -56,8 +56,6 @@ Rails.application.routes.draw do
resources :dossiers, only: [:show]
- resources :demandes, only: [:index]
-
resources :bill_signatures, only: [:index]
resources :exports, only: [:index, :show]
@@ -80,9 +78,6 @@ Rails.application.routes.draw do
end
resources :safe_mailers, only: [:index, :edit, :update, :destroy, :new, :create, :show]
- post 'demandes/create_administrateur'
- post 'demandes/refuse_administrateur'
-
authenticate :super_admin do
mount Flipper::UI.app(-> { Flipper.instance }) => "/features", as: :flipper
match "/delayed_job" => DelayedJobWeb, :anchor => false, :via => [:get, :post]
@@ -130,6 +125,7 @@ Rails.application.routes.draw do
get '/users/no_procedure' => 'users/sessions#no_procedure'
get 'connexion-par-jeton/:id' => 'users/sessions#sign_in_by_link', as: 'sign_in_by_link'
get 'lien-envoye' => 'users/sessions#link_sent', as: 'link_sent'
+ post '/instructeurs/reset-link-sent' => 'users/sessions#reset_link_sent'
get '/users/password/reset-link-sent' => 'users/passwords#reset_link_sent'
end
@@ -351,6 +347,8 @@ Rails.application.routes.draw do
delete 'france_connect_information' => 'profil#destroy_fci'
end
+ get 'procedures/:id/logo', to: 'procedures#logo', as: :procedure_logo
+
#
# Expert
#
diff --git a/config/secrets.yml b/config/secrets.yml
index cf527bafe..866fa6159 100644
--- a/config/secrets.yml
+++ b/config/secrets.yml
@@ -45,8 +45,6 @@ defaults: &defaults
api_key: <%= ENV['DOLIST_API_KEY'] %>
api_entreprise:
key: <%= ENV['API_ENTREPRISE_KEY'] %>
- pipedrive:
- key: <%= ENV['PIPEDRIVE_KEY'] %>
mailtrap:
username: <%= ENV['MAILTRAP_USERNAME'] %>
password: <%= ENV['MAILTRAP_PASSWORD'] %>
@@ -111,8 +109,6 @@ test:
key_derivation_salt: test-yyMmzM9cTSD1rs3Fq3hwt3hMNg4 # ggignore
api_entreprise:
key: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ik9oIHllYWgiLCJpYXQiOjE1MTYyMzkwMjJ9.f06sBo3q2Yxnw_TYPFUEs0CozBmcV-XniH_DeKNWzKE" # ggignore
- pipedrive:
- key: pipedrive_test_key
france_connect_particulier:
identifier: france_connect_test_identifier
secret: france_connect_test_secret
diff --git a/db/migrate/20230713163641_remove_dossier_corrections_kind.rb b/db/migrate/20230713163641_remove_dossier_corrections_kind.rb
new file mode 100644
index 000000000..2b387513c
--- /dev/null
+++ b/db/migrate/20230713163641_remove_dossier_corrections_kind.rb
@@ -0,0 +1,7 @@
+class RemoveDossierCorrectionsKind < ActiveRecord::Migration[7.0]
+ def change
+ safety_assured do
+ remove_column :dossier_corrections, :kind, :string, default: 'incorrect', null: false
+ end
+ end
+end
diff --git a/db/migrate/20230801102740_add_last_authenticated_at_to_api_tokens.rb b/db/migrate/20230801102740_add_last_authenticated_at_to_api_tokens.rb
new file mode 100644
index 000000000..08d6ce8b9
--- /dev/null
+++ b/db/migrate/20230801102740_add_last_authenticated_at_to_api_tokens.rb
@@ -0,0 +1,6 @@
+class AddLastAuthenticatedAtToAPITokens < ActiveRecord::Migration[7.0]
+ def change
+ add_column :api_tokens, :last_v1_authenticated_at, :datetime
+ add_column :api_tokens, :last_v2_authenticated_at, :datetime
+ end
+end
diff --git a/db/migrate/20230801121131_remove_migrated_champ_routage_columns.rb b/db/migrate/20230801121131_remove_migrated_champ_routage_columns.rb
new file mode 100644
index 000000000..4a95b2f7d
--- /dev/null
+++ b/db/migrate/20230801121131_remove_migrated_champ_routage_columns.rb
@@ -0,0 +1,7 @@
+class RemoveMigratedChampRoutageColumns < ActiveRecord::Migration[7.0]
+ def change
+ safety_assured { remove_column :procedures, :migrated_champ_routage }
+ safety_assured { remove_column :procedure_revisions, :migrated_champ_routage }
+ safety_assured { remove_column :dossiers, :migrated_champ_routage }
+ end
+end
diff --git a/db/migrate/20230802161011_remove_routing_criteria_name_column.rb b/db/migrate/20230802161011_remove_routing_criteria_name_column.rb
new file mode 100644
index 000000000..7861905f9
--- /dev/null
+++ b/db/migrate/20230802161011_remove_routing_criteria_name_column.rb
@@ -0,0 +1,7 @@
+class RemoveRoutingCriteriaNameColumn < ActiveRecord::Migration[7.0]
+ def change
+ safety_assured do
+ remove_column :procedures, :routing_criteria_name, :string, default: "Votre ville"
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 675a76a15..8837e43d6 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.0].define(version: 2023_07_19_112020) do
+ActiveRecord::Schema[7.0].define(version: 2023_08_02_161011) do
# These are extensions that must be enabled in order to support this database
enable_extension "pgcrypto"
enable_extension "plpgsql"
@@ -93,6 +93,8 @@ ActiveRecord::Schema[7.0].define(version: 2023_07_19_112020) do
t.bigint "allowed_procedure_ids", array: true
t.datetime "created_at", precision: 6, null: false
t.string "encrypted_token", null: false
+ t.datetime "last_v1_authenticated_at"
+ t.datetime "last_v2_authenticated_at"
t.string "name", null: false
t.datetime "updated_at", precision: 6, null: false
t.integer "version", default: 3, null: false
@@ -336,7 +338,6 @@ ActiveRecord::Schema[7.0].define(version: 2023_07_19_112020) do
t.bigint "dossier_id", null: false
t.datetime "resolved_at", precision: 6
t.datetime "updated_at", precision: 6, null: false
- t.string "kind", default: "correction", null: false
t.string "reason", default: "incorrect", null: false
t.index ["commentaire_id"], name: "index_dossier_corrections_on_commentaire_id"
t.index ["dossier_id"], name: "index_dossier_corrections_on_dossier_id"
@@ -776,7 +777,6 @@ ActiveRecord::Schema[7.0].define(version: 2023_07_19_112020) do
t.datetime "published_at", precision: 6
t.bigint "published_revision_id"
t.bigint "replaced_by_procedure_id"
- t.text "routing_criteria_name", default: "Votre ville"
t.boolean "routing_enabled"
t.bigint "service_id"
t.jsonb "sva_svr", default: {}, null: false
diff --git a/lib/tasks/auto_annotate_models.rake b/lib/tasks/auto_annotate_models.rake
deleted file mode 100644
index c972ee747..000000000
--- a/lib/tasks/auto_annotate_models.rake
+++ /dev/null
@@ -1,59 +0,0 @@
-# NOTE: only doing this in development as some production environments (Heroku)
-# NOTE: are sensitive to local FS writes, and besides -- it's just not proper
-# NOTE: to have a dev-mode tool do its thing in production.
-if Rails.env.development?
- require 'annotate'
- task :set_annotation_options do
- # You can override any of these by setting an environment variable of the
- # same name.
- Annotate.set_defaults(
- 'active_admin' => 'false',
- 'additional_file_patterns' => [],
- 'routes' => 'false',
- 'models' => 'true',
- 'position_in_routes' => 'before',
- 'position_in_class' => 'before',
- 'position_in_test' => 'before',
- 'position_in_fixture' => 'before',
- 'position_in_factory' => 'before',
- 'position_in_serializer' => 'before',
- 'show_foreign_keys' => 'false',
- 'show_complete_foreign_keys' => 'false',
- 'show_indexes' => 'false',
- 'simple_indexes' => 'false',
- 'model_dir' => 'app/models',
- 'root_dir' => '',
- 'include_version' => 'false',
- 'require' => '',
- 'exclude_tests' => 'true',
- 'exclude_fixtures' => 'true',
- 'exclude_factories' => 'true',
- 'exclude_serializers' => 'true',
- 'exclude_scaffolds' => 'true',
- 'exclude_controllers' => 'true',
- 'exclude_helpers' => 'true',
- 'exclude_sti_subclasses' => 'false',
- 'ignore_model_sub_dir' => 'false',
- 'ignore_columns' => nil,
- 'ignore_routes' => nil,
- 'ignore_unknown_models' => 'true',
- 'hide_limit_column_types' => 'integer,bigint,boolean',
- 'hide_default_column_types' => 'json,jsonb,hstore',
- 'skip_on_db_migrate' => 'false',
- 'format_bare' => 'true',
- 'format_rdoc' => 'false',
- 'format_yard' => 'false',
- 'format_markdown' => 'false',
- 'sort' => 'false',
- 'force' => 'false',
- 'frozen' => 'false',
- 'classified_sort' => 'true',
- 'trace' => 'false',
- 'wrapper_open' => nil,
- 'wrapper_close' => nil,
- 'with_comment' => 'true'
- )
- end
-
- Annotate.load_tasks
-end
diff --git a/lib/tasks/deployment/20230718143350_reset_dossier_brouillon_groupe_instructeur_id.rake b/lib/tasks/deployment/20230718143350_reset_dossier_brouillon_groupe_instructeur_id.rake
new file mode 100644
index 000000000..a76286bd9
--- /dev/null
+++ b/lib/tasks/deployment/20230718143350_reset_dossier_brouillon_groupe_instructeur_id.rake
@@ -0,0 +1,21 @@
+namespace :after_party do
+ desc 'Deployment task: reset_dossier_brouillon_groupe_instructeur_id'
+ task reset_dossier_brouillon_groupe_instructeur_id: :environment do
+ puts "Running deploy task 'reset_dossier_brouillon_groupe_instructeur_id'"
+
+ dossier_brouillon = Dossier.state_brouillon.where.not(groupe_instructeur_id: nil)
+ progress = ProgressReport.new(dossier_brouillon.count)
+
+ # Put your task implementation HERE.
+ dossier_brouillon.in_batches do |relation|
+ progress.inc(relation.count)
+ relation.update_all(groupe_instructeur_id: nil)
+ end
+
+ progress.finish
+ # Update task as completed. If you remove the line below, the task will
+ # run with every deploy (or every time you call after_party:run).
+ AfterParty::TaskRecord
+ .create version: AfterParty::TaskRecorder.new(__FILE__).timestamp
+ end
+end
diff --git a/lib/tasks/deployment/20230721145042_purge_invalid_geo_areas.rake b/lib/tasks/deployment/20230721145042_purge_invalid_geo_areas.rake
deleted file mode 100644
index 0ab8d4730..000000000
--- a/lib/tasks/deployment/20230721145042_purge_invalid_geo_areas.rake
+++ /dev/null
@@ -1,22 +0,0 @@
-namespace :after_party do
- desc 'Deployment task: purge_invalid_geo_areas'
- task purge_invalid_geo_areas: :environment do
- puts "Running deploy task 'purge_invalid_geo_areas'"
-
- geo_areas = GeoArea.selections_utilisateur
- progress = ProgressReport.new(geo_areas.count)
-
- geo_areas.find_each do |geo_area|
- if !geo_area.valid?
- geo_area.destroy
- end
- progress.inc
- end
- progress.finish
-
- # Update task as completed. If you remove the line below, the task will
- # run with every deploy (or every time you call after_party:run).
- AfterParty::TaskRecord
- .create version: AfterParty::TaskRecorder.new(__FILE__).timestamp
- end
-end
diff --git a/lib/tasks/deployment/20230728085422_update_routing_rule_for_groups_routing_from_drop_down_other.rake b/lib/tasks/deployment/20230728085422_update_routing_rule_for_groups_routing_from_drop_down_other.rake
new file mode 100644
index 000000000..672975800
--- /dev/null
+++ b/lib/tasks/deployment/20230728085422_update_routing_rule_for_groups_routing_from_drop_down_other.rake
@@ -0,0 +1,23 @@
+namespace :after_party do
+ desc 'Deployment task: update_routing_rule_for_groups_routing_from_drop_down_other'
+ task update_routing_rule_for_groups_routing_from_drop_down_other: :environment do
+ puts "Running deploy task 'update_routing_rule_for_groups_routing_from_drop_down_other'"
+
+ # Put your task implementation HERE.
+ include Logic
+
+ GroupeInstructeur
+ .joins(:procedure)
+ .where(procedures: { routing_enabled: true })
+ .in_batches do |groupe_instructeurs|
+ groupe_instructeurs
+ .filter { |gi| gi.routing_rule.present? && gi.routing_rule.right.value == 'Autre' }
+ .each { |gi| gi.update(routing_rule: ds_eq(gi.routing_rule.left, constant('__other__'))) }
+ end
+
+ # Update task as completed. If you remove the line below, the task will
+ # run with every deploy (or every time you call after_party:run).
+ AfterParty::TaskRecord
+ .create version: AfterParty::TaskRecorder.new(__FILE__).timestamp
+ end
+end
diff --git a/lib/tasks/routing_engine.rake b/lib/tasks/routing_engine.rake
new file mode 100644
index 000000000..f62f28805
--- /dev/null
+++ b/lib/tasks/routing_engine.rake
@@ -0,0 +1,23 @@
+require Rails.root.join("lib", "tasks", "task_helper")
+
+namespace :routing_engine do
+ desc <<~EOD
+ Given an id in argument, run the RoutingEngine for a dossier, after having set `forced_groupe_instructeur` field to false.
+ ex: rails routing_engine:run\[1352684\]
+ EOD
+ task :run, [:dossier_id] => :environment do |_t, args|
+ dossier = Dossier.find_by(id: args[:dossier_id])
+
+ if dossier.present?
+ dossier.update!(forced_groupe_instructeur: false)
+
+ dossier.reload
+
+ RoutingEngine.compute(dossier)
+
+ rake_puts "Dossier #{args[:dossier_id]} routed to groupe instructeur #{dossier.groupe_instructeur.label}"
+ else
+ rake_puts "Dossier with id #{args[:dossier_id]} not found in db"
+ end
+ end
+end
diff --git a/package.json b/package.json
index 6efef06ab..8228a19ce 100644
--- a/package.json
+++ b/package.json
@@ -1,8 +1,8 @@
{
"dependencies": {
- "@coldwired/actions": "^0.11.0",
- "@coldwired/turbo-stream": "^0.11.0",
- "@coldwired/utils": "^0.10.0",
+ "@coldwired/actions": "^0.11.1",
+ "@coldwired/turbo-stream": "^0.11.1",
+ "@coldwired/utils": "^0.11.1",
"@gouvfr/dsfr": "^1.7.2",
"@graphiql/plugin-explorer": "^0.2.0",
"@graphiql/toolkit": "^0.8.4",
diff --git a/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb b/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb
index fdaeb450a..40c731ae4 100644
--- a/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb
+++ b/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb
@@ -719,25 +719,47 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do
end
describe '#create_simple_routing' do
- let!(:procedure3) do
- create(:procedure,
- types_de_champ_public: [
- { type: :drop_down_list, libelle: 'Votre ville', options: ['Paris', 'Lyon', 'Marseille'] },
- { type: :text, libelle: 'Un champ texte' }
- ],
- administrateurs: [admin])
+ context 'with a drop_down_list type de champ' do
+ let!(:procedure3) do
+ create(:procedure,
+ types_de_champ_public: [
+ { type: :drop_down_list, libelle: 'Votre ville', options: ['Paris', 'Lyon', 'Marseille'] },
+ { type: :text, libelle: 'Un champ texte' }
+ ],
+ administrateurs: [admin])
+ end
+
+ let!(:drop_down_tdc) { procedure3.draft_revision.types_de_champ.first }
+
+ before { post :create_simple_routing, params: { procedure_id: procedure3.id, create_simple_routing: { stable_id: drop_down_tdc.stable_id } } }
+
+ 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 match_array(['Paris', 'Lyon', 'Marseille'])
+ expect(procedure3.reload.defaut_groupe_instructeur.routing_rule).to eq(ds_eq(champ_value(drop_down_tdc.stable_id), constant('Lyon')))
+ expect(procedure3.routing_enabled).to be_truthy
+ end
end
- let!(:drop_down_tdc) { procedure3.draft_revision.types_de_champ.first }
+ context 'with a departements type de champ' do
+ let!(:procedure3) do
+ create(:procedure,
+ types_de_champ_public: [{ type: :departements }],
+ administrateurs: [admin])
+ end
- before { post :create_simple_routing, params: { procedure_id: procedure3.id, create_simple_routing: { stable_id: drop_down_tdc.stable_id } } }
+ let!(:departements_tdc) { procedure3.draft_revision.types_de_champ.first }
- 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 match_array(['Paris', 'Lyon', 'Marseille'])
- expect(procedure3.reload.defaut_groupe_instructeur.routing_rule).to eq(ds_eq(champ_value(drop_down_tdc.stable_id), constant('Lyon')))
- expect(procedure3.routing_enabled).to be_truthy
+ before { post :create_simple_routing, params: { procedure_id: procedure3.id, create_simple_routing: { stable_id: departements_tdc.stable_id } } }
+
+ 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 – Ain")
+ expect(procedure3.reload.defaut_groupe_instructeur.routing_rule).to eq(ds_eq(champ_value(departements_tdc.stable_id), constant('01')))
+ expect(procedure3.routing_enabled).to be_truthy
+ end
end
end
diff --git a/spec/controllers/api/v2/graphql_controller_stored_queries_spec.rb b/spec/controllers/api/v2/graphql_controller_stored_queries_spec.rb
index 09180b5ce..2833a95b9 100644
--- a/spec/controllers/api/v2/graphql_controller_stored_queries_spec.rb
+++ b/spec/controllers/api/v2/graphql_controller_stored_queries_spec.rb
@@ -277,7 +277,7 @@ describe API::V2::GraphqlController do
it {
expect(gql_errors).to be_nil
expect(gql_data[:demarcheDescriptor][:id]).to eq(procedure.to_typed_id)
- expect(gql_data[:demarcheDescriptor][:demarcheUrl]).to match("commencer/#{procedure.path}")
+ expect(gql_data[:demarcheDescriptor][:demarcheURL]).to match("commencer/#{procedure.path}")
}
end
diff --git a/spec/controllers/instructeurs/dossiers_controller_spec.rb b/spec/controllers/instructeurs/dossiers_controller_spec.rb
index 564574188..f76083a19 100644
--- a/spec/controllers/instructeurs/dossiers_controller_spec.rb
+++ b/spec/controllers/instructeurs/dossiers_controller_spec.rb
@@ -949,7 +949,7 @@ describe Instructeurs::DossiersController, type: :controller do
expect(champ_multiple_drop_down_list.value).to eq('["val1","val2"]')
expect(champ_linked_drop_down_list.primary_value).to eq('primary')
expect(champ_linked_drop_down_list.secondary_value).to eq('secondary')
- expect(champ_datetime.value).to eq('2019-12-21T13:17:00+01:00')
+ expect(champ_datetime.value).to eq(Time.zone.parse('2019-12-21T13:17:00').iso8601)
expect(champ_repetition.champs.first.value).to eq('text')
expect(champ_drop_down_list.value).to eq('other value')
expect(dossier.reload.last_champ_private_updated_at).to eq(now)
diff --git a/spec/controllers/instructeurs/procedures_controller_spec.rb b/spec/controllers/instructeurs/procedures_controller_spec.rb
index a6b7614f0..ee7b4c19f 100644
--- a/spec/controllers/instructeurs/procedures_controller_spec.rb
+++ b/spec/controllers/instructeurs/procedures_controller_spec.rb
@@ -486,6 +486,76 @@ describe Instructeurs::ProceduresController, type: :controller do
end
end
+ describe '#email_usagers' do
+ let(:instructeur) { create(:instructeur) }
+ let(:procedure) { create(:procedure) }
+ let!(:gi_1) { create(:groupe_instructeur, label: 'gi_1', procedure: procedure, instructeurs: [instructeur]) }
+ let!(:dossier_without_groupe) { create(:dossier, :brouillon, procedure: procedure, groupe_instructeur: nil) }
+
+ subject do
+ get :email_usagers, params: { procedure_id: procedure.id }
+ end
+
+ it { is_expected.to redirect_to(new_user_session_path) }
+
+ context 'when authenticated' do
+ before { sign_in(instructeur.user) }
+ it 'lists dossier brouillon in groupe_instructeur as well as dossiers_brouillon outside groupe_instructeur' do
+ is_expected.to have_http_status(200)
+ expect(assigns(:dossiers_without_groupe_count)).to eq(1)
+ end
+ end
+ end
+
+ describe '#create_multiple_commentaire' do
+ let(:instructeur) { create(:instructeur) }
+ let!(:gi_p1_1) { create(:groupe_instructeur, label: '1', procedure: procedure, instructeurs: [instructeur]) }
+ let!(:gi_p1_2) { create(:groupe_instructeur, label: '2', procedure: procedure) }
+ let(:body) { "avant\napres" }
+ let(:bulk_message) { BulkMessage.first }
+ let!(:dossier) { create(:dossier, state: "brouillon", procedure: procedure, groupe_instructeur: gi_p1_1) }
+ let!(:dossier_2) { create(:dossier, state: "brouillon", procedure: procedure, groupe_instructeur: gi_p1_1) }
+ let!(:dossier_3) { create(:dossier, state: "brouillon", procedure: procedure, groupe_instructeur: gi_p1_2) }
+ let!(:procedure) { create(:procedure, :published, instructeurs: [instructeur]) }
+
+ before do
+ sign_in(instructeur.user)
+ procedure
+ end
+
+ let!(:dossier_4) { create(:dossier, state: "brouillon", procedure: procedure, groupe_instructeur: nil) }
+ before do
+ post :create_multiple_commentaire,
+ params: {
+ procedure_id: procedure.id,
+ bulk_message: { body: body }
+ }
+ end
+
+ it "creates a commentaire for 1 dossiers" do
+ expect(Commentaire.count).to eq(1)
+ expect(dossier.commentaires).to eq([])
+ expect(dossier_2.commentaires).to eq([])
+ expect(dossier_3.commentaires).to eq([])
+ expect(dossier_4.commentaires.first.body).to eq("avant\napres")
+ end
+
+ it "creates a Bulk Message for 2 groupes instructeurs" do
+ expect(BulkMessage.count).to eq(1)
+ expect(bulk_message.body).to eq("avant\napres")
+ expect(bulk_message.groupe_instructeurs).to be_empty
+ end
+
+ it "creates a flash notice" do
+ expect(flash.notice).to be_present
+ expect(flash.notice).to eq("Tous les messages ont été envoyés avec succès")
+ end
+
+ it "redirect to instructeur_procedure_path" do
+ expect(response).to redirect_to instructeur_procedure_path(procedure)
+ end
+ end
+
describe '#download_export' do
let(:instructeur) { create(:instructeur) }
let!(:procedure) { create(:procedure) }
@@ -563,49 +633,4 @@ describe Instructeurs::ProceduresController, type: :controller do
it { is_expected.to have_http_status(:forbidden) }
end
end
-
- describe '#create_multiple_commentaire' do
- let(:instructeur) { create(:instructeur) }
- let!(:gi_p1_1) { create(:groupe_instructeur, label: '1', procedure: procedure) }
- let!(:gi_p1_2) { create(:groupe_instructeur, label: '2', procedure: procedure) }
- let(:body) { "avant\napres" }
- let(:bulk_message) { BulkMessage.first }
- let!(:dossier) { create(:dossier, state: "brouillon", procedure: procedure, groupe_instructeur: gi_p1_1) }
- let!(:dossier_2) { create(:dossier, state: "brouillon", procedure: procedure, groupe_instructeur: gi_p1_1) }
- let!(:dossier_3) { create(:dossier, state: "brouillon", procedure: procedure, groupe_instructeur: gi_p1_2) }
- let!(:procedure) { create(:procedure, :published, instructeurs: [instructeur]) }
-
- before do
- sign_in(instructeur.user)
- instructeur.groupe_instructeurs << gi_p1_1
- procedure
- post :create_multiple_commentaire,
- params: {
- procedure_id: procedure.id,
- commentaire: { body: body }
- }
- end
-
- it "creates a commentaire for 2 dossiers" do
- expect(Commentaire.count).to eq(2)
- expect(dossier.commentaires.first.body).to eq("avant\napres")
- expect(dossier_2.commentaires.first.body).to eq("avant\napres")
- expect(dossier_3.commentaires).to eq([])
- end
-
- it "creates a Bulk Message for 2 groupes instructeurs" do
- expect(BulkMessage.count).to eq(1)
- expect(bulk_message.body).to eq("avant\napres")
- expect(bulk_message.groupe_instructeurs).to match([gi_p1_1])
- end
-
- it "creates a flash notice" do
- expect(flash.notice).to be_present
- expect(flash.notice).to eq("Tous les messages ont été envoyés avec succès")
- end
-
- it "redirect to instructeur_procedure_path" do
- expect(response).to redirect_to instructeur_procedure_path(procedure)
- end
- end
end
diff --git a/spec/controllers/manager/demandes_controller_spec.rb b/spec/controllers/manager/demandes_controller_spec.rb
deleted file mode 100644
index 33498bfb5..000000000
--- a/spec/controllers/manager/demandes_controller_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-describe Manager::DemandesController, type: :controller do
- let(:super_admin) { create(:super_admin) }
-
- describe 'GET #index' do
- before do
- sign_in super_admin
- end
-
- it "display pending demandes" do
- approved_administrateur = create(:administrateur, email: "approved@example.com")
- pending_demande = { email: 'pending@example.com' }
- demandes = [{ email: approved_administrateur.email }, pending_demande]
- allow(PipedriveService).to receive(:get_demandes).and_return(demandes)
-
- get :index
-
- expect(assigns(:pending_demandes)).to eq([pending_demande])
- end
- end
-end
diff --git a/spec/controllers/users/sessions_controller_spec.rb b/spec/controllers/users/sessions_controller_spec.rb
index 43212984d..9ccf0ced1 100644
--- a/spec/controllers/users/sessions_controller_spec.rb
+++ b/spec/controllers/users/sessions_controller_spec.rb
@@ -244,4 +244,36 @@ describe Users::SessionsController, type: :controller do
end
end
end
+
+ describe '#reset_link_sent' do
+ let(:instructeur) { create(:instructeur, user: user) }
+ before { sign_in(user) }
+ subject { post :reset_link_sent }
+
+ context 'when the instructeur is signed without trust_device_token' do
+ it 'send InstructeurMailer.send_login_token' do
+ expect(InstructeurMailer).to receive(:send_login_token).with(instructeur, anything).and_return(double(deliver_later: true))
+ expect { subject }.to change { instructeur.trusted_device_tokens.count }.by(1)
+ end
+ end
+
+ context 'when the instructeur is signed with an young trust_device_token' do
+ before { instructeur.create_trusted_device_token }
+ it 'doesnot send InstructeurMailer.send_login_token' do
+ expect(InstructeurMailer).not_to receive(:send_login_token)
+ expect { subject }.to change { instructeur.trusted_device_tokens.count }.by(0)
+ end
+ end
+
+ context 'when the instructeur is signed with an old trust_device_token' do
+ let(:token) { instructeur.create_trusted_device_token }
+ before do
+ travel_to 15.minutes.from_now
+ end
+ it 'send InstructeurMailer.send_login_token' do
+ expect(InstructeurMailer).to receive(:send_login_token).with(instructeur, anything).and_return(double(deliver_later: true))
+ expect { subject }.to change { instructeur.trusted_device_tokens.count }.by(1)
+ end
+ end
+ end
end
diff --git a/spec/helpers/procedure_helper_spec.rb b/spec/helpers/procedure_helper_spec.rb
index 6a2a92020..7423b251e 100644
--- a/spec/helpers/procedure_helper_spec.rb
+++ b/spec/helpers/procedure_helper_spec.rb
@@ -10,6 +10,26 @@ RSpec.describe ProcedureHelper, type: :helper do
end
end
+ describe 'can_send_groupe_message?' do
+ let(:procedure) { create(:procedure, groupe_instructeurs: [gi1, gi2]) }
+ let(:current_instructeur) { create(:instructeur) }
+ subject { can_send_groupe_message?(procedure) }
+
+ context 'when current_instructeur is in all procedure.groupes_instructeur' do
+ let(:gi1) { create(:groupe_instructeur, instructeurs: [current_instructeur]) }
+ let(:gi2) { create(:groupe_instructeur, instructeurs: [current_instructeur]) }
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when current_instructeur is in all procedure.groupes_instructeur' do
+ let(:instructeur2) { create(:instructeur) }
+ let(:gi1) { create(:groupe_instructeur, instructeurs: [current_instructeur]) }
+ let(:gi2) { create(:groupe_instructeur, instructeurs: [instructeur2]) }
+
+ it { is_expected.to be_falsy }
+ end
+ end
+
describe '#estimated_fill_duration_minutes' do
subject { estimated_fill_duration_minutes(procedure.reload) }
diff --git a/spec/jobs/migrations/batch_update_datetime_values_job_spec.rb b/spec/jobs/migrations/batch_update_datetime_values_job_spec.rb
index 5cdf4f516..28d012871 100644
--- a/spec/jobs/migrations/batch_update_datetime_values_job_spec.rb
+++ b/spec/jobs/migrations/batch_update_datetime_values_job_spec.rb
@@ -4,24 +4,26 @@ describe Migrations::BatchUpdateDatetimeValuesJob, type: :job do
end
context "when the value is a valid ISO8601 date" do
- let!(:datetime_champ) { build(:champ_datetime, value: "2023-01-10T00:00:00+01:00") }
+ let!(:value) { Time.zone.parse('10/01/2023 13:30').iso8601 }
+ let!(:datetime_champ) { build(:champ_datetime, value: value) }
subject { described_class.perform_now([datetime_champ.id]) }
it "keeps the existing value" do
subject
- expect(datetime_champ.reload.value).to eq("2023-01-10T00:00:00+01:00")
+ expect(datetime_champ.reload.value).to eq(value)
end
end
context "when the value is a date convertible to IS8061" do
- let!(:datetime_champ) { build(:champ_datetime, value: "2023-01-10") }
+ let!(:value) { "2023-01-10" }
+ let!(:datetime_champ) { build(:champ_datetime, value: value) }
subject { described_class.perform_now([datetime_champ.id]) }
it "updates the value to ISO8601" do
subject
- expect(datetime_champ.reload.value).to eq("2023-01-10T00:00:00+01:00")
+ expect(datetime_champ.reload.value).to eq(Time.zone.parse(value).iso8601)
end
end
diff --git a/spec/jobs/procedure_sva_svr_process_dossier_job_spec.rb b/spec/jobs/procedure_sva_svr_process_dossier_job_spec.rb
index 1ce2053eb..b916c4310 100644
--- a/spec/jobs/procedure_sva_svr_process_dossier_job_spec.rb
+++ b/spec/jobs/procedure_sva_svr_process_dossier_job_spec.rb
@@ -2,6 +2,10 @@ RSpec.describe ProcedureSVASVRProcessDossierJob, type: :job do
include ActiveJob::TestHelper
include ActiveSupport::Testing::TimeHelpers
+ before do
+ travel_to Date.new(2023, 8, 15, 12)
+ end
+
let(:procedure) { create(:procedure, :published, :sva, :for_individual) }
let!(:dossier) { create(:dossier, :en_instruction, :with_individual, procedure:, depose_at: 2.months.ago - 1.day, sva_svr_decision_on: Date.current) }
diff --git a/spec/lib/api_entreprise/api_spec.rb b/spec/lib/api_entreprise/api_spec.rb
index bf69b2141..20d90da1b 100644
--- a/spec/lib/api_entreprise/api_spec.rb
+++ b/spec/lib/api_entreprise/api_spec.rb
@@ -108,6 +108,7 @@ describe APIEntreprise::API do
let(:siren) { procedure.service.siret[0..8] }
let(:dinum_siret) { "13002526500013" }
it 'send default recipient' do
+ ENV["API_ENTREPRISE_DEFAULT_SIRET"] = dinum_siret
subject
expect(WebMock).to have_requested(:get, /https:\/\/entreprise.api.gouv.fr\/v3\/insee\/sirene\/unites_legales\/#{siren}/).with(query: hash_including({ recipient: dinum_siret }))
end
diff --git a/spec/lib/biz_dev_spec.rb b/spec/lib/biz_dev_spec.rb
index 0d22c87a2..76497baa0 100644
--- a/spec/lib/biz_dev_spec.rb
+++ b/spec/lib/biz_dev_spec.rb
@@ -19,20 +19,4 @@ describe BizDev, lib: true do
it { is_expected.not_to be_empty }
end
end
-
- describe '#pipedrive_id' do
- subject { described_class.pipedrive_id(administration_id) }
-
- context 'when administration is a business developer' do
- let(:administration_id) { first_biz_dev_id }
-
- it { is_expected.to be > 0 }
- end
-
- context 'when administration is not a business developer' do
- let(:administration_id) { non_biz_dev_id }
-
- it { is_expected.to be > 0 }
- end
- end
end
diff --git a/spec/lib/pipedrive/deal_adapter_spec.rb b/spec/lib/pipedrive/deal_adapter_spec.rb
deleted file mode 100644
index 5d7583673..000000000
--- a/spec/lib/pipedrive/deal_adapter_spec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-describe Pipedrive::DealAdapter do
- let(:url) { PIPEDRIVE_API_URL }
- let(:status) { 200 }
- let(:body) { '{}' }
-
- before do
- stub_request(:get, url)
- .to_return(status: status, body: body)
- end
-
- describe ".get_deals_ids_for_person" do
- let(:url) { %r{/persons/1/deals\?*} }
- subject { Pipedrive::DealAdapter.get_deals_ids_for_person('1') }
-
- context "with valid data" do
- let(:body) { '{ "success": true, "data": [ { "id": 34 }, { "id": 35 } ] }' }
- it { is_expected.to eq [34, 35] }
- end
-
- context "when no data are returned" do
- let(:body) { '{ "success": true, "data": null }' }
- it { is_expected.to eq [] }
- end
- end
-end
diff --git a/spec/models/administrateur_spec.rb b/spec/models/administrateur_spec.rb
index c4267115b..065fda8ca 100644
--- a/spec/models/administrateur_spec.rb
+++ b/spec/models/administrateur_spec.rb
@@ -208,7 +208,7 @@ describe Administrateur, type: :model do
subject { Administrateur.unused }
let(:new_admin) { create(:administrateur) }
- let(:unused_admin) { create(:administrateur) }
+ let(:unused_admin) { create(:administrateur, :with_api_token) }
before do
new_admin.user.update(last_sign_in_at: (6.months - 1.day).ago)
@@ -225,6 +225,18 @@ describe Administrateur, type: :model do
it { is_expected.to be_empty }
end
+ context 'with a with_api_token on api v1' do
+ before { unused_admin.api_tokens.first.touch(:last_v1_authenticated_at) }
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'with a with_api_token on api v2' do
+ before { unused_admin.api_tokens.first.touch(:last_v2_authenticated_at) }
+
+ it { is_expected.to be_empty }
+ end
+
context 'with a service' do
let(:service) { create(:service) }
diff --git a/spec/models/champ_spec.rb b/spec/models/champ_spec.rb
index 56940fc07..85e17b2df 100644
--- a/spec/models/champ_spec.rb
+++ b/spec/models/champ_spec.rb
@@ -99,13 +99,13 @@ describe Champ do
context 'when the value is sent by a modern browser' do
let(:value) { '2017-12-31 10:23' }
- it { expect(champ.value).to eq("2017-12-31T10:23:00+01:00") }
+ it { expect(champ.value).to eq(Time.zone.parse("2017-12-31T10:23:00").iso8601) }
end
context 'when the value is sent by a old browser' do
let(:value) { '31/12/2018 09:26' }
- it { expect(champ.value).to eq("2018-12-31T09:26:00+01:00") }
+ it { expect(champ.value).to eq(Time.zone.parse("2018-12-31T09:26:00").iso8601) }
end
end
diff --git a/spec/models/champs/datetime_champ_spec.rb b/spec/models/champs/datetime_champ_spec.rb
index f61561e8a..a8ef0bd42 100644
--- a/spec/models/champs/datetime_champ_spec.rb
+++ b/spec/models/champs/datetime_champ_spec.rb
@@ -29,19 +29,19 @@ describe Champs::DatetimeChamp do
it 'preserves if ISO8601' do
champ = champ_with_value("2023-12-21T03:20")
champ.save
- expect(champ.reload.value).to eq("2023-12-21T03:20:00+01:00")
+ expect(champ.reload.value).to eq(Time.zone.parse("2023-12-21T03:20:00").iso8601)
end
it 'converts to ISO8601 if form format' do
champ = champ_with_value("{3=>21, 2=>12, 1=>2023, 4=>3, 5=>20}")
champ.save
- expect(champ.reload.value).to eq("2023-12-21T03:20:00+01:00")
+ expect(champ.reload.value).to eq(Time.zone.parse("2023-12-21T03:20:00").iso8601)
end
it 'converts to ISO8601 if old browser form format' do
champ = champ_with_value("21/12/2023 03:20")
champ.save
- expect(champ.reload.value).to eq("2023-12-21T03:20:00+01:00")
+ expect(champ.reload.value).to eq(Time.zone.parse("2023-12-21T03:20:00").iso8601)
end
end
diff --git a/spec/models/concern/dossier_clone_concern_spec.rb b/spec/models/concern/dossier_clone_concern_spec.rb
index aa8b31481..fbd2501a2 100644
--- a/spec/models/concern/dossier_clone_concern_spec.rb
+++ b/spec/models/concern/dossier_clone_concern_spec.rb
@@ -15,7 +15,8 @@ RSpec.describe DossierCloneConcern do
describe '#clone' do
let(:procedure) { create(:procedure, :with_type_de_champ, :with_type_de_champ_private) }
let(:dossier) { create(:dossier, procedure: procedure) }
- let(:new_dossier) { dossier.clone }
+ let(:fork) { false }
+ let(:new_dossier) { dossier.clone(fork:) }
context 'reset most attributes' do
it { expect(new_dossier.id).not_to eq(dossier.id) }
@@ -49,7 +50,14 @@ RSpec.describe DossierCloneConcern do
end
context 'copies some attributes' do
- it { expect(new_dossier.groupe_instructeur).to eq(dossier.groupe_instructeur) }
+ context 'when fork' do
+ let(:fork) { true }
+ it { expect(new_dossier.groupe_instructeur).to eq(dossier.groupe_instructeur) }
+ end
+
+ context 'when not forked' do
+ it { expect(new_dossier.groupe_instructeur).to be_nil }
+ end
it { expect(new_dossier.autorisation_donnees).to eq(dossier.autorisation_donnees) }
it { expect(new_dossier.revision_id).to eq(dossier.revision_id) }
it { expect(new_dossier.user_id).to eq(dossier.user_id) }
diff --git a/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb
index 3d7af58f8..9080e54d3 100644
--- a/spec/models/dossier_spec.rb
+++ b/spec/models/dossier_spec.rb
@@ -466,27 +466,63 @@ describe Dossier, type: :model do
after { Timecop.return }
context 'when dossier is en_construction' do
- before do
- dossier.passer_en_construction!
- dossier.reload
+ context 'when the procedure.routing_enabled? is false' do
+ before do
+ dossier.passer_en_construction!
+ dossier.reload
+ end
+
+ it { expect(dossier.state).to eq(Dossier.states.fetch(:en_construction)) }
+ it { expect(dossier.en_construction_at).to eq(beginning_of_day) }
+ it { expect(dossier.depose_at).to eq(beginning_of_day) }
+ it { expect(dossier.traitement.state).to eq(Dossier.states.fetch(:en_construction)) }
+ it { expect(dossier.traitement.processed_at).to eq(beginning_of_day) }
+
+ it 'should keep first en_construction_at date' do
+ Timecop.return
+ dossier.passer_en_instruction!(instructeur: instructeur)
+ dossier.repasser_en_construction!(instructeur: instructeur)
+
+ expect(dossier.traitements.size).to eq(3)
+ expect(dossier.traitements.first.processed_at).to eq(beginning_of_day)
+ expect(dossier.traitement.processed_at.round).to eq(dossier.en_construction_at.round)
+ expect(dossier.depose_at).to eq(beginning_of_day)
+ expect(dossier.en_construction_at).to be > beginning_of_day
+ end
end
- it { expect(dossier.state).to eq(Dossier.states.fetch(:en_construction)) }
- it { expect(dossier.en_construction_at).to eq(beginning_of_day) }
- it { expect(dossier.depose_at).to eq(beginning_of_day) }
- it { expect(dossier.traitement.state).to eq(Dossier.states.fetch(:en_construction)) }
- it { expect(dossier.traitement.processed_at).to eq(beginning_of_day) }
+ context 'when the procedure.routing_enabled? is true' do
+ include Logic
+ let(:gi_libelle) { 'Paris' }
+ let!(:procedure) do
+ create(:procedure,
+ types_de_champ_public: [
+ { type: :drop_down_list, libelle: 'Votre ville', options: [gi_libelle, 'Lyon', 'Marseille'] },
+ { type: :text, libelle: 'Un champ texte' }
+ ])
+ end
+ let!(:drop_down_tdc) { procedure.draft_revision.types_de_champ.first }
+ let(:dossier) { create(:dossier, :brouillon, user:, procedure:, groupe_instructeur: nil) }
+ let(:gi) do
+ create(:groupe_instructeur,
+ routing_rule: ds_eq(champ_value(drop_down_tdc.stable_id),
+ constant(gi_libelle)))
+ end
- it 'should keep first en_construction_at date' do
- Timecop.return
- dossier.passer_en_instruction!(instructeur: instructeur)
- dossier.repasser_en_construction!(instructeur: instructeur)
+ before do
+ procedure.groupe_instructeurs = [gi]
+ procedure.defaut_groupe_instructeur = gi
+ procedure.save!
+ procedure.toggle_routing
+ dossier.champs.first.value = gi_libelle
+ dossier.save!
+ dossier.passer_en_construction!
+ dossier.reload
+ end
- expect(dossier.traitements.size).to eq(3)
- expect(dossier.traitements.first.processed_at).to eq(beginning_of_day)
- expect(dossier.traitement.processed_at.round).to eq(dossier.en_construction_at.round)
- expect(dossier.depose_at).to eq(beginning_of_day)
- expect(dossier.en_construction_at).to be > beginning_of_day
+ it 'RoutingEngine.compute' do
+ expect(dossier.groupe_instructeur).not_to be_nil
+ end
end
end
diff --git a/spec/models/procedure_presentation_spec.rb b/spec/models/procedure_presentation_spec.rb
index e17b5b6f3..76ed889ac 100644
--- a/spec/models/procedure_presentation_spec.rb
+++ b/spec/models/procedure_presentation_spec.rb
@@ -60,35 +60,35 @@ describe ProcedurePresentation do
let(:tdc_private_2) { procedure.active_revision.types_de_champ_private[1] }
let(:expected) {
[
- { "label" => 'Créé le', "table" => 'self', "column" => 'created_at', 'classname' => '', 'virtual' => false, 'type' => :date, "scope" => '', "value_column" => :value },
- { "label" => 'Mis à jour le', "table" => 'self', "column" => 'updated_at', 'classname' => '', 'virtual' => false, 'type' => :date, "scope" => '', "value_column" => :value },
- { "label" => 'Déposé le', "table" => 'self', "column" => 'depose_at', 'classname' => '', 'virtual' => false, 'type' => :date, "scope" => '', "value_column" => :value },
- { "label" => 'En construction le', "table" => 'self', "column" => 'en_construction_at', 'classname' => '', 'virtual' => false, 'type' => :date, "scope" => '', "value_column" => :value },
- { "label" => 'En instruction le', "table" => 'self', "column" => 'en_instruction_at', 'classname' => '', 'virtual' => false, 'type' => :date, "scope" => '', "value_column" => :value },
- { "label" => 'Terminé le', "table" => 'self', "column" => 'processed_at', 'classname' => '', 'virtual' => false, 'type' => :date, "scope" => '', "value_column" => :value },
- { "label" => "Mis à jour depuis", "table" => "self", "column" => "updated_since", "classname" => "", 'virtual' => true, 'type' => :date, 'scope' => '', "value_column" => :value },
- { "label" => "Déposé depuis", "table" => "self", "column" => "depose_since", "classname" => "", 'virtual' => true, 'type' => :date, 'scope' => '', "value_column" => :value },
- { "label" => "En construction depuis", "table" => "self", "column" => "en_construction_since", "classname" => "", 'virtual' => true, 'type' => :date, 'scope' => '', "value_column" => :value },
- { "label" => "En instruction depuis", "table" => "self", "column" => "en_instruction_since", "classname" => "", 'virtual' => true, 'type' => :date, 'scope' => '', "value_column" => :value },
- { "label" => "Terminé depuis", "table" => "self", "column" => "processed_since", "classname" => "", 'virtual' => true, 'type' => :date, 'scope' => '', "value_column" => :value },
- { "label" => "Statut", "table" => "self", "column" => "state", "classname" => "", 'virtual' => true, 'scope' => 'instructeurs.dossiers.filterable_state', 'type' => :enum, "value_column" => :value },
- { "label" => 'Demandeur', "table" => 'user', "column" => 'email', 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value },
- { "label" => 'Email instructeur', "table" => 'followers_instructeurs', "column" => 'email', 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value },
- { "label" => 'Groupe instructeur', "table" => 'groupe_instructeur', "column" => 'id', 'classname' => '', 'virtual' => false, 'type' => :enum, "scope" => '', "value_column" => :value },
- { "label" => 'Avis', "table" => 'avis', "column" => 'answer', 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value },
- { "label" => 'SIREN', "table" => 'etablissement', "column" => 'entreprise_siren', 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value },
- { "label" => 'Forme juridique', "table" => 'etablissement', "column" => 'entreprise_forme_juridique', 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value },
- { "label" => 'Nom commercial', "table" => 'etablissement', "column" => 'entreprise_nom_commercial', 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value },
- { "label" => 'Raison sociale', "table" => 'etablissement', "column" => 'entreprise_raison_sociale', 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value },
- { "label" => 'SIRET siège social', "table" => 'etablissement', "column" => 'entreprise_siret_siege_social', 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value },
- { "label" => 'Date de création', "table" => 'etablissement', "column" => 'entreprise_date_creation', 'classname' => '', 'virtual' => false, 'type' => :date, "scope" => '', "value_column" => :value },
- { "label" => 'SIRET', "table" => 'etablissement', "column" => 'siret', 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value },
- { "label" => 'Libellé NAF', "table" => 'etablissement', "column" => 'libelle_naf', 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value },
- { "label" => 'Code postal', "table" => 'etablissement', "column" => 'code_postal', 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value },
- { "label" => tdc_1.libelle, "table" => 'type_de_champ', "column" => tdc_1.stable_id.to_s, 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value },
- { "label" => tdc_2.libelle, "table" => 'type_de_champ', "column" => tdc_2.stable_id.to_s, 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value },
- { "label" => tdc_private_1.libelle, "table" => 'type_de_champ_private', "column" => tdc_private_1.stable_id.to_s, 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value },
- { "label" => tdc_private_2.libelle, "table" => 'type_de_champ_private', "column" => tdc_private_2.stable_id.to_s, 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value }
+ { "label" => 'Créé le', "table" => 'self', "column" => 'created_at', 'classname' => '', 'virtual' => false, 'type' => :date, "scope" => '', "value_column" => :value, 'filterable' => true },
+ { "label" => 'Mis à jour le', "table" => 'self', "column" => 'updated_at', 'classname' => '', 'virtual' => false, 'type' => :date, "scope" => '', "value_column" => :value, 'filterable' => true },
+ { "label" => 'Déposé le', "table" => 'self', "column" => 'depose_at', 'classname' => '', 'virtual' => false, 'type' => :date, "scope" => '', "value_column" => :value, 'filterable' => true },
+ { "label" => 'En construction le', "table" => 'self', "column" => 'en_construction_at', 'classname' => '', 'virtual' => false, 'type' => :date, "scope" => '', "value_column" => :value, 'filterable' => true },
+ { "label" => 'En instruction le', "table" => 'self', "column" => 'en_instruction_at', 'classname' => '', 'virtual' => false, 'type' => :date, "scope" => '', "value_column" => :value, 'filterable' => true },
+ { "label" => 'Terminé le', "table" => 'self', "column" => 'processed_at', 'classname' => '', 'virtual' => false, 'type' => :date, "scope" => '', "value_column" => :value, 'filterable' => true },
+ { "label" => "Mis à jour depuis", "table" => "self", "column" => "updated_since", "classname" => "", 'virtual' => true, 'type' => :date, 'scope' => '', "value_column" => :value, 'filterable' => true },
+ { "label" => "Déposé depuis", "table" => "self", "column" => "depose_since", "classname" => "", 'virtual' => true, 'type' => :date, 'scope' => '', "value_column" => :value, 'filterable' => true },
+ { "label" => "En construction depuis", "table" => "self", "column" => "en_construction_since", "classname" => "", 'virtual' => true, 'type' => :date, 'scope' => '', "value_column" => :value, 'filterable' => true },
+ { "label" => "En instruction depuis", "table" => "self", "column" => "en_instruction_since", "classname" => "", 'virtual' => true, 'type' => :date, 'scope' => '', "value_column" => :value, 'filterable' => true },
+ { "label" => "Terminé depuis", "table" => "self", "column" => "processed_since", "classname" => "", 'virtual' => true, 'type' => :date, 'scope' => '', "value_column" => :value, 'filterable' => true },
+ { "label" => "Statut", "table" => "self", "column" => "state", "classname" => "", 'virtual' => true, 'scope' => 'instructeurs.dossiers.filterable_state', 'type' => :enum, "value_column" => :value, 'filterable' => true },
+ { "label" => 'Demandeur', "table" => 'user', "column" => 'email', 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value, 'filterable' => true },
+ { "label" => 'Email instructeur', "table" => 'followers_instructeurs', "column" => 'email', 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value, 'filterable' => true },
+ { "label" => 'Groupe instructeur', "table" => 'groupe_instructeur', "column" => 'id', 'classname' => '', 'virtual' => false, 'type' => :enum, "scope" => '', "value_column" => :value, 'filterable' => true },
+ { "label" => 'Avis oui/non', "table" => 'avis', "column" => 'question_answer', 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value, 'filterable' => false },
+ { "label" => 'SIREN', "table" => 'etablissement', "column" => 'entreprise_siren', 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value, 'filterable' => true },
+ { "label" => 'Forme juridique', "table" => 'etablissement', "column" => 'entreprise_forme_juridique', 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value, 'filterable' => true },
+ { "label" => 'Nom commercial', "table" => 'etablissement', "column" => 'entreprise_nom_commercial', 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value, 'filterable' => true },
+ { "label" => 'Raison sociale', "table" => 'etablissement', "column" => 'entreprise_raison_sociale', 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value, 'filterable' => true },
+ { "label" => 'SIRET siège social', "table" => 'etablissement', "column" => 'entreprise_siret_siege_social', 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value, 'filterable' => true },
+ { "label" => 'Date de création', "table" => 'etablissement', "column" => 'entreprise_date_creation', 'classname' => '', 'virtual' => false, 'type' => :date, "scope" => '', "value_column" => :value, 'filterable' => true },
+ { "label" => 'SIRET', "table" => 'etablissement', "column" => 'siret', 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value, 'filterable' => true },
+ { "label" => 'Libellé NAF', "table" => 'etablissement', "column" => 'libelle_naf', 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value, 'filterable' => true },
+ { "label" => 'Code postal', "table" => 'etablissement', "column" => 'code_postal', 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value, 'filterable' => true },
+ { "label" => tdc_1.libelle, "table" => 'type_de_champ', "column" => tdc_1.stable_id.to_s, 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value, 'filterable' => true },
+ { "label" => tdc_2.libelle, "table" => 'type_de_champ', "column" => tdc_2.stable_id.to_s, 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value, 'filterable' => true },
+ { "label" => tdc_private_1.libelle, "table" => 'type_de_champ_private', "column" => tdc_private_1.stable_id.to_s, 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value, 'filterable' => true },
+ { "label" => tdc_private_2.libelle, "table" => 'type_de_champ_private', "column" => tdc_private_2.stable_id.to_s, 'classname' => '', 'virtual' => false, 'type' => :text, "scope" => '', "value_column" => :value, 'filterable' => true }
]
}
@@ -105,9 +105,9 @@ describe ProcedurePresentation do
end
context 'when the procedure is for individuals' do
- let(:name_field) { { "label" => "Prénom", "table" => "individual", "column" => "prenom", 'classname' => '', 'virtual' => false, "type" => :text, "scope" => '', "value_column" => :value } }
- let(:surname_field) { { "label" => "Nom", "table" => "individual", "column" => "nom", 'classname' => '', 'virtual' => false, "type" => :text, "scope" => '', "value_column" => :value } }
- let(:gender_field) { { "label" => "Civilité", "table" => "individual", "column" => "gender", 'classname' => '', 'virtual' => false, "type" => :text, "scope" => '', "value_column" => :value } }
+ let(:name_field) { { "label" => "Prénom", "table" => "individual", "column" => "prenom", 'classname' => '', 'virtual' => false, "type" => :text, "scope" => '', "value_column" => :value, 'filterable' => true } }
+ let(:surname_field) { { "label" => "Nom", "table" => "individual", "column" => "nom", 'classname' => '', 'virtual' => false, "type" => :text, "scope" => '', "value_column" => :value, 'filterable' => true } }
+ let(:gender_field) { { "label" => "Civilité", "table" => "individual", "column" => "gender", 'classname' => '', 'virtual' => false, "type" => :text, "scope" => '', "value_column" => :value, 'filterable' => true } }
let(:procedure) { create(:procedure, :for_individual) }
let(:procedure_presentation) { create(:procedure_presentation, assign_to: assign_to) }
@@ -120,8 +120,8 @@ describe ProcedurePresentation do
let(:procedure) { create(:procedure, :for_individual, :sva) }
let(:procedure_presentation) { create(:procedure_presentation, assign_to: assign_to) }
- let(:decision_on) { { "label" => "Date décision SVA", "table" => "self", "column" => "sva_svr_decision_on", 'classname' => '', 'virtual' => false, "type" => :date, "scope" => '', "value_column" => :value } }
- let(:decision_before_field) { { "label" => "Date décision SVA avant", "table" => "self", "column" => "sva_svr_decision_before", 'classname' => '', 'virtual' => true, "type" => :date, "scope" => '', "value_column" => :value } }
+ let(:decision_on) { { "label" => "Date décision SVA", "table" => "self", "column" => "sva_svr_decision_on", 'classname' => '', 'virtual' => false, "type" => :date, "scope" => '', "value_column" => :value, 'filterable' => true } }
+ let(:decision_before_field) { { "label" => "Date décision SVA avant", "table" => "self", "column" => "sva_svr_decision_before", 'classname' => '', 'virtual' => true, "type" => :date, "scope" => '', "value_column" => :value, 'filterable' => true } }
subject { procedure_presentation.fields }
@@ -398,7 +398,7 @@ describe ProcedurePresentation do
context 'for avis table' do
let(:table) { 'avis' }
- let(:column) { 'answer' }
+ let(:column) { 'question_answer' }
let(:order) { 'asc' }
let!(:dossier_yes) { create(:dossier, procedure:) }
@@ -410,7 +410,7 @@ describe ProcedurePresentation do
create(:avis, dossier: dossier_no, question_answer: false)
end
- it { is_expected.to eq([dossier_yes, dossier_no].map(&:id)) }
+ it { is_expected.to eq([dossier_no, dossier_yes].map(&:id)) }
end
context 'for other tables' do
@@ -766,19 +766,6 @@ describe ProcedurePresentation do
end
end
- context 'for avis table' do
- let(:procedure) { create(:procedure, :for_individual) }
- let!(:kept_dossier) { create(:dossier, procedure:) }
- let!(:discarded_dossier) { create(:dossier, procedure:) }
- let!(:avis) { create(:avis, :with_answer, dossier: kept_dossier) }
-
- context 'for answer column' do
- let(:filter) { [{ 'table' => 'avis', 'column' => 'answer', 'value' => 'Pertinente' }] }
-
- it { is_expected.to contain_exactly(kept_dossier.id) }
- end
- end
-
context 'for followers_instructeurs table' do
let(:filter) { [{ 'table' => 'followers_instructeurs', 'column' => 'email', 'value' => 'keepmail' }] }
diff --git a/spec/models/procedure_revision_spec.rb b/spec/models/procedure_revision_spec.rb
index b115ad62f..b6011ca24 100644
--- a/spec/models/procedure_revision_spec.rb
+++ b/spec/models/procedure_revision_spec.rb
@@ -941,4 +941,16 @@ describe ProcedureRevision do
expect(type_de_champ.revisions.count).to eq(1)
}
end
+
+ describe '#routable_types_de_champ' do
+ let(:procedure) do
+ create(:procedure).tap do |p|
+ p.draft_revision.add_type_de_champ(type_champ: :text, libelle: 'l1')
+ p.draft_revision.add_type_de_champ(type_champ: :drop_down_list, libelle: 'l2')
+ p.draft_revision.add_type_de_champ(type_champ: :departements, libelle: 'l3')
+ end
+ end
+
+ it { expect(draft.routable_types_de_champ.pluck(:libelle)).to eq(['l2', 'l3']) }
+ end
end
diff --git a/spec/models/routing_engine_spec.rb b/spec/models/routing_engine_spec.rb
index ef70eb589..3095da91f 100644
--- a/spec/models/routing_engine_spec.rb
+++ b/spec/models/routing_engine_spec.rb
@@ -2,16 +2,6 @@ describe RoutingEngine, type: :model do
include Logic
describe '.compute' do
- let(:procedure) do
- create(:procedure,
- types_de_champ_public: [{ type: :drop_down_list, libelle: 'Votre ville', options: ['Paris', 'Lyon', 'Marseille'] }]).tap do |p|
- p.groupe_instructeurs.create(label: 'a second group')
- p.groupe_instructeurs.create(label: 'a third group')
- end
- end
-
- let(:drop_down_tdc) { procedure.draft_revision.types_de_champ.first }
-
let(:dossier) { create(:dossier, procedure:) }
let(:defaut_groupe) { procedure.defaut_groupe_instructeur }
let(:gi_2) { procedure.groupe_instructeurs.find_by(label: 'a second group') }
@@ -21,43 +11,75 @@ describe RoutingEngine, type: :model do
dossier.groupe_instructeur
end
- context 'without any rules' do
- it { is_expected.to eq(defaut_groupe) }
- end
-
- context 'without any matching rules' do
- before do
- procedure.groupe_instructeurs.each do |gi|
- gi.update(routing_rule: constant(false))
+ context 'with a drop down list type de champ' do
+ let(:procedure) do
+ create(:procedure,
+ types_de_champ_public: [{ type: :drop_down_list, libelle: 'Votre ville', options: ['Paris', 'Lyon', 'Marseille'] }]).tap do |p|
+ p.groupe_instructeurs.create(label: 'a second group')
+ p.groupe_instructeurs.create(label: 'a third group')
end
end
- it { is_expected.to eq(defaut_groupe) }
+ let(:drop_down_tdc) { procedure.draft_revision.types_de_champ.first }
+
+ context 'without any rules' do
+ it { is_expected.to eq(defaut_groupe) }
+ end
+
+ context 'without any matching rules' do
+ before do
+ procedure.groupe_instructeurs.each do |gi|
+ gi.update(routing_rule: constant(false))
+ end
+ end
+
+ it { is_expected.to eq(defaut_groupe) }
+ end
+
+ context 'with rules not configured yet' do
+ before do
+ procedure.groupe_instructeurs.each do |gi|
+ gi.update(routing_rule: ds_eq(empty, empty))
+ end
+ end
+
+ it { is_expected.to eq(defaut_groupe) }
+ end
+
+ context 'with a matching rule' do
+ before do
+ gi_2.update(routing_rule: ds_eq(champ_value(drop_down_tdc.stable_id), constant('Lyon')))
+ dossier.champs.first.update(value: 'Lyon')
+ end
+
+ it { is_expected.to eq(gi_2) }
+ end
+
+ context 'with a closed gi with a matching rule' do
+ before { gi_2.update(routing_rule: constant(true), closed: true) }
+
+ it { is_expected.to eq(defaut_groupe) }
+ end
end
- context 'with rules not configured yet' do
- before do
- procedure.groupe_instructeurs.each do |gi|
- gi.update(routing_rule: ds_eq(empty, empty))
+ context 'with a departements type de champ' do
+ let(:procedure) do
+ create(:procedure, types_de_champ_public: [{ type: :departements }]).tap do |p|
+ p.groupe_instructeurs.create(label: 'a second group')
+ p.groupe_instructeurs.create(label: 'a third group')
end
end
- it { is_expected.to eq(defaut_groupe) }
- end
+ let(:departements_tdc) { procedure.draft_revision.types_de_champ.first }
- context 'with a matching rule' do
- before do
- gi_2.update(routing_rule: ds_eq(champ_value(drop_down_tdc.stable_id), constant('Lyon')))
- dossier.champs.first.update(value: 'Lyon')
+ context 'with a matching rule' do
+ before do
+ gi_2.update(routing_rule: ds_eq(champ_value(departements_tdc.stable_id), constant('43')))
+ dossier.champs.first.update(value: 'Haute-Loire')
+ end
+
+ it { is_expected.to eq(gi_2) }
end
-
- it { is_expected.to eq(gi_2) }
- end
-
- context 'with a closed gi with a matching rule' do
- before { gi_2.update(routing_rule: constant(true), closed: true) }
-
- it { is_expected.to eq(defaut_groupe) }
end
end
end
diff --git a/spec/services/sva_svr_decision_date_calculator_service_spec.rb b/spec/services/sva_svr_decision_date_calculator_service_spec.rb
index e6ff87783..ca2d675bb 100644
--- a/spec/services/sva_svr_decision_date_calculator_service_spec.rb
+++ b/spec/services/sva_svr_decision_date_calculator_service_spec.rb
@@ -4,7 +4,8 @@ describe SVASVRDecisionDateCalculatorService do
include ActiveSupport::Testing::TimeHelpers
let(:procedure) { create(:procedure, sva_svr: config) }
- let(:dossier) { create(:dossier, :en_instruction, procedure:, depose_at: DateTime.new(2023, 5, 15, 12)) }
+ let(:dossier) { create(:dossier, :en_instruction, procedure:, depose_at:) }
+ let(:depose_at) { DateTime.new(2023, 5, 15, 12) }
describe '#decision_date' do
subject { described_class.new(dossier, procedure).decision_date }
@@ -152,6 +153,46 @@ describe SVASVRDecisionDateCalculatorService do
end
end
end
+
+ context 'when dossier is deposed at end of month with correction delay' do
+ let(:config) { { decision: :sva, period: 2, unit: :months, resume: :continue } }
+
+ let!(:correction) do # add 2 days
+ create(:dossier_correction, dossier:, created_at: depose_at + 1.day, resolved_at: depose_at + 2.days)
+ end
+
+ context 'start date = 30' do
+ let(:depose_at) { DateTime.new(2023, 6, 29, 12) }
+
+ it 'calculcates the date accordingly' do
+ expect(subject).to eq(Date.new(2023, 9, 1))
+ end
+ end
+
+ context 'start date = 31' do
+ let(:depose_at) { DateTime.new(2023, 7, 30, 12) }
+
+ it 'calculcates the date accordingly' do
+ expect(subject).to eq(Date.new(2023, 10, 2))
+ end
+ end
+
+ context 'start date = 1 in month having 31 days' do
+ let(:depose_at) { DateTime.new(2023, 7, 31, 12) }
+
+ it 'calculcates the date accordingly' do
+ expect(subject).to eq(Date.new(2023, 10, 3))
+ end
+ end
+
+ context 'start date = 1 in month having 30 days' do
+ let(:depose_at) { DateTime.new(2023, 6, 30, 12) }
+
+ it 'calculcates the date accordingly' do
+ expect(subject).to eq(Date.new(2023, 9, 3))
+ end
+ end
+ end
end
describe '#decision_date_from_today' do
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index b0478d438..9a04c8697 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -16,6 +16,7 @@
# users commonly want.
#
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
+require 'rspec/retry'
RSpec.configure do |config|
config.filter_run_excluding disable: true
@@ -59,3 +60,18 @@ RSpec.configure do |config|
end
end
end
+
+RSpec.configure do |config|
+ # show retry status in spec process
+ config.verbose_retry = true
+ # show exception that triggers a retry if verbose_retry is set to true
+ config.display_try_failure_messages = true
+
+ # callback to be run between retries
+ config.retry_callback = proc do |ex|
+ # run some additional clean up task - can be filtered by example metadata
+ if ex.metadata[:js]
+ Capybara.reset!
+ end
+ end
+end
diff --git a/spec/support/system_helpers.rb b/spec/support/system_helpers.rb
index eb0e006d8..b3cd3f13d 100644
--- a/spec/support/system_helpers.rb
+++ b/spec/support/system_helpers.rb
@@ -172,7 +172,7 @@ module SystemHelpers
find(:xpath, ".//label[contains(text()[normalize-space()], '#{libelle}')]")[:for]
end
- def wait_for_autosave(brouillon = true)
+ def wait_for_autosave
blur
expect(page).to have_css('.debounced-empty') # no more debounce
expect(page).to have_css('.autosave-state-idle') # no more in flight promise
diff --git a/spec/system/administrateurs/types_de_champ_spec.rb b/spec/system/administrateurs/types_de_champ_spec.rb
index ba5ef3578..363feaaff 100644
--- a/spec/system/administrateurs/types_de_champ_spec.rb
+++ b/spec/system/administrateurs/types_de_champ_spec.rb
@@ -199,6 +199,7 @@ describe 'As an administrateur I can edit types de champ', js: true do
scenario 'invalid order, it pops up errors summary' do
add_champ
select('Titre de section', from: 'Type de champ')
+ wait_until { procedure.reload.active_revision.types_de_champ_public.first&.type_champ == TypeDeChamp.type_champs.fetch(:header_section) }
first_header = procedure.active_revision.types_de_champ_public.first
select('Titre de niveau 1', from: dom_id(first_header, :header_section_level))
@@ -206,6 +207,7 @@ describe 'As an administrateur I can edit types de champ', js: true do
wait_until { procedure.reload.active_revision.types_de_champ_public.count == 2 }
second_header = procedure.active_revision.types_de_champ_public.last
select('Titre de section', from: dom_id(second_header, :type_champ))
+ wait_until { procedure.reload.active_revision.types_de_champ_public.last&.type_champ == TypeDeChamp.type_champs.fetch(:header_section) }
select('Titre de niveau 2', from: dom_id(second_header, :header_section_level))
within(".types-de-champ-block li:first-child") do
diff --git a/spec/system/routing/rules_full_scenario_spec.rb b/spec/system/routing/rules_full_scenario_spec.rb
index 50280fef7..a860d8839 100644
--- a/spec/system/routing/rules_full_scenario_spec.rb
+++ b/spec/system/routing/rules_full_scenario_spec.rb
@@ -187,7 +187,7 @@ describe 'The routing with rules', js: true do
click_on 'Modifier mon dossier'
fill_in litteraire_user.dossiers.first.champs_public.first.libelle, with: 'some value'
- wait_for_autosave(false)
+ wait_for_autosave
click_on 'Déposer les modifications'
@@ -286,7 +286,7 @@ describe 'The routing with rules', js: true do
click_on "Modifier mon dossier"
choose(new_group)
- wait_for_autosave(false)
+ wait_for_autosave
expect(page).to have_text(new_group)
diff --git a/spec/system/users/brouillon_spec.rb b/spec/system/users/brouillon_spec.rb
index 1734a32f9..cd5caf281 100644
--- a/spec/system/users/brouillon_spec.rb
+++ b/spec/system/users/brouillon_spec.rb
@@ -6,7 +6,7 @@ describe 'The user' do
let(:user_dossier) { user.dossiers.first }
let!(:dossier_to_link) { create(:dossier) }
- scenario 'fill a dossier', js: true do
+ scenario 'fill a dossier', js: true, retry: 3 do
log_in(user, procedure)
fill_individual
@@ -54,7 +54,7 @@ describe 'The user' do
expect(champ_value_for('text')).to eq('super texte')
expect(champ_value_for('textarea')).to eq('super textarea')
expect(champ_value_for('date')).to eq('2012-12-12')
- expect(champ_value_for('datetime')).to eq('2023-01-06T07:05:00+01:00')
+ expect(champ_value_for('datetime')).to eq(Time.zone.parse('2023-01-06T07:05:00').iso8601)
expect(champ_value_for('number')).to eq('42')
expect(champ_value_for('decimal_number')).to eq('17')
expect(champ_value_for('integer_number')).to eq('12')
@@ -466,7 +466,7 @@ describe 'The user' do
expect(page).to have_no_css('label', text: 'tonnage', visible: true)
fill_in('age du candidat (facultatif)', with: '18')
- wait_for_autosave(false)
+ wait_for_autosave
# the champ keeps their previous value so they are all displayed
expect(page).to have_css('label', text: 'permis de conduire', visible: true)
diff --git a/spec/system/users/dossier_shared_examples.rb b/spec/system/users/dossier_shared_examples.rb
index 67910e147..b4a3e0ee8 100644
--- a/spec/system/users/dossier_shared_examples.rb
+++ b/spec/system/users/dossier_shared_examples.rb
@@ -1,5 +1,5 @@
RSpec.shared_examples 'the user can edit the submitted demande' do
- scenario js: true do
+ scenario js: true, retry: 3 do
visit dossier_path(dossier)
expect(page).to have_current_path(dossier_path(dossier))
@@ -10,7 +10,6 @@ RSpec.shared_examples 'the user can edit the submitted demande' do
expect(page).to have_current_path(modifier_dossier_path(dossier))
fill_in('Texte obligatoire', with: 'Nouveau texte')
- wait_for_autosave(false)
click_on 'Déposer les modifications'
click_on 'Demande'
diff --git a/spec/views/shared/_procedure_description.html.haml_spec.rb b/spec/views/shared/_procedure_description.html.haml_spec.rb
index d3a2375bf..0e1c13e32 100644
--- a/spec/views/shared/_procedure_description.html.haml_spec.rb
+++ b/spec/views/shared/_procedure_description.html.haml_spec.rb
@@ -47,6 +47,16 @@ describe 'shared/_procedure_description', type: :view do
end
end
+ context 'when procedure has usual_traitement_time' do
+ before { assign(:usual_traitement_time, 1.day) }
+
+ it 'shows a usual traitement text' do
+ subject
+ expect(rendered).to have_text("Quels sont des délais d'instruction pour cette démarche ?")
+ expect(rendered).to have_text("Habituellement, les dossiers de cette démarche sont traités dans un délai de 1 jour.")
+ end
+ end
+
context 'when the procedure has pieces jointes' do
let(:procedure) { create(:procedure, :draft, :with_titre_identite, :with_piece_justificative, :with_siret) }
it 'shows the pieces jointes list for draft procedure' do
diff --git a/yarn.lock b/yarn.lock
index 8daafad15..d4d42c039 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1155,28 +1155,28 @@
"@babel/helper-validator-identifier" "^7.19.1"
to-fast-properties "^2.0.0"
-"@coldwired/actions@^0.11.0":
- version "0.11.0"
- resolved "https://registry.yarnpkg.com/@coldwired/actions/-/actions-0.11.0.tgz#b50f833074ff4cd0b80afe022efb9c44b048b21a"
- integrity sha512-IIF1fCCPWRywUfF1nG0QvOzjqKZWKBoniyS2qEJbejpE5FB17eohLIG4GZpkxFtzW+yb96ASRcqAFYcmMEjmYQ==
+"@coldwired/actions@^0.11.1":
+ version "0.11.1"
+ resolved "https://registry.yarnpkg.com/@coldwired/actions/-/actions-0.11.1.tgz#1e2c387dcaadfd4d1d319a9611ab46695ad0726d"
+ integrity sha512-1KX5sjFCtOiLawxCUIq/oYboVE6t6ELKXJto+E7uMmERoHN/2lrr0JmmX5bIsjaHGeqTzZUweOa7Sp705kexIQ==
dependencies:
- "@coldwired/utils" "^0.10.0"
+ "@coldwired/utils" "^0.11.1"
morphdom "^2.7.0"
tiny-invariant "^1.3.1"
-"@coldwired/turbo-stream@^0.11.0":
- version "0.11.0"
- resolved "https://registry.yarnpkg.com/@coldwired/turbo-stream/-/turbo-stream-0.11.0.tgz#fef5338cf95c5e331aa229c5edda92383bc6a05d"
- integrity sha512-Ty1xvjBzqp9dXZfibH6mYTgESmccxe6utG9wZbla+GcsibgCDJJ7NWQEs13RNUhVeCeSRyDL8Ho//UpwqFUEHg==
+"@coldwired/turbo-stream@^0.11.1":
+ version "0.11.1"
+ resolved "https://registry.yarnpkg.com/@coldwired/turbo-stream/-/turbo-stream-0.11.1.tgz#0f0f710422f61700cb8d8d8368799dbce64dd083"
+ integrity sha512-i8ubx6EeLAw84KGYxnxZUlEgVidBmAMCItZcgM3fpv9EN6f4tt3rc53sA+0wAECeZoP6FmqvkNxlPuFIMlBo3A==
dependencies:
- "@coldwired/actions" "^0.11.0"
- "@coldwired/utils" "^0.10.0"
+ "@coldwired/actions" "^0.11.1"
+ "@coldwired/utils" "^0.11.1"
tiny-invariant "^1.3.1"
-"@coldwired/utils@^0.10.0":
- version "0.10.0"
- resolved "https://registry.yarnpkg.com/@coldwired/utils/-/utils-0.10.0.tgz#9d7fd3b3abc437db39abf714b263b55afa2fcc43"
- integrity sha512-5rbSe+k60GgXb55uVvqloest7JWSdSIwRCSirs/u7JWWv6UP+UuYEYQjCpgQVTqBNwYMXiaB843VnWApxsf8oQ==
+"@coldwired/utils@^0.11.1":
+ version "0.11.1"
+ resolved "https://registry.yarnpkg.com/@coldwired/utils/-/utils-0.11.1.tgz#d126246ab66591467e9e4c765769f133f6236ddb"
+ integrity sha512-vuW1hVhD5U4NX/0dl+fT4RL92T5fEITwc9l/DnaBoP5SAuCAVRnHCWcdyROGz55E4WvSXFqAHD6qkxRwOKG2og==
"@emotion/is-prop-valid@^0.8.2":
version "0.8.8"