From 72494de76f8d1927abfbdad5d7b119e4172eb019 Mon Sep 17 00:00:00 2001 From: Mathieu Magnin Date: Tue, 25 Apr 2017 12:09:11 +0200 Subject: [PATCH 01/20] Create new model Avis --- app/models/avis.rb | 4 ++++ app/models/dossier.rb | 1 + app/models/gestionnaire.rb | 1 + config/initializers/inflections.rb | 2 ++ db/migrate/20170425100757_create_avis.rb | 13 +++++++++++++ db/schema.rb | 14 +++++++++++++- 6 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 app/models/avis.rb create mode 100644 db/migrate/20170425100757_create_avis.rb diff --git a/app/models/avis.rb b/app/models/avis.rb new file mode 100644 index 000000000..2e6c622a2 --- /dev/null +++ b/app/models/avis.rb @@ -0,0 +1,4 @@ +class Avis < ApplicationRecord + belongs_to :dossier + belongs_to :gestionnaire +end diff --git a/app/models/dossier.rb b/app/models/dossier.rb index c6eee566f..71506ee9c 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -25,6 +25,7 @@ class Dossier < ActiveRecord::Base has_many :invites_gestionnaires, class_name: 'InviteGestionnaire', dependent: :destroy has_many :follows has_many :notifications, dependent: :destroy + has_many :avis, dependent: :destroy belongs_to :procedure belongs_to :user diff --git a/app/models/gestionnaire.rb b/app/models/gestionnaire.rb index f4cb1578b..0457deacb 100644 --- a/app/models/gestionnaire.rb +++ b/app/models/gestionnaire.rb @@ -12,6 +12,7 @@ class Gestionnaire < ActiveRecord::Base has_many :followed_dossiers, through: :follows, source: :dossier has_many :follows has_many :preference_list_dossiers + has_many :avis after_create :build_default_preferences_list_dossier after_create :build_default_preferences_smart_listing_page diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index a3bd49fb8..864ba4221 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -15,6 +15,7 @@ ActiveSupport::Inflector.inflections(:en) do |inflect| inflect.irregular 'type_de_champ', 'types_de_champ' inflect.irregular 'type_de_champ_private', 'types_de_champ_private' inflect.irregular 'assign_to', 'assign_tos' + inflect.irregular('avis', 'avis') end # These inflection rules are supported but not enabled by default: @@ -24,4 +25,5 @@ end ActiveSupport::Inflector.inflections(:fr) do |inflect| inflect.plural(/$/, 's') inflect.plural(/(hib|ch|bij|caill|p|gen|jouj)ou$/i, '\1oux') + inflect.irregular('avis', 'avis') end diff --git a/db/migrate/20170425100757_create_avis.rb b/db/migrate/20170425100757_create_avis.rb new file mode 100644 index 000000000..229be2178 --- /dev/null +++ b/db/migrate/20170425100757_create_avis.rb @@ -0,0 +1,13 @@ +class CreateAvis < ActiveRecord::Migration[5.0] + def change + create_table :avis do |t| + t.string :email + t.text :introduction + t.text :answer + t.references :gestionnaire + t.references :dossier + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 4af90d2e2..55f008b87 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: 20170523081220) do +ActiveRecord::Schema.define(version: 20170425100757) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -71,6 +71,18 @@ ActiveRecord::Schema.define(version: 20170523081220) do t.index ["procedure_id"], name: "index_assign_tos_on_procedure_id", using: :btree end + create_table "avis", force: :cascade do |t| + t.string "email" + t.text "introduction" + t.text "answer" + t.integer "gestionnaire_id" + t.integer "dossier_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["dossier_id"], name: "index_avis_on_dossier_id", using: :btree + t.index ["gestionnaire_id"], name: "index_avis_on_gestionnaire_id", using: :btree + end + create_table "cadastres", force: :cascade do |t| t.string "surface_intersection" t.float "surface_parcelle" From c3bf15d49f77eac516c0a54b161f49e09aa186d1 Mon Sep 17 00:00:00 2001 From: Mathieu Magnin Date: Tue, 25 Apr 2017 17:02:54 +0200 Subject: [PATCH 02/20] Create and list Avis on Dossier detail page --- app/controllers/backoffice/avis_controller.rb | 21 ++++++++ .../backoffice/dossiers_controller.rb | 2 + app/models/avis.rb | 4 ++ app/views/dossiers/_avis.html.haml | 52 +++++++++++++++++++ app/views/dossiers/_dossier_show.html.haml | 3 +- config/routes.rb | 1 + spec/models/avis_spec.rb | 20 +++++++ 7 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 app/controllers/backoffice/avis_controller.rb create mode 100644 app/views/dossiers/_avis.html.haml create mode 100644 spec/models/avis_spec.rb diff --git a/app/controllers/backoffice/avis_controller.rb b/app/controllers/backoffice/avis_controller.rb new file mode 100644 index 000000000..3d1559f6e --- /dev/null +++ b/app/controllers/backoffice/avis_controller.rb @@ -0,0 +1,21 @@ +class Backoffice::AvisController < ApplicationController + + def create + avis = Avis.new(create_params) + avis.dossier = dossier + avis.save + + redirect_to backoffice_dossier_path(dossier) + end + + private + + def dossier + current_gestionnaire.dossiers.find(params[:dossier_id]) + end + + def create_params + params.require(:avis).permit(:email, :introduction) + end + +end diff --git a/app/controllers/backoffice/dossiers_controller.rb b/app/controllers/backoffice/dossiers_controller.rb index c2dc2b89c..11ff0d7a6 100644 --- a/app/controllers/backoffice/dossiers_controller.rb +++ b/app/controllers/backoffice/dossiers_controller.rb @@ -29,6 +29,8 @@ class Backoffice::DossiersController < Backoffice::DossiersListController end Notification.where(dossier_id: params[:id].to_i).update_all already_read: true + + @new_avis = Avis.new(introduction: "Bonjour, merci de me donner votre avis sur ce dossier.") end def filter diff --git a/app/models/avis.rb b/app/models/avis.rb index 2e6c622a2..5bbe6244f 100644 --- a/app/models/avis.rb +++ b/app/models/avis.rb @@ -1,4 +1,8 @@ class Avis < ApplicationRecord belongs_to :dossier belongs_to :gestionnaire + + def email_to_display + gestionnaire.try(:email) || email + end end diff --git a/app/views/dossiers/_avis.html.haml b/app/views/dossiers/_avis.html.haml new file mode 100644 index 000000000..feeedd37c --- /dev/null +++ b/app/views/dossiers/_avis.html.haml @@ -0,0 +1,52 @@ +- if @current_gestionnaire + + .default-data-block.default_visible + .row.show-block.infos + .header + .col-xs-12.title + .carret-right + .carret-down + AVIS EXTERNES + .body + .display-block-on-print + - dossier_facade.dossier.avis.order(updated_at: :desc).each do |avis| + - if avis.answer + .panel.panel-success + .panel-heading + %strong= avis.email_to_display + a donné son avis le + = avis.updated_at.localtime.strftime('%d/%m/%Y à %H:%M') + .panel-body + %strong Vous : + = avis.introduction + %hr + %strong= "#{avis.email_to_display} :" + = avis.answer + - else + .panel.panel-info + .panel-heading + Avis demandé à + %strong= avis.email_to_display + le + = avis.created_at.localtime.strftime('%d/%m/%Y à %H:%M') + .panel-body + %strong Vous : + = avis.introduction + %hr + .center + %em Avis en attente + .hidden-print + .panel.panel-default + .panel-heading + Demander un avis externe + .panel-body + .help-block + Invitez une personne externe à consulter le dossier et à vous donner un avis sur celui ci. + %br + Cette personne pourra également contribuer au fil de messagerie, mais ne pourra pas modifier le dossier. + = simple_form_for @new_avis, url: backoffice_dossier_avis_index_path(dossier_facade.dossier.object.id) do |f| + + = f.input 'email', label: "Email de la personne qui doit donner un avis" + = f.input 'introduction', label: "Message" + + = f.submit "Envoyer la demande d'avis", class: 'btn btn-default' diff --git a/app/views/dossiers/_dossier_show.html.haml b/app/views/dossiers/_dossier_show.html.haml index 632a32f20..f4accd099 100644 --- a/app/views/dossiers/_dossier_show.html.haml +++ b/app/views/dossiers/_dossier_show.html.haml @@ -51,7 +51,6 @@ = render partial: '/users/carte/map', locals: { dossier: @facade.dossier } = render partial: 'users/carte/init_carto', locals: { dossier: @facade.dossier } - - if @current_gestionnaire && gestionnaire_signed_in? && @champs_private.count > 0 .default-data-block.default_visible .row.show-block#private-fields @@ -65,3 +64,5 @@ = (private_fields_count == 1) ? "1 champ" : "#{private_fields_count} champs" .body = render partial: '/dossiers/infos_private_fields' + += render partial: 'dossiers/avis', locals: { dossier_facade: @facade } diff --git a/config/routes.rb b/config/routes.rb index 16b0b090a..c11e135e0 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -179,6 +179,7 @@ Rails.application.routes.draw do post 'reopen' => 'dossiers#reopen' put 'follow' => 'dossiers#follow' resources :commentaires, only: [:index] + resources :avis, only: [:create] end namespace :dossiers do diff --git a/spec/models/avis_spec.rb b/spec/models/avis_spec.rb new file mode 100644 index 000000000..fbb731329 --- /dev/null +++ b/spec/models/avis_spec.rb @@ -0,0 +1,20 @@ +require 'rails_helper' + +RSpec.describe Avis, type: :model do + describe '.email_to_display' do + let(:invited_email) { 'invited@avis.com' } + let!(:avis) { Avis.create(email: invited_email, dossier: create(:dossier)) } + + subject { avis.email_to_display } + + context 'when gestionnaire is not known' do + it{ is_expected.to eq(invited_email) } + end + + context 'when gestionnaire is known' do + let!(:avis) { Avis.create(email: nil, gestionnaire: create(:gestionnaire), dossier: create(:dossier)) } + + it{ is_expected.to eq(avis.gestionnaire.email) } + end + end +end From e831442cbd667b09a89cb17bca36c72dbab23da4 Mon Sep 17 00:00:00 2001 From: Mathieu Magnin Date: Tue, 2 May 2017 16:20:16 +0200 Subject: [PATCH 03/20] Associate gestionnaire to avis if gestionnaire is known --- app/controllers/backoffice/avis_controller.rb | 9 +++++ .../backoffice/avis_controller_spec.rb | 35 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 spec/controllers/backoffice/avis_controller_spec.rb diff --git a/app/controllers/backoffice/avis_controller.rb b/app/controllers/backoffice/avis_controller.rb index 3d1559f6e..8b20f69ad 100644 --- a/app/controllers/backoffice/avis_controller.rb +++ b/app/controllers/backoffice/avis_controller.rb @@ -1,8 +1,17 @@ class Backoffice::AvisController < ApplicationController + before_action :authenticate_gestionnaire! + def create avis = Avis.new(create_params) avis.dossier = dossier + + gestionnaire = Gestionnaire.find_by(email: create_params[:email]) + if gestionnaire + avis.gestionnaire = gestionnaire + avis.email = nil + end + avis.save redirect_to backoffice_dossier_path(dossier) diff --git a/spec/controllers/backoffice/avis_controller_spec.rb b/spec/controllers/backoffice/avis_controller_spec.rb new file mode 100644 index 000000000..041f0f03d --- /dev/null +++ b/spec/controllers/backoffice/avis_controller_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +describe Backoffice::AvisController, type: :controller do + + describe '#POST create' do + let(:gestionnaire){ create(:gestionnaire) } + let!(:dossier){ create(:dossier, state: 'received') } + let!(:assign_to){ create(:assign_to, gestionnaire: gestionnaire, procedure: dossier.procedure )} + + subject { post :create, params: { dossier_id: dossier.id, avis: { email: gestionnaire.email, introduction: "Bonjour, regardez ce joli dossier." } } } + + context 'when gestionnaire is not authenticated' do + it { is_expected.to redirect_to new_user_session_path } + it { expect{ subject }.to_not change(Avis, :count) } + end + + context 'when gestionnaire is authenticated' do + before do + sign_in gestionnaire + end + + context 'When gestionnaire is known' do + it { is_expected.to redirect_to backoffice_dossier_path(dossier.id) } + it { expect{ subject }.to change(Avis, :count).by(1) } + it do + subject + expect(gestionnaire.avis.last).to_not eq(nil) + expect(gestionnaire.avis.last.email).to eq(nil) + expect(gestionnaire.avis.last.dossier_id).to eq(dossier.id) + end + end + end + end + +end From 43f481b7ff2176d679018516df97f59d40e9e636 Mon Sep 17 00:00:00 2001 From: Mathieu Magnin Date: Thu, 27 Apr 2017 12:17:50 +0200 Subject: [PATCH 04/20] Gestionnaire can list dossiers where he is invited for avis --- .../dossiers/procedure_controller.rb | 1 + .../backoffice/dossiers_controller.rb | 3 ++ app/controllers/backoffice_controller.rb | 19 ++++++++ app/models/avis.rb | 3 ++ app/models/procedure.rb | 1 - .../dossiers/_list_invitations.html.haml | 20 +++++++++ app/views/backoffice/invitations.html.haml | 22 +++++++++ app/views/backoffice/invitations.js.erb | 4 ++ ...koffice_dossierscontroller_index.html.haml | 4 ++ ...backofficecontroller_invitations.html.haml | 1 + ...backofficecontroller_invitations.html.haml | 2 + config/routes.rb | 2 + .../controllers/backoffice_controller_spec.rb | 45 ++++++++++++++++++- spec/factories/avis.rb | 17 +++++++ 14 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 app/views/backoffice/dossiers/_list_invitations.html.haml create mode 100644 app/views/backoffice/invitations.html.haml create mode 100644 app/views/backoffice/invitations.js.erb create mode 100644 app/views/layouts/left_panels/_left_panel_backofficecontroller_invitations.html.haml create mode 100644 app/views/layouts/navbars/_navbar_backofficecontroller_invitations.html.haml create mode 100644 spec/factories/avis.rb diff --git a/app/controllers/backoffice/dossiers/procedure_controller.rb b/app/controllers/backoffice/dossiers/procedure_controller.rb index 76b96bf66..88bcf6536 100644 --- a/app/controllers/backoffice/dossiers/procedure_controller.rb +++ b/app/controllers/backoffice/dossiers/procedure_controller.rb @@ -22,4 +22,5 @@ class Backoffice::Dossiers::ProcedureController < Backoffice::DossiersListContro def retrieve_procedure current_gestionnaire.procedures.find params[:id] end + end diff --git a/app/controllers/backoffice/dossiers_controller.rb b/app/controllers/backoffice/dossiers_controller.rb index 11ff0d7a6..ac7135587 100644 --- a/app/controllers/backoffice/dossiers_controller.rb +++ b/app/controllers/backoffice/dossiers_controller.rb @@ -4,10 +4,13 @@ class Backoffice::DossiersController < Backoffice::DossiersListController before_action :ensure_gestionnaire_is_authorized, only: :show def index + return redirect_to backoffice_invitations_path if current_gestionnaire.avis.any? + procedure = current_gestionnaire.procedure_filter if procedure.nil? procedure_list = dossiers_list_facade.gestionnaire_procedures_name_and_id_list + if procedure_list.count == 0 flash.alert = "Vous n'avez aucune procédure d'affectée." return redirect_to root_path diff --git a/app/controllers/backoffice_controller.rb b/app/controllers/backoffice_controller.rb index 7cad9b2a4..fa77609d3 100644 --- a/app/controllers/backoffice_controller.rb +++ b/app/controllers/backoffice_controller.rb @@ -1,4 +1,8 @@ class BackofficeController < ApplicationController + include SmartListing::Helper::ControllerExtensions + helper SmartListing::Helper + + before_action :authenticate_gestionnaire!, only: [:invitations] def index if !gestionnaire_signed_in? @@ -7,4 +11,19 @@ class BackofficeController < ApplicationController redirect_to(:backoffice_dossiers) end end + + def invitations + pending_avis = current_gestionnaire.avis.without_answer.includes(dossier: [:procedure]).by_latest + @pending_avis = smart_listing_create :pending_avis, + pending_avis, + partial: 'backoffice/dossiers/list_invitations', + array: true + + avis_with_answer = current_gestionnaire.avis.with_answer.includes(dossier: [:procedure]).by_latest + @avis_with_answer = smart_listing_create :avis_with_answer, + avis_with_answer, + partial: 'backoffice/dossiers/list_invitations', + array: true + end + end diff --git a/app/models/avis.rb b/app/models/avis.rb index 5bbe6244f..e81c91ac8 100644 --- a/app/models/avis.rb +++ b/app/models/avis.rb @@ -2,6 +2,9 @@ class Avis < ApplicationRecord belongs_to :dossier belongs_to :gestionnaire + scope :with_answer, -> { where.not(answer: nil) } + scope :without_answer, -> { where(answer: nil) } + def email_to_display gestionnaire.try(:email) || email end diff --git a/app/models/procedure.rb b/app/models/procedure.rb index 8c863697c..864b3fcc3 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -3,7 +3,6 @@ class Procedure < ActiveRecord::Base has_many :types_de_champ, class_name: 'TypeDeChampPublic', dependent: :destroy has_many :types_de_champ_private, dependent: :destroy has_many :dossiers - has_many :notifications, through: :dossiers has_one :procedure_path, dependent: :destroy diff --git a/app/views/backoffice/dossiers/_list_invitations.html.haml b/app/views/backoffice/dossiers/_list_invitations.html.haml new file mode 100644 index 000000000..526bc5415 --- /dev/null +++ b/app/views/backoffice/dossiers/_list_invitations.html.haml @@ -0,0 +1,20 @@ +- if smart_listing.collection.any? + %table#dossiers-list.table + %thead + %th + Nº + %th + Procédure + %th + Invité le + %tbody + - smart_listing.collection.each do |avis| + %tr.dossier-row{ id: "tr_dossier_#{avis.dossier.id}", 'data-dossier_url' => backoffice_dossier_url(id: avis.dossier.id) } + %td= avis.dossier.id + %td= avis.dossier.procedure.libelle + %td= avis.created_at.strftime('%d/%m/%Y %H:%M') + = smart_listing.paginate + +- else + .center{ colspan: 2 } + %em Aucun dossier diff --git a/app/views/backoffice/invitations.html.haml b/app/views/backoffice/invitations.html.haml new file mode 100644 index 000000000..b9ffaad00 --- /dev/null +++ b/app/views/backoffice/invitations.html.haml @@ -0,0 +1,22 @@ +.col-md-12 + .default-data-block.default_visible + .row.show-block + .header + .title + .carret-right + .carret-down + = "#{@pending_avis.count} avis à rendre" + .body + = smart_listing_render :pending_avis + + %br + + .default-data-block + .row.show-block + .header + .title + .carret-right + .carret-down + = "#{@avis_with_answer.count} avis #{"rendu".pluralize(@avis_with_answer.count)}" + .body + = smart_listing_render :avis_with_answer diff --git a/app/views/backoffice/invitations.js.erb b/app/views/backoffice/invitations.js.erb new file mode 100644 index 000000000..a56437328 --- /dev/null +++ b/app/views/backoffice/invitations.js.erb @@ -0,0 +1,4 @@ +<%= smart_listing_update :pending_avis %> +<%= smart_listing_update :avis_with_answer %> + +link_init(); diff --git a/app/views/layouts/left_panels/_left_panel_backoffice_dossierscontroller_index.html.haml b/app/views/layouts/left_panels/_left_panel_backoffice_dossierscontroller_index.html.haml index c1dfe2bd7..d2ea6ea5b 100644 --- a/app/views/layouts/left_panels/_left_panel_backoffice_dossierscontroller_index.html.haml +++ b/app/views/layouts/left_panels/_left_panel_backoffice_dossierscontroller_index.html.haml @@ -20,6 +20,10 @@ #infos-block .split-hr-left #procedure-list + - if current_gestionnaire.avis.any? + = link_to backoffice_invitations_path do + .procedure-list-element{ class: ('active' if request.path == backoffice_invitations_path) } + Invitations - current_gestionnaire.procedures.by_libelle.each do |procedure| = link_to backoffice_dossiers_procedure_path(procedure.id), { title: procedure.libelle } do .procedure-list-element{ class: ('active' if procedure.id.to_s == params[:id]) } diff --git a/app/views/layouts/left_panels/_left_panel_backofficecontroller_invitations.html.haml b/app/views/layouts/left_panels/_left_panel_backofficecontroller_invitations.html.haml new file mode 100644 index 000000000..b4114cab1 --- /dev/null +++ b/app/views/layouts/left_panels/_left_panel_backofficecontroller_invitations.html.haml @@ -0,0 +1 @@ += render partial: 'layouts/left_panels/left_panel_backoffice_dossierscontroller_index' diff --git a/app/views/layouts/navbars/_navbar_backofficecontroller_invitations.html.haml b/app/views/layouts/navbars/_navbar_backofficecontroller_invitations.html.haml new file mode 100644 index 000000000..eb80c1517 --- /dev/null +++ b/app/views/layouts/navbars/_navbar_backofficecontroller_invitations.html.haml @@ -0,0 +1,2 @@ +.col-xs-10.main-info + INVITATIONS diff --git a/config/routes.rb b/config/routes.rb index c11e135e0..39c5ec5fd 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -167,6 +167,8 @@ Rails.application.routes.draw do resource :private_formulaire + get 'invitations' + resources :dossiers do post 'receive' => 'dossiers#receive' post 'refuse' => 'dossiers#refuse' diff --git a/spec/controllers/backoffice_controller_spec.rb b/spec/controllers/backoffice_controller_spec.rb index 00db207ae..540f8db82 100644 --- a/spec/controllers/backoffice_controller_spec.rb +++ b/spec/controllers/backoffice_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe BackofficeController, type: :controller do describe 'GET #index' do - context 'when gestionnaire is not connected'do + context 'when gestionnaire is not connected' do before do get :index end @@ -10,7 +10,7 @@ describe BackofficeController, type: :controller do it { expect(response).to redirect_to :new_gestionnaire_session } end - context 'when gestionnaire is connected'do + context 'when gestionnaire is connected' do before do sign_in create(:gestionnaire) get :index @@ -19,4 +19,45 @@ describe BackofficeController, type: :controller do it { expect(response).to redirect_to :backoffice_dossiers } end end + + describe 'GET #invitations' do + context 'when gestionnaire is not invited on any dossiers' do + render_views + + before do + sign_in create(:gestionnaire) + get :invitations + end + + it { expect(response.status).to eq(200) } + it { expect(response.body).to include("INVITATIONS") } + it { expect(response.body).to include("0 avis à rendre") } + it { expect(response.body).to include("0 avis rendus") } + end + + context 'when gestionnaire is invited on a dossier' do + let(:dossier){ create(:dossier) } + let(:gestionnaire){ create(:gestionnaire) } + let!(:avis){ create(:avis, dossier: dossier, gestionnaire: gestionnaire) } + render_views + + before do + sign_in gestionnaire + get :invitations + end + + it { expect(response.status).to eq(200) } + it { expect(response.body).to include("1 avis à rendre") } + it { expect(response.body).to include("0 avis rendus") } + it { expect(response.body).to include(dossier.procedure.libelle) } + + context 'when avis is already sent' do + let!(:avis){ create(:avis, dossier: dossier, gestionnaire: gestionnaire, answer: "Voici mon avis.") } + + it { expect(response.body).to include("0 avis à rendre") } + it { expect(response.body).to include("1 avis rendu") } + it { expect(response.body).to include(dossier.procedure.libelle) } + end + end + end end diff --git a/spec/factories/avis.rb b/spec/factories/avis.rb new file mode 100644 index 000000000..c69371734 --- /dev/null +++ b/spec/factories/avis.rb @@ -0,0 +1,17 @@ +FactoryGirl.define do + factory :avis do + introduction 'Bonjour, merci de me donner votre avis sur ce dossier' + + before(:create) do |avis, _evaluator| + unless avis.gestionnaire + avis.gestionnaire = create :gestionnaire + end + end + + before(:create) do |avis, _evaluator| + unless avis.dossier + avis.dossier = create :dossier + end + end + end +end From 7c662aa7b29d8a8cfbc983c038c4f0a52f17ffc9 Mon Sep 17 00:00:00 2001 From: Mathieu Magnin Date: Thu, 27 Apr 2017 16:29:04 +0200 Subject: [PATCH 05/20] Gestionnaire invited on dossier for avis, cannot see private form / change dossier state / follow dossier / see invited people / see others avis --- app/controllers/root_controller.rb | 2 + app/models/gestionnaire.rb | 4 + app/views/dossiers/_avis.html.haml | 2 +- app/views/dossiers/_dossier_show.html.haml | 2 +- ...ckoffice_dossierscontroller_show.html.haml | 4 +- ...ckoffice_dossierscontroller_show.html.haml | 73 ++++++++++--------- ...backoffice_dossierscontroller_show_spec.rb | 1 + 7 files changed, 48 insertions(+), 40 deletions(-) diff --git a/app/controllers/root_controller.rb b/app/controllers/root_controller.rb index ec123d601..fec3780b4 100644 --- a/app/controllers/root_controller.rb +++ b/app/controllers/root_controller.rb @@ -14,6 +14,8 @@ class RootController < ApplicationController return redirect_to admin_procedures_path elsif gestionnaire_signed_in? + return redirect_to backoffice_invitations_path if current_gestionnaire.avis.any? + procedure_id = current_gestionnaire.procedure_filter if procedure_id.nil? procedure_list = current_gestionnaire.procedures diff --git a/app/models/gestionnaire.rb b/app/models/gestionnaire.rb index 0457deacb..3c12cf790 100644 --- a/app/models/gestionnaire.rb +++ b/app/models/gestionnaire.rb @@ -42,6 +42,10 @@ class Gestionnaire < ActiveRecord::Base Follow.where(gestionnaire_id: id, dossier_id: dossier_id).any? end + def assigned_on_procedure?(procedure_id) + procedures.find_by(id: procedure_id).present? + end + def build_default_preferences_list_dossier procedure_id=nil PreferenceListDossier.available_columns_for(procedure_id).each do |table| diff --git a/app/views/dossiers/_avis.html.haml b/app/views/dossiers/_avis.html.haml index feeedd37c..319b5e2ac 100644 --- a/app/views/dossiers/_avis.html.haml +++ b/app/views/dossiers/_avis.html.haml @@ -1,4 +1,4 @@ -- if @current_gestionnaire +- if current_gestionnaire && current_gestionnaire.assigned_on_procedure?(@facade.dossier.procedure_id) .default-data-block.default_visible .row.show-block.infos diff --git a/app/views/dossiers/_dossier_show.html.haml b/app/views/dossiers/_dossier_show.html.haml index f4accd099..09c63d506 100644 --- a/app/views/dossiers/_dossier_show.html.haml +++ b/app/views/dossiers/_dossier_show.html.haml @@ -51,7 +51,7 @@ = render partial: '/users/carte/map', locals: { dossier: @facade.dossier } = render partial: 'users/carte/init_carto', locals: { dossier: @facade.dossier } -- if @current_gestionnaire && gestionnaire_signed_in? && @champs_private.count > 0 +- if @current_gestionnaire && gestionnaire_signed_in? && current_gestionnaire.assigned_on_procedure?(@facade.dossier.procedure_id) && @champs_private.count > 0 .default-data-block.default_visible .row.show-block#private-fields .header diff --git a/app/views/layouts/left_panels/_left_panel_backoffice_dossierscontroller_show.html.haml b/app/views/layouts/left_panels/_left_panel_backoffice_dossierscontroller_show.html.haml index a78fa8241..2560a0bb8 100644 --- a/app/views/layouts/left_panels/_left_panel_backoffice_dossierscontroller_show.html.haml +++ b/app/views/layouts/left_panels/_left_panel_backoffice_dossierscontroller_show.html.haml @@ -2,8 +2,8 @@ .infos #dossier_id= t('dynamics.dossiers.numéro') + @facade.dossier.id.to_s -#action-block - - if gestionnaire_signed_in? +- if current_gestionnaire && current_gestionnaire.assigned_on_procedure?(@facade.dossier.procedure_id) + #action-block - if !@facade.dossier.read_only? || @facade.dossier.initiated? = link_to 'Passer en instruction', backoffice_dossier_receive_path(@facade.dossier), method: :post, class: 'btn btn-danger btn-block', data: { confirm: "Confirmer vous le passage en instruction de ce dossier ?" } diff --git a/app/views/layouts/navbars/_navbar_backoffice_dossierscontroller_show.html.haml b/app/views/layouts/navbars/_navbar_backoffice_dossierscontroller_show.html.haml index 97027181d..2c72a80fe 100644 --- a/app/views/layouts/navbars/_navbar_backoffice_dossierscontroller_show.html.haml +++ b/app/views/layouts/navbars/_navbar_backoffice_dossierscontroller_show.html.haml @@ -1,40 +1,41 @@ .col-xs-7.main-info = @facade.dossier.procedure.libelle .col-xs-3.options - .row - .col-xs-12 - - if current_gestionnaire.follow?(@facade.dossier.id) - = link_to backoffice_dossier_follow_path(dossier_id: @facade.dossier.id), "data-method" => :put, class: "button-navbar-action", id: "suivre_dossier_#{@facade.dossier.id}" do - %i.fa.fa-user-times - Ne plus suivre - - else - = link_to backoffice_dossier_follow_path(dossier_id: @facade.dossier.id), 'data-method' => :put, class: 'button-navbar-action', id: "suivre_dossier_#{@facade.dossier.id}" do - %i.fa.fa-user-plus - Suivre le dossier - .row - .col-xs-12 - #invitations.dropdown-toggle{ 'data-toggle' => 'dropdown', 'aria-haspopup' => true, 'aria-expanded' => false } - %i.fa.fa-user - = t('utils.involved') - .badge.progress-bar-info - = @facade.dossier.invites.count - .dropdown-menu.dropdown-menu-right.dropdown-pannel - %h4= t('dynamics.dossiers.followers.title') - %ul - - unless @facade.followers.empty? - - @facade.followers.each do |follower| - %li= follower.email - - else - = t('dynamics.dossiers.followers.empty') - %h4= t('dynamics.dossiers.invites.title') - %ul - - unless @facade.invites.empty? - - @facade.invites.each do |invite| - %li= invite.email - - else - = t('dynamics.dossiers.invites.empty') + - if current_gestionnaire.assigned_on_procedure?(@facade.dossier.procedure_id) + .row + .col-xs-12 + - if current_gestionnaire.follow?(@facade.dossier.id) + = link_to backoffice_dossier_follow_path(dossier_id: @facade.dossier.id), "data-method" => :put, class: "button-navbar-action", id: "suivre_dossier_#{@facade.dossier.id}" do + %i.fa.fa-user-times + Ne plus suivre + - else + = link_to backoffice_dossier_follow_path(dossier_id: @facade.dossier.id), 'data-method' => :put, class: 'button-navbar-action', id: "suivre_dossier_#{@facade.dossier.id}" do + %i.fa.fa-user-plus + Suivre le dossier + .row + .col-xs-12 + #invitations.dropdown-toggle{ 'data-toggle' => 'dropdown', 'aria-haspopup' => true, 'aria-expanded' => false } + %i.fa.fa-user + = t('utils.involved') + .badge.progress-bar-info + = @facade.dossier.invites.count + .dropdown-menu.dropdown-menu-right.dropdown-pannel + %h4= t('dynamics.dossiers.followers.title') + %ul + - unless @facade.followers.empty? + - @facade.followers.each do |follower| + %li= follower.email + - else + = t('dynamics.dossiers.followers.empty') + %h4= t('dynamics.dossiers.invites.title') + %ul + - unless @facade.invites.empty? + - @facade.invites.each do |invite| + %li= invite.email + - else + = t('dynamics.dossiers.invites.empty') - %li - = form_tag invites_dossier_path(dossier_id: @facade.dossier.id), method: :post, class: 'form-inline', id: 'send-invitation' do - = text_field_tag :email, '', class: 'form-control', placeholder: 'Envoyer une invitation', id: 'invitation-email' - = submit_tag 'Ajouter', class: 'btn btn-success', data: { confirm: "Envoyer l'invitation ?" } + %li + = form_tag invites_dossier_path(dossier_id: @facade.dossier.id), method: :post, class: 'form-inline', id: 'send-invitation' do + = text_field_tag :email, '', class: 'form-control', placeholder: 'Envoyer une invitation', id: 'invitation-email' + = submit_tag 'Ajouter', class: 'btn btn-success', data: { confirm: "Envoyer l'invitation ?" } diff --git a/spec/views/layouts/left_panels/_left_panel_backoffice_dossierscontroller_show_spec.rb b/spec/views/layouts/left_panels/_left_panel_backoffice_dossierscontroller_show_spec.rb index dd61a7578..308acb09c 100644 --- a/spec/views/layouts/left_panels/_left_panel_backoffice_dossierscontroller_show_spec.rb +++ b/spec/views/layouts/left_panels/_left_panel_backoffice_dossierscontroller_show_spec.rb @@ -6,6 +6,7 @@ describe 'layouts/left_panels/_left_panel_backoffice_dossierscontroller_show.htm let(:state) { 'draft' } let(:archived) { false } let(:gestionnaire) { create(:gestionnaire) } + let!(:assign_to) { create(:assign_to, gestionnaire: gestionnaire, procedure: dossier.procedure) } before do sign_in gestionnaire From d07943a55db9e11699459cdc8a7c8b6dee528ab8 Mon Sep 17 00:00:00 2001 From: Mathieu Magnin Date: Tue, 2 May 2017 13:54:57 +0200 Subject: [PATCH 06/20] Add by_latest scope in Avis --- app/models/avis.rb | 1 + app/views/dossiers/_avis.html.haml | 2 +- spec/models/avis_spec.rb | 12 ++++++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/app/models/avis.rb b/app/models/avis.rb index e81c91ac8..129175673 100644 --- a/app/models/avis.rb +++ b/app/models/avis.rb @@ -4,6 +4,7 @@ class Avis < ApplicationRecord scope :with_answer, -> { where.not(answer: nil) } scope :without_answer, -> { where(answer: nil) } + scope :by_latest, -> { order(updated_at: :desc) } def email_to_display gestionnaire.try(:email) || email diff --git a/app/views/dossiers/_avis.html.haml b/app/views/dossiers/_avis.html.haml index 319b5e2ac..80c896070 100644 --- a/app/views/dossiers/_avis.html.haml +++ b/app/views/dossiers/_avis.html.haml @@ -9,7 +9,7 @@ AVIS EXTERNES .body .display-block-on-print - - dossier_facade.dossier.avis.order(updated_at: :desc).each do |avis| + - dossier_facade.dossier.avis.by_latest.each do |avis| - if avis.answer .panel.panel-success .panel-heading diff --git a/spec/models/avis_spec.rb b/spec/models/avis_spec.rb index fbb731329..7f10efcf2 100644 --- a/spec/models/avis_spec.rb +++ b/spec/models/avis_spec.rb @@ -17,4 +17,16 @@ RSpec.describe Avis, type: :model do it{ is_expected.to eq(avis.gestionnaire.email) } end end + + describe '.by_latest' do + context 'with 3 avis' do + let!(:avis){ create(:avis) } + let!(:avis2){ create(:avis, updated_at: 4.hours.ago) } + let!(:avis3){ create(:avis, updated_at: 3.hours.ago) } + + subject { Avis.by_latest } + + it { expect(subject).to eq([avis, avis3, avis2])} + end + end end From f24e4a77d3d386a380e598014cb4c1450930f220 Mon Sep 17 00:00:00 2001 From: Mathieu Magnin Date: Tue, 16 May 2017 15:20:38 +0200 Subject: [PATCH 07/20] Gestionnaire can view dossier if he is invited on dossier --- .../backoffice/dossiers_controller.rb | 9 ++++---- app/models/gestionnaire.rb | 5 ++++ spec/models/gestionnaire_spec.rb | 23 +++++++++++++++++++ 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/app/controllers/backoffice/dossiers_controller.rb b/app/controllers/backoffice/dossiers_controller.rb index ac7135587..14f04fe45 100644 --- a/app/controllers/backoffice/dossiers_controller.rb +++ b/app/controllers/backoffice/dossiers_controller.rb @@ -190,11 +190,10 @@ class Backoffice::DossiersController < Backoffice::DossiersListController private def ensure_gestionnaire_is_authorized - current_gestionnaire.dossiers.find(params[:id]) - - rescue ActiveRecord::RecordNotFound - flash.alert = t('errors.messages.dossier_not_found') - redirect_to url_for(controller: '/backoffice') + unless current_gestionnaire.can_view_dossier?(params[:id]) + flash.alert = t('errors.messages.dossier_not_found') + redirect_to url_for(controller: '/backoffice') + end end def create_dossier_facade dossier_id diff --git a/app/models/gestionnaire.rb b/app/models/gestionnaire.rb index 3c12cf790..6492cca64 100644 --- a/app/models/gestionnaire.rb +++ b/app/models/gestionnaire.rb @@ -25,6 +25,11 @@ class Gestionnaire < ActiveRecord::Base self[:procedure_filter] end + def can_view_dossier?(dossier_id) + avis.where(dossier_id: dossier_id).any? || + dossiers.where(id: dossier_id).any? + end + def toggle_follow_dossier dossier_id dossier = dossier_id dossier = Dossier.find(dossier_id) unless dossier_id.class == Dossier diff --git a/spec/models/gestionnaire_spec.rb b/spec/models/gestionnaire_spec.rb index 27cb3502e..fbfbfd76f 100644 --- a/spec/models/gestionnaire_spec.rb +++ b/spec/models/gestionnaire_spec.rb @@ -395,4 +395,27 @@ describe Gestionnaire, type: :model do it { is_expected.to eq(nil) } end end + + describe '.can_view_dossier?' do + subject{ gestionnaire.can_view_dossier?(dossier.id) } + + context 'when gestionnaire is assigned on dossier' do + let!(:dossier){ create(:dossier, procedure: procedure, state: 'received') } + + it { expect(subject).to be true } + end + + context 'when gestionnaire is invited on dossier' do + let(:dossier){ create(:dossier) } + let!(:avis){ create(:avis, dossier: dossier, gestionnaire: gestionnaire) } + + it { expect(subject).to be true } + end + + context 'when gestionnaire is neither assigned nor invited on dossier' do + let(:dossier){ create(:dossier) } + + it { expect(subject).to be false } + end + end end From f6359cb7aa6781ecb79d84db5db2635534e1a6ce Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Wed, 24 May 2017 18:45:31 +0200 Subject: [PATCH 08/20] gestionnaire invited on dossier for avis, can update Avis --- app/controllers/backoffice/avis_controller.rb | 16 +++++++++ app/models/avis.rb | 1 + app/views/dossiers/_dossier_show.html.haml | 2 ++ app/views/dossiers/_edit_avis.html.haml | 13 +++++++ config/routes.rb | 2 +- .../backoffice/avis_controller_spec.rb | 34 +++++++++++++++++++ .../backoffice/dossiers_controller_spec.rb | 19 +++++++++++ 7 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 app/views/dossiers/_edit_avis.html.haml diff --git a/app/controllers/backoffice/avis_controller.rb b/app/controllers/backoffice/avis_controller.rb index 8b20f69ad..2bd8a23b9 100644 --- a/app/controllers/backoffice/avis_controller.rb +++ b/app/controllers/backoffice/avis_controller.rb @@ -17,14 +17,30 @@ class Backoffice::AvisController < ApplicationController redirect_to backoffice_dossier_path(dossier) end + def update + if avis.update(update_params) + flash[:notice] = 'Merci, votre avis a été enregistré.' + end + + redirect_to backoffice_dossier_path(avis.dossier_id) + end + private def dossier current_gestionnaire.dossiers.find(params[:dossier_id]) end + def avis + current_gestionnaire.avis.find(params[:id]) + end + def create_params params.require(:avis).permit(:email, :introduction) end + def update_params + params.require(:avis).permit(:answer) + end + end diff --git a/app/models/avis.rb b/app/models/avis.rb index 129175673..b63ca92ff 100644 --- a/app/models/avis.rb +++ b/app/models/avis.rb @@ -4,6 +4,7 @@ class Avis < ApplicationRecord scope :with_answer, -> { where.not(answer: nil) } scope :without_answer, -> { where(answer: nil) } + scope :for_dossier, ->(dossier_id) { where(dossier_id: dossier_id) } scope :by_latest, -> { order(updated_at: :desc) } def email_to_display diff --git a/app/views/dossiers/_dossier_show.html.haml b/app/views/dossiers/_dossier_show.html.haml index 09c63d506..cfbe4ee02 100644 --- a/app/views/dossiers/_dossier_show.html.haml +++ b/app/views/dossiers/_dossier_show.html.haml @@ -1,3 +1,5 @@ += render partial: 'dossiers/edit_avis', locals: { dossier_facade: @facade } + = render partial: 'dossiers/messagerie', locals: { dossier_facade: @facade } - if @facade.procedure.individual_with_siret diff --git a/app/views/dossiers/_edit_avis.html.haml b/app/views/dossiers/_edit_avis.html.haml new file mode 100644 index 000000000..491291793 --- /dev/null +++ b/app/views/dossiers/_edit_avis.html.haml @@ -0,0 +1,13 @@ +- if current_gestionnaire + - avis_for_dossier = current_gestionnaire.avis.for_dossier(dossier_facade.dossier.id).by_latest + - if avis_for_dossier.any? + .panel.panel-default + .panel-body + %h4 Votre avis est sollicité sur le dossier : + - avis_for_dossier.each do |avis| + %hr + %p= avis.introduction + = simple_form_for avis, url: backoffice_dossier_avis_path(dossier_facade.dossier, avis) do |f| + = f.input 'answer', label: "Votre avis" + - submit_label = if avis.answer then "Modifier votre avis" else "Enregistrer votre avis" end + = f.submit submit_label, class: 'btn btn-default' diff --git a/config/routes.rb b/config/routes.rb index 39c5ec5fd..16fadf98d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -181,7 +181,7 @@ Rails.application.routes.draw do post 'reopen' => 'dossiers#reopen' put 'follow' => 'dossiers#follow' resources :commentaires, only: [:index] - resources :avis, only: [:create] + resources :avis, only: [:create, :update] end namespace :dossiers do diff --git a/spec/controllers/backoffice/avis_controller_spec.rb b/spec/controllers/backoffice/avis_controller_spec.rb index 041f0f03d..d3731e63c 100644 --- a/spec/controllers/backoffice/avis_controller_spec.rb +++ b/spec/controllers/backoffice/avis_controller_spec.rb @@ -32,4 +32,38 @@ describe Backoffice::AvisController, type: :controller do end end + describe '#POST update' do + let(:gestionnaire){ create(:gestionnaire) } + let(:dossier){ create(:dossier, state: 'received') } + let(:avis){ create(:avis, dossier: dossier, gestionnaire: gestionnaire )} + + subject { post :update, params: { dossier_id: dossier.id, id: avis.id, avis: { answer: "Ok ce dossier est valide." } } } + + context 'when gestionnaire is not authenticated' do + it { is_expected.to redirect_to new_user_session_path } + it { expect(avis.answer).to be_nil } + end + + context 'when gestionnaire is authenticated' do + before do + sign_in gestionnaire + end + + context 'and is invited on dossier' do + it { is_expected.to redirect_to backoffice_dossier_path(dossier.id) } + it do + subject + expect(avis.reload.answer).to eq("Ok ce dossier est valide.") + end + end + + context 'but is not invited on dossier' do + let(:gestionnaire2) { create(:gestionnaire) } + let(:avis){ create(:avis, dossier: dossier, gestionnaire: gestionnaire2 )} + + it { expect{ subject }.to raise_error(ActiveRecord::RecordNotFound) } + end + end + end + end diff --git a/spec/controllers/backoffice/dossiers_controller_spec.rb b/spec/controllers/backoffice/dossiers_controller_spec.rb index 7ba92db57..169e976d6 100644 --- a/spec/controllers/backoffice/dossiers_controller_spec.rb +++ b/spec/controllers/backoffice/dossiers_controller_spec.rb @@ -109,6 +109,25 @@ describe Backoffice::DossiersController, type: :controller do it { expect(subject).to redirect_to('/backoffice') } end + + describe 'he can invite somebody for avis' do + render_views + + it { expect(subject.body).to include("Invitez une personne externe à consulter le dossier et à vous donner un avis sur celui ci.") } + end + + context 'and is invited on a dossier' do + let(:dossier_invited){ create(:dossier, procedure: create(:procedure)) } + let!(:avis){ create(:avis, dossier: dossier_invited, gestionnaire: gestionnaire) } + + subject { get :show, params: { id: dossier_invited.id } } + + render_views + + it { expect(subject.status).to eq(200) } + it { expect(subject.body).to include("Votre avis est sollicité sur le dossier") } + it { expect(subject.body).to_not include("Invitez une personne externe à consulter le dossier et à vous donner un avis sur celui ci.") } + end end context 'gestionnaire does not connected but dossier id is correct' do From efdac753c6f04a8764f1eadbbed959cd423d7579 Mon Sep 17 00:00:00 2001 From: Mathieu Magnin Date: Tue, 2 May 2017 15:37:06 +0200 Subject: [PATCH 09/20] When an Avis is created an email is sent to the Gestionnaire --- app/mailers/avis_mailer.rb | 9 +++++++ app/models/avis.rb | 6 +++++ .../you_are_invited_on_dossier.html.haml | 24 +++++++++++++++++++ spec/mailers/avis_mailer_spec.rb | 13 ++++++++++ spec/mailers/previews/avis_mailer_preview.rb | 8 +++++++ 5 files changed, 60 insertions(+) create mode 100644 app/mailers/avis_mailer.rb create mode 100644 app/views/avis_mailer/you_are_invited_on_dossier.html.haml create mode 100644 spec/mailers/avis_mailer_spec.rb create mode 100644 spec/mailers/previews/avis_mailer_preview.rb diff --git a/app/mailers/avis_mailer.rb b/app/mailers/avis_mailer.rb new file mode 100644 index 000000000..601ee464d --- /dev/null +++ b/app/mailers/avis_mailer.rb @@ -0,0 +1,9 @@ +class AvisMailer < ApplicationMailer + + def you_are_invited_on_dossier(avis) + @avis = avis + email = @avis.gestionnaire.try(:email) || @avis.email + mail(to: email, subject: "Donnez votre avis sur le dossier nº #{@avis.dossier.id} (#{@avis.dossier.procedure.libelle})") + end + +end diff --git a/app/models/avis.rb b/app/models/avis.rb index b63ca92ff..4a2b8520d 100644 --- a/app/models/avis.rb +++ b/app/models/avis.rb @@ -2,6 +2,8 @@ class Avis < ApplicationRecord belongs_to :dossier belongs_to :gestionnaire + after_create :notify_gestionnaire + scope :with_answer, -> { where.not(answer: nil) } scope :without_answer, -> { where(answer: nil) } scope :for_dossier, ->(dossier_id) { where(dossier_id: dossier_id) } @@ -10,4 +12,8 @@ class Avis < ApplicationRecord def email_to_display gestionnaire.try(:email) || email end + + def notify_gestionnaire + AvisMailer.you_are_invited_on_dossier(self).deliver_now + end end diff --git a/app/views/avis_mailer/you_are_invited_on_dossier.html.haml b/app/views/avis_mailer/you_are_invited_on_dossier.html.haml new file mode 100644 index 000000000..ac2403812 --- /dev/null +++ b/app/views/avis_mailer/you_are_invited_on_dossier.html.haml @@ -0,0 +1,24 @@ +%html + %body + %p + Bonjour, + %br + = "Vous avez été invité à donner votre avis sur le dossier nº #{@avis.dossier.id} de la procédure : #{@avis.dossier.procedure.libelle}." + %br + Message de votre interlocuteur : + + %p{ style: 'border: 1px solid grey' } + = @avis.introduction + + %p + = link_to "Connectez-vous pour donner votre avis", new_gestionnaire_session_url + + Bonne journée, + %br + %br + L'équipe Téléprocédures Simplifiées + %br + %br + %hr + %br + Merci de ne pas répondre à cet email. Postez directement vos questions dans votre dossier sur la plateforme. diff --git a/spec/mailers/avis_mailer_spec.rb b/spec/mailers/avis_mailer_spec.rb new file mode 100644 index 000000000..657a327a6 --- /dev/null +++ b/spec/mailers/avis_mailer_spec.rb @@ -0,0 +1,13 @@ +require "rails_helper" + +RSpec.describe AvisMailer, type: :mailer do + describe '.you_are_invited_on_dossier' do + let(:avis) { create(:avis) } + + subject { described_class.you_are_invited_on_dossier(avis) } + + it { expect(subject.subject).to eq("Donnez votre avis sur le dossier nº #{avis.dossier.id} (#{avis.dossier.procedure.libelle})") } + it { expect(subject.body).to include("Vous avez été invité à donner votre avis sur le dossier nº #{avis.dossier.id} de la procédure : #{avis.dossier.procedure.libelle}.") } + it { expect(subject.body).to include(avis.introduction) } + end +end diff --git a/spec/mailers/previews/avis_mailer_preview.rb b/spec/mailers/previews/avis_mailer_preview.rb new file mode 100644 index 000000000..c911615e6 --- /dev/null +++ b/spec/mailers/previews/avis_mailer_preview.rb @@ -0,0 +1,8 @@ +# Preview all emails at http://localhost:3000/rails/mailers/avis_mailer +class AvisMailerPreview < ActionMailer::Preview + + def you_are_invited_on_dossier + AvisMailer.you_are_invited_on_dossier(Avis.last) + end + +end From 4e064dbaeda7fcf88040488611fdf9595289945b Mon Sep 17 00:00:00 2001 From: Mathieu Magnin Date: Tue, 2 May 2017 16:13:09 +0200 Subject: [PATCH 10/20] Add a method to link multiple avis to a gestionnaire by his email --- app/models/avis.rb | 4 ++++ spec/models/avis_spec.rb | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/app/models/avis.rb b/app/models/avis.rb index 4a2b8520d..248d0c130 100644 --- a/app/models/avis.rb +++ b/app/models/avis.rb @@ -16,4 +16,8 @@ class Avis < ApplicationRecord def notify_gestionnaire AvisMailer.you_are_invited_on_dossier(self).deliver_now end + + def self.link_avis_to_gestionnaire(gestionnaire) + Avis.where(email: gestionnaire.email).update_all(email: nil, gestionnaire_id: gestionnaire.id) + end end diff --git a/spec/models/avis_spec.rb b/spec/models/avis_spec.rb index 7f10efcf2..f870d9e79 100644 --- a/spec/models/avis_spec.rb +++ b/spec/models/avis_spec.rb @@ -29,4 +29,26 @@ RSpec.describe Avis, type: :model do it { expect(subject).to eq([avis, avis3, avis2])} end end + + describe ".link_avis_to_gestionnaire" do + let(:gestionnaire){ create(:gestionnaire) } + + subject{ Avis.link_avis_to_gestionnaire(gestionnaire) } + + context 'when there are 2 avis linked by email to a gestionnaire' do + let!(:avis){ create(:avis, email: gestionnaire.email, gestionnaire: nil) } + let!(:avis2){ create(:avis, email: gestionnaire.email, gestionnaire: nil) } + + before do + subject + avis.reload + avis2.reload + end + + it { expect(avis.email).to be_nil } + it { expect(avis.gestionnaire).to eq(gestionnaire) } + it { expect(avis2.email).to be_nil } + it { expect(avis2.gestionnaire).to eq(gestionnaire) } + end + end end From aaf155df7232225338388f7ea355952c96d5b975 Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Fri, 12 May 2017 10:22:18 +0200 Subject: [PATCH 11/20] Avis: add sign_up logic for new tps gestionnaire --- .../stylesheets/new_design/avis_sign_up.scss | 92 +++++++++++++++++++ app/controllers/backoffice/avis_controller.rb | 15 ++- app/models/avis.rb | 5 + app/views/backoffice/avis/sign_up.html.haml | 15 +++ config/routes.rb | 2 + .../backoffice/avis_controller_spec.rb | 26 ++++++ spec/models/avis_spec.rb | 29 ++++++ 7 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 app/assets/stylesheets/new_design/avis_sign_up.scss create mode 100644 app/views/backoffice/avis/sign_up.html.haml diff --git a/app/assets/stylesheets/new_design/avis_sign_up.scss b/app/assets/stylesheets/new_design/avis_sign_up.scss new file mode 100644 index 000000000..10d6d64ee --- /dev/null +++ b/app/assets/stylesheets/new_design/avis_sign_up.scss @@ -0,0 +1,92 @@ +@import "typography"; +@import "colors"; + +.avis-sign-up { + display: flex; + + .left, + .right { + width: 50%; + padding: 60px 86px; + } + + .left { + p { + margin: auto; + max-width: 410px; + text-align: center; + } + + .description { + font-size: 30px; + line-height: 1.3; + } + + .dossier { + font-size: 18px; + font-weight: bold; + margin-top: 15px; + } + } + + .right { + background-color: $light-grey; + + h1 { + font-size: 36px; + font-weight: bold; + margin-bottom: 60px; + } + + form { + max-width: 420px; + } + + label, + input { + display: block; + width: 100%; + } + + label { + font-size: 14px; + line-height: 1.57; + margin: 24px 0 8px; + } + + input { + border: solid 1px $border-grey; + border-radius: 4px; + height: 56px; + padding: 0 15px; + font-family: Muli; + font-size: 14px; + + &:disabled { + background-color: $border-grey; + } + } + + button { + display: inline-block; + height: 60px; + line-height: 60px; + border: none; + border-radius: 60px; + background-color: $blue; + color: #FFFFFF; + font-size: 16px; + font-weight: bold; + text-align: center; + width: 100%; + margin: 55px 0; + + &:hover { + color: #FFFFFF; + text-decoration: none; + background-color: $light-blue; + cursor: pointer; + } + } + } +} diff --git a/app/controllers/backoffice/avis_controller.rb b/app/controllers/backoffice/avis_controller.rb index 2bd8a23b9..50cab0e5d 100644 --- a/app/controllers/backoffice/avis_controller.rb +++ b/app/controllers/backoffice/avis_controller.rb @@ -1,6 +1,7 @@ class Backoffice::AvisController < ApplicationController - before_action :authenticate_gestionnaire! + before_action :authenticate_gestionnaire!, except: [:sign_up] + before_action :check_avis_exists_and_email_belongs_to_avis, only: [:sign_up] def create avis = Avis.new(create_params) @@ -25,6 +26,13 @@ class Backoffice::AvisController < ApplicationController redirect_to backoffice_dossier_path(avis.dossier_id) end + def sign_up + @email = params[:email] + @dossier = Avis.includes(:dossier).find(params[:id]).dossier + + render layout: 'new_application' + end + private def dossier @@ -43,4 +51,9 @@ class Backoffice::AvisController < ApplicationController params.require(:avis).permit(:answer) end + def check_avis_exists_and_email_belongs_to_avis + if !Avis.avis_exists_and_email_belongs_to_avis?(params[:id], params[:email]) + redirect_to url_for(root_path) + end + end end diff --git a/app/models/avis.rb b/app/models/avis.rb index 248d0c130..afc6ec285 100644 --- a/app/models/avis.rb +++ b/app/models/avis.rb @@ -20,4 +20,9 @@ class Avis < ApplicationRecord def self.link_avis_to_gestionnaire(gestionnaire) Avis.where(email: gestionnaire.email).update_all(email: nil, gestionnaire_id: gestionnaire.id) end + + def self.avis_exists_and_email_belongs_to_avis?(avis_id, email) + avis = Avis.find_by(id: avis_id) + avis.present? && avis.email == email + end end diff --git a/app/views/backoffice/avis/sign_up.html.haml b/app/views/backoffice/avis/sign_up.html.haml new file mode 100644 index 000000000..c02191ce7 --- /dev/null +++ b/app/views/backoffice/avis/sign_up.html.haml @@ -0,0 +1,15 @@ +.avis-sign-up + .left + %p.description= @dossier.procedure.libelle + %p.dossier Dossier n°#{@dossier.id} + .right + %h1 Créez-vous un compte + + = form_for(Gestionnaire.new, url: { controller: 'backoffice/avis', action: :create_gestionnaire }, method: :post) do |f| + = f.label :email, 'Email' + = f.email_field :email, value: @email, disabled: true + + = f.label :password, 'Mot de passe' + = f.password_field :password, autofocus: true, required: true, placeholder: '8 caractères minimum' + + %button Créer un compte diff --git a/config/routes.rb b/config/routes.rb index 16fadf98d..3911fd3a1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -30,6 +30,8 @@ Rails.application.routes.draw do put '/gestionnaires' => 'gestionnaires/registrations#update', :as => 'gestionnaires_registration' end + get 'avis/:id/sign_up/email/:email' => 'backoffice/avis#sign_up', constraints: { email: /.*/ }, as: 'avis_sign_up' + devise_scope :administrateur do get '/administrateurs/sign_in/demo' => 'administrateurs/sessions#demo' end diff --git a/spec/controllers/backoffice/avis_controller_spec.rb b/spec/controllers/backoffice/avis_controller_spec.rb index d3731e63c..055fb8be8 100644 --- a/spec/controllers/backoffice/avis_controller_spec.rb +++ b/spec/controllers/backoffice/avis_controller_spec.rb @@ -66,4 +66,30 @@ describe Backoffice::AvisController, type: :controller do end end + describe '.sign_up' do + let(:invited_email) { 'invited@avis.com' } + let(:dossier) { create(:dossier) } + let!(:avis) { Avis.create(email: invited_email, dossier: dossier) } + let(:invitations_email) { true } + + before do + expect(Avis).to receive(:avis_exists_and_email_belongs_to_avis?) + .with(avis.id.to_s, invited_email) + .and_return(invitations_email) + get :sign_up, params: { id: avis.id, email: invited_email } + end + + context 'when the email belongs to the invitation' do + it { expect(subject.status).to eq(200) } + it { expect(assigns(:email)).to eq(invited_email) } + it { expect(assigns(:dossier)).to eq(dossier) } + end + + context 'when the email does not belong to the invitation' do + let(:invitations_email) { false } + + it { is_expected.to redirect_to root_path } + end + end + end diff --git a/spec/models/avis_spec.rb b/spec/models/avis_spec.rb index f870d9e79..47a39c82e 100644 --- a/spec/models/avis_spec.rb +++ b/spec/models/avis_spec.rb @@ -51,4 +51,33 @@ RSpec.describe Avis, type: :model do it { expect(avis2.gestionnaire).to eq(gestionnaire) } end end + + describe '.avis_exists_and_email_belongs_to_avis' do + let(:dossier) { create(:dossier) } + let(:invited_email) { 'invited@avis.com' } + let!(:avis) { Avis.create(email: invited_email, dossier: dossier) } + + subject { Avis.avis_exists_and_email_belongs_to_avis?(avis_id, email) } + + context 'when the avis is unknown' do + let(:avis_id) { 666 } + let(:email) { 'unknown@mystery.com' } + + it { is_expected.to be false } + end + + context 'when the avis is known' do + let(:avis_id) { avis.id } + + context 'when the email belongs to the invitation' do + let(:email) { invited_email } + it { is_expected.to be true } + end + + context 'when the email is unknown' do + let(:email) { 'unknown@mystery.com' } + it { is_expected.to be false } + end + end + end end From 842999d229e82902f37d229e69eee8a41f75d3c3 Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Fri, 12 May 2017 10:22:53 +0200 Subject: [PATCH 12/20] Avis: add create_gestionnaire logic --- app/controllers/backoffice/avis_controller.rb | 21 +++++++- config/routes.rb | 1 + .../backoffice/avis_controller_spec.rb | 48 +++++++++++++++++++ 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/app/controllers/backoffice/avis_controller.rb b/app/controllers/backoffice/avis_controller.rb index 50cab0e5d..69e481dba 100644 --- a/app/controllers/backoffice/avis_controller.rb +++ b/app/controllers/backoffice/avis_controller.rb @@ -1,7 +1,7 @@ class Backoffice::AvisController < ApplicationController - before_action :authenticate_gestionnaire!, except: [:sign_up] - before_action :check_avis_exists_and_email_belongs_to_avis, only: [:sign_up] + before_action :authenticate_gestionnaire!, except: [:sign_up, :create_gestionnaire] + before_action :check_avis_exists_and_email_belongs_to_avis, only: [:sign_up, :create_gestionnaire] def create avis = Avis.new(create_params) @@ -33,6 +33,23 @@ class Backoffice::AvisController < ApplicationController render layout: 'new_application' end + def create_gestionnaire + email = params[:email] + password = params['gestionnaire']['password'] + + gestionnaire = Gestionnaire.new(email: email, password: password) + + if gestionnaire.save + sign_in(gestionnaire, scope: :gestionnaire) + Avis.link_avis_to_gestionnaire(gestionnaire) + avis = Avis.find(params[:id]) + redirect_to url_for(backoffice_dossier_path(avis.dossier_id)) + else + flash[:alert] = gestionnaire.errors.full_messages.join('
') + redirect_to url_for(avis_sign_up_path(params[:id], email)) + end + end + private def dossier diff --git a/config/routes.rb b/config/routes.rb index 3911fd3a1..8e2c90217 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -31,6 +31,7 @@ Rails.application.routes.draw do end get 'avis/:id/sign_up/email/:email' => 'backoffice/avis#sign_up', constraints: { email: /.*/ }, as: 'avis_sign_up' + post 'avis/:id/sign_up/email/:email' => 'backoffice/avis#create_gestionnaire', constraints: { email: /.*/ } devise_scope :administrateur do get '/administrateurs/sign_in/demo' => 'administrateurs/sessions#demo' diff --git a/spec/controllers/backoffice/avis_controller_spec.rb b/spec/controllers/backoffice/avis_controller_spec.rb index 055fb8be8..6823e9a00 100644 --- a/spec/controllers/backoffice/avis_controller_spec.rb +++ b/spec/controllers/backoffice/avis_controller_spec.rb @@ -92,4 +92,52 @@ describe Backoffice::AvisController, type: :controller do end end + describe '.create_gestionnaire' do + let(:invited_email) { 'invited@avis.com' } + let(:dossier) { create(:dossier) } + let!(:avis) { Avis.create(email: invited_email, dossier: dossier) } + let(:avis_id) { avis.id } + let(:password) { '12345678' } + let(:created_gestionnaire) { Gestionnaire.find_by(email: invited_email) } + let(:invitations_email) { true } + + before do + allow(Avis).to receive(:link_avis_to_gestionnaire) + expect(Avis).to receive(:avis_exists_and_email_belongs_to_avis?) + .with(avis_id.to_s, invited_email) + .and_return(invitations_email) + + post :create_gestionnaire, params: { id: avis_id, + email: invited_email, + gestionnaire: { + password: password + } } + end + + context 'when the email does not belong to the invitation' do + let(:invitations_email) { false } + + it { is_expected.to redirect_to root_path } + end + + context 'when the email belongs to the invitation' do + context 'when the gestionnaire creation succeeds' do + it { expect(created_gestionnaire).to be_present } + it { expect(created_gestionnaire.valid_password?(password)).to be true } + + it { expect(Avis).to have_received(:link_avis_to_gestionnaire) } + + it { expect(subject.current_gestionnaire).to eq(created_gestionnaire) } + it { is_expected.to redirect_to backoffice_dossier_path(dossier) } + end + + context 'when the gestionnaire creation fails' do + let(:password) { '' } + + it { expect(created_gestionnaire).to be_nil } + it { is_expected.to redirect_to avis_sign_up_path(avis_id, invited_email) } + it { expect(flash.alert).to eq('Password : Le mot de passe est vide') } + end + end + end end From 516a8c28c5074dab3568102a22afbb691b424b52 Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Fri, 5 May 2017 16:02:20 +0200 Subject: [PATCH 13/20] Avis: change invitation mail when the recipient is not tps --- .../avis_mailer/you_are_invited_on_dossier.html.haml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/views/avis_mailer/you_are_invited_on_dossier.html.haml b/app/views/avis_mailer/you_are_invited_on_dossier.html.haml index ac2403812..76c9f4149 100644 --- a/app/views/avis_mailer/you_are_invited_on_dossier.html.haml +++ b/app/views/avis_mailer/you_are_invited_on_dossier.html.haml @@ -10,8 +10,12 @@ %p{ style: 'border: 1px solid grey' } = @avis.introduction - %p - = link_to "Connectez-vous pour donner votre avis", new_gestionnaire_session_url + - if @avis.gestionnaire.present? + %p + = link_to "Connectez-vous pour donner votre avis", new_gestionnaire_session_url + - else + %p + = link_to "Inscrivez-vous pour donner votre avis", avis_sign_up_url(@avis.id, @avis.email) Bonne journée, %br From f9aee06040d64288ebbe3b5a70a4a2239480149c Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Fri, 5 May 2017 17:38:43 +0200 Subject: [PATCH 14/20] AvisController: add redirection logic for various login cases --- app/controllers/backoffice/avis_controller.rb | 15 +++++ .../backoffice/avis_controller_spec.rb | 61 +++++++++++++++---- 2 files changed, 64 insertions(+), 12 deletions(-) diff --git a/app/controllers/backoffice/avis_controller.rb b/app/controllers/backoffice/avis_controller.rb index 69e481dba..ded272fae 100644 --- a/app/controllers/backoffice/avis_controller.rb +++ b/app/controllers/backoffice/avis_controller.rb @@ -1,6 +1,7 @@ class Backoffice::AvisController < ApplicationController before_action :authenticate_gestionnaire!, except: [:sign_up, :create_gestionnaire] + before_action :redirect_if_no_sign_up_needed, only: [:sign_up] before_action :check_avis_exists_and_email_belongs_to_avis, only: [:sign_up, :create_gestionnaire] def create @@ -68,6 +69,20 @@ class Backoffice::AvisController < ApplicationController params.require(:avis).permit(:answer) end + def redirect_if_no_sign_up_needed + avis = Avis.find(params[:id]) + + if current_gestionnaire.present? + # a gestionnaire is authenticated ... lets see if it can view the dossier + + redirect_to backoffice_dossier_url(avis.dossier) + elsif avis.gestionnaire.present? && avis.gestionnaire.email == params[:email] + # the avis gestionnaire has already signed up and it sould sign in + + redirect_to new_gestionnaire_session_url + end + end + def check_avis_exists_and_email_belongs_to_avis if !Avis.avis_exists_and_email_belongs_to_avis?(params[:id], params[:email]) redirect_to url_for(root_path) diff --git a/spec/controllers/backoffice/avis_controller_spec.rb b/spec/controllers/backoffice/avis_controller_spec.rb index 6823e9a00..08f1d5e82 100644 --- a/spec/controllers/backoffice/avis_controller_spec.rb +++ b/spec/controllers/backoffice/avis_controller_spec.rb @@ -72,23 +72,60 @@ describe Backoffice::AvisController, type: :controller do let!(:avis) { Avis.create(email: invited_email, dossier: dossier) } let(:invitations_email) { true } - before do - expect(Avis).to receive(:avis_exists_and_email_belongs_to_avis?) - .with(avis.id.to_s, invited_email) - .and_return(invitations_email) - get :sign_up, params: { id: avis.id, email: invited_email } + context 'when the new gestionnaire has never signed up' do + before do + expect(Avis).to receive(:avis_exists_and_email_belongs_to_avis?) + .with(avis.id.to_s, invited_email) + .and_return(invitations_email) + get :sign_up, params: { id: avis.id, email: invited_email } + end + + context 'when the email belongs to the invitation' do + it { expect(subject.status).to eq(200) } + it { expect(assigns(:email)).to eq(invited_email) } + it { expect(assigns(:dossier)).to eq(dossier) } + end + + context 'when the email does not belong to the invitation' do + let(:invitations_email) { false } + + it { is_expected.to redirect_to root_path } + end end - context 'when the email belongs to the invitation' do - it { expect(subject.status).to eq(200) } - it { expect(assigns(:email)).to eq(invited_email) } - it { expect(assigns(:dossier)).to eq(dossier) } + context 'when the gestionnaire has already signed up and belongs to the invitation' do + let(:gestionnaire) { create(:gestionnaire, email: invited_email) } + let!(:avis) { Avis.create(dossier: dossier, gestionnaire: gestionnaire) } + + context 'when the gestionnaire is authenticated' do + before do + sign_in gestionnaire + get :sign_up, params: { id: avis.id, email: invited_email } + end + + it { is_expected.to redirect_to backoffice_dossier_url(avis.dossier) } + end + + context 'when the gestionnaire is not authenticated' do + before do + get :sign_up, params: { id: avis.id, email: invited_email } + end + + it { is_expected.to redirect_to new_gestionnaire_session_url } + end end - context 'when the email does not belong to the invitation' do - let(:invitations_email) { false } + context 'when the gestionnaire has already signed up / is authenticated and does not belong to the invitation' do + let(:gestionnaire) { create(:gestionnaire, email: 'other@gmail.com') } + let!(:avis) { Avis.create(email: invited_email, dossier: dossier) } - it { is_expected.to redirect_to root_path } + before do + sign_in gestionnaire + get :sign_up, params: { id: avis.id, email: invited_email } + end + + # redirected to dossier but then the gestionnaire gonna be banished ! + it { is_expected.to redirect_to backoffice_dossier_url(avis.dossier) } end end From 612a8c4b91fbd04e59564e69e618539274ff5045 Mon Sep 17 00:00:00 2001 From: Mathieu Magnin Date: Thu, 18 May 2017 16:14:26 +0200 Subject: [PATCH 15/20] Confirm with flash after avis is sent --- app/controllers/backoffice/avis_controller.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/controllers/backoffice/avis_controller.rb b/app/controllers/backoffice/avis_controller.rb index ded272fae..ed59a671b 100644 --- a/app/controllers/backoffice/avis_controller.rb +++ b/app/controllers/backoffice/avis_controller.rb @@ -8,13 +8,16 @@ class Backoffice::AvisController < ApplicationController avis = Avis.new(create_params) avis.dossier = dossier - gestionnaire = Gestionnaire.find_by(email: create_params[:email]) + email = create_params[:email] + gestionnaire = Gestionnaire.find_by(email: email) if gestionnaire avis.gestionnaire = gestionnaire avis.email = nil end - avis.save + if avis.save + flash[:notice] = "Votre demande d'avis a bien été envoyée à #{email}" + end redirect_to backoffice_dossier_path(dossier) end From 3483ec075b468f67ae4df8abd2ba569fad2e9713 Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Wed, 24 May 2017 17:51:43 +0200 Subject: [PATCH 16/20] DossierController: extract dossier_id from params[:id] --- app/controllers/backoffice/dossiers_controller.rb | 5 +++-- spec/controllers/backoffice/dossiers_controller_spec.rb | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/controllers/backoffice/dossiers_controller.rb b/app/controllers/backoffice/dossiers_controller.rb index 14f04fe45..5c9b7f4ca 100644 --- a/app/controllers/backoffice/dossiers_controller.rb +++ b/app/controllers/backoffice/dossiers_controller.rb @@ -23,7 +23,8 @@ class Backoffice::DossiersController < Backoffice::DossiersListController end def show - create_dossier_facade params[:id] + dossier_id = params[:id] + create_dossier_facade dossier_id unless @facade.nil? @champs_private = @facade.champs_private @@ -31,7 +32,7 @@ class Backoffice::DossiersController < Backoffice::DossiersListController @headers_private = @champs_private.select { |champ| champ.type_champ == 'header_section' } end - Notification.where(dossier_id: params[:id].to_i).update_all already_read: true + Notification.where(dossier_id: dossier_id).update_all already_read: true @new_avis = Avis.new(introduction: "Bonjour, merci de me donner votre avis sur ce dossier.") end diff --git a/spec/controllers/backoffice/dossiers_controller_spec.rb b/spec/controllers/backoffice/dossiers_controller_spec.rb index 169e976d6..7a647f51c 100644 --- a/spec/controllers/backoffice/dossiers_controller_spec.rb +++ b/spec/controllers/backoffice/dossiers_controller_spec.rb @@ -97,7 +97,7 @@ describe Backoffice::DossiersController, type: :controller do describe 'all notifications unread are changed' do it do - expect(Notification).to receive(:where).with(dossier_id: dossier_id).and_return(Notification::ActiveRecord_Relation) + expect(Notification).to receive(:where).with(dossier_id: dossier_id.to_s).and_return(Notification::ActiveRecord_Relation) expect(Notification::ActiveRecord_Relation).to receive(:update_all).with(already_read: true).and_return(true) subject From 34a7905828f133082be2305095dc927428b43a18 Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Wed, 24 May 2017 17:55:00 +0200 Subject: [PATCH 17/20] DossierController: giving an advice does not remove the notifications --- app/controllers/backoffice/dossiers_controller.rb | 6 +++++- spec/controllers/backoffice/dossiers_controller_spec.rb | 7 +++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/app/controllers/backoffice/dossiers_controller.rb b/app/controllers/backoffice/dossiers_controller.rb index 5c9b7f4ca..8cc2260ae 100644 --- a/app/controllers/backoffice/dossiers_controller.rb +++ b/app/controllers/backoffice/dossiers_controller.rb @@ -32,7 +32,11 @@ class Backoffice::DossiersController < Backoffice::DossiersListController @headers_private = @champs_private.select { |champ| champ.type_champ == 'header_section' } end - Notification.where(dossier_id: dossier_id).update_all already_read: true + # if the current_gestionnaire does not own the dossier, it is here to give an advice + # and it should not remove the notifications + if current_gestionnaire.dossiers.find_by(id: dossier_id).present? + Notification.where(dossier_id: dossier_id).update_all(already_read: true) + end @new_avis = Avis.new(introduction: "Bonjour, merci de me donner votre avis sur ce dossier.") end diff --git a/spec/controllers/backoffice/dossiers_controller_spec.rb b/spec/controllers/backoffice/dossiers_controller_spec.rb index 7a647f51c..a5889ec9f 100644 --- a/spec/controllers/backoffice/dossiers_controller_spec.rb +++ b/spec/controllers/backoffice/dossiers_controller_spec.rb @@ -127,6 +127,13 @@ describe Backoffice::DossiersController, type: :controller do it { expect(subject.status).to eq(200) } it { expect(subject.body).to include("Votre avis est sollicité sur le dossier") } it { expect(subject.body).to_not include("Invitez une personne externe à consulter le dossier et à vous donner un avis sur celui ci.") } + + describe 'the notifications are not marked as read' do + it do + expect(Notification).not_to receive(:where) + subject + end + end end end From cdcd5b951f1175a9c16d39d22d752b1baee4d92d Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Mon, 22 May 2017 17:10:17 +0200 Subject: [PATCH 18/20] AvisController: add a notification when a avis has been received --- app/controllers/backoffice/avis_controller.rb | 1 + app/models/notification.rb | 3 ++- app/services/notification_service.rb | 2 ++ spec/controllers/backoffice/avis_controller_spec.rb | 6 ++++++ 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/app/controllers/backoffice/avis_controller.rb b/app/controllers/backoffice/avis_controller.rb index ed59a671b..650bce8be 100644 --- a/app/controllers/backoffice/avis_controller.rb +++ b/app/controllers/backoffice/avis_controller.rb @@ -24,6 +24,7 @@ class Backoffice::AvisController < ApplicationController def update if avis.update(update_params) + NotificationService.new('avis', params[:dossier_id]).notify flash[:notice] = 'Merci, votre avis a été enregistré.' end diff --git a/app/models/notification.rb b/app/models/notification.rb index af36da06e..0740ee823 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -5,7 +5,8 @@ class Notification < ActiveRecord::Base cerfa: 'cerfa', piece_justificative: 'piece_justificative', champs: 'champs', - submitted: 'submitted' + submitted: 'submitted', + avis: 'avis' } scope :unread, -> { where(already_read: false) } end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 18415ebbd..a401064cf 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -35,6 +35,8 @@ class NotificationService attribut when 'submitted' "Le dossier nº #{@dossier_id} a été déposé." + when 'avis' + 'Un nouvel avis a été rendu' else 'Notification par défaut' end diff --git a/spec/controllers/backoffice/avis_controller_spec.rb b/spec/controllers/backoffice/avis_controller_spec.rb index 08f1d5e82..60fba087b 100644 --- a/spec/controllers/backoffice/avis_controller_spec.rb +++ b/spec/controllers/backoffice/avis_controller_spec.rb @@ -39,6 +39,11 @@ describe Backoffice::AvisController, type: :controller do subject { post :update, params: { dossier_id: dossier.id, id: avis.id, avis: { answer: "Ok ce dossier est valide." } } } + before :each do + notification = double('notification', notify: true) + allow(NotificationService).to receive(:new).and_return(notification) + end + context 'when gestionnaire is not authenticated' do it { is_expected.to redirect_to new_user_session_path } it { expect(avis.answer).to be_nil } @@ -54,6 +59,7 @@ describe Backoffice::AvisController, type: :controller do it do subject expect(avis.reload.answer).to eq("Ok ce dossier est valide.") + expect(NotificationService).to have_received(:new).at_least(:once) end end From 23e57f5cc469ac0c5c60632178f10b83d95bacf3 Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Mon, 22 May 2017 17:45:49 +0200 Subject: [PATCH 19/20] Navbar: add deprecation warning for invitations --- .../_navbar_backoffice_dossierscontroller_show.html.haml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/views/layouts/navbars/_navbar_backoffice_dossierscontroller_show.html.haml b/app/views/layouts/navbars/_navbar_backoffice_dossierscontroller_show.html.haml index 2c72a80fe..6604a98c1 100644 --- a/app/views/layouts/navbars/_navbar_backoffice_dossierscontroller_show.html.haml +++ b/app/views/layouts/navbars/_navbar_backoffice_dossierscontroller_show.html.haml @@ -28,6 +28,8 @@ - else = t('dynamics.dossiers.followers.empty') %h4= t('dynamics.dossiers.invites.title') + %p + %b Attention, les invitations sur les dossiers vont disparaître en faveur des avis externes situés en bas de la page %ul - unless @facade.invites.empty? - @facade.invites.each do |invite| From 64f7cab3cf7ff6b61536e3af2e8f456c3b72bd59 Mon Sep 17 00:00:00 2001 From: Simon Lehericey Date: Tue, 23 May 2017 13:28:17 +0200 Subject: [PATCH 20/20] Avis: add claimant gestionnaire to track who asks for an avis --- app/controllers/backoffice/avis_controller.rb | 2 +- app/models/avis.rb | 1 + .../avis_mailer/you_are_invited_on_dossier.html.haml | 2 +- db/migrate/20170523092900_add_claimant_to_avis.rb | 5 +++++ db/schema.rb | 5 ++++- spec/controllers/backoffice/avis_controller_spec.rb | 8 ++++---- spec/factories/avis.rb | 6 ++++++ spec/mailers/avis_mailer_spec.rb | 3 ++- spec/models/avis_spec.rb | 12 +++++++++--- 9 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 db/migrate/20170523092900_add_claimant_to_avis.rb diff --git a/app/controllers/backoffice/avis_controller.rb b/app/controllers/backoffice/avis_controller.rb index 650bce8be..4d77496d2 100644 --- a/app/controllers/backoffice/avis_controller.rb +++ b/app/controllers/backoffice/avis_controller.rb @@ -5,7 +5,7 @@ class Backoffice::AvisController < ApplicationController before_action :check_avis_exists_and_email_belongs_to_avis, only: [:sign_up, :create_gestionnaire] def create - avis = Avis.new(create_params) + avis = Avis.new(create_params.merge(claimant: current_gestionnaire)) avis.dossier = dossier email = create_params[:email] diff --git a/app/models/avis.rb b/app/models/avis.rb index afc6ec285..59eff74fc 100644 --- a/app/models/avis.rb +++ b/app/models/avis.rb @@ -1,6 +1,7 @@ class Avis < ApplicationRecord belongs_to :dossier belongs_to :gestionnaire + belongs_to :claimant, class_name: 'Gestionnaire' after_create :notify_gestionnaire diff --git a/app/views/avis_mailer/you_are_invited_on_dossier.html.haml b/app/views/avis_mailer/you_are_invited_on_dossier.html.haml index 76c9f4149..26b129266 100644 --- a/app/views/avis_mailer/you_are_invited_on_dossier.html.haml +++ b/app/views/avis_mailer/you_are_invited_on_dossier.html.haml @@ -3,7 +3,7 @@ %p Bonjour, %br - = "Vous avez été invité à donner votre avis sur le dossier nº #{@avis.dossier.id} de la procédure : #{@avis.dossier.procedure.libelle}." + = "Vous avez été invité par #{@avis.claimant.email} à donner votre avis sur le dossier nº #{@avis.dossier.id} de la procédure : #{@avis.dossier.procedure.libelle}." %br Message de votre interlocuteur : diff --git a/db/migrate/20170523092900_add_claimant_to_avis.rb b/db/migrate/20170523092900_add_claimant_to_avis.rb new file mode 100644 index 000000000..c8a34e182 --- /dev/null +++ b/db/migrate/20170523092900_add_claimant_to_avis.rb @@ -0,0 +1,5 @@ +class AddClaimantToAvis < ActiveRecord::Migration[5.0] + def change + add_reference :avis, :claimant, foreign_key: { to_table: :gestionnaires }, null: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 55f008b87..796086d82 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: 20170425100757) do +ActiveRecord::Schema.define(version: 20170523092900) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -79,6 +79,8 @@ ActiveRecord::Schema.define(version: 20170425100757) do t.integer "dossier_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.integer "claimant_id", null: false + t.index ["claimant_id"], name: "index_avis_on_claimant_id", using: :btree t.index ["dossier_id"], name: "index_avis_on_dossier_id", using: :btree t.index ["gestionnaire_id"], name: "index_avis_on_gestionnaire_id", using: :btree end @@ -446,6 +448,7 @@ ActiveRecord::Schema.define(version: 20170425100757) do t.index ["procedure_id"], name: "index_without_continuation_mails_on_procedure_id", using: :btree end + add_foreign_key "avis", "gestionnaires", column: "claimant_id" add_foreign_key "cerfas", "dossiers" add_foreign_key "closed_mails", "procedures" add_foreign_key "commentaires", "dossiers" diff --git a/spec/controllers/backoffice/avis_controller_spec.rb b/spec/controllers/backoffice/avis_controller_spec.rb index 60fba087b..c1af9658b 100644 --- a/spec/controllers/backoffice/avis_controller_spec.rb +++ b/spec/controllers/backoffice/avis_controller_spec.rb @@ -75,7 +75,7 @@ describe Backoffice::AvisController, type: :controller do describe '.sign_up' do let(:invited_email) { 'invited@avis.com' } let(:dossier) { create(:dossier) } - let!(:avis) { Avis.create(email: invited_email, dossier: dossier) } + let!(:avis) { create(:avis, email: invited_email, dossier: dossier) } let(:invitations_email) { true } context 'when the new gestionnaire has never signed up' do @@ -101,7 +101,7 @@ describe Backoffice::AvisController, type: :controller do context 'when the gestionnaire has already signed up and belongs to the invitation' do let(:gestionnaire) { create(:gestionnaire, email: invited_email) } - let!(:avis) { Avis.create(dossier: dossier, gestionnaire: gestionnaire) } + let!(:avis) { create(:avis, dossier: dossier, gestionnaire: gestionnaire) } context 'when the gestionnaire is authenticated' do before do @@ -123,7 +123,7 @@ describe Backoffice::AvisController, type: :controller do context 'when the gestionnaire has already signed up / is authenticated and does not belong to the invitation' do let(:gestionnaire) { create(:gestionnaire, email: 'other@gmail.com') } - let!(:avis) { Avis.create(email: invited_email, dossier: dossier) } + let!(:avis) { create(:avis, email: invited_email, dossier: dossier) } before do sign_in gestionnaire @@ -138,7 +138,7 @@ describe Backoffice::AvisController, type: :controller do describe '.create_gestionnaire' do let(:invited_email) { 'invited@avis.com' } let(:dossier) { create(:dossier) } - let!(:avis) { Avis.create(email: invited_email, dossier: dossier) } + let!(:avis) { create(:avis, email: invited_email, dossier: dossier) } let(:avis_id) { avis.id } let(:password) { '12345678' } let(:created_gestionnaire) { Gestionnaire.find_by(email: invited_email) } diff --git a/spec/factories/avis.rb b/spec/factories/avis.rb index c69371734..7568cdfe9 100644 --- a/spec/factories/avis.rb +++ b/spec/factories/avis.rb @@ -13,5 +13,11 @@ FactoryGirl.define do avis.dossier = create :dossier end end + + before(:create) do |avis, _evaluator| + unless avis.claimant + avis.claimant = create :gestionnaire + end + end end end diff --git a/spec/mailers/avis_mailer_spec.rb b/spec/mailers/avis_mailer_spec.rb index 657a327a6..cc5320d7a 100644 --- a/spec/mailers/avis_mailer_spec.rb +++ b/spec/mailers/avis_mailer_spec.rb @@ -7,7 +7,8 @@ RSpec.describe AvisMailer, type: :mailer do subject { described_class.you_are_invited_on_dossier(avis) } it { expect(subject.subject).to eq("Donnez votre avis sur le dossier nº #{avis.dossier.id} (#{avis.dossier.procedure.libelle})") } - it { expect(subject.body).to include("Vous avez été invité à donner votre avis sur le dossier nº #{avis.dossier.id} de la procédure : #{avis.dossier.procedure.libelle}.") } + it { expect(subject.body).to include("Vous avez été invité par #{avis.claimant.email} à donner votre avis sur le dossier nº #{avis.dossier.id} de la procédure : #{avis.dossier.procedure.libelle}.") } it { expect(subject.body).to include(avis.introduction) } + end end diff --git a/spec/models/avis_spec.rb b/spec/models/avis_spec.rb index 47a39c82e..231210158 100644 --- a/spec/models/avis_spec.rb +++ b/spec/models/avis_spec.rb @@ -1,9 +1,15 @@ require 'rails_helper' RSpec.describe Avis, type: :model do + let(:claimant) { create(:gestionnaire) } + describe '.email_to_display' do let(:invited_email) { 'invited@avis.com' } - let!(:avis) { Avis.create(email: invited_email, dossier: create(:dossier)) } + let!(:avis) do + avis = create(:avis, email: invited_email, dossier: create(:dossier)) + avis.gestionnaire = nil + avis + end subject { avis.email_to_display } @@ -12,7 +18,7 @@ RSpec.describe Avis, type: :model do end context 'when gestionnaire is known' do - let!(:avis) { Avis.create(email: nil, gestionnaire: create(:gestionnaire), dossier: create(:dossier)) } + let!(:avis) { create(:avis, email: nil, gestionnaire: create(:gestionnaire), dossier: create(:dossier)) } it{ is_expected.to eq(avis.gestionnaire.email) } end @@ -55,7 +61,7 @@ RSpec.describe Avis, type: :model do describe '.avis_exists_and_email_belongs_to_avis' do let(:dossier) { create(:dossier) } let(:invited_email) { 'invited@avis.com' } - let!(:avis) { Avis.create(email: invited_email, dossier: dossier) } + let!(:avis) { create(:avis, email: invited_email, dossier: dossier) } subject { Avis.avis_exists_and_email_belongs_to_avis?(avis_id, email) }