add expert logic
This commit is contained in:
parent
3cfbe38a8b
commit
d2ab2debb6
15 changed files with 311 additions and 3 deletions
|
@ -20,7 +20,7 @@ class ApplicationController < ActionController::Base
|
|||
before_action :setup_tracking
|
||||
before_action :set_locale
|
||||
|
||||
helper_method :multiple_devise_profile_connect?, :instructeur_signed_in?, :current_instructeur,
|
||||
helper_method :multiple_devise_profile_connect?, :instructeur_signed_in?, :current_instructeur, :current_expert, :expert_signed_in?,
|
||||
:administrateur_signed_in?, :current_administrateur, :current_account
|
||||
|
||||
def staging_authenticate
|
||||
|
@ -32,7 +32,9 @@ class ApplicationController < ActionController::Base
|
|||
def multiple_devise_profile_connect?
|
||||
user_signed_in? && instructeur_signed_in? ||
|
||||
instructeur_signed_in? && administrateur_signed_in? ||
|
||||
user_signed_in? && administrateur_signed_in?
|
||||
instructeur_signed_in? && expert_signed_in? ||
|
||||
user_signed_in? && administrateur_signed_in? ||
|
||||
user_signed_in? && expert_signed_in?
|
||||
end
|
||||
|
||||
def current_instructeur
|
||||
|
@ -51,6 +53,14 @@ class ApplicationController < ActionController::Base
|
|||
current_administrateur.present?
|
||||
end
|
||||
|
||||
def current_expert
|
||||
current_user&.expert
|
||||
end
|
||||
|
||||
def expert_signed_in?
|
||||
current_expert.present?
|
||||
end
|
||||
|
||||
def current_account
|
||||
{
|
||||
administrateur: current_administrateur,
|
||||
|
@ -70,6 +80,8 @@ class ApplicationController < ActionController::Base
|
|||
def authenticate_logged_user!
|
||||
if instructeur_signed_in?
|
||||
authenticate_instructeur!
|
||||
elsif expert_signed_in?
|
||||
authenticate_expert!
|
||||
elsif administrateur_signed_in?
|
||||
authenticate_administrateur!
|
||||
else
|
||||
|
@ -83,6 +95,12 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
end
|
||||
|
||||
def authenticate_expert!
|
||||
if !expert_signed_in?
|
||||
redirect_to new_user_session_path
|
||||
end
|
||||
end
|
||||
|
||||
def authenticate_administrateur!
|
||||
if !administrateur_signed_in?
|
||||
redirect_to new_user_session_path
|
||||
|
|
59
app/controllers/experts/avis_controller.rb
Normal file
59
app/controllers/experts/avis_controller.rb
Normal file
|
@ -0,0 +1,59 @@
|
|||
module Experts
|
||||
class AvisController < ExpertController
|
||||
include CreateAvisConcern
|
||||
|
||||
before_action :authenticate_expert!, except: [:sign_up, :create_instructeur]
|
||||
before_action :check_if_avis_revoked, only: [:show]
|
||||
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_instructeur]
|
||||
before_action :set_avis_and_dossier, only: [:show, :instruction, :messagerie, :create_commentaire, :update]
|
||||
|
||||
A_DONNER_STATUS = 'a-donner'
|
||||
DONNES_STATUS = 'donnes'
|
||||
|
||||
def index
|
||||
avis = current_expert.avis.includes(dossier: [groupe_instructeur: :procedure])
|
||||
@avis_by_procedure = avis.to_a.group_by(&:procedure)
|
||||
end
|
||||
|
||||
def procedure
|
||||
@procedure = Procedure.find(params[:procedure_id])
|
||||
expert_avis = current_expert.avis.includes(:dossier).where(dossiers: { groupe_instructeur: GroupeInstructeur.where(procedure: @procedure.id) })
|
||||
@avis_a_donner = expert_avis.without_answer
|
||||
@avis_donnes = expert_avis.with_answer
|
||||
|
||||
@statut = params[:statut].presence || A_DONNER_STATUS
|
||||
|
||||
@avis = case @statut
|
||||
when A_DONNER_STATUS
|
||||
@avis_a_donner
|
||||
when DONNES_STATUS
|
||||
@avis_donnes
|
||||
end
|
||||
|
||||
@avis = @avis.page([params[:page].to_i, 1].max)
|
||||
end
|
||||
|
||||
def show
|
||||
end
|
||||
|
||||
def instruction
|
||||
@new_avis = Avis.new
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_if_avis_revoked
|
||||
avis = Avis.find(params[:id])
|
||||
if avis.revoked?
|
||||
flash.alert = "Vous n'avez plus accès à ce dossier."
|
||||
redirect_to url_for(root_path)
|
||||
end
|
||||
end
|
||||
|
||||
def set_avis_and_dossier
|
||||
@avis = Avis.find(params[:id])
|
||||
@dossier = @avis.dossier
|
||||
end
|
||||
end
|
||||
end
|
9
app/controllers/experts/expert_controller.rb
Normal file
9
app/controllers/experts/expert_controller.rb
Normal file
|
@ -0,0 +1,9 @@
|
|||
module Experts
|
||||
class ExpertController < ApplicationController
|
||||
before_action :authenticate_expert!
|
||||
|
||||
def nav_bar_profile
|
||||
:expert
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,7 +1,6 @@
|
|||
module Instructeurs
|
||||
class ProceduresController < InstructeurController
|
||||
before_action :ensure_ownership!, except: [:index]
|
||||
before_action :redirect_to_avis_if_needed, only: [:index]
|
||||
|
||||
ITEMS_PER_PAGE = 25
|
||||
|
||||
|
|
|
@ -8,8 +8,17 @@
|
|||
#
|
||||
class Expert < ApplicationRecord
|
||||
has_one :user
|
||||
has_many :experts_procedures
|
||||
has_many :avis, through: :experts_procedures
|
||||
has_many :dossiers, through: :avis
|
||||
|
||||
default_scope { eager_load(:user) }
|
||||
|
||||
def email
|
||||
user.email
|
||||
end
|
||||
|
||||
def self.by_email(email)
|
||||
Expert.eager_load(:user).find_by(users: { email: email })
|
||||
end
|
||||
end
|
||||
|
|
11
app/views/experts/avis/_header.html.haml
Normal file
11
app/views/experts/avis/_header.html.haml
Normal file
|
@ -0,0 +1,11 @@
|
|||
.sub-header
|
||||
.container
|
||||
%ul.breadcrumbs
|
||||
%li= link_to('Avis', expert_all_avis_path)
|
||||
%li= link_to(dossier.procedure.libelle, procedure_expert_avis_index_path(avis.procedure))
|
||||
%li= link_to("Dossier nº #{dossier.id}", expert_avis_path(avis.procedure, avis))
|
||||
|
||||
%ul.tabs
|
||||
= dynamic_tab_item('Demande', expert_avis_path(avis.procedure, avis))
|
||||
= dynamic_tab_item('Avis', instruction_expert_avis_path(avis.procedure, avis), notification: avis.answer.blank?)
|
||||
= dynamic_tab_item('Messagerie', messagerie_expert_avis_path(avis.procedure, avis))
|
41
app/views/experts/avis/index.html.haml
Normal file
41
app/views/experts/avis/index.html.haml
Normal file
|
@ -0,0 +1,41 @@
|
|||
- content_for(:title, "Avis")
|
||||
|
||||
.container
|
||||
%h1.page-title Avis
|
||||
|
||||
%ul.procedure-list
|
||||
- @avis_by_procedure.each do |p, procedure_avis|
|
||||
%li.procedure-item.flex.align-start
|
||||
= link_to(procedure_instructeur_avis_index_path(p)) do
|
||||
.flex
|
||||
|
||||
.procedure-logo{ style: "background-image: url(#{p.logo_url})" }
|
||||
|
||||
.procedure-details
|
||||
%p.procedure-title
|
||||
= procedure_libelle p
|
||||
%ul.procedure-stats.flex
|
||||
%li
|
||||
%object
|
||||
= link_to(procedure_instructeur_avis_index_path(p, statut: Instructeurs::AvisController::A_DONNER_STATUS)) do
|
||||
- without_answer_count = procedure_avis.select { |a| a.answer.nil? }.size
|
||||
- if without_answer_count > 0
|
||||
%span.notifications{ 'aria-label': "notifications" }
|
||||
.stats-number
|
||||
= without_answer_count
|
||||
.stats-legend
|
||||
avis à donner
|
||||
%li
|
||||
%object
|
||||
= link_to(procedure_instructeur_avis_index_path(p, statut: Instructeurs::AvisController::DONNES_STATUS)) do
|
||||
- with_answer_count = procedure_avis.select { |a| a.answer.present? }.size
|
||||
.stats-number= with_answer_count
|
||||
.stats-legend
|
||||
= pluralize(with_answer_count, "avis donné")
|
||||
|
||||
- if p.close?
|
||||
.procedure-status
|
||||
%span.label Close
|
||||
- elsif p.depubliee?
|
||||
.procedure-status
|
||||
%span.label Dépubliée
|
38
app/views/experts/avis/instruction.html.haml
Normal file
38
app/views/experts/avis/instruction.html.haml
Normal file
|
@ -0,0 +1,38 @@
|
|||
- content_for(:title, "Avis · Dossier nº #{@dossier.id} (#{@dossier.owner_name})")
|
||||
|
||||
= render partial: 'header', locals: { avis: @avis, dossier: @dossier }
|
||||
|
||||
.container
|
||||
%section.give-avis
|
||||
%h1.tab-title Donner votre avis
|
||||
%h2.claimant
|
||||
Demandeur :
|
||||
%span.email= @avis.claimant.email
|
||||
%span.date Demande d'avis envoyée le #{l(@avis.created_at, format: '%d/%m/%y')}
|
||||
%p.introduction= @avis.introduction
|
||||
|
||||
- if @avis.introduction_file.attached?
|
||||
= render partial: 'shared/attachment/show', locals: { attachment: @avis.introduction_file.attachment }
|
||||
%br/
|
||||
|
||||
= form_for @avis, url: expert_avis_path(@avis.procedure, @avis), html: { class: 'form' } do |f|
|
||||
= f.text_area :answer, rows: 3, placeholder: 'Votre avis', required: true
|
||||
= text_upload_and_render f, @avis.piece_justificative_file
|
||||
|
||||
.flex.justify-between.align-baseline
|
||||
%p.confidentiel.flex
|
||||
- if @avis.confidentiel?
|
||||
%span.icon.lock
|
||||
%span
|
||||
Cet avis est confidentiel et n'est pas affiché aux autres experts consultés
|
||||
- else
|
||||
%span
|
||||
Cet avis est partagé avec les autres experts
|
||||
.send-wrapper
|
||||
= f.submit 'Envoyer votre avis', class: 'button send'
|
||||
|
||||
- if !@dossier.termine? && !feature_enabled_for?(:expert_not_allowed_to_invite, @avis.procedure)
|
||||
= render partial: "instructeurs/shared/avis/form", locals: { url: avis_expert_avis_path(@avis.procedure, @avis), linked_dossiers: @dossier.linked_dossiers_for(current_expert), must_be_confidentiel: @avis.confidentiel?, avis: @new_avis }
|
||||
|
||||
- if @dossier.avis_for(current_expert).present?
|
||||
= render partial: 'instructeurs/shared/avis/list', locals: { avis: @dossier.avis_for(current_expert), avis_seen_at: nil }
|
45
app/views/experts/avis/procedure.html.haml
Normal file
45
app/views/experts/avis/procedure.html.haml
Normal file
|
@ -0,0 +1,45 @@
|
|||
- avis_statut = (@statut == Experts::AvisController::A_DONNER_STATUS) ? 'à donner' : 'rendus'
|
||||
- content_for(:title, "Avis #{avis_statut}")
|
||||
|
||||
#procedure-show
|
||||
.sub-header
|
||||
.container.flex
|
||||
|
||||
.procedure-logo{ style: "background-image: url(#{@procedure.logo_url})",
|
||||
role: 'img', 'aria-label': "logo de la démarche #{@procedure.libelle}" }
|
||||
|
||||
.procedure-header
|
||||
%h1= procedure_libelle @procedure
|
||||
|
||||
%ul.tabs
|
||||
= tab_item('avis à donner',
|
||||
procedure_expert_avis_index_path(statut: Instructeurs::AvisController::A_DONNER_STATUS),
|
||||
active: @statut == Instructeurs::AvisController::A_DONNER_STATUS,
|
||||
badge: @avis_a_donner.count,
|
||||
notification: @avis_a_donner.any?)
|
||||
|
||||
= tab_item("avis #{'donné'.pluralize(@avis_donnes.count)}",
|
||||
procedure_expert_avis_index_path(statut: Instructeurs::AvisController::DONNES_STATUS),
|
||||
active: @statut == Instructeurs::AvisController::DONNES_STATUS,
|
||||
badge: @avis_donnes.count)
|
||||
|
||||
.container
|
||||
- if @avis.present?
|
||||
%table.table.dossiers-table.hoverable
|
||||
%thead
|
||||
%tr
|
||||
%th.number-col Nº dossier
|
||||
%th Demandeur
|
||||
%th Démarche
|
||||
%tbody
|
||||
- @avis.each do |avis|
|
||||
%tr
|
||||
%td.number-col
|
||||
= link_to(instructeur_avis_path(avis.procedure, avis), class: 'cell-link') do
|
||||
%span.icon.folder
|
||||
#{avis.dossier.id}
|
||||
%td= link_to(avis.dossier.user.email, instructeur_avis_path(avis.procedure, avis), class: 'cell-link')
|
||||
%td= link_to(avis.procedure.libelle, instructeur_avis_path(avis.procedure, avis), class: 'cell-link')
|
||||
= paginate(@avis)
|
||||
- else
|
||||
%h2.empty-text Aucun avis
|
30
app/views/experts/avis/shared/avis/_form.html.haml
Normal file
30
app/views/experts/avis/shared/avis/_form.html.haml
Normal file
|
@ -0,0 +1,30 @@
|
|||
%section.ask-avis
|
||||
%h1.tab-title Inviter des personnes à donner leur avis
|
||||
%p.avis-notice Les invités pourront consulter le dossier, donner un avis et contribuer au fil de messagerie. Ils ne pourront pas modifier le dossier.
|
||||
|
||||
= form_for avis, url: url, html: { class: 'form' } do |f|
|
||||
= f.email_field :emails, placeholder: 'Adresses email, séparées par des virgules', required: true, multiple: true, onchange: "javascript:DS.replaceSemicolonByComma(event);"
|
||||
= f.text_area :introduction, rows: 3, value: avis.introduction || 'Bonjour, merci de me donner votre avis sur ce dossier.', required: true
|
||||
%p.tab-title Ajouter une pièce jointe
|
||||
.form-group
|
||||
= text_upload_and_render f, avis.introduction_file
|
||||
|
||||
- if linked_dossiers.present?
|
||||
= f.check_box :invite_linked_dossiers, {}, true, false
|
||||
= f.label :invite_linked_dossiers, t('helpers.label.invite_linked_dossiers', count: linked_dossiers.length, ids: linked_dossiers.map(&:id).to_sentence)
|
||||
|
||||
.flex.justify-between.align-baseline
|
||||
- if must_be_confidentiel
|
||||
%p.confidentiel.flex
|
||||
%span.icon.lock
|
||||
%span
|
||||
Cet avis sera confidentiel : il ne sera pas affiché aux autres experts consultés, mais sera visible par les instructeurs.
|
||||
|
||||
- else
|
||||
.confidentiel-wrapper
|
||||
= f.label :confidentiel, 'Cet avis sera '
|
||||
= f.select :confidentiel, [['partagé avec les autres experts', false], ['confidentiel', true]], {}, onchange: "javascript:DS.toggleCondidentielExplanation(event);"
|
||||
.confidentiel-explanation.hidden
|
||||
Il ne sera pas affiché aux autres experts consultés, mais sera visible par les instructeurs.
|
||||
|
||||
= f.submit 'Demander un avis', class: 'button primary send'
|
5
app/views/experts/avis/show.html.haml
Normal file
5
app/views/experts/avis/show.html.haml
Normal file
|
@ -0,0 +1,5 @@
|
|||
- content_for(:title, "Demande · Dossier nº #{@dossier.id} (#{@dossier.owner_name})")
|
||||
|
||||
= render partial: 'header', locals: { avis: @avis, dossier: @dossier }
|
||||
|
||||
= render partial: 'shared/dossiers/demande', locals: { dossier: @dossier, demande_seen_at: nil, profile: 'instructeur' }
|
|
@ -22,6 +22,11 @@
|
|||
= link_to instructeur_procedures_path, class: "menu-item menu-link" do
|
||||
= image_tag "icons/switch-profile.svg", alt: ''
|
||||
= t('go_instructor', scope: [:layouts])
|
||||
- if expert_signed_in? && nav_bar_profile != :expert
|
||||
%li
|
||||
= link_to expert_all_avis_path, class: "menu-item menu-link" do
|
||||
= image_tag "icons/switch-profile.svg", alt: ''
|
||||
= t('go_expert', scope: [:layouts])
|
||||
- if administrateur_signed_in? && nav_bar_profile != :administrateur
|
||||
%li
|
||||
= link_to admin_procedures_path, class: "menu-item menu-link" do
|
||||
|
|
|
@ -3,6 +3,7 @@ en:
|
|||
go_superadmin: "Switch to super-admin"
|
||||
go_user: "Switch to user"
|
||||
go_instructor: "Switch to instructor"
|
||||
go_expert: "Switch to expert"
|
||||
go_admin: "Switch to administrator"
|
||||
profile: "See my profile"
|
||||
logout: "Log out"
|
||||
|
|
|
@ -3,6 +3,7 @@ fr:
|
|||
go_superadmin: "Passer en super-admin"
|
||||
go_user: "Passer en usager"
|
||||
go_instructor: "Passer en instructeur"
|
||||
go_expert: "Passer en expert"
|
||||
go_admin: "Passer en administrateur"
|
||||
profile: "Voir mon profil"
|
||||
logout: "Se déconnecter"
|
||||
|
|
|
@ -285,6 +285,43 @@ Rails.application.routes.draw do
|
|||
patch 'update_email' => 'profil#update_email'
|
||||
end
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Expert
|
||||
#
|
||||
scope module: 'experts', as: 'expert' do
|
||||
get 'avis', to: 'avis#index', as: 'all_avis'
|
||||
|
||||
# this redirections are ephemeral, to ensure that emails sent to experts before are still valid
|
||||
# TODO : they will be removed in September, 2020
|
||||
get 'avis/:id', to: redirect('/procedures/old/avis/%{id}')
|
||||
get 'avis/:id/sign_up/email/:email', to: redirect("/procedures/old/avis/%{id}/sign_up/email/%{email}"), constraints: { email: /.*/ }
|
||||
|
||||
resources :procedures, only: [ :show], param: :procedure_id do
|
||||
member do
|
||||
resources :avis, only: [:show, :update] do
|
||||
get '', action: 'procedure', on: :collection, as: :procedure
|
||||
member do
|
||||
get 'instruction'
|
||||
get 'messagerie'
|
||||
post 'commentaire' => 'avis#create_commentaire'
|
||||
post 'avis' => 'avis#create_avis'
|
||||
patch 'revoquer'
|
||||
get 'revive'
|
||||
get 'bilans_bdf'
|
||||
|
||||
get 'sign_up/email/:email' => 'avis#sign_up', constraints: { email: /.*/ }, as: 'sign_up'
|
||||
post 'sign_up/email/:email' => 'avis#create_instructeur', constraints: { email: /.*/ }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Instructeur
|
||||
#
|
||||
|
|
Loading…
Reference in a new issue