Merge branch 'dev'

This commit is contained in:
gregoirenovel 2018-09-07 12:23:54 +02:00
commit 98a3ce038b
43 changed files with 412 additions and 152 deletions

View file

@ -34,4 +34,8 @@
.button.edit-form { .button.edit-form {
float: right; float: right;
} }
.messagerie-explanation {
margin-bottom: $default-padding * 2;
}
} }

View file

@ -4,10 +4,11 @@ module NewUser
helper_method :new_demarche_url helper_method :new_demarche_url
before_action :ensure_ownership!, except: [:index, :show, :demande, :messagerie, :modifier, :update, :recherche] before_action :ensure_ownership!, except: [:index, :show, :demande, :messagerie, :brouillon, :update_brouillon, :modifier, :update, :recherche]
before_action :ensure_ownership_or_invitation!, only: [:show, :demande, :messagerie, :modifier, :update, :create_commentaire] before_action :ensure_ownership_or_invitation!, only: [:show, :demande, :messagerie, :brouillon, :update_brouillon, :modifier, :update, :create_commentaire]
before_action :ensure_dossier_can_be_updated, only: [:update_identite, :update] before_action :ensure_dossier_can_be_updated, only: [:update_identite, :update_brouillon, :modifier, :update]
before_action :forbid_invite_submission!, only: [:update] before_action :forbid_invite_submission!, only: [:update_brouillon]
before_action :forbid_closed_submission!, only: [:update_brouillon]
def index def index
@user_dossiers = current_user.dossiers.includes(:procedure).order_by_updated_at.page(page) @user_dossiers = current_user.dossiers.includes(:procedure).order_by_updated_at.page(page)
@ -25,7 +26,7 @@ module NewUser
def show def show
if dossier.brouillon? if dossier.brouillon?
redirect_to modifier_dossier_path(dossier) redirect_to brouillon_dossier_path(dossier)
elsif !Flipflop.new_dossier_details? elsif !Flipflop.new_dossier_details?
redirect_to users_dossier_recapitulatif_path(dossier) redirect_to users_dossier_recapitulatif_path(dossier)
@ -64,7 +65,7 @@ module NewUser
if @dossier.procedure.module_api_carto.use_api_carto if @dossier.procedure.module_api_carto.use_api_carto
redirect_to users_dossier_carte_path(@dossier.id) redirect_to users_dossier_carte_path(@dossier.id)
else else
redirect_to modifier_dossier_path(@dossier) redirect_to brouillon_dossier_path(@dossier)
end end
else else
flash.now.alert = @dossier.errors.full_messages flash.now.alert = @dossier.errors.full_messages
@ -72,7 +73,7 @@ module NewUser
end end
end end
def modifier def brouillon
@dossier = dossier_with_champs @dossier = dossier_with_champs
# TODO: remove when the champs are unifed # TODO: remove when the champs are unifed
@ -85,41 +86,53 @@ module NewUser
end end
end end
# FIXME: remove PiecesJustificativesService # FIXME:
# delegate draft save logic to champ ? # - remove PiecesJustificativesService
# - delegate draft save logic to champ ?
def update_brouillon
@dossier = dossier_with_champs
errors = update_dossier_and_compute_errors
if errors.present?
flash.now.alert = errors
render :brouillon
else
if save_draft?
flash.now.notice = 'Votre brouillon a bien été sauvegardé.'
render :brouillon
else
@dossier.en_construction!
NotificationMailer.send_initiated_notification(@dossier).deliver_later
redirect_to merci_dossier_path(@dossier)
end
end
end
def modifier
@dossier = dossier_with_champs
end
# FIXME:
# - remove PiecesJustificativesService
def update def update
@dossier = dossier_with_champs @dossier = dossier_with_champs
errors = PiecesJustificativesService.upload!(@dossier, current_user, params) errors = update_dossier_and_compute_errors
if champs_params[:dossier] && !@dossier.update(champs_params[:dossier])
errors += @dossier.errors.full_messages
end
if !draft?
errors += @dossier.champs.select(&:mandatory_and_blank?)
.map { |c| "Le champ #{c.libelle.truncate(200)} doit être rempli." }
errors += PiecesJustificativesService.missing_pj_error_messages(@dossier)
end
if errors.present? if errors.present?
flash.now.alert = errors flash.now.alert = errors
render :modifier render :modifier
elsif draft?
flash.now.notice = 'Votre brouillon a bien été sauvegardé.'
render :modifier
elsif @dossier.can_transition_to_en_construction?
@dossier.en_construction!
NotificationMailer.send_initiated_notification(@dossier).deliver_later
redirect_to merci_dossier_path(@dossier)
elsif current_user.owns?(dossier)
if Flipflop.new_dossier_details?
redirect_to demande_dossier_path(@dossier)
else
redirect_to users_dossier_recapitulatif_path(@dossier)
end
else else
redirect_to users_dossiers_invite_path(@dossier.invite_for_user(current_user)) if current_user.owns?(dossier)
if Flipflop.new_dossier_details?
redirect_to demande_dossier_path(@dossier)
else
redirect_to users_dossier_recapitulatif_path(@dossier)
end
else
redirect_to users_dossiers_invite_path(@dossier.invite_for_user(current_user))
end
end end
end end
@ -131,7 +144,7 @@ module NewUser
@commentaire = CommentaireService.create(current_user, dossier, commentaire_params) @commentaire = CommentaireService.create(current_user, dossier, commentaire_params)
if @commentaire.save if @commentaire.save
flash.notice = "Message envoyé" flash.notice = "Votre message a bien été envoyé à linstructeur en charge de votre dossier."
redirect_to messagerie_dossier_path(dossier) redirect_to messagerie_dossier_path(dossier)
else else
flash.now.alert = @commentaire.errors.full_messages flash.now.alert = @commentaire.errors.full_messages
@ -209,6 +222,22 @@ module NewUser
Dossier.with_champs.find(params[:id]) Dossier.with_champs.find(params[:id])
end end
def update_dossier_and_compute_errors
errors = PiecesJustificativesService.upload!(@dossier, current_user, params)
if champs_params[:dossier] && !@dossier.update(champs_params[:dossier])
errors += @dossier.errors.full_messages
end
if !save_draft?
errors += @dossier.champs.select(&:mandatory_and_blank?)
.map { |c| "Le champ #{c.libelle.truncate(200)} doit être rempli." }
errors += PiecesJustificativesService.missing_pj_error_messages(@dossier)
end
errors
end
def ensure_ownership! def ensure_ownership!
if !current_user.owns?(dossier) if !current_user.owns?(dossier)
forbidden! forbidden!
@ -227,6 +256,12 @@ module NewUser
end end
end end
def forbid_closed_submission!
if passage_en_construction? && !dossier.can_transition_to_en_construction?
forbidden!
end
end
def forbidden! def forbidden!
flash[:alert] = "Vous n'avez pas accès à ce dossier" flash[:alert] = "Vous n'avez pas accès à ce dossier"
redirect_to root_path redirect_to root_path
@ -245,10 +280,10 @@ module NewUser
end end
def passage_en_construction? def passage_en_construction?
dossier.brouillon? && !draft? dossier.brouillon? && !save_draft?
end end
def draft? def save_draft?
params[:save_draft] params[:save_draft]
end end
end end

View file

@ -25,7 +25,7 @@ class Users::CarteController < UsersController
dossier.update(json_latlngs: safe_json_latlngs) dossier.update(json_latlngs: safe_json_latlngs)
redirect_to modifier_dossier_path(dossier) redirect_to brouillon_dossier_path(dossier)
end end
def get_position def get_position

View file

@ -10,7 +10,7 @@ class Users::Dossiers::InvitesController < UsersController
@facade = InviteDossierFacades.new params[:id].to_i, current_user.email @facade = InviteDossierFacades.new params[:id].to_i, current_user.email
if @facade.dossier.brouillon? if @facade.dossier.brouillon?
redirect_to modifier_dossier_path(@facade.dossier) redirect_to brouillon_dossier_path(@facade.dossier)
else else
render 'users/recapitulatif/show' render 'users/recapitulatif/show'
end end

View file

@ -142,7 +142,7 @@ class Users::DossiersController < UsersController
if @facade.dossier.procedure.module_api_carto.use_api_carto if @facade.dossier.procedure.module_api_carto.use_api_carto
redirect_to url_for(controller: :carte, action: :show, dossier_id: @facade.dossier.id) redirect_to url_for(controller: :carte, action: :show, dossier_id: @facade.dossier.id)
else else
redirect_to modifier_dossier_path(@facade.dossier) redirect_to brouillon_dossier_path(@facade.dossier)
end end
end end
end end

View file

@ -4,4 +4,14 @@ module CommentaireHelper
"from-me" "from-me"
end end
end end
def commentaire_is_from_guest(commentaire)
commentaire.dossier.invites.map(&:email).include?(commentaire.email)
end
def commentaire_date(commentaire)
is_current_year = (commentaire.created_at.year == Date.current.year)
template = is_current_year ? :message_date : :message_date_with_year
I18n.l(commentaire.created_at.localtime, format: template)
end
end end

View file

@ -17,7 +17,7 @@ module DossierHelper
def url_for_dossier(dossier) def url_for_dossier(dossier)
if dossier.brouillon? if dossier.brouillon?
modifier_dossier_path(dossier) brouillon_dossier_path(dossier)
else else
users_dossier_recapitulatif_path(dossier) users_dossier_recapitulatif_path(dossier)
end end

View file

@ -9,7 +9,11 @@ module TabsHelper
} }
end end
def active_tab_item(label, url, badge: nil, notification: false) def dynamic_tab_item(label, url_or_urls, badge: nil, notification: false)
tab_item(label, url, active: current_page?(url), badge: badge, notification: notification) urls = [url_or_urls].flatten
url = urls.first
active = urls.any? { |u| current_page?(u) }
tab_item(label, url, active: active, badge: badge, notification: notification)
end end
end end

View file

@ -18,7 +18,11 @@ class Gestionnaire < ApplicationRecord
has_many :dossiers_from_avis, through: :avis, source: :dossier has_many :dossiers_from_avis, through: :avis, source: :dossier
def visible_procedures def visible_procedures
procedures.publiees_ou_archivees if Flipflop.publish_draft?
procedures.avec_lien
else
procedures.publiees_ou_archivees
end
end end
def can_view_dossier?(dossier_id) def can_view_dossier?(dossier_id)

View file

@ -46,6 +46,7 @@ class Procedure < ApplicationRecord
scope :by_libelle, -> { order(libelle: :asc) } scope :by_libelle, -> { order(libelle: :asc) }
scope :created_during, -> (range) { where(created_at: range) } scope :created_during, -> (range) { where(created_at: range) }
scope :cloned_from_library, -> { where(cloned_from_library: true) } scope :cloned_from_library, -> { where(cloned_from_library: true) }
scope :avec_lien, -> { joins(:procedure_path) }
validates :libelle, presence: true, allow_blank: false, allow_nil: false validates :libelle, presence: true, allow_blank: false, allow_nil: false
validates :description, presence: true, allow_blank: false, allow_nil: false validates :description, presence: true, allow_blank: false, allow_nil: false

View file

@ -49,14 +49,27 @@
%div %div
%h3 Lien démarche %h3 Lien démarche
%div{ style: 'margin-left: 3%;' } %div{ style: 'margin-top: 30px;' }
- if @procedure.archivee? - if @procedure.archivee?
%b .alert.alert-info
Cette démarche est archivée et nest donc pas accessible par le public. Cette démarche est archivée et nest donc pas accessible par le public.
- elsif @procedure.brouillon_avec_lien? || @procedure.publiee? - elsif @procedure.publiee?
= link_to procedure_lien(@procedure), sanitize_url(procedure_lien(@procedure)), target: :blank = link_to procedure_lien(@procedure), sanitize_url(procedure_lien(@procedure)), target: :blank
- elsif @procedure.brouillon_avec_lien?
- if @procedure.gestionnaires.present? && @procedure.service.present?
= link_to procedure_lien(@procedure), sanitize_url(procedure_lien(@procedure)), target: :blank
- else
.alert.alert-info
Pour pouvoir tester cette démarche, vous devez dabord lui affecter
- if @procedure.gestionnaires.empty?
= link_to("des instructeurs", admin_procedure_instructeurs_path(@procedure))
- if @procedure.gestionnaires.empty? && @procedure.service.nil?
et
- if @procedure.service.nil?
= link_to("un service", services_path(procedure_id: @procedure))
\.
- else - else
%b .alert.alert-info
Cette démarche na pas encore de lien, et nest donc pas accessible par le public. Cette démarche na pas encore de lien, et nest donc pas accessible par le public.
%br %br

View file

@ -1,5 +1,5 @@
- if !@facade.dossier.read_only? - if !@facade.dossier.read_only?
- if user_signed_in? && (current_user.owns_or_invite?(@facade.dossier)) - if user_signed_in? && (current_user.owns_or_invite?(@facade.dossier))
= link_to modifier_dossier_path(@facade.dossier), class: 'action', id: 'maj_infos' do = link_to brouillon_dossier_path(@facade.dossier), class: 'action', id: 'maj_infos' do
#edit-dossier.col-lg-2.col-md-2.col-sm-2.col-xs-2.action #edit-dossier.col-lg-2.col-md-2.col-sm-2.col-xs-2.action
= "MODIFIER" = "MODIFIER"

View file

@ -41,7 +41,7 @@
- if champ.type_champ == TypeDeChamp.type_champs.fetch(:dossier_link) - if champ.type_champ == TypeDeChamp.type_champs.fetch(:dossier_link)
- dossier = Dossier.includes(:procedure).find_by(id: champ.decorate.value) - dossier = Dossier.includes(:procedure).find_by(id: champ.decorate.value)
- if dossier - if dossier
= link_to("Dossier #{dossier.id}", modifier_dossier_path(dossier), target: '_blank') = link_to("Dossier #{dossier.id}", brouillon_dossier_path(dossier), target: '_blank')
%br %br
= sanitize(dossier.text_summary) = sanitize(dossier.text_summary)
- else - else

View file

@ -5,6 +5,6 @@
%li= "#{dossier.procedure.libelle}, dossier nº #{dossier.id}" %li= "#{dossier.procedure.libelle}, dossier nº #{dossier.id}"
%ul.tabs %ul.tabs
= active_tab_item('Demande', gestionnaire_avis_path(avis)) = dynamic_tab_item('Demande', gestionnaire_avis_path(avis))
= active_tab_item('Avis', instruction_gestionnaire_avis_path(avis), notification: avis.answer.blank?) = dynamic_tab_item('Avis', instruction_gestionnaire_avis_path(avis), notification: avis.answer.blank?)
= active_tab_item('Messagerie', messagerie_gestionnaire_avis_path(avis)) = dynamic_tab_item('Messagerie', messagerie_gestionnaire_avis_path(avis))

View file

@ -21,23 +21,23 @@
%ul.tabs %ul.tabs
- notifications_summary = current_gestionnaire.notifications_for_dossier(dossier) - notifications_summary = current_gestionnaire.notifications_for_dossier(dossier)
= active_tab_item('Demande', = dynamic_tab_item('Demande',
gestionnaire_dossier_path(dossier.procedure, dossier), gestionnaire_dossier_path(dossier.procedure, dossier),
notification: notifications_summary[:demande]) notification: notifications_summary[:demande])
= active_tab_item('Annotations privées', = dynamic_tab_item('Annotations privées',
annotations_privees_gestionnaire_dossier_path(dossier.procedure, dossier), annotations_privees_gestionnaire_dossier_path(dossier.procedure, dossier),
notification: notifications_summary[:annotations_privees]) notification: notifications_summary[:annotations_privees])
= active_tab_item('Avis externes', = dynamic_tab_item('Avis externes',
avis_gestionnaire_dossier_path(dossier.procedure, dossier), avis_gestionnaire_dossier_path(dossier.procedure, dossier),
notification: notifications_summary[:avis]) notification: notifications_summary[:avis])
= active_tab_item('Messagerie', = dynamic_tab_item('Messagerie',
messagerie_gestionnaire_dossier_path(dossier.procedure, dossier), messagerie_gestionnaire_dossier_path(dossier.procedure, dossier),
notification: notifications_summary[:messagerie]) notification: notifications_summary[:messagerie])
= active_tab_item('Personnes impliquées', = dynamic_tab_item('Personnes impliquées',
personnes_impliquees_gestionnaire_dossier_path(dossier.procedure, dossier)) personnes_impliquees_gestionnaire_dossier_path(dossier.procedure, dossier))
.container .container

View file

@ -0,0 +1,11 @@
- content_for(:title, "Modification du brouillon nº #{@dossier.id} (#{@dossier.procedure.libelle})")
- content_for :footer do
= render partial: "new_user/dossiers/footer", locals: { dossier: @dossier }
.dossier-edit
.dossier-header.sub-header
.container
= render partial: "shared/dossiers/header", locals: { dossier: @dossier, apercu: false }
= render partial: "shared/dossiers/edit", locals: { dossier: @dossier, apercu: false }

View file

@ -39,7 +39,7 @@
= dossier.id = dossier.id
%td %td
= link_to(url_for_dossier(dossier), class: 'cell-link') do = link_to(url_for_dossier(dossier), class: 'cell-link') do
= dossier.procedure.libelle = procedure_libelle(dossier.procedure)
%td.status-col %td.status-col
= link_to(url_for_dossier(dossier), class: 'cell-link') do = link_to(url_for_dossier(dossier), class: 'cell-link') do
= render partial: 'shared/dossiers/status_badge', locals: { dossier: dossier } = render partial: 'shared/dossiers/status_badge', locals: { dossier: dossier }

View file

@ -3,4 +3,8 @@
#dossier-show #dossier-show
= render partial: 'new_user/dossiers/show/header', locals: { dossier: @dossier } = render partial: 'new_user/dossiers/show/header', locals: { dossier: @dossier }
.container
%p.messagerie-explanation
La messagerie vous permet de contacter linstructeur en charge de votre dossier.
= render partial: "shared/dossiers/messagerie", locals: { dossier: @dossier, user_email: current_user.email, messagerie_seen_at: nil, new_commentaire: @commentaire, form_url: commentaire_dossier_path(@dossier) } = render partial: "shared/dossiers/messagerie", locals: { dossier: @dossier, user_email: current_user.email, messagerie_seen_at: nil, new_commentaire: @commentaire, form_url: commentaire_dossier_path(@dossier) }

View file

@ -1,11 +1,7 @@
- content_for(:title, "Modification du brouillon #{@dossier.id} (#{@dossier.procedure.libelle})") - content_for(:title, "Modifier · Dossier #{@dossier.id} (#{@dossier.procedure.libelle})")
- content_for :footer do #dossier-show
= render partial: "new_user/dossiers/footer", locals: { dossier: @dossier } = render partial: 'new_user/dossiers/show/header', locals: { dossier: @dossier }
.dossier-edit .container
.dossier-header.sub-header = render partial: "shared/dossiers/edit", locals: { dossier: @dossier, apercu: false }
.container
= render partial: "shared/dossiers/header", locals: { dossier: @dossier, apercu: false }
= render partial: "shared/dossiers/edit", locals: { dossier: @dossier, apercu: false }

View file

@ -8,6 +8,6 @@
%h2 Dossier nº #{dossier.id} %h2 Dossier nº #{dossier.id}
%ul.tabs %ul.tabs
= active_tab_item('Résumé', dossier_path(dossier)) = dynamic_tab_item('Résumé', dossier_path(dossier))
= active_tab_item('Demande', demande_dossier_path(dossier)) = dynamic_tab_item('Demande', [demande_dossier_path(dossier), modifier_dossier_path(dossier)])
= active_tab_item('Messagerie', messagerie_dossier_path(dossier)) = dynamic_tab_item('Messagerie', messagerie_dossier_path(dossier))

View file

@ -3,6 +3,8 @@
- if apercu - if apercu
- form_options = { url: '', method: :get, html: { class: 'form', multipart: true } } - form_options = { url: '', method: :get, html: { class: 'form', multipart: true } }
- elsif dossier.brouillon?
- form_options = { url: brouillon_dossier_url(dossier), method: :patch, html: { class: 'form', multipart: true } }
- else - else
- form_options = { url: modifier_dossier_url(dossier), method: :patch, html: { class: 'form', multipart: true } } - form_options = { url: modifier_dossier_url(dossier), method: :patch, html: { class: 'form', multipart: true } }

View file

@ -1,6 +1,6 @@
%h1 %h1
%span.icon.folder %span.icon.folder
= dossier.procedure.libelle = procedure_libelle(dossier.procedure)
.dossier-form-actions .dossier-form-actions
- if current_user.owns?(dossier) - if current_user.owns?(dossier)

View file

@ -7,5 +7,5 @@
.notice .notice
(taille max : 20 Mo) (taille max : 20 Mo)
.send-wrapper %div
= f.submit 'Envoyer', class: 'button send', data: { disable: true } = f.submit 'Envoyer', class: 'button primary send', data: { disable: true }

View file

@ -4,10 +4,10 @@
%h2 %h2
%span.mail %span.mail
= render partial: 'shared/dossiers/messages/message_issuer', locals: { commentaire: commentaire, user_email: user_email } = render partial: 'shared/dossiers/messages/message_issuer', locals: { commentaire: commentaire, user_email: user_email }
- if ![user_email, commentaire.dossier.user.email, OLD_CONTACT_EMAIL, CONTACT_EMAIL].include?(commentaire.email) - if commentaire_is_from_guest(commentaire)
%span.guest Invité %span.guest Invité
%span.date{ class: highlight_if_unseen_class(messagerie_seen_at, commentaire.created_at) } %span.date{ class: highlight_if_unseen_class(messagerie_seen_at, commentaire.created_at) }
= I18n.l(commentaire.created_at.localtime, format: '%d/%m/%Y à %H:%M ') = commentaire_date(commentaire)
.rich-text= sanitize(commentaire.body) .rich-text= sanitize(commentaire.body)
- if commentaire.piece_justificative - if commentaire.piece_justificative

View file

@ -5,4 +5,4 @@
- when CONTACT_EMAIL - when CONTACT_EMAIL
Email automatique Email automatique
- else - else
= commentaire.email = commentaire.sender

View file

@ -0,0 +1,10 @@
{
:en => {
:time => {
:formats => {
:message_date => lambda { |time, _| "%B #{time.day.ordinalize} at %H:%M" },
:message_date_with_year => lambda { |time, _| "%B #{time.day.ordinalize} %Y at %H:%M" }
}
}
}
}

View file

@ -0,0 +1,10 @@
{
:fr => {
:time => {
:formats => {
:message_date => lambda { |time, _| "le #{time.day == 1 ? '1er' : time.day} %B à %H h %M" },
:message_date_with_year => lambda { |time, _| "le #{time.day == 1 ? '1er' : time.day} %B %Y à %H h %M" }
}
}
}
}

View file

@ -271,11 +271,13 @@ Rails.application.routes.draw do
# #
scope module: 'new_user' do scope module: 'new_user' do
resources :dossiers, only: [:index, :show, :update] do resources :dossiers, only: [:index, :show] do
member do member do
get 'identite' get 'identite'
patch 'update_identite' patch 'update_identite'
get 'modifier' get 'brouillon'
patch 'brouillon', to: 'dossiers#update_brouillon'
get 'modifier', to: 'dossiers#modifier'
patch 'modifier', to: 'dossiers#update' patch 'modifier', to: 'dossiers#update'
get 'merci' get 'merci'
get 'demande' get 'demande'

View file

@ -69,14 +69,14 @@ describe InvitesController, type: :controller do
context 'when user has access to dossier' do context 'when user has access to dossier' do
before do before do
request.env["HTTP_REFERER"] = "/dossiers/#{dossier.id}/modifier" request.env["HTTP_REFERER"] = "/dossiers/#{dossier.id}/brouillon"
dossier.update(user: signed_in_profile) dossier.update(user: signed_in_profile)
end end
it { expect { subject }.to change(InviteUser, :count).by(1) } it { expect { subject }.to change(InviteUser, :count).by(1) }
it "redirects to the previous URL" do it "redirects to the previous URL" do
expect(subject).to redirect_to("/dossiers/#{dossier.id}/modifier") expect(subject).to redirect_to("/dossiers/#{dossier.id}/brouillon")
end end
context 'when email is assign to an user' do context 'when email is assign to an user' do

View file

@ -174,7 +174,7 @@ describe NewUser::DossiersController, type: :controller do
let(:dossier_params) { { autorisation_donnees: true } } let(:dossier_params) { { autorisation_donnees: true } }
it do it do
expect(response).to redirect_to(modifier_dossier_path(dossier)) expect(response).to redirect_to(brouillon_dossier_path(dossier))
end end
context 'on a procedure with carto' do context 'on a procedure with carto' do
@ -208,14 +208,14 @@ describe NewUser::DossiersController, type: :controller do
end end
end end
describe '#modifier' do describe '#brouillon' do
before { sign_in(user) } before { sign_in(user) }
let!(:dossier) { create(:dossier, user: user, autorisation_donnees: true) } let!(:dossier) { create(:dossier, user: user, autorisation_donnees: true) }
subject { get :modifier, params: { id: dossier.id } } subject { get :brouillon, params: { id: dossier.id } }
context 'when autorisation_donnees is checked' do context 'when autorisation_donnees is checked' do
it { is_expected.to render_template(:modifier) } it { is_expected.to render_template(:brouillon) }
end end
context 'when autorisation_donnees is not checked' do context 'when autorisation_donnees is not checked' do
@ -238,12 +238,12 @@ describe NewUser::DossiersController, type: :controller do
let!(:dossier) { create(:dossier, user: user) } let!(:dossier) { create(:dossier, user: user) }
it 'returns the edit page' do it 'returns the edit page' do
get :modifier, params: { id: dossier.id } get :brouillon, params: { id: dossier.id }
expect(response).to have_http_status(:success) expect(response).to have_http_status(:success)
end end
end end
describe '#update' do describe '#update_brouillon' do
before { sign_in(user) } before { sign_in(user) }
let!(:dossier) { create(:dossier, user: user) } let!(:dossier) { create(:dossier, user: user) }
let(:first_champ) { dossier.champs.first } let(:first_champ) { dossier.champs.first }
@ -261,7 +261,7 @@ describe NewUser::DossiersController, type: :controller do
end end
let(:payload) { submit_payload } let(:payload) { submit_payload }
subject { patch :update, params: payload } subject { patch :update_brouillon, params: payload }
context 'when the dossier cannot be updated by the user' do context 'when the dossier cannot be updated by the user' do
let!(:dossier) { create(:dossier, :en_instruction, user: user) } let!(:dossier) { create(:dossier, :en_instruction, user: user) }
@ -295,7 +295,7 @@ describe NewUser::DossiersController, type: :controller do
end end
end end
it 'sends an email only on the first #update' do it 'sends an email only on the first #update_brouillon' do
delivery = double delivery = double
expect(delivery).to receive(:deliver_later).with(no_args) expect(delivery).to receive(:deliver_later).with(no_args)
@ -309,6 +309,137 @@ describe NewUser::DossiersController, type: :controller do
subject subject
end end
context 'when the update fails' do
before do
expect_any_instance_of(Dossier).to receive(:save).and_return(false)
expect_any_instance_of(Dossier).to receive(:errors)
.and_return(double(full_messages: ['nop']))
subject
end
it { expect(response).to render_template(:brouillon) }
it { expect(flash.alert).to eq(['nop']) }
it 'does not send an email' do
expect(NotificationMailer).not_to receive(:send_initiated_notification)
subject
end
end
context 'when the pj service returns an error' do
before do
expect(PiecesJustificativesService).to receive(:upload!).and_return(['nop'])
subject
end
it { expect(response).to render_template(:brouillon) }
it { expect(flash.alert).to eq(['nop']) }
end
context 'when a mandatory champ is missing' do
let(:value) { nil }
before do
first_champ.type_de_champ.update(mandatory: true, libelle: 'l')
allow(PiecesJustificativesService).to receive(:missing_pj_error_messages).and_return(['pj'])
subject
end
it { expect(response).to render_template(:brouillon) }
it { expect(flash.alert).to eq(['Le champ l doit être rempli.', 'pj']) }
context 'and the user saves a draft' do
let(:payload) { submit_payload.merge(save_draft: true) }
it { expect(response).to render_template(:brouillon) }
it { expect(flash.notice).to eq('Votre brouillon a bien été sauvegardé.') }
it { expect(dossier.reload.state).to eq(Dossier.states.fetch(:brouillon)) }
end
end
context 'when dossier has no champ' do
let(:submit_payload) { { id: dossier.id } }
it 'does not raise any errors' do
subject
expect(response).to redirect_to(merci_dossier_path(dossier))
end
end
context 'when the user has an invitation but is not the owner' do
let(:dossier) { create(:dossier) }
let!(:invite) { create(:invite, dossier: dossier, user: user, type: 'InviteUser') }
context 'and the invite saves a draft' do
let(:payload) { submit_payload.merge(save_draft: true) }
before do
first_champ.type_de_champ.update(mandatory: true, libelle: 'l')
allow(PiecesJustificativesService).to receive(:missing_pj_error_messages).and_return(['pj'])
subject
end
it { expect(response).to render_template(:brouillon) }
it { expect(flash.notice).to eq('Votre brouillon a bien été sauvegardé.') }
it { expect(dossier.reload.state).to eq(Dossier.states.fetch(:brouillon)) }
end
context 'and the invite tries to submit the dossier' do
before { subject }
it { expect(response).to redirect_to(root_path) }
it { expect(flash.alert).to eq("Vous n'avez pas accès à ce dossier") }
end
end
end
describe '#update' do
before { sign_in(user) }
let!(:dossier) { create(:dossier, :en_construction, user: user) }
let(:first_champ) { dossier.champs.first }
let(:value) { 'beautiful value' }
let(:submit_payload) do
{
id: dossier.id,
dossier: {
champs_attributes: {
id: first_champ.id,
value: value
}
}
}
end
let(:payload) { submit_payload }
subject { patch :update, params: payload }
context 'when the dossier cannot be updated by the user' do
let!(:dossier) { create(:dossier, :en_instruction, user: user) }
it 'redirects to the dossiers list' do
subject
expect(response).to redirect_to(dossiers_path)
expect(flash.alert).to eq('Votre dossier ne peut plus être modifié')
end
end
context 'when dossier can be updated by the owner' do
it 'updates the champs' do
subject
expect(response).to redirect_to(users_dossier_recapitulatif_path(dossier))
expect(first_champ.reload.value).to eq('beautiful value')
expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_construction))
end
end
context 'when the update fails' do context 'when the update fails' do
before do before do
expect_any_instance_of(Dossier).to receive(:save).and_return(false) expect_any_instance_of(Dossier).to receive(:save).and_return(false)
@ -351,14 +482,6 @@ describe NewUser::DossiersController, type: :controller do
it { expect(response).to render_template(:modifier) } it { expect(response).to render_template(:modifier) }
it { expect(flash.alert).to eq(['Le champ l doit être rempli.', 'pj']) } it { expect(flash.alert).to eq(['Le champ l doit être rempli.', 'pj']) }
context 'and the user saves a draft' do
let(:payload) { submit_payload.merge(save_draft: true) }
it { expect(response).to render_template(:modifier) }
it { expect(flash.notice).to eq('Votre brouillon a bien été sauvegardé.') }
it { expect(dossier.reload.state).to eq(Dossier.states.fetch(:brouillon)) }
end
end end
context 'when dossier has no champ' do context 'when dossier has no champ' do
@ -367,7 +490,7 @@ describe NewUser::DossiersController, type: :controller do
it 'does not raise any errors' do it 'does not raise any errors' do
subject subject
expect(response).to redirect_to(merci_dossier_path(dossier)) expect(response).to redirect_to(users_dossier_recapitulatif_path(dossier))
end end
end end
@ -375,38 +498,14 @@ describe NewUser::DossiersController, type: :controller do
let(:dossier) { create(:dossier) } let(:dossier) { create(:dossier) }
let!(:invite) { create(:invite, dossier: dossier, user: user, type: 'InviteUser') } let!(:invite) { create(:invite, dossier: dossier, user: user, type: 'InviteUser') }
context 'and the invite saves a draft' do before do
let(:payload) { submit_payload.merge(save_draft: true) } dossier.en_construction!
subject
before do
first_champ.type_de_champ.update(mandatory: true, libelle: 'l')
allow(PiecesJustificativesService).to receive(:missing_pj_error_messages).and_return(['pj'])
subject
end
it { expect(response).to render_template(:modifier) }
it { expect(flash.notice).to eq('Votre brouillon a bien été sauvegardé.') }
it { expect(dossier.reload.state).to eq(Dossier.states.fetch(:brouillon)) }
end end
context 'and the invite tries to submit the dossier' do it { expect(first_champ.reload.value).to eq('beautiful value') }
before { subject } it { expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_construction)) }
it { expect(response).to redirect_to(users_dossiers_invite_path(invite)) }
it { expect(response).to redirect_to(root_path) }
it { expect(flash.alert).to eq("Vous n'avez pas accès à ce dossier") }
end
context 'and the invite updates a dossier en constructions' do
before do
dossier.en_construction!
subject
end
it { expect(first_champ.reload.value).to eq('beautiful value') }
it { expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_construction)) }
it { expect(response).to redirect_to(users_dossiers_invite_path(invite)) }
end
end end
end end
@ -486,11 +585,15 @@ describe NewUser::DossiersController, type: :controller do
sign_in(user) sign_in(user)
end end
after do
Flipflop::FeatureSet.current.test!.switch!(:new_dossier_details, false)
end
subject! { get(:show, params: { id: dossier.id }) } subject! { get(:show, params: { id: dossier.id }) }
context 'when the dossier is a brouillon' do context 'when the dossier is a brouillon' do
let(:dossier) { create(:dossier, user: user) } let(:dossier) { create(:dossier, user: user) }
it { is_expected.to redirect_to(modifier_dossier_path(dossier)) } it { is_expected.to redirect_to(brouillon_dossier_path(dossier)) }
end end
context 'when the dossier has been submitted' do context 'when the dossier has been submitted' do
@ -517,6 +620,10 @@ describe NewUser::DossiersController, type: :controller do
sign_in(user) sign_in(user)
end end
after do
Flipflop::FeatureSet.current.test!.switch!(:new_dossier_details, false)
end
subject! { get(:demande, params: { id: dossier.id }) } subject! { get(:demande, params: { id: dossier.id }) }
it { expect(assigns(:dossier)).to eq(dossier) } it { expect(assigns(:dossier)).to eq(dossier) }

View file

@ -105,7 +105,7 @@ shared_examples 'carte_controller_spec' do
end end
it 'Redirection vers le formulaire de la procedure' do it 'Redirection vers le formulaire de la procedure' do
expect(response).to redirect_to(modifier_dossier_path(dossier)) expect(response).to redirect_to(brouillon_dossier_path(dossier))
end end
end end

View file

@ -56,7 +56,7 @@ describe Users::Dossiers::InvitesController, type: :controller do
let(:dossier) { create :dossier, state: Dossier.states.fetch(:brouillon) } let(:dossier) { create :dossier, state: Dossier.states.fetch(:brouillon) }
it { is_expected.to have_http_status(302) } it { is_expected.to have_http_status(302) }
it { is_expected.to redirect_to modifier_dossier_path(dossier) } it { is_expected.to redirect_to brouillon_dossier_path(dossier) }
end end
context 'and dossier is not a brouillon' do context 'and dossier is not a brouillon' do

View file

@ -355,7 +355,7 @@ describe Users::DossiersController, type: :controller do
context 'procedure not use api carto' do context 'procedure not use api carto' do
it 'redirects to demande' do it 'redirects to demande' do
expect(response).to redirect_to(modifier_dossier_path(dossier)) expect(response).to redirect_to(brouillon_dossier_path(dossier))
end end
end end

View file

@ -96,12 +96,12 @@ feature 'The user' do
click_on 'Enregistrer le brouillon' click_on 'Enregistrer le brouillon'
expect(user_dossier.reload.brouillon?).to be(true) expect(user_dossier.reload.brouillon?).to be(true)
expect(page).to have_content('Votre brouillon a bien été sauvegardé') expect(page).to have_content('Votre brouillon a bien été sauvegardé')
expect(page).to have_current_path(modifier_dossier_path(user_dossier)) expect(page).to have_current_path(brouillon_dossier_path(user_dossier))
# Check an incomplete dossier cannot be submitted when mandatory fields are missing # Check an incomplete dossier cannot be submitted when mandatory fields are missing
click_on 'Soumettre le dossier' click_on 'Soumettre le dossier'
expect(user_dossier.reload.brouillon?).to be(true) expect(user_dossier.reload.brouillon?).to be(true)
expect(page).to have_current_path(modifier_dossier_path(user_dossier)) expect(page).to have_current_path(brouillon_dossier_path(user_dossier))
# Check a dossier can be submitted when all mandatory fields are filled # Check a dossier can be submitted when all mandatory fields are filled
fill_in('texte obligatoire', with: 'super texte') fill_in('texte obligatoire', with: 'super texte')
@ -152,7 +152,7 @@ feature 'The user' do
fill_in('individual_nom', with: 'nom') fill_in('individual_nom', with: 'nom')
check 'dossier_autorisation_donnees' check 'dossier_autorisation_donnees'
click_on 'Continuer' click_on 'Continuer'
expect(page).to have_current_path(modifier_dossier_path(user_dossier)) expect(page).to have_current_path(brouillon_dossier_path(user_dossier))
end end
def select_date_and_time(date, field) def select_date_and_time(date, field)

View file

@ -16,7 +16,7 @@ feature 'Invitations' do
fill_in 'Libelle du champ', with: 'Some edited value' fill_in 'Libelle du champ', with: 'Some edited value'
send_invite_to "user_invite@exemple.fr" send_invite_to "user_invite@exemple.fr"
expect(page).to have_current_path(modifier_dossier_path(dossier)) expect(page).to have_current_path(brouillon_dossier_path(dossier))
expect(page).to have_text("Une invitation a été envoyée à user_invite@exemple.fr.") expect(page).to have_text("Une invitation a été envoyée à user_invite@exemple.fr.")
expect(page).to have_text("user_invite@exemple.fr") expect(page).to have_text("user_invite@exemple.fr")
@ -29,7 +29,7 @@ feature 'Invitations' do
expect(page).to have_current_path(new_user_session_path) expect(page).to have_current_path(new_user_session_path)
submit_login_form(invited_user) submit_login_form(invited_user)
expect(page).to have_current_path(modifier_dossier_path(dossier)) expect(page).to have_current_path(brouillon_dossier_path(dossier))
expect(page).to have_no_selector('.button.invite-user-action') expect(page).to have_no_selector('.button.invite-user-action')
fill_in 'Libelle du champ', with: 'Some edited value' fill_in 'Libelle du champ', with: 'Some edited value'
@ -43,7 +43,7 @@ feature 'Invitations' do
expect(page).to have_current_path(new_user_session_path) expect(page).to have_current_path(new_user_session_path)
submit_login_form(invited_user) submit_login_form(invited_user)
expect(page).to have_current_path(modifier_dossier_path(dossier)) expect(page).to have_current_path(brouillon_dossier_path(dossier))
expect(page).to have_button('Soumettre le dossier', disabled: true) expect(page).to have_button('Soumettre le dossier', disabled: true)
expect(page).to have_selector('.invite-cannot-submit') expect(page).to have_selector('.invite-cannot-submit')
@ -75,10 +75,10 @@ feature 'Invitations' do
# We should be able to just click() the link, but Capybara detects that the # We should be able to just click() the link, but Capybara detects that the
# enclosing div would be clicked instead. # enclosing div would be clicked instead.
expect(page).to have_link("MODIFIER", href: modifier_dossier_path(dossier)) expect(page).to have_link("MODIFIER", href: brouillon_dossier_path(dossier))
visit modifier_dossier_path(dossier) visit brouillon_dossier_path(dossier)
expect(page).to have_current_path(modifier_dossier_path(dossier)) expect(page).to have_current_path(brouillon_dossier_path(dossier))
fill_in "Libelle du champ", with: "Some edited value" fill_in "Libelle du champ", with: "Some edited value"
click_button "Enregistrer les modifications du dossier" click_button "Enregistrer les modifications du dossier"
@ -105,7 +105,7 @@ feature 'Invitations' do
def navigate_to_brouillon(dossier) def navigate_to_brouillon(dossier)
expect(page).to have_current_path(dossiers_path) expect(page).to have_current_path(dossiers_path)
click_on(dossier.id) click_on(dossier.id)
expect(page).to have_current_path(modifier_dossier_path(dossier)) expect(page).to have_current_path(brouillon_dossier_path(dossier))
end end
def navigate_to_recapitulatif(dossier) def navigate_to_recapitulatif(dossier)

View file

@ -61,7 +61,7 @@ feature 'linked dropdown lists' do
fill_in('individual_nom', with: 'nom') fill_in('individual_nom', with: 'nom')
check 'dossier_autorisation_donnees' check 'dossier_autorisation_donnees'
click_on 'Continuer' click_on 'Continuer'
expect(page).to have_current_path(modifier_dossier_path(user_dossier)) expect(page).to have_current_path(brouillon_dossier_path(user_dossier))
end end
def primary_id_for(libelle) def primary_id_for(libelle)

View file

@ -64,7 +64,7 @@ feature 'user path for dossier creation' do
page.find_by_id('etape_suivante').click page.find_by_id('etape_suivante').click
end end
scenario 'user is on edition page' do scenario 'user is on edition page' do
expect(page).to have_current_path(modifier_dossier_path(Dossier.last)) expect(page).to have_current_path(brouillon_dossier_path(Dossier.last))
end end
context 'user fill and validate description page' do context 'user fill and validate description page' do
before do before do

View file

@ -28,7 +28,7 @@ feature 'As a User I wanna create a dossier' do
expect(page).to have_current_path(users_dossier_carte_path(procedure_for_individual.dossiers.last.id)) expect(page).to have_current_path(users_dossier_carte_path(procedure_for_individual.dossiers.last.id))
click_button('Etape suivante') click_button('Etape suivante')
expect(page).to have_current_path(modifier_dossier_path(procedure_for_individual.dossiers.last)) expect(page).to have_current_path(brouillon_dossier_path(procedure_for_individual.dossiers.last))
expect(user.dossiers.first.individual.birthdate).to eq(Date.new(1987, 10, 14)) expect(user.dossiers.first.individual.birthdate).to eq(Date.new(1987, 10, 14))
end end
@ -40,7 +40,7 @@ feature 'As a User I wanna create a dossier' do
expect(page).to have_current_path(users_dossier_carte_path(procedure_for_individual.dossiers.last.id.to_s)) expect(page).to have_current_path(users_dossier_carte_path(procedure_for_individual.dossiers.last.id.to_s))
click_button('Etape suivante') click_button('Etape suivante')
expect(page).to have_current_path(modifier_dossier_path(procedure_for_individual.dossiers.last)) expect(page).to have_current_path(brouillon_dossier_path(procedure_for_individual.dossiers.last))
expect(user.dossiers.first.individual.birthdate).to eq(Date.new(1987, 10, 14)) expect(user.dossiers.first.individual.birthdate).to eq(Date.new(1987, 10, 14))
end end
@ -55,7 +55,7 @@ feature 'As a User I wanna create a dossier' do
expect(page).to have_current_path(users_dossier_carte_path(procedure_for_individual.dossiers.last)) expect(page).to have_current_path(users_dossier_carte_path(procedure_for_individual.dossiers.last))
click_button('Etape suivante') click_button('Etape suivante')
expect(page).to have_current_path(modifier_dossier_path(procedure_for_individual.dossiers.last)) expect(page).to have_current_path(brouillon_dossier_path(procedure_for_individual.dossiers.last))
expect(user.dossiers.first.individual.birthdate).to eq(nil) expect(user.dossiers.first.individual.birthdate).to eq(nil)
end end
@ -85,7 +85,7 @@ feature 'As a User I wanna create a dossier' do
page.find_by_id('etape_suivante').click page.find_by_id('etape_suivante').click
expect(page).to have_current_path(users_dossier_carte_path(procedure_with_siret.dossiers.last.id.to_s)) expect(page).to have_current_path(users_dossier_carte_path(procedure_with_siret.dossiers.last.id.to_s))
page.find_by_id('etape_suivante').click page.find_by_id('etape_suivante').click
expect(page).to have_current_path(modifier_dossier_path(procedure_with_siret.dossiers.last)) expect(page).to have_current_path(brouillon_dossier_path(procedure_with_siret.dossiers.last))
end end
end end
end end

View file

@ -18,4 +18,51 @@ RSpec.describe CommentaireHelper, type: :helper do
it { is_expected.to eq nil } it { is_expected.to eq nil }
end end
end end
describe '.commentaire_is_from_guest' do
let(:dossier) { create(:dossier) }
let!(:guest) { create(:invite_user, dossier: dossier) }
subject { commentaire_is_from_guest(commentaire) }
context 'when the commentaire sender is not a guest' do
let(:commentaire) { create(:commentaire, dossier: dossier, email: "michel@pref.fr") }
it { is_expected.to be false }
end
context 'when the commentaire sender is a guest on this dossier' do
let(:commentaire) { create(:commentaire, dossier: dossier, email: guest.email) }
it { is_expected.to be true }
end
end
describe '.commentaire_date' do
let(:present_date) { Time.local(2018, 9, 2, 10, 5, 0) }
let(:creation_date) { present_date }
let(:commentaire) do
Timecop.freeze(creation_date) { create(:commentaire, email: "michel@pref.fr") }
end
subject do
Timecop.freeze(present_date) { commentaire_date(commentaire) }
end
it 'doesnt include the creation year' do
expect(subject).to eq 'le 2 septembre à 10 h 05'
end
context 'when displaying a commentaire created on a previous year' do
let(:creation_date) { present_date.prev_year }
it 'includes the creation year' do
expect(subject).to eq 'le 2 septembre 2017 à 10 h 05'
end
end
context 'when formatting the first day of the month' do
let(:present_date) { Time.local(2018, 9, 1, 10, 5, 0) }
it 'includes the ordinal' do
expect(subject).to eq 'le 1er septembre à 10 h 05'
end
end
end
end end

View file

@ -31,7 +31,7 @@ RSpec.describe DossierHelper, type: :helper do
context "when the dossier is in the brouillon state" do context "when the dossier is in the brouillon state" do
let(:dossier) { create(:dossier, state: Dossier.states.fetch(:brouillon)) } let(:dossier) { create(:dossier, state: Dossier.states.fetch(:brouillon)) }
it { is_expected.to eq "/dossiers/#{dossier.id}/modifier" } it { is_expected.to eq "/dossiers/#{dossier.id}/brouillon" }
end end
context "when the dossier is any other state" do context "when the dossier is any other state" do

View file

@ -1,6 +1,6 @@
require 'spec_helper' require 'spec_helper'
describe 'new_user/dossiers/modifier.html.haml', type: :view do describe 'new_user/dossiers/brouillon.html.haml', type: :view do
let(:procedure) { create(:procedure, :with_api_carto, :with_two_type_de_piece_justificative, :with_notice, for_individual: true) } let(:procedure) { create(:procedure, :with_api_carto, :with_two_type_de_piece_justificative, :with_notice, for_individual: true) }
let(:dossier) { create(:dossier, :with_entreprise, :with_service, state: Dossier.states.fetch(:brouillon), procedure: procedure) } let(:dossier) { create(:dossier, :with_entreprise, :with_service, state: Dossier.states.fetch(:brouillon), procedure: procedure) }
let(:footer) { view.content_for(:footer) } let(:footer) { view.content_for(:footer) }

View file

@ -26,7 +26,7 @@ describe 'new_user/dossiers/index.html.haml', type: :view do
dossier = user_dossiers.first dossier = user_dossiers.first
expect(rendered).to have_text(dossier_brouillon.id) expect(rendered).to have_text(dossier_brouillon.id)
expect(rendered).to have_text(dossier_brouillon.procedure.libelle) expect(rendered).to have_text(dossier_brouillon.procedure.libelle)
expect(rendered).to have_link(dossier_brouillon.id, href: modifier_dossier_path(dossier_brouillon)) expect(rendered).to have_link(dossier_brouillon.id, href: brouillon_dossier_path(dossier_brouillon))
expect(rendered).to have_text(dossier_en_construction.id) expect(rendered).to have_text(dossier_en_construction.id)
expect(rendered).to have_text(dossier_en_construction.procedure.libelle) expect(rendered).to have_text(dossier_en_construction.procedure.libelle)

View file

@ -31,7 +31,7 @@ describe 'users/recapitulatif/show.html.haml', type: :view do
end end
it 'le lien vers l édition est correct' do it 'le lien vers l édition est correct' do
expect(rendered).to have_selector("a[id=maj_infos][href='/dossiers/#{dossier_id}/modifier']") expect(rendered).to have_selector("a[id=maj_infos][href='/dossiers/#{dossier_id}/brouillon']")
end end
end end