diff --git a/app/components/dossiers/accuse_lecture_component.rb b/app/components/dossiers/accuse_lecture_component.rb new file mode 100644 index 000000000..78fe76f7f --- /dev/null +++ b/app/components/dossiers/accuse_lecture_component.rb @@ -0,0 +1,5 @@ +class Dossiers::AccuseLectureComponent < ApplicationComponent + def initialize(dossier:) + @dossier = dossier + end +end diff --git a/app/components/dossiers/accuse_lecture_component/accuse_lecture_component.en.yml b/app/components/dossiers/accuse_lecture_component/accuse_lecture_component.en.yml new file mode 100644 index 000000000..e7885eab3 --- /dev/null +++ b/app/components/dossiers/accuse_lecture_component/accuse_lecture_component.en.yml @@ -0,0 +1,4 @@ +--- +en: + text_accuse_lecture: This procedure is subject to a reading acknowledgment. By requesting the display of the decision taken on your file, you accept the reading acknowledgment and thereby the triggering of the legal deadline in the event of an appeal. + btn_accuse_lecture: I would like to display the decision diff --git a/app/components/dossiers/accuse_lecture_component/accuse_lecture_component.fr.yml b/app/components/dossiers/accuse_lecture_component/accuse_lecture_component.fr.yml new file mode 100644 index 000000000..dd8a4b038 --- /dev/null +++ b/app/components/dossiers/accuse_lecture_component/accuse_lecture_component.fr.yml @@ -0,0 +1,4 @@ +--- +fr: + text_accuse_lecture: Cette démarche est soumise à un accusé de lecture. En demandant l’affichage de la décision prise sur votre dossier, vous acceptez l’accusé de lecture et par là même le démarrage du délai légal en cas de recours. + btn_accuse_lecture: Je souhaite afficher la décision diff --git a/app/components/dossiers/accuse_lecture_component/accuse_lecture_component.html.haml b/app/components/dossiers/accuse_lecture_component/accuse_lecture_component.html.haml new file mode 100644 index 000000000..d8722f95f --- /dev/null +++ b/app/components/dossiers/accuse_lecture_component/accuse_lecture_component.html.haml @@ -0,0 +1,10 @@ += render Dsfr::CalloutComponent.new(title: nil) do |c| + - c.with_body do + = t('.text_accuse_lecture') + + = form_for @dossier, + method: :get, + url: set_accuse_lecture_agreement_at_dossier_path(@dossier), + data: { controller: 'autosubmit', turbo: 'true' } do |f| + + = f.submit t('.btn_accuse_lecture'), class: "fr-btn fr-mt-2w" diff --git a/app/components/procedure/card/accuse_lecture_component.rb b/app/components/procedure/card/accuse_lecture_component.rb new file mode 100644 index 000000000..d3a4c2448 --- /dev/null +++ b/app/components/procedure/card/accuse_lecture_component.rb @@ -0,0 +1,5 @@ +class Procedure::Card::AccuseLectureComponent < ApplicationComponent + def initialize(procedure:) + @procedure = procedure + end +end diff --git a/app/components/procedure/card/accuse_lecture_component/accuse_lecture_component.fr.yml b/app/components/procedure/card/accuse_lecture_component/accuse_lecture_component.fr.yml new file mode 100644 index 000000000..1ee8f864b --- /dev/null +++ b/app/components/procedure/card/accuse_lecture_component/accuse_lecture_component.fr.yml @@ -0,0 +1,4 @@ +--- +fr: + title: Accusé de lecture + subtitle: Pour les démarches avec voies de recours diff --git a/app/components/procedure/card/accuse_lecture_component/accuse_lecture_component.html.haml b/app/components/procedure/card/accuse_lecture_component/accuse_lecture_component.html.haml new file mode 100644 index 000000000..8a722dc72 --- /dev/null +++ b/app/components/procedure/card/accuse_lecture_component/accuse_lecture_component.html.haml @@ -0,0 +1,11 @@ +.fr-col-6.fr-col-md-4.fr-col-lg-3 + = link_to accuse_lecture_admin_procedure_path(@procedure), class: 'fr-tile fr-enlarge-link' do + .fr-tile__body.flex.column.align-center.justify-between + - if @procedure.accuse_lecture.present? + %p.fr-badge.fr-badge--success Activé + - else + %p.fr-badge.fr-badge--info Désactivé + %div + %h3.fr-h6.fr-mt-10v= t('.title') + %p.fr-tile-subtitle= t('.subtitle') + %p.fr-btn.fr-btn--tertiary= t('views.shared.actions.edit') diff --git a/app/controllers/administrateurs/procedures_controller.rb b/app/controllers/administrateurs/procedures_controller.rb index a5c1eaa3a..986ded89f 100644 --- a/app/controllers/administrateurs/procedures_controller.rb +++ b/app/controllers/administrateurs/procedures_controller.rb @@ -3,7 +3,7 @@ module Administrateurs layout 'all', only: [:all, :administrateurs] respond_to :html, :xlsx - before_action :retrieve_procedure, only: [:champs, :annotations, :modifications, :edit, :zones, :monavis, :update_monavis, :jeton, :update_jeton, :publication, :publish, :transfert, :close, :confirmation, :allow_expert_review, :allow_expert_messaging, :experts_require_administrateur_invitation, :reset_draft, :publish_revision, :check_path] + before_action :retrieve_procedure, only: [:champs, :annotations, :modifications, :edit, :zones, :monavis, :update_monavis, :accuse_lecture, :update_accuse_lecture, :jeton, :update_jeton, :publication, :publish, :transfert, :close, :confirmation, :allow_expert_review, :allow_expert_messaging, :experts_require_administrateur_invitation, :reset_draft, :publish_revision, :check_path] before_action :draft_valid?, only: [:apercu] after_action :reset_procedure, only: [:update] @@ -276,6 +276,13 @@ module Administrateurs render 'monavis' end + def accuse_lecture + end + + def update_accuse_lecture + @procedure.update!(procedure_params) + end + def jeton end @@ -515,6 +522,7 @@ module Administrateurs :logo, :auto_archive_on, :monavis_embed, + :accuse_lecture, :api_entreprise_token, :duree_conservation_dossiers_dans_ds, { zone_ids: [] }, diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index d00d049dd..00234d794 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -124,6 +124,13 @@ module Users @dossier = dossier end + def set_accuse_lecture_agreement_at + @dossier = dossier + @dossier.update!(accuse_lecture_agreement_at: Time.zone.now) + flash.notice = 'Accusé de lecture accepté' + redirect_back(fallback_location: demande_dossier_path(@dossier)) + end + def identite @dossier = dossier @user = current_user diff --git a/app/helpers/dossier_helper.rb b/app/helpers/dossier_helper.rb index f3aef3dc8..7394a71e6 100644 --- a/app/helpers/dossier_helper.rb +++ b/app/helpers/dossier_helper.rb @@ -78,6 +78,14 @@ module DossierHelper end end + def status_badge_user(dossier, alignment_class = '') + if dossier.hide_info_with_accuse_lecture? + tag.span 'traité', role: 'status', class: "fr-badge fr-badge--sm fr-badge--no-icon #{alignment_class}" + else + status_badge(dossier.state, alignment_class) + end + end + def status_badge(state, alignment_class = '') status_text = dossier_display_state(state, lower: true) tag.span status_text, role: 'status', class: class_names( diff --git a/app/mailers/notification_mailer.rb b/app/mailers/notification_mailer.rb index 70f5b4091..4459e741d 100644 --- a/app/mailers/notification_mailer.rb +++ b/app/mailers/notification_mailer.rb @@ -6,7 +6,7 @@ # The subject and body of a Notification can be customized by each demarche. # class NotificationMailer < ApplicationMailer - before_action :set_dossier, except: [:send_notification_for_tiers] + before_action :set_dossier, except: [:send_notification_for_tiers, :send_accuse_lecture_notification] before_action :set_services_publics_plus, only: :send_notification helper ServiceHelper @@ -42,6 +42,16 @@ class NotificationMailer < ApplicationMailer mail(subject: @subject, to: @email, template_name: 'send_notification_for_tiers') end + def send_accuse_lecture_notification(dossier) + @dossier = dossier + @subject = "La décision a été rendue pour votre démarche #{@dossier.procedure.libelle.truncate_words(50)}" + @email = @dossier.user_email_for(:notification) + + @logo_url = procedure_logo_url(@dossier.procedure) + + mail(subject: @subject, to: @email, template_name: 'send_accuse_lecture_notification') + end + def self.send_en_construction_notification(dossier) with(dossier: dossier, state: Dossier.states.fetch(:en_construction)).send_notification end diff --git a/app/models/concerns/dossier_state_concern.rb b/app/models/concerns/dossier_state_concern.rb index 908f2bbd6..1c99ffb65 100644 --- a/app/models/concerns/dossier_state_concern.rb +++ b/app/models/concerns/dossier_state_concern.rb @@ -120,7 +120,11 @@ module DossierStateConcern disable_notification = h.fetch(:disable_notification, false) if !disable_notification - NotificationMailer.send_accepte_notification(self).deliver_later + if procedure.accuse_lecture? + NotificationMailer.send_accuse_lecture_notification(self).deliver_later + else + NotificationMailer.send_accepte_notification(self).deliver_later + end NotificationMailer.send_notification_for_tiers(self).deliver_later if self.for_tiers? end @@ -152,7 +156,11 @@ module DossierStateConcern end def after_commit_accepter_automatiquement - NotificationMailer.send_accepte_notification(self).deliver_later + if procedure.accuse_lecture? + NotificationMailer.send_accuse_lecture_notification(self).deliver_later + else + NotificationMailer.send_accepte_notification(self).deliver_later + end NotificationMailer.send_notification_for_tiers(self).deliver_later if self.for_tiers? send_dossier_decision_to_experts(self) @@ -184,7 +192,11 @@ module DossierStateConcern disable_notification = h.fetch(:disable_notification, false) if !disable_notification - NotificationMailer.send_refuse_notification(self).deliver_later + if procedure.accuse_lecture? + NotificationMailer.send_accuse_lecture_notification(self).deliver_later + else + NotificationMailer.send_refuse_notification(self).deliver_later + end NotificationMailer.send_notification_for_tiers(self).deliver_later if self.for_tiers? end @@ -209,7 +221,11 @@ module DossierStateConcern end def after_commit_refuser_automatiquement - NotificationMailer.send_refuse_notification(self).deliver_later + if procedure.accuse_lecture? + NotificationMailer.send_accuse_lecture_notification(self).deliver_later + else + NotificationMailer.send_refuse_notification(self).deliver_later + end NotificationMailer.send_notification_for_tiers(self).deliver_later if self.for_tiers? send_dossier_decision_to_experts(self) @@ -241,7 +257,11 @@ module DossierStateConcern disable_notification = h.fetch(:disable_notification, false) if !disable_notification - NotificationMailer.send_sans_suite_notification(self).deliver_later + if procedure.accuse_lecture? + NotificationMailer.send_accuse_lecture_notification(self).deliver_later + else + NotificationMailer.send_sans_suite_notification(self).deliver_later + end NotificationMailer.send_notification_for_tiers(self).deliver_later if self.for_tiers? end diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 7c9be0b1f..d2aafd943 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -1180,6 +1180,14 @@ class Dossier < ApplicationRecord end end + def hide_info_with_accuse_lecture? + procedure.accuse_lecture? && termine? && accuse_lecture_agreement_at.blank? + end + + def termine_and_accuse_lecture? + procedure.accuse_lecture? && termine? + end + private def champs_by_public_id diff --git a/app/models/dossiers_filter.rb b/app/models/dossiers_filter.rb index 66163b534..c542c3cac 100644 --- a/app/models/dossiers_filter.rb +++ b/app/models/dossiers_filter.rb @@ -23,6 +23,7 @@ class DossiersFilter dossiers_result = dossiers dossiers_result = dossiers_result.where(state: state) if state.present? && state != Dossier::A_CORRIGER dossiers_result = dossiers_result.with_pending_corrections if state.present? && state == Dossier::A_CORRIGER + dossiers_result = exclude_accuse_lecture(dossiers_result) if state.present? && Dossier::TERMINE.include?(state) dossiers_result = dossiers_result.where('dossiers.created_at >= ?', from_created_at_date) if from_created_at_date.present? dossiers_result = dossiers_result.where('dossiers.depose_at >= ?', from_depose_at_date) if from_depose_at_date.present? dossiers_result @@ -47,4 +48,8 @@ class DossiersFilter rescue Date::Error nil end + + def exclude_accuse_lecture(dossiers) + dossiers.joins(:procedure).where.not('dossiers.accuse_lecture_agreement_at IS NULL AND procedures.accuse_lecture = TRUE ') + end end diff --git a/app/services/mail_template_presenter_service.rb b/app/services/mail_template_presenter_service.rb index 26fa043ab..b0e9db3bb 100644 --- a/app/services/mail_template_presenter_service.rb +++ b/app/services/mail_template_presenter_service.rb @@ -3,9 +3,13 @@ class MailTemplatePresenterService include ActionView::Helpers::TextHelper def self.create_commentaire_for_state(dossier, state) - service = new(dossier, state) - body = ["

[#{service.safe_subject}]

", service.safe_body].join('') - CommentaireService.create!(CONTACT_EMAIL, dossier, body: body) + if dossier.procedure.accuse_lecture? && Dossier::TERMINE.include?(state) + CommentaireService.create!(CONTACT_EMAIL, dossier, body: I18n.t('layouts.mailers.accuse_lecture.commentaire_html', service: dossier.procedure.service.nom)) + else + service = new(dossier, state) + body = ["

[#{service.safe_subject}]

", service.safe_body].join('') + CommentaireService.create!(CONTACT_EMAIL, dossier, body: body) + end end def safe_body diff --git a/app/views/administrateurs/procedures/accuse_lecture.html.haml b/app/views/administrateurs/procedures/accuse_lecture.html.haml new file mode 100644 index 000000000..13e998dec --- /dev/null +++ b/app/views/administrateurs/procedures/accuse_lecture.html.haml @@ -0,0 +1,43 @@ += render partial: 'administrateurs/breadcrumbs', + locals: { steps: [['Démarches', admin_procedures_back_path(@procedure)], + [@procedure.libelle.truncate_words(10), admin_procedure_path(@procedure)], + ['Accusé de lecture']] } + +.fr-container + .fr-grid-row + .fr-col-12.fr-col-offset-md-2.fr-col-md-8 + %h1.page-title + Accusé de lecture + + = render Dsfr::CalloutComponent.new(title: nil) do |c| + - c.with_body do + %p + Pour les démarches avec voies de recours, il est possible d’activer l’accusé de lecture. + %br + %p + Cette fonctionnalité permet à l’instructeur de connaître la date de lecture de la décision finale par l’usager. + %br + %p + L’usager n’a plus accès à la décision finale par mail, mais il doit se connecter sur la plateforme #{Current.application_name} pour en prendre connaissance et en accuser lecture. + + %ul.fr-toggle__list + %li + = form_for @procedure, + method: :patch, + url: update_accuse_lecture_admin_procedure_path(@procedure), + data: { controller: 'autosubmit', turbo: 'true' } do |f| + + = render Dsfr::ToggleComponent.new(form: f, + target: :accuse_lecture, + title: "Accusé de lecture de la démarche", + hint: "L’accusé de lecture est à activer uniquement pour les démarches avec voies de recours car il complexifie l’accès à la décision finale pour les usagers", + opt: {"checked" => @procedure.accuse_lecture}) + +.padded-fixed-footer + .fixed-footer + .fr-container + .fr-grid-row + .fr-col-12.fr-col-offset-md-2.fr-col-md-8 + %ul.fr-btns-group.fr-btns-group--inline-md + %li + = link_to 'Enregistrer et revenir à la page de suivi', admin_procedure_path(id: @procedure), class: 'fr-btn' diff --git a/app/views/administrateurs/procedures/show.html.haml b/app/views/administrateurs/procedures/show.html.haml index 446f37d1c..16ef212bf 100644 --- a/app/views/administrateurs/procedures/show.html.haml +++ b/app/views/administrateurs/procedures/show.html.haml @@ -89,3 +89,4 @@ = render Procedure::Card::MonAvisComponent.new(procedure: @procedure) = render Procedure::Card::DossierSubmittedMessageComponent.new(procedure: @procedure) = render Procedure::Card::ChorusComponent.new(procedure: @procedure) + = render Procedure::Card::AccuseLectureComponent.new(procedure: @procedure) diff --git a/app/views/notification_mailer/send_accuse_lecture_notification.html.haml b/app/views/notification_mailer/send_accuse_lecture_notification.html.haml new file mode 100644 index 000000000..3e3a81573 --- /dev/null +++ b/app/views/notification_mailer/send_accuse_lecture_notification.html.haml @@ -0,0 +1,23 @@ +- content_for :procedure_logo do + = render 'layouts/mailers/logo', url: @logo_url + +%p + = t("layouts.mailers.accuse_lecture.good_morning") + +%p + = t("layouts.mailers.accuse_lecture.first_part", + dossier_id: number_with_delimiter(@dossier.id)) + + %span{ :style => "font-weight: bold;" } + = @dossier.procedure.libelle + + = t("layouts.mailers.accuse_lecture.second_part") +%p + = t("layouts.mailers.accuse_lecture.third_part") + = link_to APPLICATION_NAME, dossier_url(@dossier) + +%p + = t(:best_regards, scope: [:views, :shared, :greetings]) + %br + = t('layouts.mailers.signature.team') + = APPLICATION_NAME diff --git a/app/views/notification_mailer/send_notification_for_tiers.html.haml b/app/views/notification_mailer/send_notification_for_tiers.html.haml index 75306e99b..83c73e69d 100644 --- a/app/views/notification_mailer/send_notification_for_tiers.html.haml +++ b/app/views/notification_mailer/send_notification_for_tiers.html.haml @@ -15,8 +15,10 @@ - if @repasser_en_instruction = t("layouts.mailers.for_tiers.repasser_en_instruction") + - elsif @dossier.hide_info_with_accuse_lecture? + = t("layouts.mailers.for_tiers.accuse_lecture", processed_at: l(@dossier.updated_at.to_date)) - else - = t("layouts.mailers.for_tiers.#{@dossier.state}", processed_at: l(@dossier.updated_at.to_date) ) + = t("layouts.mailers.for_tiers.#{@dossier.state}", processed_at: l(@dossier.updated_at.to_date)) %p = t("layouts.mailers.for_tiers.second_part") diff --git a/app/views/shared/dossiers/_demande.html.haml b/app/views/shared/dossiers/_demande.html.haml index edaa7d4f5..4a7e9d1d9 100644 --- a/app/views/shared/dossiers/_demande.html.haml +++ b/app/views/shared/dossiers/_demande.html.haml @@ -5,11 +5,20 @@ .fr-container.counter-start-header-section.dossier-show{ class: class_names("dossier-show-instructeur" => profile =="instructeur") } .fr-grid-row.fr-grid-row--center .fr-col-12.fr-col-xl-8 + - if profile == 'instructeur' && dossier.termine_and_accuse_lecture? + = render Dsfr::CalloutComponent.new(title: nil) do |c| + - c.with_html_body do + = t('views.shared.dossiers.demande.accuse_lecture') + - if dossier.accuse_lecture_agreement_at.present? + = t('views.shared.dossiers.demande.accuse_lecture_with_agreement', agreement: l(dossier.accuse_lecture_agreement_at, format: :long)) + - else + = t('views.shared.dossiers.demande.accuse_lecture_without_agreement') + %h2.fr-h6.fr-background-alt--grey.fr-mb-0 .flex-grow.fr-py-3v.fr-px-2w= t('views.shared.dossiers.demande.en_construction') - if dossier.depose_at.present? - = render partial: "shared/dossiers/infos_generales", locals: { dossier: dossier } + = render partial: "shared/dossiers/infos_generales", locals: { dossier: dossier, profile: profile } - if dossier.for_tiers? diff --git a/app/views/shared/dossiers/_header.html.haml b/app/views/shared/dossiers/_header.html.haml index 3dafe0e39..c162b080d 100644 --- a/app/views/shared/dossiers/_header.html.haml +++ b/app/views/shared/dossiers/_header.html.haml @@ -1,6 +1,6 @@ %h1 = procedure_libelle(dossier.procedure) - = status_badge(dossier.state, 'super') + = status_badge_user(dossier, 'super') %h2 = t('views.users.dossiers.show.header.dossier_number', dossier_id: dossier.id) = t('views.users.dossiers.show.header.created_date', date_du_dossier: I18n.l(dossier.created_at)) diff --git a/app/views/shared/dossiers/_infos_generales.html.haml b/app/views/shared/dossiers/_infos_generales.html.haml index d9f54812b..7cc311970 100644 --- a/app/views/shared/dossiers/_infos_generales.html.haml +++ b/app/views/shared/dossiers/_infos_generales.html.haml @@ -9,18 +9,22 @@ .fr-highlight %p.fr-text--sm.fr-text-mention--grey Sauf mention contraire, les champs ont été saisis à la date du dépôt du dossier. - - if dossier.justificatif_motivation.attached? - = render Dossiers::RowShowComponent.new(label: "Justificatif") do |c| - - c.with_value do - .action - = render Attachment::ShowComponent.new(attachment: dossier.justificatif_motivation.attachment) + - if profile == 'usager' && dossier.hide_info_with_accuse_lecture? + = render Dossiers::AccuseLectureComponent.new(dossier: dossier) - - if dossier.motivation.present? - = render Dossiers::RowShowComponent.new(label: "Motivation") do |c| - - c.with_value do - = simple_format dossier.motivation + - else + - if dossier.justificatif_motivation.attached? + = render Dossiers::RowShowComponent.new(label: "Justificatif") do |c| + - c.with_value do + .action + = render Attachment::ShowComponent.new(attachment: dossier.justificatif_motivation.attachment) - - if dossier.attestation.present? && dossier.attestation.pdf.attached? - = render Dossiers::RowShowComponent.new(label: "Attestation") do |c| - - c.with_value do - = render Dsfr::DownloadComponent.new(attachment: dossier.attestation.pdf, name: t(:download_attestation, scope: [:views, :shared, :dossiers, :form])) + - if dossier.motivation.present? + = render Dossiers::RowShowComponent.new(label: "Motivation") do |c| + - c.with_value do + = simple_format dossier.motivation + + - if dossier.attestation.present? && dossier.attestation.pdf.attached? + = render Dossiers::RowShowComponent.new(label: "Attestation") do |c| + - c.with_value do + = render Dsfr::DownloadComponent.new(attachment: dossier.attestation.pdf, name: t(:download_attestation, scope: [:views, :shared, :dossiers, :form])) diff --git a/app/views/users/dossiers/_dossiers_list.html.haml b/app/views/users/dossiers/_dossiers_list.html.haml index 2b327e753..8ab0cfa5f 100644 --- a/app/views/users/dossiers/_dossiers_list.html.haml +++ b/app/views/users/dossiers/_dossiers_list.html.haml @@ -44,7 +44,7 @@ %span.fr-badge.fr-badge--sm.fr-badge--warning = t('views.users.dossiers.dossiers_list.deleted_badge') - else - = status_badge(dossier.state, 'fr-mb-1w') + = status_badge_user(dossier, 'fr-mb-1w') - if dossier.pending_correction? %br diff --git a/app/views/users/dossiers/show/_header.html.haml b/app/views/users/dossiers/show/_header.html.haml index 466518cb5..2d0a73858 100644 --- a/app/views/users/dossiers/show/_header.html.haml +++ b/app/views/users/dossiers/show/_header.html.haml @@ -2,7 +2,7 @@ .fr-container %h1 = dossier.procedure.libelle - = status_badge(dossier.state, 'super') + = status_badge_user(dossier, 'super') = pending_correction_badge(:for_user) if dossier.pending_correction? %h2 = t('views.users.dossiers.show.header.dossier_number', dossier_id: dossier.id) diff --git a/app/views/users/dossiers/show/_status_overview.html.haml b/app/views/users/dossiers/show/_status_overview.html.haml index 557365963..b1c4f6ea6 100644 --- a/app/views/users/dossiers/show/_status_overview.html.haml +++ b/app/views/users/dossiers/show/_status_overview.html.haml @@ -54,46 +54,50 @@ %p = t('views.users.dossiers.show.status_overview.use_mailbox_for_questions_html', mailbox_url: messagerie_dossier_url(dossier)) - - elsif dossier.accepte? - .accepte - %p.decision{ role: 'status' } - = dsfr_icon('fr-icon-checkbox-circle-fill fr-text-default--success') - = t('views.users.dossiers.show.status_overview.acceptee_html') + - elsif dossier.termine? + - if dossier.hide_info_with_accuse_lecture? + = render Dossiers::AccuseLectureComponent.new(dossier: dossier) - - if dossier.motivation.present? - %h3= t('views.users.dossiers.show.status_overview.accepte_motivation') - %blockquote= simple_format(dossier.motivation) + - elsif dossier.accepte? + .accepte + %p.decision{ role: 'status' } + = dsfr_icon('fr-icon-checkbox-circle-fill fr-text-default--success') + = t('views.users.dossiers.show.status_overview.acceptee_html') - = render partial: 'users/dossiers/show/download_justificatif', locals: { dossier: dossier } + - if dossier.motivation.present? + %h3= t('views.users.dossiers.show.status_overview.accepte_motivation') + %blockquote= simple_format(dossier.motivation) - - if dossier.attestation.present? + = render partial: 'users/dossiers/show/download_justificatif', locals: { dossier: dossier } + + - if dossier.attestation.present? + .action + = link_to attestation_dossier_path(dossier), class: "fr-btn fr-icon-download-line fr-btn--icon-left", **external_link_attributes do + = t('views.users.dossiers.show.status_overview.accepte_attestation') + + + - elsif dossier.refuse? + .refuse + %p.decision{ role: 'status' } + = dsfr_icon('fr-icon-close-circle-fill fr-text-default--error') + = t('views.users.dossiers.show.status_overview.refuse_html') + + - if dossier.motivation.present? + %h3= t('views.users.dossiers.show.status_overview.refuse_motivation') + %blockquote= simple_format(dossier.motivation) + + = render partial: 'users/dossiers/show/download_justificatif', locals: { dossier: dossier } .action - = link_to attestation_dossier_path(dossier), class: "fr-btn fr-icon-download-line fr-btn--icon-left", target: '_blank', rel: 'noopener' do - = t('views.users.dossiers.show.status_overview.accepte_attestation') + = link_to t('views.users.dossiers.show.status_overview.refuse_reply'), messagerie_dossier_url(dossier, anchor: 'new_commentaire'), class: 'fr-link' + - elsif dossier.sans_suite? + .sans-suite + %p.decision{ role: 'status' } + = dsfr_icon('fr-icon-intermediate-circle-fill') + = t('views.users.dossiers.show.status_overview.sans_suite_html') - - elsif dossier.refuse? - .refuse - %p.decision{ role: 'status' } - = dsfr_icon('fr-icon-close-circle-fill fr-text-default--error') - = t('views.users.dossiers.show.status_overview.refuse_html') + = render partial: 'users/dossiers/show/download_justificatif', locals: { dossier: dossier } - - if dossier.motivation.present? - %h3= t('views.users.dossiers.show.status_overview.refuse_motivation') - %blockquote= simple_format(dossier.motivation) - - = render partial: 'users/dossiers/show/download_justificatif', locals: { dossier: dossier } - .action - = link_to t('views.users.dossiers.show.status_overview.refuse_reply'), messagerie_dossier_url(dossier, anchor: 'new_commentaire'), class: 'fr-link' - - - elsif dossier.sans_suite? - .sans-suite - %p.decision{ role: 'status' } - = dsfr_icon('fr-icon-intermediate-circle-fill') - = t('views.users.dossiers.show.status_overview.sans_suite_html') - - = render partial: 'users/dossiers/show/download_justificatif', locals: { dossier: dossier } - - - if dossier.motivation.present? - %h3= t('views.users.dossiers.show.status_overview.sans_suite_motivation') - %blockquote= simple_format(dossier.motivation) + - if dossier.motivation.present? + %h3= t('views.users.dossiers.show.status_overview.sans_suite_motivation') + %blockquote= simple_format(dossier.motivation) diff --git a/config/locales/en.yml b/config/locales/en.yml index 7bab87554..d86e72fc9 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -362,6 +362,9 @@ en: form: "Form" edit_siret: "Edit SIRET" edit_identity: "Edit identity data" + accuse_lecture: This procedure is subject to a reading receipt. + accuse_lecture_with_agreement: The user has read the decision taken on his file on %{agreement}. + accuse_lecture_without_agreement: The user has not yet learned of the decision on their file. gestionnaires: groupe_gestionnaires: delete: Delete diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 45ffc83bd..8da981b0e 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -365,6 +365,9 @@ fr: form: "Sections du formulaire" edit_siret: "Modifier le SIRET" edit_identity: "Modifier l’identité" + accuse_lecture: Cette démarche est soumise à un accusé de lecture. + accuse_lecture_with_agreement: L’usager a pris connaissance de la décision concernant son dossier le %{agreement}. + accuse_lecture_without_agreement: L’usager n’a pas encore pris connaissance de la décision concernant son dossier. gestionnaires: groupe_gestionnaires: delete: Supprimer diff --git a/config/locales/models/mail/initiated_mail/fr.yml b/config/locales/models/mail/initiated_mail/fr.yml index 25a85492d..37e154c4e 100644 --- a/config/locales/models/mail/initiated_mail/fr.yml +++ b/config/locales/models/mail/initiated_mail/fr.yml @@ -4,4 +4,4 @@ fr: mail: initiated_mail: default_subject: Votre dossier nº %{dossier_number} a bien été déposé (%{procedure_libelle}) - proof_of_receipt: Accusé de réception + proof_of_receipt: Accusé de lecture diff --git a/config/locales/shared.en.yml b/config/locales/shared.en.yml index 38431ed9b..2fb779193 100644 --- a/config/locales/shared.en.yml +++ b/config/locales/shared.en.yml @@ -13,9 +13,9 @@ en: brouillon: "Expires on %{date} (%{duree_conservation_totale} months after this file was created)" en_construction: "Expires on %{date} (%{duree_conservation_totale} months after this file was last modified)" en_instruction: "This file is being instructed, the administration will answer as soon as possible" - accepte: "Expires on %{date} (%{duree_conservation_totale} months after this file was accepted)" - refuse: "Expires on %{date} (%{duree_conservation_totale} months after this file was rejected)" - sans_suite: "Expires on %{date} (%{duree_conservation_totale} months after this file was closed)" + accepte: "Expires on %{date} (%{duree_conservation_totale} months after this file was processed)" + refuse: "Expires on %{date} (%{duree_conservation_totale} months after this file was processed)" + sans_suite: "Expires on %{date} (%{duree_conservation_totale} months after this file was processed)" champs: cnaf: show: diff --git a/config/locales/shared.fr.yml b/config/locales/shared.fr.yml index 00b238b57..c510bd870 100644 --- a/config/locales/shared.fr.yml +++ b/config/locales/shared.fr.yml @@ -13,9 +13,9 @@ fr: brouillon: "Expirera le %{date} (%{duree_conservation_totale} mois après la création du dossier)" en_construction: "Expirera le %{date} (%{duree_conservation_totale} mois après le dépôt du dossier)" en_instruction: "Ce dossier est en instruction, il n’expirera pas" - accepte: "Expirera le %{date} (%{duree_conservation_totale} mois après l’acceptation du dossier)" - refuse: "Expirera le %{date} (%{duree_conservation_totale} mois après le refus du dossier)" - sans_suite: "Expirera le %{date} (%{duree_conservation_totale} mois après le classement sans suite du dossier)" + accepte: "Expirera le %{date} (%{duree_conservation_totale} mois après le traitement du dossier)" + refuse: "Expirera le %{date} (%{duree_conservation_totale} mois après le traitement du dossier)" + sans_suite: "Expirera le %{date} (%{duree_conservation_totale} mois après le traitement dossier)" champs: diff --git a/config/locales/views/layouts/mailers/en.yml b/config/locales/views/layouts/mailers/en.yml index f683354e7..bfdd5c74c 100644 --- a/config/locales/views/layouts/mailers/en.yml +++ b/config/locales/views/layouts/mailers/en.yml @@ -24,3 +24,10 @@ en: accepte: has been accepted on %{processed_at}. refuse: has been refused on %{processed_at}. sans_suite: has been closed without continuation on %{processed_at}. + accuse_lecture: has been processed on %{processed_at}. + accuse_lecture: + good_morning: Hello, + first_part: We inform you that a decision on file no. %{dossier_id} of the procedure + second_part: has been rendered. + third_part: To find out its nature, please log in to your account + commentaire_html:

Hello,

We inform you that a decision on your file has been rendered.

Sincerely,
%{service} diff --git a/config/locales/views/layouts/mailers/fr.yml b/config/locales/views/layouts/mailers/fr.yml index 314d426f9..c465e93f9 100644 --- a/config/locales/views/layouts/mailers/fr.yml +++ b/config/locales/views/layouts/mailers/fr.yml @@ -25,5 +25,13 @@ fr: accepte: a été accepté le %{processed_at}. refuse: a été refusé le %{processed_at}. sans_suite: a été classé sans suite le %{processed_at}. + accuse_lecture: a été traité le %{processed_at}. + accuse_lecture: + good_morning: Bonjour, + first_part: Nous vous informons qu'une décision sur le dossier nº %{dossier_id} de la démarche + second_part: a été rendue. + third_part: Pour en connaitre la nature, veuillez vous connecter à votre compte + commentaire_html:

Bonjour,

Nous vous informons qu'une décision sur votre dossier a été rendue.

Cordialement,
%{service} + commentaire_groupe_gestionnaire_footer: do_not_reply_html: Merci de ne pas répondre à cet email. Consultez votre message sur %{application_name} ou contactez votre expéditeur par mail diff --git a/config/routes.rb b/config/routes.rb index 18317b7f5..094758d24 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -369,6 +369,7 @@ Rails.application.routes.draw do get 'attestation' get 'transferer', to: 'dossiers#transferer' get 'papertrail', format: :pdf + get 'set_accuse_lecture_agreement_at' end collection do @@ -571,6 +572,8 @@ Rails.application.routes.draw do get 'modifications' get 'monavis' patch 'update_monavis' + get 'accuse_lecture' + patch 'update_accuse_lecture' get 'jeton' patch 'update_jeton' put :allow_expert_review diff --git a/db/migrate/20240319150925_add_accuse_lecture_to_procedures.rb b/db/migrate/20240319150925_add_accuse_lecture_to_procedures.rb new file mode 100644 index 000000000..f2550a4c2 --- /dev/null +++ b/db/migrate/20240319150925_add_accuse_lecture_to_procedures.rb @@ -0,0 +1,5 @@ +class AddAccuseLectureToProcedures < ActiveRecord::Migration[7.0] + def change + add_column :procedures, :accuse_lecture, :boolean, default: false, null: false + end +end diff --git a/db/migrate/20240321152801_add_accuse_lecture_agreement_to_dossiers.rb b/db/migrate/20240321152801_add_accuse_lecture_agreement_to_dossiers.rb new file mode 100644 index 000000000..401e512ad --- /dev/null +++ b/db/migrate/20240321152801_add_accuse_lecture_agreement_to_dossiers.rb @@ -0,0 +1,5 @@ +class AddAccuseLectureAgreementToDossiers < ActiveRecord::Migration[7.0] + def change + add_column :dossiers, :accuse_lecture_agreement_at, :date + end +end diff --git a/db/schema.rb b/db/schema.rb index dcc3a65d3..1caaf322c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -442,6 +442,7 @@ ActiveRecord::Schema[7.0].define(version: 2024_04_16_062900) do end create_table "dossiers", id: :serial, force: :cascade do |t| + t.date "accuse_lecture_agreement_at" t.string "api_entreprise_job_exceptions", array: true t.boolean "archived", default: false t.datetime "archived_at", precision: nil @@ -857,6 +858,7 @@ ActiveRecord::Schema[7.0].define(version: 2024_04_16_062900) do create_table "procedures", id: :serial, force: :cascade do |t| t.string "aasm_state", default: "brouillon" + t.boolean "accuse_lecture", default: false, null: false t.boolean "allow_expert_messaging", default: true, null: false t.boolean "allow_expert_review", default: true, null: false t.string "api_entreprise_token" diff --git a/spec/controllers/instructeurs/dossiers_controller_spec.rb b/spec/controllers/instructeurs/dossiers_controller_spec.rb index d64142354..f72f52003 100644 --- a/spec/controllers/instructeurs/dossiers_controller_spec.rb +++ b/spec/controllers/instructeurs/dossiers_controller_spec.rb @@ -6,7 +6,9 @@ describe Instructeurs::DossiersController, type: :controller do let(:administration) { create(:administration) } let(:instructeurs) { [instructeur] } let(:procedure) { create(:procedure, :published, :for_individual, instructeurs: instructeurs) } + let(:procedure_accuse_lecture) { create(:procedure, :published, :for_individual, :accuse_lecture, instructeurs: instructeurs) } let(:dossier) { create(:dossier, :en_construction, :with_individual, procedure: procedure) } + let(:dossier_accuse_lecture) { create(:dossier, :en_construction, :with_individual, procedure: procedure_accuse_lecture) } let(:dossier_for_tiers) { create(:dossier, :en_construction, :for_tiers_with_notification, procedure: procedure) } let(:dossier_for_tiers_without_notif) { create(:dossier, :en_construction, :for_tiers_without_notification, procedure: procedure) } let(:fake_justificatif) { fixture_file_upload('spec/fixtures/files/piece_justificative_0.pdf', 'application/pdf') } @@ -376,6 +378,34 @@ describe Instructeurs::DossiersController, type: :controller do end end + context "with accuse de lecture procedure" do + before do + dossier_accuse_lecture.passer_en_instruction!(instructeur: instructeur) + sign_in(instructeur.user) + end + context 'with classer_sans_suite' do + subject { post :terminer, params: { process_action: "classer_sans_suite", procedure_id: procedure_accuse_lecture.id, dossier_id: dossier_accuse_lecture.id }, format: :turbo_stream } + + it 'Notification accuse de lecture email is sent and not the others' do + expect(NotificationMailer).to receive(:send_accuse_lecture_notification) + .with(dossier_accuse_lecture).and_return(NotificationMailer) + expect(NotificationMailer).to receive(:deliver_later) + + expect(NotificationMailer).not_to receive(:send_sans_suite_notification) + .with(dossier_accuse_lecture) + + subject + end + + it { expect(subject.body).to include('header-top') } + + it 'creates a commentaire' do + expect { subject }.to change { Commentaire.count }.by(1) + expect(dossier_accuse_lecture.commentaires.last.body).to eq("

Bonjour,

Nous vous informons qu'une décision sur votre dossier a été rendue.

Cordialement,
#{procedure_accuse_lecture.service.nom}") + end + end + end + context "with classer_sans_suite" do before do dossier.passer_en_instruction!(instructeur: instructeur) diff --git a/spec/factories/procedure.rb b/spec/factories/procedure.rb index 74785ebfa..6799dbeda 100644 --- a/spec/factories/procedure.rb +++ b/spec/factories/procedure.rb @@ -283,6 +283,10 @@ FactoryBot.define do referentiel_de_programmation: { c: 3 }) end end + + trait :accuse_lecture do + accuse_lecture { true } + end end end diff --git a/spec/mailers/notification_mailer_spec.rb b/spec/mailers/notification_mailer_spec.rb index 831df8985..74308afb5 100644 --- a/spec/mailers/notification_mailer_spec.rb +++ b/spec/mailers/notification_mailer_spec.rb @@ -29,6 +29,25 @@ RSpec.describe NotificationMailer, type: :mailer do end end + describe 'send_notification_for_tiers with accuse lecture procedure' do + let(:dossier_for_tiers) { create(:dossier, :accepte, :for_tiers_with_notification, procedure: create(:procedure, :accuse_lecture, :for_individual)) } + + subject { described_class.send_notification_for_tiers(dossier_for_tiers) } + + it { expect(subject.subject).to include("Votre dossier rempli par le mandataire #{dossier_for_tiers.mandataire_first_name} #{dossier_for_tiers.mandataire_last_name} a été mis à jour") } + it { expect(subject.to).to eq([dossier_for_tiers.individual.email]) } + it { expect(subject.body).to include("a été traité le") } + it { expect(subject.body).to include("Pour en savoir plus, veuillez vous rapprocher de\r\n#{dossier_for_tiers.user.email}.") } + end + + describe 'send_accuse_lecture_notification' do + let(:dossier) { create(:dossier, :accepte, procedure: create(:procedure, :accuse_lecture)) } + subject { described_class.send_accuse_lecture_notification(dossier) } + + it { expect(subject.subject).to include("La décision a été rendue pour votre démarche #{dossier.procedure.libelle}") } + it { expect(subject.body).to include("Pour en connaitre la nature, veuillez vous connecter à votre compte\r\ndemarches-simplifiees.fr") } + end + describe 'send_en_construction_notification' do let(:dossier) { create(:dossier, :en_construction, :with_individual, user: user, procedure:) } diff --git a/spec/mailers/previews/notification_mailer_preview.rb b/spec/mailers/previews/notification_mailer_preview.rb index 24b05836d..f16838ba5 100644 --- a/spec/mailers/previews/notification_mailer_preview.rb +++ b/spec/mailers/previews/notification_mailer_preview.rb @@ -23,6 +23,10 @@ class NotificationMailerPreview < ActionMailer::Preview NotificationMailer.send_notification_for_tiers(dossier) end + def send_accuse_lecture_notification + NotificationMailer.send_accuse_lecture_notification(dossier) + end + private def dossier diff --git a/spec/system/users/list_dossiers_spec.rb b/spec/system/users/list_dossiers_spec.rb index 669e64480..56f5064c4 100644 --- a/spec/system/users/list_dossiers_spec.rb +++ b/spec/system/users/list_dossiers_spec.rb @@ -1,5 +1,6 @@ describe 'user access to the list of their dossiers', js: true do let(:user) { create(:user) } + let(:procedure_accuse_lecture) { create(:procedure, :accuse_lecture) } let!(:dossier_brouillon) { create(:dossier, user: user) } let!(:dossier_en_construction) { create(:dossier, :with_populated_champs, :en_construction, user: user) } let!(:dossier_en_construction_2) { create(:dossier, :en_construction, user: user) } @@ -9,6 +10,8 @@ describe 'user access to the list of their dossiers', js: true do let!(:dossier_a_corriger) { create(:dossier_correction, dossier: dossier_en_construction_2) } let!(:dossier_archived) { create(:dossier, :en_instruction, :archived, user: user) } let!(:dossier_for_tiers) { create(:dossier, :en_instruction, :for_tiers_with_notification, user: user) } + let!(:dossier_en_construction_with_accuse_lecture) { create(:dossier, :en_construction, user: user, procedure: procedure_accuse_lecture) } + let!(:dossier_accepte_with_accuse_lecture) { create(:dossier, :accepte, user: user, procedure: procedure_accuse_lecture) } let(:dossiers_per_page) { 25 } let(:last_updated_dossier) { dossier_en_construction } @@ -31,8 +34,8 @@ describe 'user access to the list of their dossiers', js: true do expect(page).to have_content(dossier_en_construction.procedure.libelle) expect(page).to have_content(dossier_en_instruction.procedure.libelle) expect(page).to have_content(dossier_archived.procedure.libelle) - expect(page).to have_text('6 en cours') - expect(page).to have_text('2 traités') + expect(page).to have_text('7 en cours') + expect(page).to have_text('3 traités') end it 'the list must be ordered by last updated' do @@ -55,8 +58,8 @@ describe 'user access to the list of their dossiers', js: true do page.click_link("Suivant") page.click_link("Suivant") expect(page).to have_link(dossier_en_instruction.procedure.libelle) - expect(page).to have_text('6 en cours') - expect(page).to have_text('2 traités') + expect(page).to have_text('7 en cours') + expect(page).to have_text('3 traités') end end @@ -70,9 +73,9 @@ describe 'user access to the list of their dossiers', js: true do context 'when user uses filter' do scenario 'user filters state on tab "en-cours"' do - expect(page).to have_text('6 en cours') - expect(page).to have_text('2 traités') - expect(page).to have_text('6 sur 6 dossiers') + expect(page).to have_text('7 en cours') + expect(page).to have_text('3 traités') + expect(page).to have_text('7 sur 7 dossiers') click_on('Sélectionner un filtre') expect(page).to have_select 'Statut', selected: 'Sélectionner un statut', options: ['Sélectionner un statut', 'Brouillon', 'En construction', 'En instruction', 'À corriger'] @@ -92,9 +95,9 @@ describe 'user access to the list of their dossiers', js: true do scenario 'user filters state on tab "traité"' do visit dossiers_path(statut: 'traites') - expect(page).to have_text('6 en cours') - expect(page).to have_text('2 traités') - expect(page).to have_text('2 sur 2 dossiers') + expect(page).to have_text('7 en cours') + expect(page).to have_text('3 traités') + expect(page).to have_text('3 sur 3 dossiers') click_on('Sélectionner un filtre') expect(page).to have_select 'Statut', selected: 'Sélectionner un statut', options: ['Sélectionner un statut', 'Accepté', 'Refusé', 'Classé sans suite'] @@ -105,18 +108,29 @@ describe 'user access to the list of their dossiers', js: true do click_on('Sélectionner un filtre') click_on('Annuler') - expect(page).to have_text('2 sur 2 dossiers') + + click_on('Sélectionner un filtre') + expect(page).to have_select 'Statut', selected: 'Sélectionner un statut', options: ['Sélectionner un statut', 'Accepté', 'Refusé', 'Classé sans suite'] + select('Accepté', from: 'Statut') + click_on('Appliquer les filtres') + # we expect 1 dossier because we want do hide decision for dossier with accuse de lecture + expect(page).to have_text('1 dossier') + expect(page).to have_select 'Statut', selected: 'Accepté', options: ['Sélectionner un statut', 'Accepté', 'Refusé', 'Classé sans suite'] + + click_on('Sélectionner un filtre') + click_on('Annuler') + expect(page).to have_text('3 sur 3 dossiers') expect(page).to have_select 'Statut', selected: 'Sélectionner un statut', options: ['Sélectionner un statut', 'Accepté', 'Refusé', 'Classé sans suite'] end scenario 'user filters by created_at' do dossier_en_construction.update!(created_at: Date.yesterday) - expect(page).to have_text('6 sur 6 dossiers') + expect(page).to have_text('7 sur 7 dossiers') click_on('Sélectionner un filtre') fill_in 'from_created_at_date', with: Date.today click_on('Appliquer les filtres') - expect(page).to have_text('5 sur 5 dossiers') + expect(page).to have_text('6 sur 6 dossiers') end scenario 'user uses multiple filters' do @@ -124,26 +138,26 @@ describe 'user access to the list of their dossiers', js: true do expect(page).to have_select 'Statut', selected: 'Sélectionner un statut', options: ['Sélectionner un statut', 'Brouillon', 'En construction', 'En instruction', 'À corriger'] - expect(page).to have_text('6 sur 6 dossiers') + expect(page).to have_text('7 sur 7 dossiers') click_on('Sélectionner un filtre') fill_in 'from_created_at_date', with: Date.today click_on('Appliquer les filtres') - expect(page).to have_text('5 sur 5 dossiers') + expect(page).to have_text('6 sur 6 dossiers') expect(page).to have_text('1 filtre actif') click_on('Sélectionner un filtre') select('En construction', from: 'Statut') click_on('Appliquer les filtres') - expect(page).to have_text('1 dossier') + expect(page).to have_text('2 dossiers') expect(page).to have_text('2 filtres actifs') click_on('Sélectionner un filtre') fill_in 'from_depose_at_date', with: Date.today click_on('Appliquer les filtres') - expect(page).to have_text('1 dossier') + expect(page).to have_text('2 sur 2 dossiers') expect(page).to have_text('3 filtres actifs') click_on('3 filtres actifs') - expect(page).to have_text('6 sur 6 dossiers') + expect(page).to have_text('7 sur 7 dossiers') expect(page).not_to have_text('5 filtres actifs') end end @@ -285,8 +299,8 @@ describe 'user access to the list of their dossiers', js: true do describe "filter by procedure" do context "when dossiers are on different procedures" do it "can filter by procedure" do - expect(page).to have_text('6 en cours') - expect(page).to have_text('2 traités') + expect(page).to have_text('7 en cours') + expect(page).to have_text('3 traités') expect(page).to have_select('procedure_id', selected: 'Toutes les démarches') select dossier_brouillon.procedure.libelle, from: 'procedure_id' expect(page).to have_text('1 en cours') diff --git a/spec/views/instructeur/dossiers/show.html.haml_spec.rb b/spec/views/instructeur/dossiers/show.html.haml_spec.rb index c9cd5eec9..ffbcb4e85 100644 --- a/spec/views/instructeur/dossiers/show.html.haml_spec.rb +++ b/spec/views/instructeur/dossiers/show.html.haml_spec.rb @@ -173,4 +173,32 @@ describe 'instructeurs/dossiers/show', type: :view do end end end + + describe 'accuse de lecture ' do + context 'dossier not termine' do + let(:dossier) { create(:dossier, :en_instruction, procedure: create(:procedure, :accuse_lecture)) } + + it 'does not display a text about accuse de lecture for instructeur' do + expect(subject).not_to have_text('Cette démarche est soumise à un accusé de lecture') + end + end + + context 'dossier termine with accuse de lecture not accepted by user' do + let(:dossier) { create(:dossier, :accepte, procedure: create(:procedure, :accuse_lecture)) } + + it 'displays a text about accuse de lecture for instructeur' do + expect(subject).to have_text('Cette démarche est soumise à un accusé de lecture') + expect(subject).to have_text('L’usager n’a pas encore pris connaissance de la décision concernant son dossier') + end + end + + context 'dossier termine with accuse de lecture accepted by user' do + let(:dossier) { create(:dossier, :accepte, accuse_lecture_agreement_at: Time.zone.now, procedure: create(:procedure, :accuse_lecture)) } + + it 'displays a text about accuse de lecture for instructeur' do + expect(subject).to have_text('Cette démarche est soumise à un accusé de lecture') + expect(subject).to have_text('L’usager a pris connaissance de la décision concernant son dossier le') + end + end + end end diff --git a/spec/views/shared/dossiers/_infos_generales.html.haml_spec.rb b/spec/views/shared/dossiers/_infos_generales.html.haml_spec.rb index 627f637b3..2e82c0423 100644 --- a/spec/views/shared/dossiers/_infos_generales.html.haml_spec.rb +++ b/spec/views/shared/dossiers/_infos_generales.html.haml_spec.rb @@ -1,6 +1,6 @@ describe 'shared/dossiers/_infos_generales', type: :view do let(:dossier) { create(:dossier, :en_construction) } - subject { render } + subject { render 'shared/dossiers/infos_generales', dossier: dossier, profile: 'instructeur' } before do sign_in(current_role.user) allow(view).to receive(:current_instructeur).and_return(current_role) @@ -32,6 +32,14 @@ describe 'shared/dossiers/_infos_generales', type: :view do end end + context 'with a motivation and procedure with accuse de lecture' do + let(:dossier) { create :dossier, :accepte, :with_justificatif, procedure: create(:procedure, :accuse_lecture) } + + it 'still displays the motivation text for the instructeur' do + expect(subject).to have_content(dossier.motivation) + end + end + context 'with an attestation' do let(:dossier) { create :dossier, :accepte, :with_attestation } diff --git a/spec/views/users/dossiers/demande.html.haml_spec.rb b/spec/views/users/dossiers/demande.html.haml_spec.rb index 55d185dff..e38fd440d 100644 --- a/spec/views/users/dossiers/demande.html.haml_spec.rb +++ b/spec/views/users/dossiers/demande.html.haml_spec.rb @@ -59,4 +59,23 @@ describe 'users/dossiers/demande', type: :view do expect(rendered).to have_text(dossier.individual.email.to_s) end end + + context 'when a dossier is accepte with motivation' do + let(:dossier) { create(:dossier, :accepte, :with_motivation) } + + it 'displays the motivation' do + expect(rendered).not_to have_text('Cette démarche est soumise à un accusé de lecture.') + expect(rendered).to have_text('Motivation') + end + end + + context 'when a dossier is accepte with motivation and with accuse de lecture' do + let(:dossier) { create(:dossier, :accepte, :with_motivation, procedure: create(:procedure, :accuse_lecture)) } + + it 'display information about accuse de lecture and not the motivation' do + expect(rendered).to have_text('Cette démarche est soumise à un accusé de lecture.') + expect(rendered).not_to have_text('Motivation') + expect(rendered).not_to have_text('L’usager n’a pas encore pris connaissance de la décision concernant son dossier') + end + end end diff --git a/spec/views/users/dossiers/index.html.haml_spec.rb b/spec/views/users/dossiers/index.html.haml_spec.rb index b4eb96b2b..16af59636 100644 --- a/spec/views/users/dossiers/index.html.haml_spec.rb +++ b/spec/views/users/dossiers/index.html.haml_spec.rb @@ -1,10 +1,13 @@ describe 'users/dossiers/index', type: :view do let(:user) { create(:user) } + let(:procedure_accuse_lecture) { create(:procedure, :accuse_lecture) } let(:dossier_brouillon) { create(:dossier, state: Dossier.states.fetch(:brouillon), user: user) } let(:dossier_en_construction) { create(:dossier, state: Dossier.states.fetch(:en_construction), user: user) } + let(:dossier_en_construction_with_accuse_lecture) { create(:dossier, state: Dossier.states.fetch(:en_construction), user: user, procedure: procedure_accuse_lecture) } let(:dossier_termine) { create(:dossier, state: Dossier.states.fetch(:accepte), user: user) } + let(:dossier_termine_with_accuse_lecture) { create(:dossier, state: Dossier.states.fetch(:accepte), user: user, procedure: procedure_accuse_lecture) } let(:dossiers_invites) { [] } - let(:user_dossiers) { Kaminari.paginate_array([dossier_brouillon, dossier_en_construction, dossier_termine]).page(1) } + let(:user_dossiers) { Kaminari.paginate_array([dossier_brouillon, dossier_en_construction, dossier_termine, dossier_en_construction_with_accuse_lecture, dossier_termine_with_accuse_lecture]).page(1) } let(:statut) { 'en-cours' } let(:filter) { DossiersFilter.new(user, ActionController::Parameters.new(random_param: 'random_param')) } @@ -28,7 +31,7 @@ describe 'users/dossiers/index', type: :view do end it 'affiche les dossiers' do - expect(rendered).to have_selector('.card', count: 3) + expect(rendered).to have_selector('.card', count: 5) end it 'affiche les informations des dossiers' do @@ -40,6 +43,9 @@ describe 'users/dossiers/index', type: :view do expect(rendered).to have_text(dossier_en_construction.id.to_s) expect(rendered).to have_text(dossier_en_construction.procedure.libelle) expect(rendered).to have_link(dossier_en_construction.procedure.libelle, href: dossier_path(dossier_en_construction)) + + expect(rendered).to have_selector('.fr-badge', text: 'traité', count: 1) + expect(rendered).to have_selector('.fr-badge', text: 'en construction', count: 2) end it 'n’affiche pas une alerte pour continuer à remplir un dossier' do @@ -132,13 +138,13 @@ describe 'users/dossiers/index', type: :view do it "cache key depends on dossiers list" do render - expect(rendered).to have_text(/3\s+en cours/) + expect(rendered).to have_text(/5\s+en cours/) assign(:user_dossiers, Kaminari.paginate_array(user_dossiers.concat([create(:dossier, :en_construction, user: user)])).page(1)) user.reload render - expect(rendered).to have_text(/4\s+en cours/) + expect(rendered).to have_text(/6\s+en cours/) end it "cache key dpeends on dossier invites" do diff --git a/spec/views/users/dossiers/show/_header.html.haml_spec.rb b/spec/views/users/dossiers/show/_header.html.haml_spec.rb index f072d0191..1be2c4b8f 100644 --- a/spec/views/users/dossiers/show/_header.html.haml_spec.rb +++ b/spec/views/users/dossiers/show/_header.html.haml_spec.rb @@ -18,6 +18,26 @@ describe 'users/dossiers/show/header', type: :view do expect(rendered).to have_link("Demande", href: demande_dossier_path(dossier)) end + context "when the procedure is with accuse de lecture with a dossier en construction" do + let(:procedure) { create(:procedure, :accuse_lecture) } + let(:dossier) { create(:dossier, :en_construction, procedure: procedure) } + + it "affiche les informations du dossier" do + expect(rendered).to have_text("Dossier nº #{dossier.id}") + expect(rendered).to have_text("en construction") + end + end + + context "when the procedure is with accuse de lecture with a dossier termine" do + let(:procedure) { create(:procedure, :accuse_lecture) } + let(:dossier) { create(:dossier, :accepte, procedure: procedure) } + + it "n'affiche pas les informations de décision" do + expect(rendered).to have_text("Dossier nº #{dossier.id}") + expect(rendered).to have_text("traité") + end + end + context "when the procedure is closed with a dossier en construction" do let(:procedure) { create(:procedure, :closed) } let(:dossier) { create(:dossier, :en_construction, procedure: procedure) } diff --git a/spec/views/users/dossiers/show/_status_overview.html.haml_spec.rb b/spec/views/users/dossiers/show/_status_overview.html.haml_spec.rb index 9af4570b4..9f1bfcfab 100644 --- a/spec/views/users/dossiers/show/_status_overview.html.haml_spec.rb +++ b/spec/views/users/dossiers/show/_status_overview.html.haml_spec.rb @@ -92,4 +92,12 @@ describe 'users/dossiers/show/_status_overview', type: :view do it { is_expected.to have_selector('.status-explanation .sans-suite') } it { is_expected.to have_text(dossier.motivation) } end + + context 'when terminé but the procedure has an accuse de lecture' do + let(:dossier) { create(:dossier, :sans_suite, :with_motivation, procedure: create(:procedure, :accuse_lecture)) } + + it { is_expected.not_to have_selector('.status-explanation .sans-suite') } + it { is_expected.not_to have_text(dossier.motivation) } + it { is_expected.to have_text('Cette démarche est soumise à un accusé de lecture.') } + end end