diff --git a/app/assets/stylesheets/helpers.scss b/app/assets/stylesheets/helpers.scss deleted file mode 100644 index 4577ef84c..000000000 --- a/app/assets/stylesheets/helpers.scss +++ /dev/null @@ -1,42 +0,0 @@ -@import "constants"; - -.m-0 { - margin: 0px !important; -} - -.mb-1 { - margin-bottom: $default-spacer; -} - -.mr-1 { - margin-right: $default-spacer !important; -} - -.mb-4 { - margin-bottom: 4 * $default-spacer !important; -} - -.ml-1 { - margin-left: $default-spacer; -} - -.pl-0 { - padding-left: 0px !important; -} - -.p-0 { - padding: 0px !important; -} - -.bold { - font-weight: bold; -} - -.numbers-delimiter { - display: inline-block; - width: 5px; -} - -.text-center { - text-align: center; -} diff --git a/app/assets/stylesheets/merci.scss b/app/assets/stylesheets/merci.scss index e52b91bb2..b40f676a2 100644 --- a/app/assets/stylesheets/merci.scss +++ b/app/assets/stylesheets/merci.scss @@ -2,38 +2,8 @@ @import "common"; @import "constants"; -.merci { - text-align: center; - margin-bottom: 60px; - +.merci .monavis { img { - margin-top: 4 * $default-padding; - } - - h1 { - margin: (2 * $default-padding) 0; - } - - b { - font-weight: bold; - } - - .send { - margin-bottom: 2 * $default-padding; - font-size: 20px; - } - - p { - margin: $default-padding; - } - - a { - margin-top: 40px; - } - - .monavis { - img { - margin-top: 2 * $default-padding; - } + margin-top: 2 * $default-padding; } } diff --git a/app/assets/stylesheets/utils.scss b/app/assets/stylesheets/utils.scss index 535217901..14e90df81 100644 --- a/app/assets/stylesheets/utils.scss +++ b/app/assets/stylesheets/utils.scss @@ -1,6 +1,7 @@ @import "colors"; @import "constants"; +// floats .pull-left { float: left; } @@ -13,6 +14,9 @@ clear: both; } + +// text +.text-center, .center { text-align: center; } @@ -21,12 +25,21 @@ text-align: right; } -.hidden { - display: none; +.text-sm { + font-size: 14px; } -.width-100 { - width: 100%; +.text-lg { + font-size: 18px; +} + +.bold { + font-weight: bold; +} + +.numbers-delimiter { + display: inline-block; + width: 5px; } .empty-text { @@ -45,95 +58,42 @@ } } +// display +.hidden { + display: none; +} + +// sizing +.width-100 { + width: 100%; +} + +// who known .highlighted { background: $orange-bg; color: $black; } -.text-sm { - font-size: 14px; -} +// generate spacer utility like bootstrap my-2 -> margin-left/right: 2 * $default-spacer +// using $direction.key as css modifier, $direction.values to set css properties +// scale it using $steps +$directions: ( + "t": ("margin-top"), + "r": ("margin-right"), + "b": ("margin-bottom"), + "l": ("margin-left"), + "x": ("margin-left", "margin-right"), + "y": ("margin-top", "margin-bottom"), + "": ("margin") +); +$steps: (0, 1, 2, 3, 4, 5, 6, 7, 8); -.text-lg { - font-size: 18px; -} - -.mt-1 { - margin-top: $default-spacer; -} - -.mt-2 { - margin-top: 2 * $default-spacer; -} - -.mt-3 { - margin-top: 3 * $default-spacer; -} - -.mt-4 { - margin-top: 4 * $default-spacer; -} - -.mt-8 { - margin-top: 8 * $default-spacer; -} - -.mb-1 { - margin-bottom: $default-spacer; -} - -.mb-2 { - margin-bottom: 2 * $default-spacer; -} - -.mb-3 { - margin-bottom: 3 * $default-spacer; -} - -.mb-4 { - margin-bottom: 4 * $default-spacer; -} - -.mb-8 { - margin-bottom: 8 * $default-spacer; -} - -.pt-1 { - padding-top: $default-spacer; -} - -.pt-2 { - padding-top: 2 * $default-spacer; -} - -.pt-3 { - padding-top: 3 * $default-spacer; -} - -.pt-4 { - padding-top: 4 * $default-spacer; -} - -.pt-8 { - padding-top: 8 * $default-spacer; -} - -.pb-1 { - padding-bottom: $default-spacer; -} - -.pb-2 { - padding-bottom: 2 * $default-spacer; -} - -.pb-3 { - padding-bottom: 3 * $default-spacer; -} - -.pb-4 { - padding-bottom: 4 * $default-spacer; -} - -.pb-8 { - padding-bottom: 8 * $default-spacer; +@each $modifier, $properties in $directions { + @each $step in $steps { + @each $property in $properties { + .m#{$modifier}-#{$step} { + #{$property}: $step * $default-spacer; + } + } + } } diff --git a/app/controllers/administrateurs/dossier_submitted_messages_controller.rb b/app/controllers/administrateurs/dossier_submitted_messages_controller.rb new file mode 100644 index 000000000..21cc6bb77 --- /dev/null +++ b/app/controllers/administrateurs/dossier_submitted_messages_controller.rb @@ -0,0 +1,45 @@ +module Administrateurs + class DossierSubmittedMessagesController < AdministrateurController + before_action :retrieve_procedure + + def edit + @dossier_submitted_message = build_dossier_submitted_message + end + + def update + @dossier_submitted_message = build_dossier_submitted_message(dossier_submitted_message_params) + + if @dossier_submitted_message.save + redirect_to admin_procedure_path(@procedure), flash: { notice: "Les informations de fin de dépot ont bien été sauvegardées." } + else + flash.alert = "Impossible de sauvegarder les informations de fin de dépot, veuillez ré-essayer." + render :edit, status: 400 + end + end + + def create + @dossier_submitted_message = build_dossier_submitted_message(dossier_submitted_message_params) + if @dossier_submitted_message.save + redirect_to admin_procedure_path(@procedure), flash: { notice: "Les informations de fin de dépot ont bien été sauvegardées." } + else + flash.alert = "Impossible de sauvegarder les informations de \"fin de dépot\", veuillez ré-essayer." + render :edit, status: 400 + end + end + + private + + # for now, only works on active revision no matter the procedure_revision_policy + def build_dossier_submitted_message(attributes = {}) + dossier_submitted_message = @procedure.active_revision.dossier_submitted_message || @procedure.active_revision.build_dossier_submitted_message + + dossier_submitted_message.attributes = attributes unless attributes.empty? + dossier_submitted_message + end + + def dossier_submitted_message_params + params.require(:dossier_submitted_message) + .permit(:message_on_submit_by_usager) + end + end +end diff --git a/app/models/champs/cnaf_champ.rb b/app/models/champs/cnaf_champ.rb index fc3c10744..e8d2d38d6 100644 --- a/app/models/champs/cnaf_champ.rb +++ b/app/models/champs/cnaf_champ.rb @@ -6,6 +6,7 @@ # data :jsonb # fetch_external_data_exceptions :string is an Array # private :boolean default(FALSE), not null +# rebased_at :datetime # row :integer # type :string # value :string diff --git a/app/models/dossier_submitted_message.rb b/app/models/dossier_submitted_message.rb new file mode 100644 index 000000000..01238804c --- /dev/null +++ b/app/models/dossier_submitted_message.rb @@ -0,0 +1,12 @@ +# == Schema Information +# +# Table name: dossier_submitted_messages +# +# id :bigint not null, primary key +# message_on_submit_by_usager :string +# created_at :datetime not null +# updated_at :datetime not null +# +class DossierSubmittedMessage < ApplicationRecord + has_many :revisions, class_name: 'ProcedureRevision', inverse_of: :dossier_submitted_message, dependent: :nullify +end diff --git a/app/models/procedure.rb b/app/models/procedure.rb index ff8b74fbd..d3be28e47 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -18,7 +18,6 @@ # description :string # direction :string # duree_conservation_dossiers_dans_ds :integer -# duree_conservation_dossiers_hors_ds :integer # durees_conservation_required :boolean default(TRUE) # encrypted_api_particulier_token :string # euro_flag :boolean default(FALSE) @@ -80,6 +79,10 @@ class Procedure < ApplicationRecord has_one :draft_attestation_template, through: :draft_revision, source: :attestation_template has_one :published_attestation_template, through: :published_revision, source: :attestation_template + has_one :published_dossier_submitted_message, dependent: :destroy, through: :published_revision, source: :dossier_submitted_message + has_one :draft_dossier_submitted_message, dependent: :destroy, through: :draft_revision, source: :dossier_submitted_message + has_many :dossier_submitted_messages, through: :revisions, source: :dossier_submitted_message + has_many :experts_procedures, dependent: :destroy has_many :experts, through: :experts_procedures @@ -92,6 +95,10 @@ class Procedure < ApplicationRecord belongs_to :service, optional: true belongs_to :zone, optional: true + def active_dossier_submitted_message + published_dossier_submitted_message || draft_dossier_submitted_message + end + def active_revision brouillon? ? draft_revision : published_revision end @@ -441,7 +448,8 @@ class Procedure < ApplicationRecord revision_types_de_champ_private: { type_de_champ: :types_de_champ }, - attestation_template: [] + attestation_template: [], + dossier_submitted_message: [] } } include_list[:groupe_instructeurs] = :instructeurs if !is_different_admin diff --git a/app/models/procedure_revision.rb b/app/models/procedure_revision.rb index b1fd83078..458dd0c38 100644 --- a/app/models/procedure_revision.rb +++ b/app/models/procedure_revision.rb @@ -7,12 +7,14 @@ # created_at :datetime not null # updated_at :datetime not null # attestation_template_id :bigint -# procedure_id :bigint not null +# dossier_submitted_message_id :bigint +# procedure_id :bigint not null # class ProcedureRevision < ApplicationRecord self.implicit_order_column = :created_at belongs_to :procedure, -> { with_discarded }, inverse_of: :revisions, optional: false belongs_to :attestation_template, inverse_of: :revisions, optional: true, dependent: :destroy + belongs_to :dossier_submitted_message, inverse_of: :revisions, optional: true, dependent: :destroy has_many :dossiers, inverse_of: :revision, foreign_key: :revision_id diff --git a/app/models/zone.rb b/app/models/zone.rb index 9a699c428..2d5e57c57 100644 --- a/app/models/zone.rb +++ b/app/models/zone.rb @@ -3,7 +3,7 @@ # Table name: zones # # id :bigint not null, primary key -# acronym :string +# acronym :string not null # label :string # created_at :datetime not null # updated_at :datetime not null diff --git a/app/views/administrateurs/dossier_submitted_messages/_informations.html.haml b/app/views/administrateurs/dossier_submitted_messages/_informations.html.haml new file mode 100644 index 000000000..f5ae76910 --- /dev/null +++ b/app/views/administrateurs/dossier_submitted_messages/_informations.html.haml @@ -0,0 +1,3 @@ += f.label :message_on_submit_by_usager do + Message affiché après l'envoie du dossier += f.text_area :message_on_submit_by_usager, placeholder: "Merci votre dossier sera traité dans les plus bref delais" diff --git a/app/views/administrateurs/dossier_submitted_messages/edit.html.haml b/app/views/administrateurs/dossier_submitted_messages/edit.html.haml new file mode 100644 index 000000000..633073303 --- /dev/null +++ b/app/views/administrateurs/dossier_submitted_messages/edit.html.haml @@ -0,0 +1,34 @@ +- content_for(:root_class, 'scroll-margins-for-sticky-footer') + += render partial: 'administrateurs/breadcrumbs', + locals: { steps: [link_to('Démarches', admin_procedures_path), + link_to(@procedure.libelle, admin_procedure_path(@procedure)), + 'Fin de dépot'] } + +.procedure-form + .procedure-form__columns.container + = form_for @dossier_submitted_message, + url: url_for({ controller: 'administrateurs/dossier_submitted_messages', action: :update, id: @procedure.id }), + html: { class: 'form procedure-form__column--form' } do |f| + + %h1.page-title + Fin du dépot + %p.notice + L'utilisateur se vera afficher ce message une fois le dossier envoyé + + = render partial: 'administrateurs/dossier_submitted_messages/informations', locals: { f: f } + + + .procedure-form__actions + .actions-left + = f.submit 'Enregistrer', class: 'button primary send' + + .procedure-form__column--preview + %h3 + .procedure-form__preview-title + Aperçu + .notice + Cet aperçu est mis à jour après chaque sauvegarde. + + .procedure-preview + = render partial: 'users/dossiers/merci', locals: { procedure: @procedure, dossier: nil} diff --git a/app/views/administrateurs/procedures/show.html.haml b/app/views/administrateurs/procedures/show.html.haml index 04dc0bb42..05b43bcbe 100644 --- a/app/views/administrateurs/procedures/show.html.haml +++ b/app/views/administrateurs/procedures/show.html.haml @@ -234,3 +234,18 @@ %p.card-admin-title MonAvis %p.card-admin-subtitle Avis des usagers sur votre démarche %p.button Modifier + + = link_to edit_admin_procedure_dossier_submitted_message_path(@procedure), class: 'card-admin' do + - if @procedure.active_dossier_submitted_message.present? + %div + %span.icon.accept + %p.card-admin-status-accept Validé + - else + %div + %span.icon.clock + %p.card-admin-status-todo À configurer + %div + %p.card-admin-title Fin de dépot + %p.card-admin-subtitle Orienter l'usager suite à l'envoie de son dossier + %p.button Modifier + diff --git a/app/views/users/dossiers/_merci.html.haml b/app/views/users/dossiers/_merci.html.haml new file mode 100644 index 000000000..a6ba51366 --- /dev/null +++ b/app/views/users/dossiers/_merci.html.haml @@ -0,0 +1,26 @@ +.merci.text-center.mb-7 + .container + = image_tag('user/envoi-dossier.svg', alt: '', class: 'mt-8') + %h1.mt-4.mb-3.mx-0= t('views.users.dossiers.merci.thanks') + %p.send.m-2.text-lg + = t('views.users.dossiers.merci.dossier_send_l1') + %strong= procedure.libelle + = t('views.users.dossiers.merci.dossier_send_l2') + %p.m-2 + = t('views.users.dossiers.merci.dossier_acces_l1') + %strong= t('views.users.dossiers.merci.dossier_acces_l2') + %p.m-2 + = t('views.users.dossiers.merci.dossier_edit_l1') + - if !dossier&.read_only? + %strong= t('views.users.dossiers.merci.dossier_edit_l2') + = t('views.users.dossiers.merci.dossier_edit_l3') + %strong= t('views.users.dossiers.merci.dossier_edit_l4') + - if procedure.active_dossier_submitted_message + %p.m-2= procedure.active_dossier_submitted_message.message_on_submit_by_usager + + .flex.column.align-center + = link_to t('views.users.dossiers.merci.acces_dossier'), dossier ? dossier_path(dossier) : "#dossier" , class: 'button large primary mt-4' + = link_to t('views.users.dossiers.merci.submit_dossier'), procedure_lien(procedure), class: 'mt-4' + + .monavis + != procedure.monavis_embed diff --git a/app/views/users/dossiers/merci.html.haml b/app/views/users/dossiers/merci.html.haml index 9b689d21c..063ce5a4e 100644 --- a/app/views/users/dossiers/merci.html.haml +++ b/app/views/users/dossiers/merci.html.haml @@ -3,26 +3,4 @@ - content_for :footer do = render partial: "users/procedure_footer", locals: { procedure: @dossier.procedure, dossier: @dossier } -.merci - .container - = image_tag('user/envoi-dossier.svg', alt: '') - %h1= t('views.users.dossiers.merci.thanks') - %p.send - = t('views.users.dossiers.merci.dossier_send_l1') - %b= @dossier.procedure.libelle - = t('views.users.dossiers.merci.dossier_send_l2') - %p - = t('views.users.dossiers.merci.dossier_acces_l1') - %b= t('views.users.dossiers.merci.dossier_acces_l2') - %p - = t('views.users.dossiers.merci.dossier_edit_l1') - - if !@dossier.read_only? - %b= t('views.users.dossiers.merci.dossier_edit_l2') - = t('views.users.dossiers.merci.dossier_edit_l3') - %b= t('views.users.dossiers.merci.dossier_edit_l4') - - .flex.column.align-center - = link_to t('views.users.dossiers.merci.acces_dossier'), dossier_path(@dossier), class: 'button large primary' - = link_to t('views.users.dossiers.merci.submit_dossier'), procedure_lien(@dossier.procedure) - .monavis - != @dossier.procedure.monavis_embed += render partial: 'users/dossiers/merci', locals: { dossier: @dossier, procedure: @dossier.procedure} diff --git a/config/brakeman.ignore b/config/brakeman.ignore index d1cd809da..ac201cf2d 100644 --- a/config/brakeman.ignore +++ b/config/brakeman.ignore @@ -1,5 +1,46 @@ { "ignored_warnings": [ + { + "warning_type": "Cross-Site Scripting", + "warning_code": 2, + "fingerprint": "1b805585567775589825c0eda58cb84c074fc760d0a7afb101c023a51427f2b5", + "check_name": "CrossSiteScripting", + "message": "Unescaped model attribute", + "file": "app/views/users/dossiers/_merci.html.haml", + "line": 26, + "link": "https://brakemanscanner.org/docs/warning_types/cross_site_scripting", + "code": "current_user.dossiers.includes(:procedure).find(params[:id]).procedure.monavis_embed", + "render_path": [ + { + "type": "controller", + "class": "Users::DossiersController", + "method": "merci", + "line": 196, + "file": "app/controllers/users/dossiers_controller.rb", + "rendered": { + "name": "users/dossiers/merci", + "file": "app/views/users/dossiers/merci.html.haml" + } + }, + { + "type": "template", + "name": "users/dossiers/merci", + "line": 6, + "file": "app/views/users/dossiers/merci.html.haml", + "rendered": { + "name": "users/dossiers/_merci", + "file": "app/views/users/dossiers/_merci.html.haml" + } + } + ], + "location": { + "type": "template", + "template": "users/dossiers/_merci" + }, + "user_input": "current_user.dossiers.includes(:procedure)", + "confidence": "Weak", + "note": "" + }, { "warning_type": "Cross-Site Scripting", "warning_code": 2, @@ -38,7 +79,7 @@ "check_name": "SQL", "message": "Possible SQL injection", "file": "app/models/traitement.rb", - "line": 51, + "line": 52, "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/", "code": "ActiveRecord::Base.connection.execute(\"select date_trunc('month', r1.processed_at::TIMESTAMPTZ AT TIME ZONE '#{Time.zone.formatted_offset}'::INTERVAL) as month, count(r1.processed_at)\\nfrom (#{Traitement.select(\"max(traitements.processed_at) as processed_at\").termine.where(:dossier => Dossier.state_termine.where(:groupe_instructeur => groupe_instructeurs)).group(:dossier_id).to_sql}) as r1\\ngroup by date_trunc('month', r1.processed_at::TIMESTAMPTZ AT TIME ZONE '#{Time.zone.formatted_offset}'::INTERVAL)\\norder by month desc\\n\")", "render_path": null, @@ -51,37 +92,6 @@ "confidence": "Medium", "note": "" }, - { - "warning_type": "Cross-Site Scripting", - "warning_code": 2, - "fingerprint": "483ae8c038244eb3ed709e89846335e2c8ff6579260348ec31d3d03d1c94ad64", - "check_name": "CrossSiteScripting", - "message": "Unescaped model attribute", - "file": "app/views/users/dossiers/merci.html.haml", - "line": 28, - "link": "https://brakemanscanner.org/docs/warning_types/cross_site_scripting", - "code": "current_user.dossiers.includes(:procedure).find(params[:id]).procedure.monavis_embed", - "render_path": [ - { - "type": "controller", - "class": "Users::DossiersController", - "method": "merci", - "line": 195, - "file": "app/controllers/users/dossiers_controller.rb", - "rendered": { - "name": "users/dossiers/merci", - "file": "app/views/users/dossiers/merci.html.haml" - } - } - ], - "location": { - "type": "template", - "template": "users/dossiers/merci" - }, - "user_input": "current_user.dossiers.includes(:procedure)", - "confidence": "Weak", - "note": "" - }, { "warning_type": "SQL Injection", "warning_code": 0, @@ -102,26 +112,6 @@ "confidence": "Medium", "note": "The table and column are escaped, which should make this safe" }, - { - "warning_type": "SQL Injection", - "warning_code": 0, - "fingerprint": "c0f93612a68c32da58f327e0b5fa33dd42fd8beb2984cf023338c5aadbbdacca", - "check_name": "SQL", - "message": "Possible SQL injection", - "file": "app/models/stat.rb", - "line": 83, - "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/", - "code": "association.where(date_attribute => ((3.months.ago.beginning_of_month..max_date))).group(\"DATE_TRUNC('month', #{date_attribute}::TIMESTAMPTZ AT TIME ZONE '#{Time.zone.formatted_offset}'::INTERVAL)\")", - "render_path": null, - "location": { - "type": "method", - "class": "Stat", - "method": "last_four_months_hash" - }, - "user_input": "date_attribute", - "confidence": "Weak", - "note": "" - }, { "warning_type": "Redirect", "warning_code": 18, @@ -129,7 +119,7 @@ "check_name": "Redirect", "message": "Possible unprotected redirect", "file": "app/controllers/instructeurs/procedures_controller.rb", - "line": 195, + "line": 202, "link": "https://brakemanscanner.org/docs/warning_types/redirect/", "code": "redirect_to(Export.find_or_create_export(params[:export_format], (params[:time_span_type] or \"everything\"), current_instructeur.groupe_instructeurs.where(:procedure => procedure)).file.service_url)", "render_path": null, @@ -141,28 +131,8 @@ "user_input": "Export.find_or_create_export(params[:export_format], (params[:time_span_type] or \"everything\"), current_instructeur.groupe_instructeurs.where(:procedure => procedure)).file.service_url", "confidence": "High", "note": "" - }, - { - "warning_type": "SQL Injection", - "warning_code": 0, - "fingerprint": "f2bb9bc6a56e44ab36ee18152c657395841cff354baed0a302b8d18650551529", - "check_name": "SQL", - "message": "Possible SQL injection", - "file": "app/models/stat.rb", - "line": 97, - "link": "https://brakemanscanner.org/docs/warning_types/sql_injection/", - "code": "association.where(\"#{date_attribute} < ?\", max_date).group(\"DATE_TRUNC('month', #{date_attribute}::TIMESTAMPTZ AT TIME ZONE '#{Time.zone.formatted_offset}'::INTERVAL)\")", - "render_path": null, - "location": { - "type": "method", - "class": "Stat", - "method": "cumulative_hash" - }, - "user_input": "date_attribute", - "confidence": "Weak", - "note": "" } ], - "updated": "2021-12-01 17:39:08 -1000", + "updated": "2022-02-22 15:46:39 +0100", "brakeman_version": "5.1.1" } diff --git a/config/routes.rb b/config/routes.rb index cc303bc9e..42c18a106 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -466,6 +466,7 @@ Rails.application.routes.draw do resource :attestation_template, only: [:edit, :update, :create] do get 'preview', on: :member end + resource :dossier_submitted_message, only: [:edit, :update, :create] # ADDED TO ACCESS IT FROM THE IFRAME get 'attestation_template/preview' => 'attestation_templates#preview' end diff --git a/db/migrate/20220204130722_create_dossier_submitted_messages.rb b/db/migrate/20220204130722_create_dossier_submitted_messages.rb new file mode 100644 index 000000000..d9208e66d --- /dev/null +++ b/db/migrate/20220204130722_create_dossier_submitted_messages.rb @@ -0,0 +1,9 @@ +class CreateDossierSubmittedMessages < ActiveRecord::Migration[6.1] + def change + create_table :dossier_submitted_messages do |t| + t.string :message_on_submit_by_usager + t.timestamps + end + add_reference :procedure_revisions, :dossier_submitted_message, foreign_key: { to_table: :dossier_submitted_messages }, null: true, index: true + end +end diff --git a/db/schema.rb b/db/schema.rb index d90acf3a6..3ef845f12 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: 2022_02_04_093401) do +ActiveRecord::Schema.define(version: 2022_02_04_130722) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -275,6 +275,12 @@ ActiveRecord::Schema.define(version: 2022_02_04_093401) do t.index ["keep_until"], name: "index_dossier_operation_logs_on_keep_until" end + create_table "dossier_submitted_messages", force: :cascade do |t| + t.string "message_on_submit_by_usager" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + end + create_table "dossier_transfer_logs", force: :cascade do |t| t.string "from", null: false t.string "to", null: false @@ -324,10 +330,10 @@ ActiveRecord::Schema.define(version: 2022_02_04_093401) do t.datetime "identity_updated_at" t.datetime "depose_at" t.datetime "hidden_by_user_at" + t.datetime "hidden_by_administration_at" t.string "hidden_by_reason" t.index "to_tsvector('french'::regconfig, (search_terms || private_search_terms))", name: "index_dossiers_on_search_terms_private_search_terms", using: :gin t.index "to_tsvector('french'::regconfig, search_terms)", name: "index_dossiers_on_search_terms", using: :gin - t.datetime "hidden_by_administration_at" t.index ["archived"], name: "index_dossiers_on_archived" t.index ["dossier_transfer_id"], name: "index_dossiers_on_dossier_transfer_id" t.index ["groupe_instructeur_id"], name: "index_dossiers_on_groupe_instructeur_id" @@ -595,7 +601,9 @@ ActiveRecord::Schema.define(version: 2022_02_04_093401) do t.datetime "updated_at", null: false t.datetime "published_at" t.bigint "attestation_template_id" + t.bigint "dossier_submitted_message_id" t.index ["attestation_template_id"], name: "index_procedure_revisions_on_attestation_template_id" + t.index ["dossier_submitted_message_id"], name: "index_procedure_revisions_on_dossier_submitted_message_id" t.index ["procedure_id"], name: "index_procedure_revisions_on_procedure_id" end @@ -876,6 +884,7 @@ ActiveRecord::Schema.define(version: 2022_02_04_093401) do add_foreign_key "procedure_revision_types_de_champ", "procedure_revisions", column: "revision_id" add_foreign_key "procedure_revision_types_de_champ", "types_de_champ" add_foreign_key "procedure_revisions", "attestation_templates" + add_foreign_key "procedure_revisions", "dossier_submitted_messages" add_foreign_key "procedure_revisions", "procedures" add_foreign_key "procedures", "procedure_revisions", column: "draft_revision_id" add_foreign_key "procedures", "procedure_revisions", column: "published_revision_id" diff --git a/spec/controllers/administrateurs/dossier_submitted_messages_controller_spec.rb b/spec/controllers/administrateurs/dossier_submitted_messages_controller_spec.rb new file mode 100644 index 000000000..2a1b825ec --- /dev/null +++ b/spec/controllers/administrateurs/dossier_submitted_messages_controller_spec.rb @@ -0,0 +1,81 @@ +include ActionDispatch::TestProcess + +describe Administrateurs::DossierSubmittedMessagesController, type: :controller do + let(:administrateur) { create(:administrateur) } + + before { sign_in(administrateur.user) } + + describe '#create' do + context 'when procedure is not published' do + let(:procedure) { create(:procedure, administrateur: administrateur) } + + it 'creates a DossierSubmittedMessage on draft_revision' do + message_on_submit_by_usager = "hello" + expect { + post(:create, params: { procedure_id: procedure.id, dossier_submitted_message: { message_on_submit_by_usager: message_on_submit_by_usager } }) + }.to change { DossierSubmittedMessage.count }.by(1) + expect(response).to redirect_to admin_procedure_path(procedure) + expect(procedure.reload.draft_revision.dossier_submitted_message).to eq(DossierSubmittedMessage.first) + end + end + + context 'when procedure is published' do + let(:procedure) { create(:procedure, :published, administrateur: administrateur) } + + it 'creates a DossierSubmittedMessage on published_revision' do + message_on_submit_by_usager = "hello" + expect { + post(:create, params: { procedure_id: procedure.id, dossier_submitted_message: { message_on_submit_by_usager: message_on_submit_by_usager } }) + }.to change { DossierSubmittedMessage.count }.by(1) + expect(response).to redirect_to admin_procedure_path(procedure) + expect(procedure.reload.published_revision.dossier_submitted_message).to eq(DossierSubmittedMessage.first) + end + end + end + + describe '#edit' do + context 'when procedure is draft and have a DossierSubmittedMessage' do + let(:procedure) { create(:procedure, :with_dossier_submitted_message, administrateur: administrateur) } + + it 'assigns the existing DossierSubmittedMessage' do + get(:edit, params: { procedure_id: procedure.id }) + expect(response).to have_http_status(200) + expect(assigns(:dossier_submitted_message)).to eq(procedure.active_dossier_submitted_message) + end + end + + context 'when draft procedure does not have dossier_submitted_message' do + let(:procedure) { create(:procedure, administrateur: administrateur) } + + it 'builds a new DossierSubmittedMessage' do + get(:edit, params: { procedure_id: procedure.id }) + expect(response).to have_http_status(200) + expect(assigns(:dossier_submitted_message).persisted?).to eq(false) + expect(assigns(:dossier_submitted_message)).to be_an_instance_of(DossierSubmittedMessage) + end + end + end + + describe '#update' do + context 'when procedure is draft' do + let(:procedure) { create(:procedure, :with_dossier_submitted_message, administrateur: administrateur) } + + it 'updates the existing DossierSubmittedMessage on draft_revision' do + new_message_on_submit_by_usager = "hello" + patch(:update, params: { procedure_id: procedure.id, dossier_submitted_message: { message_on_submit_by_usager: new_message_on_submit_by_usager } }) + expect(response).to redirect_to admin_procedure_path(procedure) + expect(procedure.draft_revision.dossier_submitted_message.message_on_submit_by_usager).to eq(new_message_on_submit_by_usager) + end + end + + context 'when draft procedure is published' do + let(:procedure) { create(:procedure, :published, :with_dossier_submitted_message, administrateur: administrateur) } + it 'updates the existing DossierSubmittedMessage on published_revision' do + new_message_on_submit_by_usager = "hello" + patch(:update, params: { procedure_id: procedure.id, dossier_submitted_message: { message_on_submit_by_usager: new_message_on_submit_by_usager } }) + expect(response).to redirect_to admin_procedure_path(procedure) + expect(procedure.published_revision.dossier_submitted_message.message_on_submit_by_usager).to eq(new_message_on_submit_by_usager) + end + end + end + end diff --git a/spec/factories/dossier_submitted_message.rb b/spec/factories/dossier_submitted_message.rb new file mode 100644 index 000000000..9b8bcec7d --- /dev/null +++ b/spec/factories/dossier_submitted_message.rb @@ -0,0 +1,5 @@ +FactoryBot.define do + factory :dossier_submitted_message do + message_on_submit_by_usager { "BAM !" } + end +end diff --git a/spec/factories/procedure.rb b/spec/factories/procedure.rb index a99eb46f3..ea3ed20c4 100644 --- a/spec/factories/procedure.rb +++ b/spec/factories/procedure.rb @@ -24,10 +24,11 @@ FactoryBot.define do types_de_champ_private { [] } updated_at { nil } attestation_template { nil } + dossier_submitted_message { nil } end after(:build) do |procedure, evaluator| - initial_revision = build(:procedure_revision, procedure: procedure, attestation_template: evaluator.attestation_template) + initial_revision = build(:procedure_revision, procedure: procedure, attestation_template: evaluator.attestation_template, dossier_submitted_message: evaluator.dossier_submitted_message) add_types_de_champs(evaluator.types_de_champ, to: initial_revision, scope: :public) add_types_de_champs(evaluator.types_de_champ_private, to: initial_revision, scope: :private) @@ -319,6 +320,12 @@ FactoryBot.define do end end end + + trait :with_dossier_submitted_message do + after(:build) do |procedure, _evaluator| + build(:dossier_submitted_message, revisions: [procedure.active_revision]) + end + end end end