diff --git a/app/assets/stylesheets/avis.scss b/app/assets/stylesheets/avis.scss index 95374b85f..d53b7e3d5 100644 --- a/app/assets/stylesheets/avis.scss +++ b/app/assets/stylesheets/avis.scss @@ -65,13 +65,6 @@ .lock { margin-right: $default-spacer; } - - .confidentiel-explanation { - font-size: 14px; - color: $dark-grey; - margin-top: - $default-padding; - margin-bottom: 2 * $default-padding; - } } .list-avis { diff --git a/app/controllers/concerns/create_avis_concern.rb b/app/controllers/concerns/create_avis_concern.rb index 44d7249ef..270a3504d 100644 --- a/app/controllers/concerns/create_avis_concern.rb +++ b/app/controllers/concerns/create_avis_concern.rb @@ -4,6 +4,16 @@ module CreateAvisConcern private def create_avis_from_params(dossier, instructeur_or_expert, confidentiel = false) + if create_avis_params[:emails].empty? + avis = Avis.new(create_avis_params) + errors = avis.errors + errors.add(:emails, :blank) + + flash.alert = errors.full_message(:emails, errors[:emails].first) + + return avis + end + confidentiel ||= create_avis_params[:confidentiel] # Because of a limitation of the email_field rails helper, # the :emails parameter is a 1-element array. @@ -33,7 +43,8 @@ module CreateAvisConcern claimant: instructeur_or_expert, dossier: dossier, confidentiel: confidentiel, - experts_procedure: experts_procedure + experts_procedure: experts_procedure, + question_label: create_avis_params[:question_label] } end end @@ -71,6 +82,6 @@ module CreateAvisConcern end def create_avis_params - params.require(:avis).permit(:introduction_file, :introduction, :confidentiel, :invite_linked_dossiers, :emails) + params.require(:avis).permit(:introduction_file, :introduction, :confidentiel, :invite_linked_dossiers, :emails, :question_label) end end diff --git a/app/controllers/experts/avis_controller.rb b/app/controllers/experts/avis_controller.rb index 2801c3343..13bc62d3f 100644 --- a/app/controllers/experts/avis_controller.rb +++ b/app/controllers/experts/avis_controller.rb @@ -179,7 +179,7 @@ module Experts end def avis_params - params.require(:avis).permit(:answer, :piece_justificative_file) + params.require(:avis).permit(:answer, :piece_justificative_file, :question_answer) end def commentaire_params diff --git a/app/graphql/schema.graphql b/app/graphql/schema.graphql index 98f462410..8c39554cc 100644 --- a/app/graphql/schema.graphql +++ b/app/graphql/schema.graphql @@ -177,6 +177,8 @@ type Avis { id: ID! instructeur: Profile! @deprecated(reason: "Utilisez le champ `claimant` à la place.") question: String! + questionAnswer: Boolean + questionLabel: String reponse: String } diff --git a/app/graphql/types/avis_type.rb b/app/graphql/types/avis_type.rb index b2620374d..1aff2f908 100644 --- a/app/graphql/types/avis_type.rb +++ b/app/graphql/types/avis_type.rb @@ -4,6 +4,8 @@ module Types field :question, String, null: false, method: :introduction field :reponse, String, null: true, method: :answer + field :question_label, String, null: true + field :question_answer, Boolean, null: true field :date_question, GraphQL::Types::ISO8601DateTime, null: false, method: :created_at field :date_reponse, GraphQL::Types::ISO8601DateTime, null: true, method: :updated_at diff --git a/app/javascript/entrypoints/main.css b/app/javascript/entrypoints/main.css index aa42a6ab0..2e4478c31 100644 --- a/app/javascript/entrypoints/main.css +++ b/app/javascript/entrypoints/main.css @@ -9,6 +9,7 @@ /* Verify README of each component to insert them in the expected order. */ @import '@gouvfr/dsfr/dist/component/alert/alert.css'; @import '@gouvfr/dsfr/dist/component/radio/radio.css'; +@import '@gouvfr/dsfr/dist/component/select/select.css'; @import '@gouvfr/dsfr/dist/component/toggle/toggle.css'; @import '@gouvfr/dsfr/dist/component/badge/badge.css'; @import '@gouvfr/dsfr/dist/component/breadcrumb/breadcrumb.css'; diff --git a/app/models/avis.rb b/app/models/avis.rb index 724b904bc..cd8e7c532 100644 --- a/app/models/avis.rb +++ b/app/models/avis.rb @@ -8,6 +8,8 @@ # confidentiel :boolean default(FALSE), not null # email :string # introduction :text +# question_answer :boolean +# question_label :string # reminded_at :datetime # revoked_at :datetime # created_at :datetime not null @@ -41,6 +43,7 @@ class Avis < ApplicationRecord validates :email, format: { with: Devise.email_regexp, message: "n'est pas valide" }, allow_nil: true validates :claimant, presence: true + validates :question_answer, presence: { on: :update, if: -> { question_label.present? } } validates :piece_justificative_file, size: { less_than: FILE_MAX_SIZE } validates :introduction_file, size: { less_than: FILE_MAX_SIZE } before_validation -> { sanitize_email(:email) } @@ -67,8 +70,10 @@ class Avis < ApplicationRecord def spreadsheet_columns [ ['Dossier ID', dossier_id.to_s], - ['Question / Introduction', :introduction], + ['Introduction', :introduction], ['Réponse', :answer], + ['Question', :question_label], + ['Réponse oui/non', :question_answer], ['Créé le', :created_at], ['Répondu le', :updated_at], ['Instructeur', claimant&.email], diff --git a/app/serializers/avis_serializer.rb b/app/serializers/avis_serializer.rb index 0b40903e3..a1212c0a7 100644 --- a/app/serializers/avis_serializer.rb +++ b/app/serializers/avis_serializer.rb @@ -1,6 +1,8 @@ class AvisSerializer < ActiveModel::Serializer attributes :answer, :introduction, + :question_label, + :question_answer, :created_at, :answered_at diff --git a/app/views/dossiers/show.pdf.prawn b/app/views/dossiers/show.pdf.prawn index 4889c45ab..a2a451765 100644 --- a/app/views/dossiers/show.pdf.prawn +++ b/app/views/dossiers/show.pdf.prawn @@ -211,6 +211,10 @@ end def add_avis(pdf, avis) format_in_2_lines(pdf, "Avis de #{avis.email_to_display}#{avis.confidentiel? ? ' (confidentiel)' : ''}", avis.answer || 'En attente de réponse') + + if avis.question_answer.present? + format_in_2_columns(pdf, "Réponse oui/non ", t("question_answer.#{avis.question_answer}", scope: 'helpers.label')) + end end def add_etat_dossier(pdf, dossier) diff --git a/app/views/experts/avis/instruction.html.haml b/app/views/experts/avis/instruction.html.haml index 0772abd9d..fb6577350 100644 --- a/app/views/experts/avis/instruction.html.haml +++ b/app/views/experts/avis/instruction.html.haml @@ -15,8 +15,27 @@ = render Attachment::ShowComponent.new(attachment: @avis.introduction_file.attachment) %br/ = render Attachment::DeleteFormComponent.new - = form_for @avis, url: expert_avis_path(@avis.procedure, @avis), html: { class: 'form', data: { controller: 'persisted-form', persisted_form_key_value: dom_id(@avis) }, multipart: true } do |f| - = f.text_area :answer, rows: 3, placeholder: 'Votre avis', required: true + = form_for @avis, url: expert_avis_path(@avis.procedure, @avis), html: { data: { controller: 'persisted-form', persisted_form_key_value: dom_id(@avis) }, multipart: true } do |f| + + - if @avis.question_label + .fr-form-group + %fieldset.fr-fieldset.fr-fieldset--inline + %legend#radio-inline-legend.fr-fieldset__legend.fr-text--regular + = @avis.question_label + .fr-fieldset__content + .fr-radio-group + = f.radio_button :question_answer, true + = f.label :question_answer, 'oui', value: true, class: 'fr-label' + + .fr-radio-group + = f.radio_button :question_answer, false + = f.label :question_answer, 'non', value: false, class: 'fr-label' + + .fr-select-group + = f.text_area :answer, rows: 3, class: 'fr-input', placeholder: 'Votre avis', required: true + + + = render Attachment::EditComponent.new(attached_file: @avis.piece_justificative_file, view_as: :download) .flex.justify-between.align-baseline @@ -32,7 +51,7 @@ = f.submit 'Envoyer votre avis', class: 'fr-btn' - if !@dossier.termine? - = render partial: "experts/shared/avis/form", locals: { url: avis_expert_avis_path(@avis.procedure, @avis), linked_dossiers: @dossier.linked_dossiers_for(current_expert), must_be_confidentiel: @avis.confidentiel?, avis: @new_avis } + = render partial: "experts/avis/shared/form", locals: { url: avis_expert_avis_path(@avis.procedure, @avis), linked_dossiers: @dossier.linked_dossiers_for(current_expert), must_be_confidentiel: @avis.confidentiel?, avis: @new_avis } - if @dossier.avis_for_expert(current_expert).present? - = render partial: 'experts/shared/avis/list', locals: { avis: @dossier.avis_for_expert(current_expert), avis_seen_at: nil } + = render partial: 'experts/avis/shared/list', locals: { avis: @dossier.avis_for_expert(current_expert), avis_seen_at: nil } diff --git a/app/views/experts/shared/avis/_form.html.haml b/app/views/experts/avis/shared/_form.html.haml similarity index 64% rename from app/views/experts/shared/avis/_form.html.haml rename to app/views/experts/avis/shared/_form.html.haml index f0bec0090..b8ad8197e 100644 --- a/app/views/experts/shared/avis/_form.html.haml +++ b/app/views/experts/avis/shared/_form.html.haml @@ -3,15 +3,17 @@ %h1.tab-title Inviter des personnes à donner leur avis %p.avis-notice Les invités pourront consulter le dossier, donner un avis et contribuer au fil de messagerie. Ils ne pourront pas modifier le dossier. = render Attachment::DeleteFormComponent.new - = form_for avis, url: url, html: { class: 'form', multipart: true, data: { controller: 'persisted-form', persisted_form_key_value: dom_id(@avis.dossier, :avis_by_expert) } } do |f| + = form_for avis, url: url, html: { multipart: true, data: { controller: 'persisted-form', persisted_form_key_value: dom_id(@avis.dossier, :avis_by_expert) } } do |f| = hidden_field_tag 'avis[emails]', nil - = react_component("ComboMultiple", - options: [], selected: [], disabled: [], - group: '.ask-avis', - name: 'emails', - label: 'Emails', - acceptNewValues: true) - = f.text_area :introduction, rows: 3, value: avis.introduction || 'Bonjour, merci de me donner votre avis sur ce dossier.', required: true + .fr-input-group + = react_component("ComboMultiple", + options: [], selected: [], disabled: [], + group: '.ask-avis', + name: 'emails', + label: 'Emails', + acceptNewValues: true) + .fr-input-group + = f.text_area :introduction, rows: 3, class: 'fr-input', value: avis.introduction || 'Bonjour, merci de me donner votre avis sur ce dossier.', required: true %p.tab-title Ajouter une pièce jointe .form-group = render Attachment::EditComponent.new(attached_file: avis.introduction_file) @@ -29,9 +31,9 @@ - else .confidentiel-wrapper - = f.label :confidentiel, 'Cet avis sera ' - = f.select :confidentiel, [['partagé avec les autres experts', false], ['confidentiel', true]], {}, onchange: "javascript:DS.toggleCondidentielExplanation(event);" + = f.label :confidentiel, 'Cet avis sera ', class: 'fr-label' + = f.select :confidentiel, [['partagé avec les autres experts', false], ['confidentiel', true]], {}, onchange: "javascript:DS.toggleCondidentielExplanation(event);", class: 'fr-input' .confidentiel-explanation.hidden Il ne sera pas affiché aux autres experts consultés, mais sera visible par les instructeurs. - = f.submit 'Demander un avis', class: 'button primary send' + = f.submit 'Demander un avis', class: 'fr-btn fr-mt-2w' diff --git a/app/views/experts/shared/avis/_list.html.haml b/app/views/experts/avis/shared/_list.html.haml similarity index 91% rename from app/views/experts/shared/avis/_list.html.haml rename to app/views/experts/avis/shared/_list.html.haml index a2436d926..962d6813d 100644 --- a/app/views/experts/shared/avis/_list.html.haml +++ b/app/views/experts/avis/shared/_list.html.haml @@ -17,6 +17,8 @@ %span.date.fr-text--xs.fr-text-mention--grey{ class: highlight_if_unseen_class(avis_seen_at, avis.created_at) } = t('demande_envoyee_le', scope: 'views.shared.avis', date: l(avis.created_at, format: '%d/%m/%y à %H:%M')) %p= avis.introduction + - if avis.question_label + %p= avis.question_label .answer.flex.align-start %span.icon.bubble.avis-icon @@ -35,4 +37,6 @@ - if avis.piece_justificative_file.attached? = render Attachment::ShowComponent.new(attachment: avis.piece_justificative_file.attachment) .answer-body + - if avis.question_answer + %p= t("question_answer.#{avis.question_answer}", scope: 'helpers.label') = render SimpleFormatComponent.new(avis.answer, allow_a: false) diff --git a/app/views/experts/avis/shared/avis/_form.html.haml b/app/views/experts/avis/shared/avis/_form.html.haml deleted file mode 100644 index e8685241c..000000000 --- a/app/views/experts/avis/shared/avis/_form.html.haml +++ /dev/null @@ -1,30 +0,0 @@ -%section.ask-avis - %h1.tab-title Inviter des personnes à donner leur avis - %p.avis-notice Les invités pourront consulter le dossier, donner un avis et contribuer au fil de messagerie. Ils ne pourront pas modifier le dossier. - - = form_for avis, url: url, html: { class: 'form' } do |f| - = f.email_field :emails, placeholder: 'Adresses email, séparées par des virgules', required: true, multiple: true, data: { controller: 'format', format: 'list' } - = f.text_area :introduction, rows: 3, value: avis.introduction || 'Bonjour, merci de me donner votre avis sur ce dossier.', required: true - %p.tab-title Ajouter une pièce jointe - .form-group - = render Attachment::EditComponent.new(attached_file: avis.introduction_file) - - - if linked_dossiers.present? - = f.check_box :invite_linked_dossiers, {}, true, false - = f.label :invite_linked_dossiers, t('helpers.label.invite_linked_dossiers', count: linked_dossiers.length, ids: linked_dossiers.map(&:id).to_sentence) - - .flex.justify-between.align-baseline - - if must_be_confidentiel - %p.confidentiel.flex - %span.icon.lock - %span - Cet avis sera confidentiel : il ne sera pas affiché aux autres experts consultés, mais sera visible par les instructeurs. - - - else - .confidentiel-wrapper - = f.label :confidentiel, 'Cet avis sera ' - = f.select :confidentiel, [['partagé avec les autres experts', false], ['confidentiel', true]], {}, onchange: "javascript:DS.toggleCondidentielExplanation(event);" - .confidentiel-explanation.hidden - Il ne sera pas affiché aux autres experts consultés, mais sera visible par les instructeurs. - - = f.submit 'Demander un avis', class: 'button primary send' diff --git a/app/views/instructeurs/avis/instruction.html.haml b/app/views/instructeurs/avis/instruction.html.haml deleted file mode 100644 index 93deba394..000000000 --- a/app/views/instructeurs/avis/instruction.html.haml +++ /dev/null @@ -1,39 +0,0 @@ -- content_for(:title, "Avis · Dossier nº #{@dossier.id} (#{@dossier.owner_name})") - -= render partial: 'header', locals: { avis: @avis, dossier: @dossier } - -.container - %section.give-avis - %h1.tab-title Donner votre avis - %h2.claimant - Demandeur : - %span.email= @avis.claimant.email - %span.date Demande d’avis envoyée le #{l(@avis.created_at, format: '%d/%m/%y')} - %p.introduction= @avis.introduction - - - if @avis.introduction_file.attached? - = render Attachment::ShowComponent.new(attachment: @avis.introduction_file.attachment) - %br/ - - = render Attachment::DeleteFormComponent.new - = form_for @avis, url: instructeur_avis_path(@avis.procedure, @avis), html: { class: 'form' } do |f| - = f.text_area :answer, rows: 3, placeholder: 'Votre avis', required: true - = render Attachment::EditComponent.new(attached_file: @avis.piece_justificative_file) - - .flex.justify-between.align-baseline - %p.confidentiel.flex - - if @avis.confidentiel? - %span.icon.lock - %span - Cet avis est confidentiel et n’est pas affiché aux autres experts consultés - - else - %span - Cet avis est partagé avec les autres experts - .send-wrapper - = f.submit 'Envoyer votre avis', class: 'fr-btn' - - - if !@dossier.termine? - = render partial: "instructeurs/shared/avis/form", locals: { url: avis_instructeur_avis_path(@avis.procedure, @avis), linked_dossiers: @dossier.linked_dossiers_for(current_instructeur), must_be_confidentiel: @avis.confidentiel?, avis: @new_avis } - - - if @dossier.avis_for(current_instructeur).present? - = render partial: 'instructeurs/shared/avis/list', locals: { avis: @dossier.avis_for(current_instructeur), avis_seen_at: nil } diff --git a/app/views/instructeurs/shared/avis/_form.html.haml b/app/views/instructeurs/avis/shared/_form.html.haml similarity index 52% rename from app/views/instructeurs/shared/avis/_form.html.haml rename to app/views/instructeurs/avis/shared/_form.html.haml index 99f99c666..c8d66f1d1 100644 --- a/app/views/instructeurs/shared/avis/_form.html.haml +++ b/app/views/instructeurs/avis/shared/_form.html.haml @@ -9,17 +9,28 @@ Entrez les adresses email des experts à qui vous souhaitez demander un avis = render Attachment::DeleteFormComponent.new - = form_for avis, url: url, html: { class: 'form', multipart: true, data: { controller: 'persisted-form', persisted_form_key_value: dom_id(@dossier, :avis_by_instructeur) } } do |f| + = form_for avis, url: url, html: { multipart: true, data: { controller: 'persisted-form', persisted_form_key_value: dom_id(@dossier, :avis_by_instructeur) } } do |f| = hidden_field_tag 'avis[emails]', nil - = react_component("ComboMultiple", - options: @dossier.procedure.experts_require_administrateur_invitation ? @experts_emails : [], - selected: [], disabled: [], - label: 'Emails', - group: '.ask-avis', - name: 'emails', - describedby: 'avis-emails-description', - acceptNewValues: !@dossier.procedure.experts_require_administrateur_invitation) - = f.text_area :introduction, rows: 3, value: avis.introduction || 'Bonjour, merci de me donner votre avis sur ce dossier.', required: true + .fr-input-group + = react_component("ComboMultiple", + options: @dossier.procedure.experts_require_administrateur_invitation ? @experts_emails : [], + selected: [], disabled: [], + label: 'Emails', + group: '.ask-avis', + name: 'emails', + describedby: 'avis-emails-description', + acceptNewValues: !@dossier.procedure.experts_require_administrateur_invitation) + + .fr-input-group + = f.label :introduction, t('helpers.label.introduction'), class: 'fr-label' + = f.text_area :introduction, rows: 3, class: 'fr-input', value: avis.introduction || 'Bonjour, merci de me donner votre avis sur ce dossier.', required: true + + .fr-input-group + = f.label :question_label, class: 'fr-label' do + = t('helpers.label.question_label') + %span.fr-hint-text + = t('helpers.label.question_label_hint') + = f.text_area :question_label, label: "question", class: 'fr-input' %p.tab-title Ajouter une pièce jointe .form-group = render Attachment::EditComponent.new(attached_file: avis.introduction_file) @@ -37,9 +48,10 @@ - else .confidentiel-wrapper - = f.label :confidentiel, 'Cet avis sera ' - = f.select :confidentiel, [['partagé avec les autres experts', false], ['confidentiel', true]], {}, onchange: "javascript:DS.toggleCondidentielExplanation(event);" + = f.label :confidentiel, 'Cet avis sera ', class: 'fr-label' + = f.select :confidentiel, [['partagé avec les autres experts', false], ['confidentiel', true]], {}, onchange: "javascript:DS.toggleCondidentielExplanation(event);", class: 'fr-select' .confidentiel-explanation.hidden - Il ne sera pas affiché aux autres experts consultés, mais sera visible par les instructeurs. + %small + Il ne sera pas affiché aux autres experts consultés, mais sera visible par les instructeurs. - = f.submit 'Demander un avis', class: 'fr-btn' + = f.submit 'Demander un avis', class: 'fr-btn fr-mt-2w' diff --git a/app/views/instructeurs/shared/avis/_list.html.haml b/app/views/instructeurs/avis/shared/_list.html.haml similarity index 94% rename from app/views/instructeurs/shared/avis/_list.html.haml rename to app/views/instructeurs/avis/shared/_list.html.haml index 9d66b8d2d..91577ddbf 100644 --- a/app/views/instructeurs/shared/avis/_list.html.haml +++ b/app/views/instructeurs/avis/shared/_list.html.haml @@ -17,6 +17,8 @@ %span.date.fr-text--xs.fr-text-mention--grey{ class: highlight_if_unseen_class(avis_seen_at, avis.created_at) } = t('demande_envoyee_le', scope: 'views.shared.avis', date: l(avis.created_at, format: '%d/%m/%y à %H:%M')) %p= avis.introduction + - if avis.question_label + %p= avis.question_label .answer.flex.align-start %span.icon.bubble.avis-icon @@ -51,4 +53,7 @@ - if avis.piece_justificative_file.attached? = render Attachment::ShowComponent.new(attachment: avis.piece_justificative_file.attachment) .answer-body + - if avis.question_answer + %p= t("question_answer.#{avis.question_answer}", scope: 'helpers.label') + = render SimpleFormatComponent.new(avis.answer, allow_a: false) diff --git a/app/views/instructeurs/dossiers/avis.html.haml b/app/views/instructeurs/dossiers/avis.html.haml index 700152df5..c02565ff2 100644 --- a/app/views/instructeurs/dossiers/avis.html.haml +++ b/app/views/instructeurs/dossiers/avis.html.haml @@ -5,12 +5,12 @@ .container - if !@dossier.termine? - if @dossier.procedure.allow_expert_review - = render partial: "instructeurs/shared/avis/form", locals: { url: avis_instructeur_dossier_path(@dossier.procedure, @dossier), linked_dossiers: @dossier.linked_dossiers_for(current_instructeur), must_be_confidentiel: false, avis: @avis } + = render partial: "instructeurs/avis/shared/form", locals: { url: avis_instructeur_dossier_path(@dossier.procedure, @dossier), linked_dossiers: @dossier.linked_dossiers_for(current_instructeur), must_be_confidentiel: false, avis: @avis } - else %p Cette démarche n’autorise pas la demande d’avis à un expert. Veuillez contacter votre administrateur - if @dossier.avis.present? - = render partial: 'instructeurs/shared/avis/list', locals: { avis: @dossier.avis, avis_seen_at: @avis_seen_at } + = render partial: 'instructeurs/avis/shared/list', locals: { avis: @dossier.avis, avis_seen_at: @avis_seen_at } - if @dossier.termine? && !@dossier.avis.present? .blank-tab diff --git a/config/locales/models/avis/en.yml b/config/locales/models/avis/en.yml new file mode 100644 index 000000000..bcc51ae19 --- /dev/null +++ b/config/locales/models/avis/en.yml @@ -0,0 +1,28 @@ +en: + activerecord: + models: + avis: 'opinion' + attributes: + avis: + answer: "Answer" + claimant: Claimant + confidentiel: Confidential + question_answer: "Answer yes/no" + helpers: + label: + invite_linked_dossiers: + one: Invite also the expert on this linked file n° %{ids} + other: Invite also the expert on theses linked files n° %{ids} + revoke: Revoke opinion request + remind: Remind the expert + question_label: Ask a question to the expert + question_label_hint: (optional) the expert could answer by yes/no + introduction: Introduction message + question_answer: + true: 'yes' + false: 'no' + hint: + confidentiel: "This advice is not displayed to the others consulted experts" + confirmation: + revoke: "Would you like to revoke the opinion request to %{email} ?" + remind: "Would you like to remind %{email} ?" diff --git a/config/locales/models/avis/fr.yml b/config/locales/models/avis/fr.yml index 1428849ce..1a3c8b6d4 100644 --- a/config/locales/models/avis/fr.yml +++ b/config/locales/models/avis/fr.yml @@ -7,6 +7,7 @@ fr: answer: "Réponse" claimant: Demandeur confidentiel: confidentiel + question_answer: "Réponse oui/non" helpers: label: invite_linked_dossiers: @@ -14,6 +15,12 @@ fr: other: Inviter aussi l’expert sur les dossiers liés n° %{ids} revoke: Révoquer la demande d’avis remind: Relancer l’expert + question_label: Posez une question à l'expert + question_label_hint: (facultatif) l'expert pourra répondre par oui/non + introduction: Message d'introduction + question_answer: + true: oui + false: non hint: confidentiel: "Cet avis n’est pas affiché avec les autres experts consultés" confirmation: diff --git a/db/migrate/20230303094613_add_question_columns_to_avis.rb b/db/migrate/20230303094613_add_question_columns_to_avis.rb new file mode 100644 index 000000000..310e66cfc --- /dev/null +++ b/db/migrate/20230303094613_add_question_columns_to_avis.rb @@ -0,0 +1,6 @@ +class AddQuestionColumnsToAvis < ActiveRecord::Migration[6.1] + def change + add_column :avis, :question_label, :string + add_column :avis, :question_answer, :boolean + end +end diff --git a/db/schema.rb b/db/schema.rb index c8cb05fb3..f01212cd2 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.define(version: 2023_02_18_094119) do +ActiveRecord::Schema.define(version: 2023_03_03_094613) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" @@ -164,6 +164,8 @@ ActiveRecord::Schema.define(version: 2023_02_18_094119) do t.string "email" t.bigint "experts_procedure_id" t.text "introduction" + t.boolean "question_answer" + t.string "question_label" t.datetime "reminded_at" t.datetime "revoked_at" t.datetime "updated_at", null: false diff --git a/spec/controllers/experts/avis_controller_spec.rb b/spec/controllers/experts/avis_controller_spec.rb index 239cacb33..40d271562 100644 --- a/spec/controllers/experts/avis_controller_spec.rb +++ b/spec/controllers/experts/avis_controller_spec.rb @@ -344,10 +344,11 @@ describe Experts::AvisController, type: :controller do let(:invite_linked_dossiers) { nil } let(:introduction_file) { fixture_file_upload('spec/fixtures/files/piece_justificative_0.pdf', 'application/pdf') } let(:confidentiel) { false } + let(:question_label) { '' } before do Timecop.freeze(now) - post :create_avis, params: { id: previous_avis.id, procedure_id:, avis: { emails:, introduction:, experts_procedure:, confidentiel:, invite_linked_dossiers:, introduction_file: } } + post :create_avis, params: { id: previous_avis.id, procedure_id:, avis: { emails:, introduction:, experts_procedure:, confidentiel:, invite_linked_dossiers:, introduction_file:, question_label: } } created_avis.reload end @@ -373,6 +374,15 @@ describe Experts::AvisController, type: :controller do end end + context 'with a question' do + let(:question_label) { "question" } + + it do + expect(created_avis.question_label).to eq('question') + expect(response).to redirect_to(instruction_expert_avis_path(previous_avis.procedure, previous_avis)) + end + end + context 'ask review with attachment' do let(:emails) { "[\"toto@totomail.com\"]" } diff --git a/spec/controllers/instructeurs/dossiers_controller_spec.rb b/spec/controllers/instructeurs/dossiers_controller_spec.rb index cdcdf1398..971262fa9 100644 --- a/spec/controllers/instructeurs/dossiers_controller_spec.rb +++ b/spec/controllers/instructeurs/dossiers_controller_spec.rb @@ -628,6 +628,17 @@ describe Instructeurs::DossiersController, type: :controller do it { expect(dossier.last_avis_updated_at).to eq(nil) } end + context "with no email" do + let(:emails) { "" } + + before { subject } + + it { expect(response).to render_template :avis } + it { expect(flash.alert).to eq("Le champ « Emails » doit être rempli") } + it { expect { subject }.not_to change(Avis, :count) } + it { expect(dossier.last_avis_updated_at).to eq(nil) } + end + context 'with multiple emails' do let(:emails) { "[\"toto.fr\",\"titi@titimail.com\"]" } diff --git a/spec/services/procedure_export_service_spec.rb b/spec/services/procedure_export_service_spec.rb index f25f27910..93d41cd46 100644 --- a/spec/services/procedure_export_service_spec.rb +++ b/spec/services/procedure_export_service_spec.rb @@ -364,8 +364,10 @@ describe ProcedureExportService do it 'should have headers' do expect(avis_sheet.headers).to eq([ "Dossier ID", - "Question / Introduction", + "Introduction", "Réponse", + "Question", + "Réponse oui/non", "Créé le", "Répondu le", "Instructeur", diff --git a/spec/system/experts/expert_spec.rb b/spec/system/experts/expert_spec.rb index f5e67a2b2..b78d1de56 100644 --- a/spec/system/experts/expert_spec.rb +++ b/spec/system/experts/expert_spec.rb @@ -10,6 +10,7 @@ describe 'Inviting an expert:' do let(:dossier) { create(:dossier, :en_construction, :with_dossier_link, procedure: procedure) } let(:champ) { dossier.champs_public.first } let(:avis) { create(:avis, dossier: dossier, claimant: instructeur, experts_procedure: experts_procedure, confidentiel: true) } + let(:avis_with_question) { create(:avis, dossier: dossier, claimant: instructeur, experts_procedure: experts_procedure, confidentiel: true, question_label: 'Question ?') } context 'when I don’t already have an account' do let(:password) { 'This is an expert password' } @@ -82,6 +83,37 @@ describe 'Inviting an expert:' do expect(page).to have_text('1 avis donné') end + scenario 'I can give a yes/no answer to a question' do + avis_with_question # create avis + login_as expert.user, scope: :user + + visit expert_all_avis_path + expect(page).to have_text('1 avis à donner') + expect(page).to have_text('0 avis donnés') + + click_on '1 avis à donner' + click_on avis.dossier.user.email + within('.tabs') { click_on 'Avis' } + expect(page).to have_text("Demandeur : #{avis.claimant.email}") + expect(page).to have_text('Question ?') + expect(page).to have_text('Cet avis est confidentiel') + + # check validation + click_on 'Envoyer votre avis' + expect(page).to have_content('Le champ « Réponse oui/non » doit être rempli') + + choose 'oui' + fill_in 'avis_answer', with: 'Ma réponse d’expert.' + click_on 'Envoyer votre avis' + + expect(page).to have_content('Votre réponse est enregistrée') + expect(page).to have_content('Ma réponse d’expert.') + expect(page).to have_content('oui') + + within('.breadcrumbs') { click_on 'Avis' } + expect(page).to have_text('1 avis donné') + end + # scenario 'I can invite other experts' do # end diff --git a/spec/views/instructeur/shared/avis/list.html.haml_spec.rb b/spec/views/instructeur/avis/shared/list.html.haml_spec.rb similarity index 93% rename from spec/views/instructeur/shared/avis/list.html.haml_spec.rb rename to spec/views/instructeur/avis/shared/list.html.haml_spec.rb index a92696ffa..db37921a2 100644 --- a/spec/views/instructeur/shared/avis/list.html.haml_spec.rb +++ b/spec/views/instructeur/avis/shared/list.html.haml_spec.rb @@ -1,7 +1,7 @@ -describe 'instructeurs/shared/avis/_list.html.haml', type: :view do +describe 'instructeurs/avis/shared/_list.html.haml', type: :view do before { view.extend DossierHelper } - subject { render 'instructeurs/shared/avis/list.html.haml', avis: avis, avis_seen_at: seen_at, current_instructeur: instructeur } + subject { render 'instructeurs/avis/shared/list.html.haml', avis: avis, avis_seen_at: seen_at, current_instructeur: instructeur } let(:instructeur) { create(:instructeur) } let(:instructeur2) { create(:instructeur) }