Merge branch 'develop' into customize_submission_mail

This commit is contained in:
LeSim 2017-03-07 11:05:04 +01:00 committed by GitHub
commit 9764604430
32 changed files with 370 additions and 143 deletions

View file

@ -46,6 +46,7 @@
min-height: 58px; min-height: 58px;
color: #000000; color: #000000;
overflow: hidden; overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.options { .options {

View file

@ -159,7 +159,7 @@ class Backoffice::DossiersController < Backoffice::DossiersListController
end end
def archive def archive
facade = create_dossier_facade params[:dossier_id] facade = create_dossier_facade params[:id]
unless facade.dossier.archived unless facade.dossier.archived
facade.dossier.update(archived: true) facade.dossier.update(archived: true)
flash.notice = 'Dossier archivé' flash.notice = 'Dossier archivé'
@ -167,10 +167,20 @@ class Backoffice::DossiersController < Backoffice::DossiersListController
redirect_to backoffice_dossiers_path redirect_to backoffice_dossiers_path
end end
def unarchive
@dossier = Dossier.find(params[:id])
if @dossier.archived
@dossier.update(archived: false)
flash.notice = 'Dossier désarchivé'
end
redirect_to backoffice_dossier_path(@dossier)
end
def reopen def reopen
create_dossier_facade params[:dossier_id] create_dossier_facade params[:dossier_id]
@facade.dossier.initiated! @facade.dossier.replied!
flash.notice = 'Dossier réouvert.' flash.notice = 'Dossier réouvert.'
redirect_to backoffice_dossiers_path redirect_to backoffice_dossiers_path

View file

@ -29,36 +29,31 @@ class Backoffice::DossiersListController < ApplicationController
def smartlisting_dossier dossiers_list=nil, liste='all_state' def smartlisting_dossier dossiers_list=nil, liste='all_state'
dossiers_list_facade liste dossiers_list_facade liste
service = dossiers_list_facade.service
new_dossiers_list = dossiers_list_facade.service.nouveaux
follow_dossiers_list = dossiers_list_facade.service.suivi
all_state_dossiers_list = dossiers_list_facade.service.all_state
if param_page.nil? if param_page.nil?
params[:dossiers_smart_listing] = {page: dossiers_list_facade.service.default_page} params[:dossiers_smart_listing] = {page: dossiers_list_facade.service.default_page}
end end
smart_listing_create :new_dossiers, default_smart_listing_create :new_dossiers, service.nouveaux
new_dossiers_list, default_smart_listing_create :follow_dossiers, service.suivi
partial: "backoffice/dossiers/list", default_smart_listing_create :all_state_dossiers, service.all_state
array: true, default_smart_listing_create :archived_dossiers, service.archive
default_sort: dossiers_list_facade.service.default_sort
smart_listing_create :follow_dossiers, @archived_dossiers = service.archive
follow_dossiers_list,
partial: "backoffice/dossiers/list",
array: true,
default_sort: dossiers_list_facade.service.default_sort
smart_listing_create :all_state_dossiers,
all_state_dossiers_list,
partial: "backoffice/dossiers/list",
array: true,
default_sort: dossiers_list_facade.service.default_sort
end end
private private
def default_smart_listing_create name, collection
smart_listing_create name,
collection,
partial: 'backoffice/dossiers/list',
array: true,
default_sort: dossiers_list_facade.service.default_sort
end
def param_smart_listing def param_smart_listing
params[:dossiers_smart_listing] params[:dossiers_smart_listing]
end end

View file

@ -17,20 +17,21 @@ class Users::DescriptionController < UsersController
acc acc
end end
unless @dossier.can_be_initiated?
flash[:alert] = t('errors.messages.procedure_archived')
end
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
flash.alert = t('errors.messages.dossier_not_found') flash.alert = t('errors.messages.dossier_not_found')
redirect_to url_for(root_path) redirect_to url_for(root_path)
end end
# def error def update
# show
# flash.now.alert = 'Un ou plusieurs attributs obligatoires sont manquants ou incorrects.'
# render 'show'
# end
def create
@dossier = current_user_dossier @dossier = current_user_dossier
@procedure = @dossier.procedure @procedure = @dossier.procedure
return head :forbidden unless @dossier.can_be_initiated?
@champs = @dossier.ordered_champs @champs = @dossier.ordered_champs
mandatory = true mandatory = true

View file

@ -13,8 +13,11 @@ class AdminProceduresShowFacades
def dossiers_for_pie_highchart def dossiers_for_pie_highchart
dossiers.where.not(state: :draft, archived: true).group(:state).count dossiers.where.not(state: :draft, archived: true).group(:state).count
.map{|key, value| { (DossierDecorator.case_state_fr key) => value } } .reduce({}) do |acc, (key, val)|
.reduce({}, :merge) translated_key = DossierDecorator.case_state_fr(key)
acc[translated_key].nil? ? acc[translated_key] = val : acc[translated_key] += val
acc
end
end end
def dossiers_archived_by_state_total def dossiers_archived_by_state_total

View file

@ -2,7 +2,7 @@ class DossierFacades
#TODO rechercher en fonction de la personne/email #TODO rechercher en fonction de la personne/email
def initialize(dossier_id, email, champ_id = nil) def initialize(dossier_id, email, champ_id = nil)
@dossier = Dossier.where(archived: false).find(dossier_id) @dossier = Dossier.find(dossier_id)
@champ_id = champ_id @champ_id = champ_id
end end

View file

@ -38,6 +38,8 @@ class Dossier < ActiveRecord::Base
delegate :types_de_champ, to: :procedure delegate :types_de_champ, to: :procedure
delegate :france_connect_information, to: :user delegate :france_connect_information, to: :user
before_validation :update_state_dates, if: -> { state_changed? }
after_save :build_default_champs, if: Proc.new { procedure_id_changed? } after_save :build_default_champs, if: Proc.new { procedure_id_changed? }
after_save :build_default_individual, if: Proc.new { procedure.for_individual? } after_save :build_default_individual, if: Proc.new { procedure.for_individual? }
@ -199,6 +201,8 @@ class Dossier < ActiveRecord::Base
where(state: TERMINE, archived: false).order("updated_at #{order}") where(state: TERMINE, archived: false).order("updated_at #{order}")
end end
scope :archived, -> { where(archived: true) }
def cerfa_available? def cerfa_available?
procedure.cerfa_flag? && cerfa.size != 0 procedure.cerfa_flag? && cerfa.size != 0
end end
@ -302,4 +306,21 @@ class Dossier < ActiveRecord::Base
def invite_by_user? email def invite_by_user? email
(invites_user.pluck :email).include? email (invites_user.pluck :email).include? email
end end
def can_be_initiated?
!(procedure.archived && draft?)
end
private
def update_state_dates
if initiated? && !self.initiated_at
self.initiated_at = DateTime.now
elsif received? && !self.received_at
self.received_at = DateTime.now
elsif TERMINE.include?(state)
self.processed_at = DateTime.now
end
end
end end

View file

@ -4,7 +4,10 @@ class DossierProcedureSerializer < ActiveModel::Serializer
:updated_at, :updated_at,
:archived, :archived,
:mandataire_social, :mandataire_social,
:state :state,
:initiated_at,
:received_at,
:processed_at
attribute :followers_gestionnaires_emails, key: :emails_accompagnateurs attribute :followers_gestionnaires_emails, key: :emails_accompagnateurs
end end

View file

@ -11,6 +11,7 @@ class DossiersListGestionnaireService
'a_traiter' => ouvert, 'a_traiter' => ouvert,
'a_instruire' => a_instruire, 'a_instruire' => a_instruire,
'termine' => termine, 'termine' => termine,
'archive' => archive,
'all_state' => all_state}[@liste] 'all_state' => all_state}[@liste]
end end
@ -39,6 +40,10 @@ class DossiersListGestionnaireService
@a_instruire ||= filter_dossiers.a_instruire @a_instruire ||= filter_dossiers.a_instruire
end end
def archive
@archive ||= filter_dossiers.archived
end
def termine def termine
@termine ||= filter_dossiers.termine @termine ||= filter_dossiers.termine
end end

View file

@ -1,9 +1,9 @@
%table#dossiers_list.table %table#dossiers_list.table
%thead %thead
- if smart_listing.name.to_s == 'follow_dossiers' - if smart_listing.name.to_s == 'follow_dossiers'
%th.col-md-1.col-lg-1.col-sm-1.col-xs-1.col-sm-1.col-xs-1.center %th.col-xs-1.center
%i.fa.fa-bell %i.fa.fa-bell
%th.col-md-1.col-lg-1.col-sm-1.col-xs-1.col-sm-1.col-xs-1 %th.col-xs-1
État État
- @facade_data_view.preference_list_dossiers_filter.each do |preference| - @facade_data_view.preference_list_dossiers_filter.each do |preference|
@ -17,14 +17,14 @@
%i.filter.fa.fa-filter{style: "color:#{(preference.filter.blank? ? 'grey' : 'orange')}", id: "filter_#{smart_listing.name.to_s}_#{preference.table_attr.sub('.', '_')}"} %i.filter.fa.fa-filter{style: "color:#{(preference.filter.blank? ? 'grey' : 'orange')}", id: "filter_#{smart_listing.name.to_s}_#{preference.table_attr.sub('.', '_')}"}
= render partial: 'backoffice/dossiers/filter_framed', locals:{preference: preference, filter_framed_id: "framed_filter_#{smart_listing.name.to_s}_#{preference.table_attr.sub('.', '_')}"} = render partial: 'backoffice/dossiers/filter_framed', locals:{preference: preference, filter_framed_id: "framed_filter_#{smart_listing.name.to_s}_#{preference.table_attr.sub('.', '_')}"}
%th.col-md-1.col-lg-1.col-sm-1.col-xs-1.col-sm-1.col-xs-1.center Actions %th.col-xs-1.center Actions
%th.col-md-1.col-lg-1.col-sm-1.col-xs-1.col-sm-1.col-xs-1.center Abonnés %th.col-xs-1.center Abonnés
- unless smart_listing.empty? - unless smart_listing.empty?
- smart_listing.collection.each do |dossier| - smart_listing.collection.each do |dossier|
%tr.dossier-row{id: "tr_dossier_#{dossier.id}", 'data-dossier_url' => backoffice_dossier_url(id: dossier.id)} %tr.dossier-row{id: "tr_dossier_#{dossier.id}", 'data-dossier_url' => backoffice_dossier_url(id: dossier.id)}
- if smart_listing.name.to_s == 'follow_dossiers' - if smart_listing.name.to_s == 'follow_dossiers'
%td.col-md-1.col-lg-1.col-sm-1.col-xs-1.col-sm-1.col-xs-1.center %td.col-xs-1.center
- total_notif = dossier.notifications.where(already_read: false).count - total_notif = dossier.notifications.where(already_read: false).count
- if total_notif == 0 - if total_notif == 0
.badge.progress-bar-default .badge.progress-bar-default
@ -32,7 +32,7 @@
- else - else
.badge.progress-bar-warning .badge.progress-bar-warning
= total_notif = total_notif
%td.col-md-1.col-lg-1.col-sm-1.col-xs-1.col-sm-1.col-xs-1 %td.col-xs-1
= dossier.decorate.display_state = dossier.decorate.display_state
- @facade_data_view.preference_list_dossiers_filter.each_with_index do |preference, index| - @facade_data_view.preference_list_dossiers_filter.each_with_index do |preference, index|
- unless preference.libelle == 'Statut' || preference.libelle == 'État' - unless preference.libelle == 'Statut' || preference.libelle == 'État'

View file

@ -3,53 +3,62 @@
= render partial: 'backoffice/dossiers/pref_list' = render partial: 'backoffice/dossiers/pref_list'
.default_data_block .default_data_block
%div.row.show-block#new_dossiers .row.show-block#new_dossiers
%div.header .header
%div.col-lg-10.col-md-10.col-sm-10.col-xs-10.title .col-xs-10.title
%div.carret-right .carret-right
%div.carret-down .carret-down
Nouveaux dossiers Nouveaux dossiers
%div.col-lg-2.col-md-2.col-sm-2.col-xs-2.count .col-xs-2.count
=@facade_data_view.nouveaux_total = pluralize(@facade_data_view.nouveaux_total, "dossier")
dossiers .body
%div.body
= smart_listing_render :new_dossiers = smart_listing_render :new_dossiers
.row.center .row.center
.col-lg-1.col-md-1.col-sm-1.col-xs-1 .col-xs-3
.col-lg-2.col-md-2.col-sm-2.col-xs-2
=link_to 'Tous les états', '?liste=all_state', class: 'text-info', style:"text-decoration: #{@facade_data_view.liste == 'all_state'? 'underline' : ''}" =link_to 'Tous les états', '?liste=all_state', class: 'text-info', style:"text-decoration: #{@facade_data_view.liste == 'all_state'? 'underline' : ''}"
.col-lg-2.col-md-2.col-sm-2.col-xs-2 .col-xs-3
=link_to 'En construction', '?liste=a_traiter', class: 'text-danger', style:"text-decoration: #{@facade_data_view.liste == 'a_traiter'? 'underline' : ''}" =link_to 'En construction', '?liste=a_traiter', class: 'text-danger', style:"text-decoration: #{@facade_data_view.liste == 'a_traiter'? 'underline' : ''}"
.col-lg-2.col-md-2.col-sm-2.col-xs-2 .col-xs-3
=link_to 'À receptionner', '?liste=deposes', class: 'text-purple', style:"text-decoration: #{@facade_data_view.liste == 'deposes'? 'underline' : ''}" =link_to 'En instruction', '?liste=a_instruire', class: 'text-warning', style:"text-decoration: #{@facade_data_view.liste == 'a_instruire'? 'underline' : ''}"
.col-lg-2.col-md-2.col-sm-2.col-xs-2 .col-xs-3
=link_to 'À instruire', '?liste=a_instruire', class: 'text-warning', style:"text-decoration: #{@facade_data_view.liste == 'a_instruire'? 'underline' : ''}"
.col-lg-2.col-md-2.col-sm-2.col-xs-2
=link_to 'Terminés', '?liste=termine', class: 'text-success', style:"text-decoration: #{@facade_data_view.liste == 'termine'? 'underline' : ''}" =link_to 'Terminés', '?liste=termine', class: 'text-success', style:"text-decoration: #{@facade_data_view.liste == 'termine'? 'underline' : ''}"
.default_data_block.default_visible .default_data_block.default_visible
%div.row.show-block#follow_dossiers .row.show-block#follow_dossiers
%div.header .header
%div.col-lg-10.col-md-10.col-sm-10.col-xs-10.title .col-xs-10.title
%div.carret-right .carret-right
%div.carret-down .carret-down
Dossiers suivis Dossiers suivis
%div.col-lg-2.col-md-2.col-sm-2.col-xs-2.count .col-xs-2.count
=@facade_data_view.suivi_total = pluralize(@facade_data_view.suivi_total, "dossier")
dossiers .body
%div.body
= smart_listing_render :follow_dossiers = smart_listing_render :follow_dossiers
.default_data_block .default_data_block
%div.row.show-block#all_dossiers .row.show-block#all_dossiers
%div.header .header
%div.col-lg-10.col-md-10.col-sm-10.col-xs-10.title .col-xs-10.title
%div.carret-right .carret-right
%div.carret-down .carret-down
Tous les dossiers Tous les dossiers
%div.col-lg-2.col-md-2.col-sm-2.col-xs-2.count .col-xs-2.count
=@facade_data_view.all_state_total = pluralize(@facade_data_view.all_state_total, "dossier")
dossiers .body
%div.body
= smart_listing_render :all_state_dossiers = smart_listing_render :all_state_dossiers
- if @archived_dossiers
.default_data_block
.row.show-block#archived_dossiers
.header
.col-xs-10.title
.carret-right
.carret-down
Dossiers archivés
.col-xs-2.count
= pluralize(@archived_dossiers.count, "dossier")
.body
= smart_listing_render :archived_dossiers

View file

@ -1,11 +1,11 @@
%div#first-block #first-block
%div.infos .infos
#dossier_id= t('dynamics.dossiers.numéro') + @facade.dossier.id.to_s #dossier_id= t('dynamics.dossiers.numéro') + @facade.dossier.id.to_s
%div#action-block #action-block
- if gestionnaire_signed_in? - if gestionnaire_signed_in?
- if !@facade.dossier.read_only? || @facade.dossier.initiated? - if !@facade.dossier.read_only? || @facade.dossier.initiated?
= link_to 'Accuser réception', backoffice_dossier_receive_path(@facade.dossier), method: :post, class: 'btn btn-danger btn-block' = link_to 'Passer en instruction', backoffice_dossier_receive_path(@facade.dossier), method: :post, class: 'btn btn-danger btn-block'
- elsif @facade.dossier.received? - elsif @facade.dossier.received?
= form_tag(url_for({controller: 'backoffice/dossiers', action: :close, dossier_id: @facade.dossier.id}), class: 'form-inline action_button', method: 'POST', style: 'display:inline', 'data-toggle' => :tooltip, title: 'Accepter') do = form_tag(url_for({controller: 'backoffice/dossiers', action: :close, dossier_id: @facade.dossier.id}), class: 'form-inline action_button', method: 'POST', style: 'display:inline', 'data-toggle' => :tooltip, title: 'Accepter') do
@ -19,18 +19,24 @@
%i.fa.fa-times %i.fa.fa-times
= link_to 'Reouvrir', backoffice_dossier_reopen_path(@facade.dossier), method: :post, class: 'btn btn-default btn-block' = link_to 'Reouvrir', backoffice_dossier_reopen_path(@facade.dossier), method: :post, class: 'btn btn-default btn-block'
- unless @facade.dossier.archived? %hr
= link_to 'Archiver', backoffice_dossier_archive_path(@facade.dossier), method: :post, class: 'btn btn-default btn-block' - if @facade.dossier.archived?
%p
Archivé
= link_to 'Désarchiver', unarchive_backoffice_dossier_path(@facade.dossier), method: :post, class: 'btn btn-default btn-block'
- else
= link_to 'Archiver', archive_backoffice_dossier_path(@facade.dossier), method: :post, class: 'btn btn-default btn-block'
%div#menu-block #menu-block
%div#infos-block #infos-block
%div.split-hr-left .split-hr-left
%div.dossier-state= @facade.dossier.display_state .dossier-state= @facade.dossier.display_state
%div.split-hr-left .split-hr-left
%div.notifications .notifications
- if @facade.dossier.notifications.empty? - if @facade.dossier.notifications.empty?
Aucune notification pour le moment. Aucune notification pour le moment.
- else - else

View file

@ -25,13 +25,13 @@
%a{:href => "#{url_for users_dossiers_path(liste: 'en_instruction')}", 'data-toggle' => :tooltip, title: 'Les dossiers en cours d\'examen par l\'administration compétante.'} %a{:href => "#{url_for users_dossiers_path(liste: 'en_instruction')}", 'data-toggle' => :tooltip, title: 'Les dossiers en cours d\'examen par l\'administration compétante.'}
%div.procedure_list_element{ class: @dossiers_list_facade.en_instruction_class, id: 'en_instruction' } %div.procedure_list_element{ class: @dossiers_list_facade.en_instruction_class, id: 'en_instruction' }
="En examen" ="En instruction"
.badge.progress-bar-default .badge.progress-bar-default
= @dossiers_list_facade.en_instruction_total = @dossiers_list_facade.en_instruction_total
%a{:href => "#{url_for users_dossiers_path(liste: 'termine')}", 'data-toggle' => :tooltip, title: 'Les dossiers cloturés qui peuvent être "Accepté", "Refusé" ou "Sans suite".'} %a{:href => "#{url_for users_dossiers_path(liste: 'termine')}", 'data-toggle' => :tooltip, title: 'Les dossiers cloturés qui peuvent être "Accepté", "Refusé" ou "Sans suite".'}
%div.procedure_list_element{ class: @dossiers_list_facade.termine_class, id: 'termine' } %div.procedure_list_element{ class: @dossiers_list_facade.termine_class, id: 'termine' }
= "Cloturé" = "Terminé"
.badge.progress-bar-success .badge.progress-bar-success
= @dossiers_list_facade.termine_total = @dossiers_list_facade.termine_total

View file

@ -15,7 +15,7 @@
= @dossier.procedure.libelle = @dossier.procedure.libelle
-#TODO use form_for -#TODO use form_for
= form_tag(url_for({controller: 'users/description', action: :create, dossier_id: @dossier.id}), class: 'form', method: 'POST', multipart: true) do = form_tag(url_for({controller: 'users/description', action: :update, dossier_id: @dossier.id}), class: 'form', method: 'POST', multipart: true) do
-unless @champs.nil? -unless @champs.nil?
#liste_champs #liste_champs
=render partial: 'users/description/champs', locals:{private: false} =render partial: 'users/description/champs', locals:{private: false}
@ -41,16 +41,16 @@
Vous pourrez dans tous les cas les compléter plus tard si vous ne les possédez pas de suite. Vous pourrez dans tous les cas les compléter plus tard si vous ne les possédez pas de suite.
-route = Rails.application.routes.recognize_path(request.referrer) -route = Rails.application.routes.recognize_path(request.referrer) # WTF ?
- unless route[:controller].match('admin') - unless route[:controller].match('admin')
%div{style: 'text-align:right'} %div{style: 'text-align:right'}
%h6 Tous les champs portant un * sont obligatoires. %h6 Tous les champs portant un * sont obligatoires.
-if !@dossier.draft? - if !@dossier.can_be_initiated?
.alert.alert-danger
= t('errors.messages.procedure_archived')
- elsif !@dossier.draft?
= render partial: '/layouts/modifications_terminees' = render partial: '/layouts/modifications_terminees'
- else - else
= submit_tag 'Soumettre mon dossier', id: 'suivant', name: 'submit[nouveaux]', class: %w(btn btn btn-success), style: 'float:right', data: { disable_with: 'Soumettre votre dossier', submit: true} = submit_tag 'Soumettre mon dossier', id: 'suivant', name: 'submit[nouveaux]', class: 'btn btn btn-success', style: 'float:right', disabled: @procedure.archived?, data: { disable_with: 'Soumettre votre dossier', submit: true}
= submit_tag 'Enregistrer un brouillon', id: 'brouillon', name: 'submit[brouillon]', class: %w(btn btn-xs btn-default), style: 'float:right; margin-right: 10px; margin-top: 6px', data: {disable_with: 'Enregistrer un brouillon', submit: true} = submit_tag 'Enregistrer un brouillon', id: 'brouillon', name: 'submit[brouillon]', class: 'btn btn-xs btn-default', style: 'float:right; margin-right: 10px; margin-top: 6px', disabled: @procedure.archived?, data: {disable_with: 'Enregistrer un brouillon', submit: true}
%br
%br

View file

@ -147,6 +147,7 @@ fr:
france_connect: france_connect:
connexion: "Erreur lors de la connexion à France Connect." connexion: "Erreur lors de la connexion à France Connect."
extension_white_list_error: "Le format de fichier de la pièce jointe n'est pas valide." extension_white_list_error: "Le format de fichier de la pièce jointe n'est pas valide."
procedure_archived: "Cette démarche en ligne a été fermée, il n'est plus possible de déposer de dossier."
datetime: datetime:
distance_in_words: distance_in_words:

View file

@ -9,7 +9,7 @@ fr:
date_previsionnelle: "La date de début prévisionnelle" date_previsionnelle: "La date de début prévisionnelle"
state: state:
draft: "Brouillon" draft: "Brouillon"
initiated: "Nouveau" initiated: "En construction"
replied: "En construction" replied: "En construction"
updated: "En construction" updated: "En construction"
received: "En instruction" received: "En instruction"

View file

@ -63,9 +63,8 @@ Rails.application.routes.draw do
resources :dossiers do resources :dossiers do
get '/add_siret' => 'dossiers/add_siret#show' get '/add_siret' => 'dossiers/add_siret#show'
get '/description' => 'description#show' get 'description' => 'description#show'
# get '/description/error' => 'description#error' post 'description' => 'description#update'
post 'description' => 'description#create'
patch 'pieces_justificatives' => 'description#pieces_justificatives' patch 'pieces_justificatives' => 'description#pieces_justificatives'
@ -162,9 +161,11 @@ Rails.application.routes.draw do
post 'refuse' => 'dossiers#refuse' post 'refuse' => 'dossiers#refuse'
post 'without_continuation' => 'dossiers#without_continuation' post 'without_continuation' => 'dossiers#without_continuation'
post 'close' => 'dossiers#close' post 'close' => 'dossiers#close'
post 'archive' => 'dossiers#archive' member do
post 'archive'
post 'unarchive'
end
post 'reopen' => 'dossiers#reopen' post 'reopen' => 'dossiers#reopen'
put 'follow' => 'dossiers#follow' put 'follow' => 'dossiers#follow'
resources :commentaires, only: [:index] resources :commentaires, only: [:index]
end end

View file

@ -0,0 +1,7 @@
class AddStateDatesToDossiers < ActiveRecord::Migration[5.0]
def change
add_column :dossiers, :initiated_at, :datetime
add_column :dossiers, :received_at, :datetime
add_column :dossiers, :processed_at, :datetime
end
end

View file

@ -0,0 +1,8 @@
class RemoveDepositDatetimeFromDossiers < ActiveRecord::Migration[5.0]
def change
Dossier.where.not(deposit_datetime: nil).each do |dossier|
dossier.update(initiated_at: dossier.deposit_datetime)
end
remove_column :dossiers, :deposit_datetime, :datetime
end
end

View file

@ -10,6 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20170307092820) do ActiveRecord::Schema.define(version: 20170307092820) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
@ -135,7 +136,9 @@ ActiveRecord::Schema.define(version: 20170307092820) do
t.text "json_latlngs" t.text "json_latlngs"
t.boolean "archived", default: false t.boolean "archived", default: false
t.boolean "mandataire_social", default: false t.boolean "mandataire_social", default: false
t.datetime "deposit_datetime" t.datetime "initiated_at"
t.datetime "received_at"
t.datetime "processed_at"
t.index ["procedure_id"], name: "index_dossiers_on_procedure_id", using: :btree t.index ["procedure_id"], name: "index_dossiers_on_procedure_id", using: :btree
t.index ["user_id"], name: "index_dossiers_on_user_id", using: :btree t.index ["user_id"], name: "index_dossiers_on_user_id", using: :btree
end end

View file

@ -3,6 +3,8 @@ require 'spec_helper'
describe Backoffice::Dossiers::ProcedureController, type: :controller do describe Backoffice::Dossiers::ProcedureController, type: :controller do
let(:gestionnaire) { create :gestionnaire } let(:gestionnaire) { create :gestionnaire }
let(:procedure) { create :procedure } let(:procedure) { create :procedure }
let(:archived) { false }
let(:dossier) { create :dossier, procedure: procedure, archived: archived, state: 'initiated'}
before do before do
create :assign_to, gestionnaire: gestionnaire, procedure: procedure create :assign_to, gestionnaire: gestionnaire, procedure: procedure
@ -28,6 +30,24 @@ describe Backoffice::Dossiers::ProcedureController, type: :controller do
it { is_expected.to redirect_to backoffice_dossiers_path } it { is_expected.to redirect_to backoffice_dossiers_path }
it { expect(flash[:alert]).to be_present} it { expect(flash[:alert]).to be_present}
end end
context 'when procedure contains a dossier' do
render_views
before do
dossier
subject
end
it { expect(response.body).to have_content('Tous les dossiers 1 dossier') }
context 'archived' do
let(:archived) { true }
it { expect(response.body).to have_content('Tous les dossiers 0 dossiers') }
it { expect(response.body).to have_content('Dossiers archivés 1 dossier') }
end
end
end end
describe 'GET #filter' do describe 'GET #filter' do

View file

@ -104,12 +104,6 @@ describe Backoffice::DossiersController, type: :controller do
end end
end end
context ' when dossier is archived' do
let(:dossier_id) { dossier_archived }
it { expect(subject).to redirect_to('/backoffice') }
end
context 'when dossier id does not exist' do context 'when dossier id does not exist' do
let(:dossier_id) { bad_dossier_id } let(:dossier_id) { bad_dossier_id }
@ -372,11 +366,11 @@ describe Backoffice::DossiersController, type: :controller do
subject { post :reopen, params: {dossier_id: dossier_id} } subject { post :reopen, params: {dossier_id: dossier_id} }
it 'change state to initiated' do it 'change state to replied' do
subject subject
dossier.reload dossier.reload
expect(dossier.state).to eq('initiated') expect(dossier.state).to eq('replied')
end end
it { is_expected.to redirect_to backoffice_dossiers_path } it { is_expected.to redirect_to backoffice_dossiers_path }
@ -388,7 +382,7 @@ describe Backoffice::DossiersController, type: :controller do
sign_in gestionnaire sign_in gestionnaire
end end
subject { post :archive, params: {dossier_id: dossier_id} } subject { post :archive, params: {id: dossier_id} }
it 'change state to archived' do it 'change state to archived' do
subject subject

View file

@ -17,12 +17,27 @@ shared_examples 'description_controller_spec' do
context 'when all is ok' do context 'when all is ok' do
before do before do
dossier.entreprise = create :entreprise dossier.entreprise = create :entreprise
get :show, params: {dossier_id: dossier_id}
end end
it 'returns http success' do it 'returns http success' do
get :show, params: {dossier_id: dossier_id}
expect(response).to have_http_status(:success) expect(response).to have_http_status(:success)
end end
context 'procedure is archived' do
render_views
let(:archived) { true }
it { expect(response).to have_http_status(:success) }
it { expect(response.body).to_not have_content(I18n.t('errors.messages.procedure_archived')) }
context 'dossier is a draft' do
let(:state) { 'draft' }
it { expect(response).to have_http_status(:success) }
it { expect(response.body).to have_content(I18n.t('errors.messages.procedure_archived')) }
end
end
end end
it 'redirection vers start si mauvais dossier ID' do it 'redirection vers start si mauvais dossier ID' do
@ -90,7 +105,7 @@ shared_examples 'description_controller_spec' do
end end
end end
describe 'POST #create' do describe 'POST #update' do
let(:timestamp) { Time.now } let(:timestamp) { Time.now }
let(:description) { 'Description de test Coucou, je suis un saut à la ligne Je suis un double saut la ligne.' } let(:description) { 'Description de test Coucou, je suis un saut à la ligne Je suis un double saut la ligne.' }
@ -98,7 +113,7 @@ shared_examples 'description_controller_spec' do
describe 'Premier enregistrement des données' do describe 'Premier enregistrement des données' do
let(:submit) { {nouveaux: 'nouveaux'} } let(:submit) { {nouveaux: 'nouveaux'} }
subject { post :create, params: {dossier_id: dossier_id, submit: submit} } subject { post :update, params: {dossier_id: dossier_id, submit: submit} }
before do before do
dossier.draft! dossier.draft!
@ -130,7 +145,7 @@ shared_examples 'description_controller_spec' do
context 'En train de manipuler un dossier non brouillon' do context 'En train de manipuler un dossier non brouillon' do
before do before do
dossier.initiated! dossier.initiated!
post :create, params: {dossier_id: dossier_id} post :update, params: {dossier_id: dossier_id}
dossier.reload dossier.reload
end end
@ -145,7 +160,7 @@ shared_examples 'description_controller_spec' do
end end
context 'Quand la procédure accepte les CERFA' do context 'Quand la procédure accepte les CERFA' do
subject { post :create, params: {dossier_id: dossier_id, subject { post :update, params: {dossier_id: dossier_id,
cerfa_pdf: cerfa_pdf} } cerfa_pdf: cerfa_pdf} }
it 'Notification interne is create' do it 'Notification interne is create' do
@ -154,7 +169,7 @@ shared_examples 'description_controller_spec' do
context 'Sauvegarde du CERFA PDF', vcr: {cassette_name: 'controllers_users_description_controller_save_cerfa'} do context 'Sauvegarde du CERFA PDF', vcr: {cassette_name: 'controllers_users_description_controller_save_cerfa'} do
before do before do
post :create, params: {dossier_id: dossier_id, post :update, params: {dossier_id: dossier_id,
cerfa_pdf: cerfa_pdf} cerfa_pdf: cerfa_pdf}
dossier.reload dossier.reload
end end
@ -181,7 +196,7 @@ shared_examples 'description_controller_spec' do
let(:cerfas) { Cerfa.where(dossier_id: dossier_id) } let(:cerfas) { Cerfa.where(dossier_id: dossier_id) }
before do before do
post :create, params: {dossier_id: dossier_id, cerfa_pdf: cerfa_pdf} post :update, params: {dossier_id: dossier_id, cerfa_pdf: cerfa_pdf}
end end
it "il y a deux CERFA PDF pour ce dossier" do it "il y a deux CERFA PDF pour ce dossier" do
@ -195,7 +210,7 @@ shared_examples 'description_controller_spec' do
context 'Sauvegarde du CERFA PDF' do context 'Sauvegarde du CERFA PDF' do
let!(:procedure) { create(:procedure) } let!(:procedure) { create(:procedure) }
before do before do
post :create, params: {dossier_id: dossier_id, post :update, params: {dossier_id: dossier_id,
cerfa_pdf: cerfa_pdf} cerfa_pdf: cerfa_pdf}
dossier.reload dossier.reload
end end
@ -214,7 +229,7 @@ shared_examples 'description_controller_spec' do
let(:dossier_minute_value) { '00' } let(:dossier_minute_value) { '00' }
before do before do
post :create, params: {dossier_id: dossier_id, post :update, params: {dossier_id: dossier_id,
champs: { champs: {
"'#{dossier.champs.first.id}'" => dossier_champs_first, "'#{dossier.champs.first.id}'" => dossier_champs_first,
"'#{dossier.champs.second.id}'" => dossier_date_value "'#{dossier.champs.second.id}'" => dossier_date_value
@ -254,7 +269,7 @@ shared_examples 'description_controller_spec' do
context 'Sauvegarde des pièces justificatives', vcr: {cassette_name: 'controllers_users_description_controller_sauvegarde_pj'} do context 'Sauvegarde des pièces justificatives', vcr: {cassette_name: 'controllers_users_description_controller_sauvegarde_pj'} do
let(:all_pj_type) { dossier.procedure.type_de_piece_justificative_ids } let(:all_pj_type) { dossier.procedure.type_de_piece_justificative_ids }
before do before do
post :create, params: {dossier_id: dossier_id, post :update, params: {dossier_id: dossier_id,
'piece_justificative_'+all_pj_type[0].to_s => piece_justificative_0, 'piece_justificative_'+all_pj_type[0].to_s => piece_justificative_0,
'piece_justificative_'+all_pj_type[1].to_s => piece_justificative_1} 'piece_justificative_'+all_pj_type[1].to_s => piece_justificative_1}
dossier.reload dossier.reload
@ -264,7 +279,7 @@ shared_examples 'description_controller_spec' do
it 'ClamavService safe_file? is call' do it 'ClamavService safe_file? is call' do
expect(ClamavService).to receive(:safe_file?).twice expect(ClamavService).to receive(:safe_file?).twice
post :create, params: {dossier_id: dossier_id, post :update, params: {dossier_id: dossier_id,
'piece_justificative_'+all_pj_type[0].to_s => piece_justificative_0, 'piece_justificative_'+all_pj_type[0].to_s => piece_justificative_0,
'piece_justificative_'+all_pj_type[1].to_s => piece_justificative_1} 'piece_justificative_'+all_pj_type[1].to_s => piece_justificative_1}
end end
@ -281,6 +296,22 @@ shared_examples 'description_controller_spec' do
it { expect(subject.user).to eq user } it { expect(subject.user).to eq user }
end end
end end
context 'La procédure est archivée' do
let(:archived) { true }
before do
post :update, params: { dossier_id: dossier.id }
end
it { expect(response.status).to eq(302) }
context 'Le dossier est en brouillon' do
let(:state) { 'draft' }
it { expect(response.status).to eq(403) }
end
end
end end
describe 'POST #pieces_justificatives', vcr: {cassette_name: 'controllers_users_description_controller_pieces_justificatives'} do describe 'POST #pieces_justificatives', vcr: {cassette_name: 'controllers_users_description_controller_pieces_justificatives'} do

View file

@ -5,9 +5,11 @@ require 'controllers/users/description_controller_shared_example'
describe Users::DescriptionController, type: :controller, vcr: {cassette_name: 'controllers_users_description_controller'} do describe Users::DescriptionController, type: :controller, vcr: {cassette_name: 'controllers_users_description_controller'} do
let(:owner_user) { create(:user) } let(:owner_user) { create(:user) }
let(:invite_by_user) { create :user, email: 'invite@plop.com' } let(:invite_by_user) { create :user, email: 'invite@plop.com' }
let(:archived) { false }
let(:state) { 'initiated' }
let(:procedure) { create(:procedure, :with_two_type_de_piece_justificative, :with_type_de_champ, :with_datetime, cerfa_flag: true) } let(:procedure) { create(:procedure, :with_two_type_de_piece_justificative, :with_type_de_champ, :with_datetime, cerfa_flag: true, archived: archived) }
let(:dossier) { create(:dossier, procedure: procedure, user: owner_user, state: 'initiated') } let(:dossier) { create(:dossier, procedure: procedure, user: owner_user, state: state) }
let(:dossier_id) { dossier.id } let(:dossier_id) { dossier.id }
let(:bad_dossier_id) { Dossier.count + 10000 } let(:bad_dossier_id) { Dossier.count + 10000 }

View file

@ -24,7 +24,7 @@ describe DossierDecorator do
it 'initiated is initiate' do it 'initiated is initiate' do
dossier.initiated! dossier.initiated!
expect(subject).to eq('Nouveau') expect(subject).to eq('En construction')
end end
it 'replied is repondu' do it 'replied is repondu' do

View file

@ -26,7 +26,7 @@ describe AdminProceduresShowFacades do
describe '.dossiers_for_pie_highchart' do describe '.dossiers_for_pie_highchart' do
subject { super().dossiers_for_pie_highchart } subject { super().dossiers_for_pie_highchart }
it { expect(subject).to eq({'Nouveau' => 1, "En construction"=>1}) } it { expect(subject).to eq({ 'En construction' => 3 }) }
end end
describe '.dossiers_archived_by_state_total' do describe '.dossiers_archived_by_state_total' do

View file

@ -34,7 +34,7 @@ feature 'on click on tabs button' do
context 'when he click on tabs en examen' do context 'when he click on tabs en examen' do
before do before do
visit users_dossiers_url(liste: :en_instruction) visit users_dossiers_url(liste: :en_instruction)
page.click_on 'En examen 1' page.click_on 'En instruction 1'
end end
scenario 'it redirect to users dossier termine' do scenario 'it redirect to users dossier termine' do
@ -45,7 +45,7 @@ feature 'on click on tabs button' do
context 'when he click on tabs termine' do context 'when he click on tabs termine' do
before do before do
visit users_dossiers_url(liste: :termine) visit users_dossiers_url(liste: :termine)
page.click_on 'Cloturé 3' page.click_on 'Terminé 3'
end end
scenario 'it redirect to users dossier termine' do scenario 'it redirect to users dossier termine' do

View file

@ -597,7 +597,10 @@ describe Dossier do
let(:procedure) { create(:procedure, :with_type_de_champ) } let(:procedure) { create(:procedure, :with_type_de_champ) }
let(:gestionnaire) { create(:gestionnaire) } let(:gestionnaire) { create(:gestionnaire) }
let(:follow) { create(:follow, gestionnaire: gestionnaire) } let(:follow) { create(:follow, gestionnaire: gestionnaire) }
let(:dossier) { create(:dossier, :with_entreprise, user: user, procedure: procedure, follows: [follow]) } let(:date1) { 1.day.ago }
let(:date2) { 1.hour.ago }
let(:date3) { 1.minute.ago }
let(:dossier) { create(:dossier, :with_entreprise, user: user, procedure: procedure, follows: [follow], initiated_at: date1, received_at: date2, processed_at: date3) }
describe '#export_headers' do describe '#export_headers' do
@ -608,6 +611,7 @@ describe Dossier do
end end
describe '#data_with_champs' do describe '#data_with_champs' do
subject { dossier.data_with_champs } subject { dossier.data_with_champs }
it { expect(subject[0]).to be_a_kind_of(Integer) } it { expect(subject[0]).to be_a_kind_of(Integer) }
@ -616,14 +620,17 @@ describe Dossier do
it { expect(subject[3]).to be_in([true, false]) } it { expect(subject[3]).to be_in([true, false]) }
it { expect(subject[4]).to be_in([true, false]) } it { expect(subject[4]).to be_in([true, false]) }
it { expect(subject[5]).to eq("draft") } it { expect(subject[5]).to eq("draft") }
it { expect(subject[6]).to eq(dossier.followers_gestionnaires_emails) } it { expect(subject[6]).to eq(date1) }
it { expect(subject[7]).to eq(date2) }
it { expect(subject[8]).to eq(date3) }
it { expect(subject[9]).to eq(dossier.followers_gestionnaires_emails) }
it { expect(subject.count).to eq(DossierProcedureSerializer.new(dossier).attributes.count + dossier.procedure.types_de_champ.count + dossier.export_entreprise_data.count) } it { expect(subject.count).to eq(DossierProcedureSerializer.new(dossier).attributes.count + dossier.procedure.types_de_champ.count + dossier.export_entreprise_data.count) }
end end
end end
describe '#Dossier.to_csv' do describe '#Dossier.to_csv' do
let!(:procedure) { create(:procedure) } let!(:procedure) { create(:procedure) }
let!(:dossier) { create(:dossier, :with_entreprise, user: user, procedure: procedure) } let!(:dossier) { create(:dossier, :with_entreprise, user: user, procedure: procedure, ) }
subject do subject do
dossier_hash = {} dossier_hash = {}
@ -881,6 +888,82 @@ describe Dossier do
it { is_expected.to eq "#{gestionnaire.email} #{gestionnaire2.email}" } it { is_expected.to eq "#{gestionnaire.email} #{gestionnaire2.email}" }
end end
end
describe '#update_state_dates' do
let(:state) { 'draft' }
let(:dossier) { create(:dossier, state: state) }
let(:beginning_of_day) { Time.now.beginning_of_day }
before do
Timecop.freeze(beginning_of_day)
end
context 'when dossier is initiated' do
before do
dossier.initiated!
dossier.reload
end
it { expect(dossier.state).to eq('initiated') }
it { expect(dossier.initiated_at).to eq(beginning_of_day) }
it 'should keep first initiated_at date' do
Timecop.return
dossier.received!
dossier.initiated!
expect(dossier.initiated_at).to eq(beginning_of_day)
end
end
context 'when dossier is received' do
let(:state) { 'initiated' }
before do
dossier.received!
dossier.reload
end
it { expect(dossier.state).to eq('received') }
it { expect(dossier.received_at).to eq(beginning_of_day) }
it 'should keep first received_at date if dossier is set to initiated again' do
Timecop.return
dossier.initiated!
dossier.received!
expect(dossier.received_at).to eq(beginning_of_day)
end
end
shared_examples 'dossier is processed' do |new_state|
before do
dossier.update(state: new_state)
dossier.reload
end
it { expect(dossier.state).to eq(new_state) }
it { expect(dossier.processed_at).to eq(beginning_of_day) }
end
context 'when dossier is closed' do
let(:state) { 'received' }
it_behaves_like 'dossier is processed', 'closed'
end
context 'when dossier is refused' do
let(:state) { 'received' }
it_behaves_like 'dossier is processed', 'refused'
end
context 'when dossier is without_continuation' do
let(:state) { 'received' }
it_behaves_like 'dossier is processed', 'without_continuation'
end
end end
end end

View file

@ -77,7 +77,7 @@ describe 'backoffice/dossiers/index.html.haml', type: :view do
subject { rendered } subject { rendered }
it { is_expected.to have_content('Nouveaux dossiers 1 dossiers') } it { is_expected.to have_content('Nouveaux dossiers 1 dossier') }
it { is_expected.to have_content('Dossiers suivis 0 dossiers') } it { is_expected.to have_content('Dossiers suivis 0 dossiers') }
it { is_expected.to have_content('Tous les dossiers 7 dossiers') } it { is_expected.to have_content('Tous les dossiers 7 dossiers') }

View file

@ -2,8 +2,9 @@ require 'spec_helper'
describe 'layouts/left_panels/_left_panel_backoffice_dossierscontroller_show.html.haml', type: :view do describe 'layouts/left_panels/_left_panel_backoffice_dossierscontroller_show.html.haml', type: :view do
let!(:dossier) { create(:dossier, :with_entreprise, state: state) } let!(:dossier) { create(:dossier, :with_entreprise, state: state, archived: archived) }
let(:state) { 'draft' } let(:state) { 'draft' }
let(:archived) { false }
let(:gestionnaire) { create(:gestionnaire) } let(:gestionnaire) { create(:gestionnaire) }
before do before do
@ -24,8 +25,8 @@ describe 'layouts/left_panels/_left_panel_backoffice_dossierscontroller_show.htm
context 'button dossier state changements' do context 'button dossier state changements' do
shared_examples 'button Accuser réception is present' do shared_examples 'button Passer en instruction is present' do
it { expect(rendered).to have_link('Accuser réception') } it { expect(rendered).to have_link('Passer en instruction') }
end end
context 'when dossier have state initiated' do context 'when dossier have state initiated' do
@ -35,9 +36,9 @@ describe 'layouts/left_panels/_left_panel_backoffice_dossierscontroller_show.htm
render render
end end
it { expect(rendered).to have_content('Nouveau') } it { expect(rendered).to have_content('En construction') }
include_examples 'button Accuser réception is present' include_examples 'button Passer en instruction is present'
end end
context 'when dossier have state replied' do context 'when dossier have state replied' do
@ -49,7 +50,7 @@ describe 'layouts/left_panels/_left_panel_backoffice_dossierscontroller_show.htm
it { expect(rendered).to have_content('En construction') } it { expect(rendered).to have_content('En construction') }
include_examples 'button Accuser réception is present' include_examples 'button Passer en instruction is present'
end end
context 'when dossier have state update' do context 'when dossier have state update' do
@ -61,7 +62,7 @@ describe 'layouts/left_panels/_left_panel_backoffice_dossierscontroller_show.htm
it { expect(rendered).to have_content('En construction') } it { expect(rendered).to have_content('En construction') }
include_examples 'button Accuser réception is present' include_examples 'button Passer en instruction is present'
end end
context 'when dossier have state received' do context 'when dossier have state received' do
@ -127,6 +128,28 @@ describe 'layouts/left_panels/_left_panel_backoffice_dossierscontroller_show.htm
expect(rendered).not_to have_css('form[data-toggle="tooltip"][title="Refuser"]') expect(rendered).not_to have_css('form[data-toggle="tooltip"][title="Refuser"]')
end end
end end
context 'when dossier is not archived' do
let(:archived) { false }
before do
render
end
it { expect(rendered).to have_link('Archiver') }
end
context 'when dossier is archived' do
let(:archived) { true }
before do
render
end
it { expect(rendered).to have_content('Archivé') }
it { expect(rendered).to have_link('Désarchiver') }
end
end end
end end

View file

@ -17,7 +17,7 @@ describe 'layouts/left_panels/_left_panel_users_recapitulatifcontroller_show.htm
render render
end end
it { expect(rendered).to have_content('Nouveau') } it { expect(rendered).to have_content('En construction') }
end end
context 'when dossier state is replied' do context 'when dossier state is replied' do