commit
22179f6b52
10 changed files with 190 additions and 11 deletions
|
@ -8,11 +8,11 @@ class API::V2::GraphqlController < API::V2::BaseController
|
||||||
operation_name: params[:operationName])
|
operation_name: params[:operationName])
|
||||||
|
|
||||||
render json: result
|
render json: result
|
||||||
rescue => e
|
rescue => exception
|
||||||
if Rails.env.development?
|
if Rails.env.development?
|
||||||
handle_error_in_development e
|
handle_error_in_development(exception)
|
||||||
else
|
else
|
||||||
raise e
|
handle_error_in_production(exception)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -21,7 +21,12 @@ class API::V2::GraphqlController < API::V2::BaseController
|
||||||
def process_action(*args)
|
def process_action(*args)
|
||||||
super
|
super
|
||||||
rescue ActionDispatch::Http::Parameters::ParseError => exception
|
rescue ActionDispatch::Http::Parameters::ParseError => exception
|
||||||
render status: 400, json: { errors: [{ message: exception.cause.message }] }
|
render json: {
|
||||||
|
errors: [
|
||||||
|
{ message: exception.cause.message }
|
||||||
|
],
|
||||||
|
data: nil
|
||||||
|
}, status: 400
|
||||||
end
|
end
|
||||||
|
|
||||||
# Handle form data, JSON body, or a blank value
|
# Handle form data, JSON body, or a blank value
|
||||||
|
@ -42,10 +47,32 @@ class API::V2::GraphqlController < API::V2::BaseController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_error_in_development(e)
|
def handle_error_in_development(exception)
|
||||||
logger.error e.message
|
logger.error exception.message
|
||||||
logger.error e.backtrace.join("\n")
|
logger.error exception.backtrace.join("\n")
|
||||||
|
|
||||||
render json: { error: { message: e.message, backtrace: e.backtrace }, data: {} }, status: 500
|
render json: {
|
||||||
|
errors: [
|
||||||
|
{ message: exception.message, backtrace: exception.backtrace }
|
||||||
|
],
|
||||||
|
data: nil
|
||||||
|
}, status: 500
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_error_in_production(exception)
|
||||||
|
id = SecureRandom.uuid
|
||||||
|
Raven.capture_exception(exception, extra: { exception_id: id })
|
||||||
|
|
||||||
|
render json: {
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
message: "Internal Server Error",
|
||||||
|
extensions: {
|
||||||
|
exception: { id: id }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
data: nil
|
||||||
|
}, status: 500
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module NewAdministrateur
|
module NewAdministrateur
|
||||||
class ProceduresController < AdministrateurController
|
class ProceduresController < AdministrateurController
|
||||||
before_action :retrieve_procedure, only: [:champs, :annotations, :edit, :monavis, :update_monavis, :jeton, :update_jeton, :publication, :publish, :transfert, :allow_expert_review]
|
before_action :retrieve_procedure, only: [:champs, :annotations, :edit, :monavis, :update_monavis, :jeton, :update_jeton, :publication, :publish, :transfert, :allow_expert_review, :invited_expert_list]
|
||||||
before_action :procedure_locked?, only: [:champs, :annotations]
|
before_action :procedure_locked?, only: [:champs, :annotations]
|
||||||
|
|
||||||
ITEMS_PER_PAGE = 25
|
ITEMS_PER_PAGE = 25
|
||||||
|
@ -185,6 +185,10 @@ module NewAdministrateur
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def invited_expert_list
|
||||||
|
@invited_expert_emails = Avis.invited_expert_emails(@procedure)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def apercu_tab
|
def apercu_tab
|
||||||
|
|
|
@ -19,7 +19,7 @@ module Types
|
||||||
end
|
end
|
||||||
|
|
||||||
def dossier(number:)
|
def dossier(number:)
|
||||||
Dossier.for_api_v2.find(number)
|
Dossier.state_not_brouillon.for_api_v2.find(number)
|
||||||
rescue => e
|
rescue => e
|
||||||
raise GraphQL::ExecutionError.new(e.message, extensions: { code: :not_found })
|
raise GraphQL::ExecutionError.new(e.message, extensions: { code: :not_found })
|
||||||
end
|
end
|
||||||
|
|
|
@ -56,6 +56,16 @@ class Avis < ApplicationRecord
|
||||||
Avis.find_by(id: avis_id)&.email == email
|
Avis.find_by(id: avis_id)&.email == email
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.invited_expert_emails(procedure)
|
||||||
|
Avis
|
||||||
|
.joins(dossier: :revision)
|
||||||
|
.left_joins(instructeur: :user)
|
||||||
|
.where(procedure_revisions: { procedure_id: procedure })
|
||||||
|
.map(&:email_to_display)
|
||||||
|
.uniq
|
||||||
|
.sort
|
||||||
|
end
|
||||||
|
|
||||||
def spreadsheet_columns
|
def spreadsheet_columns
|
||||||
[
|
[
|
||||||
['Dossier ID', dossier_id.to_s],
|
['Dossier ID', dossier_id.to_s],
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
.container
|
||||||
|
%h1.mt-2 Experts invités sur #{@procedure.libelle}
|
||||||
|
- if @invited_expert_emails.present?
|
||||||
|
%table.table.mt-2
|
||||||
|
%thead
|
||||||
|
%tr
|
||||||
|
%th Liste des experts
|
||||||
|
%tbody
|
||||||
|
- @invited_expert_emails.each do |expert|
|
||||||
|
%tr
|
||||||
|
%td
|
||||||
|
%span.icon.person
|
||||||
|
= expert
|
||||||
|
- else
|
||||||
|
.blank-tab
|
||||||
|
%h2.empty-text Aucun expert invité pour le moment.
|
||||||
|
%p.empty-text-details Les instructeurs de cette démarche n'ont pas encore fait appel aux experts.
|
||||||
|
|
|
@ -156,6 +156,20 @@
|
||||||
.card-admin-action
|
.card-admin-action
|
||||||
= link_to "#{@procedure.allow_expert_review? ? 'Désactiver' : 'Activer'}", allow_expert_review_admin_procedure_path(@procedure), method: :put, class: 'button'
|
= link_to "#{@procedure.allow_expert_review? ? 'Désactiver' : 'Activer'}", allow_expert_review_admin_procedure_path(@procedure), method: :put, class: 'button'
|
||||||
|
|
||||||
|
- if @procedure.allow_expert_review?
|
||||||
|
.card-admin
|
||||||
|
%div
|
||||||
|
%span.icon.preview
|
||||||
|
%p.card-admin-status-todo À voir
|
||||||
|
|
||||||
|
%div
|
||||||
|
%p.card-admin-title Liste des experts
|
||||||
|
%p.card-admin-subtitle Liste des experts invités par les instructeurs
|
||||||
|
|
||||||
|
.card-admin-action
|
||||||
|
= link_to "Voir", invited_expert_list_admin_procedure_path(@procedure), class: 'button'
|
||||||
|
|
||||||
|
|
||||||
.card-admin
|
.card-admin
|
||||||
%div
|
%div
|
||||||
%span.icon.clock
|
%span.icon.clock
|
||||||
|
|
|
@ -379,6 +379,7 @@ Rails.application.routes.draw do
|
||||||
get 'jeton'
|
get 'jeton'
|
||||||
patch 'update_jeton'
|
patch 'update_jeton'
|
||||||
put :allow_expert_review
|
put :allow_expert_review
|
||||||
|
get 'invited_expert_list'
|
||||||
end
|
end
|
||||||
|
|
||||||
get 'publication' => 'procedures#publication', as: :publication
|
get 'publication' => 'procedures#publication', as: :publication
|
||||||
|
|
|
@ -200,4 +200,46 @@ RSpec.describe Avis, type: :model do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#invited_expert_emails' do
|
||||||
|
let!(:procedure) { create(:procedure, :published) }
|
||||||
|
|
||||||
|
subject { Avis.invited_expert_emails(procedure) }
|
||||||
|
|
||||||
|
context 'when there is one dossier' do
|
||||||
|
let!(:dossier) { create(:dossier, procedure: procedure) }
|
||||||
|
|
||||||
|
context 'when a procedure has one avis and unknown instructeur' do
|
||||||
|
let!(:avis) { create(:avis, dossier: dossier, email: 'expert@expert.com') }
|
||||||
|
|
||||||
|
it { is_expected.to eq(['expert@expert.com']) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when a procedure has one avis and known instructeur' do
|
||||||
|
let!(:avis) { create(:avis, dossier: dossier, instructeur: create(:instructeur, email: 'expert@expert.com')) }
|
||||||
|
|
||||||
|
it { is_expected.to eq(['expert@expert.com']) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when a dossier has 2 avis from the same expert' do
|
||||||
|
let!(:avis) { create(:avis, dossier: dossier, email: 'expert@expert.com') }
|
||||||
|
let!(:avis2) { create(:avis, dossier: dossier, email: 'expert@expert.com') }
|
||||||
|
|
||||||
|
it { is_expected.to eq(['expert@expert.com']) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when there are two dossiers' do
|
||||||
|
let!(:dossier) { create(:dossier, procedure: procedure) }
|
||||||
|
let!(:dossier2) { create(:dossier, procedure: procedure) }
|
||||||
|
|
||||||
|
context 'and each one has an avis from 3 different experts' do
|
||||||
|
let!(:avis) { create(:avis, dossier: dossier, instructeur: create(:instructeur, email: '2_expert@expert.com')) }
|
||||||
|
let!(:unaffected_avis) { create(:avis, dossier: dossier2, email: '3_expert@expert.com') }
|
||||||
|
let!(:unaffected_avis2) { create(:avis, dossier: dossier2, email: '1_expert@expert.com') }
|
||||||
|
|
||||||
|
it { is_expected.to eq(['1_expert@expert.com', '2_expert@expert.com', '3_expert@expert.com']) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
describe 'new_administrateur/procedures/invited_expert_list.html.haml', type: :view do
|
||||||
|
let!(:procedure) { create(:procedure, :published) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
assign(:procedure, procedure)
|
||||||
|
assign(:procedure_lien, commencer_url(path: procedure.path))
|
||||||
|
allow(view).to receive(:current_administrateur).and_return(procedure.administrateurs.first)
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { render }
|
||||||
|
|
||||||
|
context 'when the procedure has 0 avis' do
|
||||||
|
let!(:dossier) { create(:dossier, procedure: procedure) }
|
||||||
|
before do
|
||||||
|
@invited_expert_emails = Avis.invited_expert_emails(procedure)
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'has 0 experts into the page' do
|
||||||
|
expect(@invited_expert_emails.count).to eq(0)
|
||||||
|
expect(@invited_expert_emails).to eq([])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the procedure has 3 avis from 2 experts and 1 unasigned' do
|
||||||
|
let!(:dossier) { create(:dossier, procedure: procedure) }
|
||||||
|
let!(:avis) { create(:avis, dossier: dossier, instructeur: create(:instructeur, email: '1_expert@expert.com')) }
|
||||||
|
let!(:avis2) { create(:avis, dossier: dossier, instructeur: create(:instructeur, email: '2_expert@expert.com')) }
|
||||||
|
let!(:unasigned_avis) { create(:avis, dossier: dossier, email: 'expert@expert.com') }
|
||||||
|
|
||||||
|
before do
|
||||||
|
@invited_expert_emails = Avis.invited_expert_emails(procedure)
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'has 3 experts and match array' do
|
||||||
|
expect(@invited_expert_emails.count).to eq(3)
|
||||||
|
expect(@invited_expert_emails).to eq(['1_expert@expert.com', '2_expert@expert.com', 'expert@expert.com'])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -44,13 +44,35 @@ describe 'new_administrateur/procedures/show.html.haml', type: :view do
|
||||||
procedure.publish!
|
procedure.publish!
|
||||||
procedure.close!
|
procedure.close!
|
||||||
procedure.reload
|
procedure.reload
|
||||||
render
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'Re-enable button is visible' do
|
describe 'Re-enable button is visible' do
|
||||||
|
before do
|
||||||
|
render
|
||||||
|
end
|
||||||
|
|
||||||
it { expect(rendered).not_to have_css('#close-procedure-link') }
|
it { expect(rendered).not_to have_css('#close-procedure-link') }
|
||||||
it { expect(rendered).to have_css('#publish-procedure-link') }
|
it { expect(rendered).to have_css('#publish-procedure-link') }
|
||||||
it { expect(rendered).to have_content('Réactiver') }
|
it { expect(rendered).to have_content('Réactiver') }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'When procedure.allow_expert_review is true, the expert list card must be visible' do
|
||||||
|
before do
|
||||||
|
render
|
||||||
|
end
|
||||||
|
it { expect(procedure.allow_expert_review).to be_truthy }
|
||||||
|
it { expect(rendered).to have_content('Liste des experts invités par les instructeurs') }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'When procedure.allow_expert_review is false, the expert list card must not be visible' do
|
||||||
|
before do
|
||||||
|
procedure.update!(allow_expert_review: false)
|
||||||
|
procedure.reload
|
||||||
|
render
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect(procedure.allow_expert_review).to be_falsy }
|
||||||
|
it { expect(rendered).not_to have_content('Liste des experts invités par les instructeurs') }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue