Merge branch 'dev'
This commit is contained in:
commit
c5eb7152cb
64 changed files with 1148 additions and 101 deletions
|
@ -17,12 +17,12 @@ jobs:
|
|||
name: Install System Dependencies
|
||||
command: apt-get update -qq && apt-get install -y build-essential nodejs
|
||||
- restore_cache:
|
||||
key: bundle-install-v3-{{ checksum "Gemfile.lock" }}
|
||||
key: bundle-install-v3-{{ arch }}-{{ checksum "Gemfile.lock" }}
|
||||
- run:
|
||||
name: Install Ruby Dependencies
|
||||
command: bundle install
|
||||
- save_cache:
|
||||
key: bundle-install-v3-{{ checksum "Gemfile.lock" }}
|
||||
key: bundle-install-v3-{{ arch }}-{{ checksum "Gemfile.lock" }}
|
||||
paths:
|
||||
- /usr/local/bundle
|
||||
- restore_cache:
|
||||
|
|
|
@ -64,10 +64,11 @@ Afin de générer la BDD de l'application, il est nécessaire d'éxécuter les c
|
|||
mailcatcher -f
|
||||
rails s
|
||||
|
||||
## Lancement des workers
|
||||
## Programmation des jobs
|
||||
|
||||
Delayed::Job.enqueue(AutoArchiveProcedureWorker.new, cron: "* * * * *")
|
||||
Delayed::Job.enqueue(WeeklyOverviewWorker.new, cron: "0 8 * * 0")
|
||||
AutoArchiveProcedureJob.set(cron: "* * * * *").perform_later
|
||||
WeeklyOverviewJob.set(cron: "0 8 * * 0").perform_later
|
||||
AutoReceiveDossiersForProcedureJob.set(cron: "* * * * *").perform_later(procedure_declaratoire_id)
|
||||
|
||||
## Exécution des tests (RSpec)
|
||||
|
||||
|
|
1
app/assets/images/close.svg
Normal file
1
app/assets/images/close.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><g stroke="#FFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12.749 1L1 12.75M12.749 12.75L1 1"/></g><path d="M-5-5h24v24H-5z"/></g></svg>
|
After Width: | Height: | Size: 286 B |
1
app/assets/images/table/down_caret.svg
Normal file
1
app/assets/images/table/down_caret.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg width="10" height="6" viewBox="0 0 10 6" xmlns="http://www.w3.org/2000/svg"><title>ic_dropdown</title><g fill="none" fill-rule="evenodd"><path stroke="#333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M1 1l4 4 4-4"/><path d="M-7-9h24v24H-7z"/></g></svg>
|
After Width: | Height: | Size: 281 B |
1
app/assets/images/table/up_caret.svg
Normal file
1
app/assets/images/table/up_caret.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg width="10" height="6" viewBox="0 0 10 6" xmlns="http://www.w3.org/2000/svg"><title>ic_dropdown</title><g fill="none" fill-rule="evenodd"><path stroke="#333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M1 5l4-4 4 4"/><path d="M-7 15h24V-9H-7z"/></g></svg>
|
After Width: | Height: | Size: 282 B |
|
@ -1,3 +1,9 @@
|
|||
document.addEventListener('turbolinks:load', function() {
|
||||
$('select.select2').select2();
|
||||
|
||||
$('select.select2-limited').select2({
|
||||
'placeholder': 'Sélectionnez des colonnes',
|
||||
'maximumSelectionLength': '2',
|
||||
'width': '300px'
|
||||
});
|
||||
});
|
||||
|
|
|
@ -104,6 +104,11 @@
|
|||
cursor: default;
|
||||
z-index: 10;
|
||||
|
||||
&.left-aligned {
|
||||
left: 0;
|
||||
right: unset;
|
||||
}
|
||||
|
||||
&.terminated {
|
||||
width: 600px;
|
||||
color: $black;
|
||||
|
@ -172,6 +177,42 @@
|
|||
}
|
||||
}
|
||||
|
||||
.dropdown-form {
|
||||
padding: 2 * $default-spacer;
|
||||
|
||||
.select2-container {
|
||||
margin-bottom: 2 * $default-spacer;
|
||||
}
|
||||
|
||||
.select2-selection {
|
||||
border: 1px solid $border-grey;
|
||||
|
||||
&.select2-selection--multiple {
|
||||
border: 1px solid $border-grey;
|
||||
}
|
||||
}
|
||||
|
||||
&.large {
|
||||
width: 340px;
|
||||
}
|
||||
|
||||
label {
|
||||
width: 100px;
|
||||
display: inline-block;
|
||||
margin-bottom: 2 * $default-spacer;
|
||||
}
|
||||
|
||||
input,
|
||||
select {
|
||||
width: 200px;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.select2-dropdown {
|
||||
border: 1px solid $border-grey;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: $blue;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,16 @@
|
|||
padding: 0;
|
||||
}
|
||||
|
||||
thead a {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.caret-icon {
|
||||
vertical-align: top;
|
||||
margin-top: 9px;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.cell-link {
|
||||
color: $black;
|
||||
padding: (3 * $default-spacer) 2px;
|
||||
|
|
|
@ -27,23 +27,22 @@
|
|||
|
||||
.header-tabs {
|
||||
li {
|
||||
@include horizontal-padding($default-padding);
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
padding: 23px $default-padding;
|
||||
height: 71px;
|
||||
line-height: 71px;
|
||||
font-size: 18px;
|
||||
color: $black;
|
||||
|
||||
&.active {
|
||||
&.active,
|
||||
&:hover {
|
||||
color: $blue;
|
||||
border-bottom: 2px solid $blue;
|
||||
}
|
||||
|
||||
&:not(.active):hover {
|
||||
background-color: $light-grey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,4 +26,22 @@
|
|||
min-width: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
.filter {
|
||||
display: inline-block;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
background-color: $light-blue;
|
||||
border-radius: 4px;
|
||||
color: #FFFFFF;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.close-icon {
|
||||
vertical-align: top;
|
||||
margin-top: 12px;
|
||||
margin-left: 6px;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,9 +35,9 @@ class Backoffice::DossiersListController < ApplicationController
|
|||
params[:dossiers_smart_listing] = {page: dossiers_list_facade.service.default_page}
|
||||
end
|
||||
|
||||
default_smart_listing_create :new_dossiers, service.nouveaux
|
||||
default_smart_listing_create :follow_dossiers, service.suivi
|
||||
default_smart_listing_create :all_state_dossiers, service.all_state
|
||||
default_smart_listing_create :new_dossiers, service.nouveaux.without_followers.order_by_updated_at('asc')
|
||||
default_smart_listing_create :follow_dossiers, service.suivi.order_by_updated_at('asc')
|
||||
default_smart_listing_create :all_state_dossiers, service.all_state.order_by_updated_at('asc')
|
||||
default_smart_listing_create :archived_dossiers, service.archive
|
||||
|
||||
@archived_dossiers = service.archive
|
||||
|
|
|
@ -32,7 +32,7 @@ module NewGestionnaire
|
|||
end
|
||||
|
||||
def unfollow
|
||||
current_gestionnaire.followed_dossiers.delete(dossier)
|
||||
current_gestionnaire.unfollow(dossier)
|
||||
flash.notice = "Vous ne suivez plus le dossier nº #{dossier.id}"
|
||||
|
||||
redirect_back(fallback_location: procedures_url)
|
||||
|
@ -40,6 +40,7 @@ module NewGestionnaire
|
|||
|
||||
def archive
|
||||
dossier.update_attributes(archived: true)
|
||||
current_gestionnaire.unfollow(dossier)
|
||||
redirect_back(fallback_location: procedures_url)
|
||||
end
|
||||
|
||||
|
@ -50,6 +51,7 @@ module NewGestionnaire
|
|||
|
||||
def create_commentaire
|
||||
Commentaire.create(commentaire_params.merge(email: current_gestionnaire.email, dossier: dossier))
|
||||
current_gestionnaire.follow(dossier)
|
||||
flash.notice = "Message envoyé"
|
||||
redirect_to messagerie_dossier_path(dossier.procedure, dossier)
|
||||
end
|
||||
|
|
|
@ -3,6 +3,8 @@ module NewGestionnaire
|
|||
before_action :ensure_ownership!, except: [:index]
|
||||
before_action :redirect_to_avis_if_needed, only: [:index]
|
||||
|
||||
ITEMS_PER_PAGE = 25
|
||||
|
||||
def index
|
||||
@procedures = current_gestionnaire.procedures.order(archived_at: :desc, published_at: :desc)
|
||||
|
||||
|
@ -26,6 +28,11 @@ module NewGestionnaire
|
|||
def show
|
||||
@procedure = procedure
|
||||
|
||||
@current_filters = current_filters
|
||||
@available_fields_to_filters = available_fields_to_filters
|
||||
@displayed_fields = procedure_presentation.displayed_fields
|
||||
@displayed_fields_values = displayed_fields_values
|
||||
|
||||
@a_suivre_dossiers = procedure
|
||||
.dossiers
|
||||
.includes(:user)
|
||||
|
@ -49,9 +56,7 @@ module NewGestionnaire
|
|||
|
||||
@archived_dossiers = procedure.dossiers.includes(:user).archived
|
||||
|
||||
@statut = params[:statut].present? ? params[:statut] : 'a-suivre'
|
||||
|
||||
@dossiers = case @statut
|
||||
@dossiers = case statut
|
||||
when 'a-suivre'
|
||||
@a_suivre_dossiers
|
||||
when 'suivis'
|
||||
|
@ -64,11 +69,116 @@ module NewGestionnaire
|
|||
@archived_dossiers
|
||||
end
|
||||
|
||||
@dossiers = @dossiers.page([params[:page].to_i, 1].max)
|
||||
sorted_ids = sorted_ids(@dossiers)
|
||||
|
||||
if @current_filters.count > 0
|
||||
filtered_ids = filtered_ids(@dossiers)
|
||||
filtered_sorted_ids = sorted_ids.select { |id| filtered_ids.include?(id) }
|
||||
else
|
||||
filtered_sorted_ids = sorted_ids
|
||||
end
|
||||
|
||||
page = params[:page].present? ? params[:page] : 1
|
||||
|
||||
filtered_sorted_paginated_ids = Kaminari
|
||||
.paginate_array(filtered_sorted_ids)
|
||||
.page(page)
|
||||
.per(ITEMS_PER_PAGE)
|
||||
|
||||
@dossiers = @dossiers.where(id: filtered_sorted_paginated_ids)
|
||||
|
||||
eager_load_displayed_fields
|
||||
|
||||
@dossiers = @dossiers.sort_by { |d| filtered_sorted_paginated_ids.index(d.id) }
|
||||
|
||||
kaminarize(page, filtered_sorted_ids.count)
|
||||
end
|
||||
|
||||
def update_displayed_fields
|
||||
values = params[:values]
|
||||
|
||||
if values.nil?
|
||||
values = []
|
||||
end
|
||||
|
||||
fields = values.map do |value|
|
||||
table, column = value.split("/")
|
||||
|
||||
c = procedure.fields.find do |field|
|
||||
field['table'] == table && field['column'] == column
|
||||
end
|
||||
|
||||
c.to_json
|
||||
end
|
||||
|
||||
procedure_presentation.update_attributes(displayed_fields: fields)
|
||||
|
||||
current_sort = procedure_presentation.sort
|
||||
if !values.include?("#{current_sort['table']}/#{current_sort['column']}")
|
||||
procedure_presentation.update_attributes(sort: Procedure.default_sort)
|
||||
end
|
||||
|
||||
redirect_back(fallback_location: procedure_url(procedure))
|
||||
end
|
||||
|
||||
def update_sort
|
||||
current_sort = procedure_presentation.sort
|
||||
table = params[:table]
|
||||
column = params[:column]
|
||||
|
||||
if table == current_sort['table'] && column == current_sort['column']
|
||||
order = current_sort['order'] == 'asc' ? 'desc' : 'asc'
|
||||
else
|
||||
order = 'asc'
|
||||
end
|
||||
|
||||
sort = {
|
||||
'table' => table,
|
||||
'column' => column,
|
||||
'order' => order
|
||||
}.to_json
|
||||
|
||||
procedure_presentation.update_attributes(sort: sort)
|
||||
|
||||
redirect_back(fallback_location: procedure_url(procedure))
|
||||
end
|
||||
|
||||
def add_filter
|
||||
filters = procedure_presentation.filters
|
||||
table, column = params[:field].split('/')
|
||||
label = procedure.fields.find { |c| c['table'] == table && c['column'] == column }['label']
|
||||
|
||||
filters[statut] << {
|
||||
'label' => label,
|
||||
'table' => table,
|
||||
'column' => column,
|
||||
'value' => params[:value]
|
||||
}
|
||||
|
||||
procedure_presentation.update_attributes(filters: filters.to_json)
|
||||
|
||||
redirect_back(fallback_location: procedure_url(procedure))
|
||||
end
|
||||
|
||||
def remove_filter
|
||||
filters = procedure_presentation.filters
|
||||
filter_to_remove = current_filters.find do |filter|
|
||||
filter['table'] == params[:table] && filter['column'] == params[:column]
|
||||
end
|
||||
|
||||
filters[statut] = filters[statut] - [filter_to_remove]
|
||||
|
||||
procedure_presentation.update_attributes(filters: filters.to_json)
|
||||
|
||||
redirect_back(fallback_location: procedure_url(procedure))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def statut
|
||||
@statut ||= params[:statut].present? ? params[:statut] : 'a-suivre'
|
||||
end
|
||||
|
||||
def procedure
|
||||
Procedure.find(params[:procedure_id])
|
||||
end
|
||||
|
@ -85,5 +195,134 @@ module NewGestionnaire
|
|||
redirect_to avis_index_path
|
||||
end
|
||||
end
|
||||
|
||||
def procedure_presentation
|
||||
@procedure_presentation ||= current_gestionnaire.procedure_presentation_for_procedure_id(params[:procedure_id])
|
||||
end
|
||||
|
||||
def displayed_fields_values
|
||||
procedure_presentation.displayed_fields.map do |field|
|
||||
"#{field['table']}/#{field['column']}"
|
||||
end
|
||||
end
|
||||
|
||||
def filtered_ids(dossiers)
|
||||
current_filters.map do |filter|
|
||||
case filter['table']
|
||||
when 'self'
|
||||
dossiers.where("? LIKE ?", filter['column'], "%#{filter['value']}%")
|
||||
|
||||
when 'france_connect_information'
|
||||
dossiers
|
||||
.includes(user: :france_connect_information)
|
||||
.where("? LIKE ?", "france_connect_informations.#{filter['column']}", "%#{filter['value']}%")
|
||||
|
||||
when 'type_de_champ', 'type_de_champ_private'
|
||||
relation = filter['table'] == 'type_de_champ' ? :champs : :champs_private
|
||||
dossiers
|
||||
.includes(relation)
|
||||
.where("champs.type_de_champ_id = ?", filter['column'].to_i)
|
||||
.where("champs.value LIKE ?", "%#{filter['value']}%")
|
||||
|
||||
when 'user', 'etablissement', 'entreprise'
|
||||
dossiers
|
||||
.includes(filter['table'])
|
||||
.where("#{filter['table'].pluralize}.#{filter['column']} LIKE ?", "%#{filter['value']}%")
|
||||
|
||||
end.pluck(:id)
|
||||
end.reduce(:&)
|
||||
end
|
||||
|
||||
def sorted_ids(dossiers)
|
||||
table = procedure_presentation.sort['table']
|
||||
column = procedure_presentation.sort['column']
|
||||
order = procedure_presentation.sort['order']
|
||||
includes = ''
|
||||
where = ''
|
||||
|
||||
case table
|
||||
when 'self'
|
||||
order = "dossiers.#{column} #{order}"
|
||||
when'france_connect_information'
|
||||
includes = { user: :france_connect_information }
|
||||
order = "france_connect_informations.#{column} #{order}"
|
||||
when 'type_de_champ', 'type_de_champ_private'
|
||||
includes = table == 'type_de_champ' ? :champs : :champs_private
|
||||
where = "champs.type_de_champ_id = #{column.to_i}"
|
||||
order = "champs.value #{order}"
|
||||
else
|
||||
includes = table
|
||||
order = "#{table.pluralize}.#{column} #{order}"
|
||||
end
|
||||
|
||||
dossiers.includes(includes).where(where).order(Dossier.sanitize_for_order(order)).pluck(:id)
|
||||
end
|
||||
|
||||
def current_filters
|
||||
@current_filters ||= procedure_presentation.filters[statut]
|
||||
end
|
||||
|
||||
def available_fields_to_filters
|
||||
current_filters_fields_ids = current_filters.map do |field|
|
||||
"#{field['table']}/#{field['column']}"
|
||||
end
|
||||
|
||||
procedure.fields_for_select.reject do |field|
|
||||
current_filters_fields_ids.include?(field[1])
|
||||
end
|
||||
end
|
||||
|
||||
def eager_load_displayed_fields
|
||||
@displayed_fields
|
||||
.reject { |field| field['table'] == 'self' }
|
||||
.group_by do |field|
|
||||
if ['type_de_champ', 'type_de_champ_private'].include?(field['table'])
|
||||
'type_de_champ_group'
|
||||
else
|
||||
field['table']
|
||||
end
|
||||
end.each do |group_key, fields|
|
||||
case group_key
|
||||
when'france_connect_information'
|
||||
@dossiers = @dossiers.includes({ user: :france_connect_information })
|
||||
when 'type_de_champ_group'
|
||||
if fields.any? { |field| field['table'] == 'type_de_champ' }
|
||||
@dossiers = @dossiers.includes(:champs).references(:champs)
|
||||
end
|
||||
|
||||
if fields.any? { |field| field['table'] == 'type_de_champ_private' }
|
||||
@dossiers = @dossiers.includes(:champs_private).references(:champs_private)
|
||||
end
|
||||
|
||||
where_conditions = fields.map do |field|
|
||||
"champs.type_de_champ_id = #{field['column']}"
|
||||
end.join(" OR ")
|
||||
|
||||
@dossiers = @dossiers.where(where_conditions)
|
||||
else
|
||||
@dossiers = @dossiers.includes(fields.first['table'])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def kaminarize(current_page, total)
|
||||
@dossiers.instance_eval <<-EVAL
|
||||
def current_page
|
||||
#{current_page}
|
||||
end
|
||||
def total_pages
|
||||
(#{total} / #{ITEMS_PER_PAGE}.to_f).ceil
|
||||
end
|
||||
def limit_value
|
||||
#{ITEMS_PER_PAGE}
|
||||
end
|
||||
def first_page?
|
||||
current_page == 1
|
||||
end
|
||||
def last_page?
|
||||
current_page == total_pages
|
||||
end
|
||||
EVAL
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -64,7 +64,7 @@ class DossiersListFacades
|
|||
end
|
||||
|
||||
def nouveaux_total
|
||||
service.nouveaux.count
|
||||
service.nouveaux.without_followers.count
|
||||
end
|
||||
|
||||
def suivi_total
|
||||
|
|
|
@ -1,2 +1,9 @@
|
|||
class ApplicationJob < ActiveJob::Base
|
||||
before_perform do |job|
|
||||
Rails.logger.info("#{job.class.name} started at #{Time.now}")
|
||||
end
|
||||
|
||||
after_perform do |job|
|
||||
Rails.logger.info("#{job.class.name} ended at #{Time.now}")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
class AutoArchiveProcedureWorker
|
||||
class AutoArchiveProcedureJob < ApplicationJob
|
||||
queue_as :cron
|
||||
|
||||
def perform(*args)
|
||||
Rails.logger.info("AutoArchiveProcedureWorker started at #{Time.now}")
|
||||
Procedure.publiees.where("auto_archive_on <= ?", Date.today).each do |procedure|
|
||||
procedure.dossiers.state_en_construction.each do |dossier|
|
||||
dossier.received!
|
||||
|
@ -8,12 +9,5 @@ class AutoArchiveProcedureWorker
|
|||
|
||||
procedure.archive
|
||||
end
|
||||
Rails.logger.info("AutoArchiveProcedureWorker ended at #{Time.now}")
|
||||
end
|
||||
|
||||
def queue_name
|
||||
"cron"
|
||||
end
|
||||
|
||||
handle_asynchronously :perform
|
||||
end
|
10
app/jobs/auto_receive_dossiers_for_procedure_job.rb
Normal file
10
app/jobs/auto_receive_dossiers_for_procedure_job.rb
Normal file
|
@ -0,0 +1,10 @@
|
|||
class AutoReceiveDossiersForProcedureJob < ApplicationJob
|
||||
queue_as :cron
|
||||
|
||||
def perform(procedure_id)
|
||||
procedure = Procedure.find_by(id: procedure_id)
|
||||
if procedure
|
||||
procedure.dossiers.state_nouveaux.update_all(state: "received", received_at: Time.now)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,7 @@
|
|||
class WeeklyOverviewWorker
|
||||
class WeeklyOverviewJob < ApplicationJob
|
||||
queue_as :cron
|
||||
|
||||
def perform(*args)
|
||||
Rails.logger.info("WeeklyOverviewWorker started at #{Time.now}")
|
||||
# Feature flipped to avoid mails in staging due to unprocessed dossier
|
||||
if Features.weekly_overview
|
||||
Gestionnaire.all
|
||||
|
@ -8,12 +9,5 @@ class WeeklyOverviewWorker
|
|||
.reject { |_, overview| overview.nil? }
|
||||
.each { |gestionnaire, overview| GestionnaireMailer.last_week_overview(gestionnaire, overview).deliver_now }
|
||||
end
|
||||
Rails.logger.info("WeeklyOverviewWorker ended at #{Time.now}")
|
||||
end
|
||||
|
||||
def queue_name
|
||||
"cron"
|
||||
end
|
||||
|
||||
handle_asynchronously :perform
|
||||
end
|
|
@ -1,4 +1,9 @@
|
|||
class AssignTo < ActiveRecord::Base
|
||||
belongs_to :procedure
|
||||
belongs_to :gestionnaire
|
||||
has_one :procedure_presentation, dependent: :destroy
|
||||
|
||||
def procedure_presentation_or_default
|
||||
self.procedure_presentation || build_procedure_presentation
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@ class Commentaire < ActiveRecord::Base
|
|||
|
||||
belongs_to :piece_justificative
|
||||
|
||||
scope :ordered, -> { order(created_at: :asc) }
|
||||
default_scope { order(created_at: :asc) }
|
||||
|
||||
after_create :notify
|
||||
|
||||
|
|
|
@ -54,12 +54,12 @@ class Dossier < ActiveRecord::Base
|
|||
|
||||
scope :order_by_updated_at, -> (order = :desc) { order(updated_at: order) }
|
||||
|
||||
scope :all_state, -> { not_archived.state_not_brouillon.order_by_updated_at(:asc) }
|
||||
scope :nouveaux, -> { not_archived.state_nouveaux.order_by_updated_at(:asc) }
|
||||
scope :en_instruction, -> { not_archived.state_en_instruction.order_by_updated_at(:asc) }
|
||||
scope :termine, -> { not_archived.state_termine.order_by_updated_at(:asc) }
|
||||
scope :downloadable, -> { state_not_brouillon.order_by_updated_at(:asc) }
|
||||
scope :en_cours, -> { not_archived.state_en_construction_ou_instruction.order_by_updated_at(:asc) }
|
||||
scope :all_state, -> { not_archived.state_not_brouillon }
|
||||
scope :nouveaux, -> { not_archived.state_nouveaux }
|
||||
scope :en_instruction, -> { not_archived.state_en_instruction }
|
||||
scope :termine, -> { not_archived.state_termine }
|
||||
scope :downloadable, -> { state_not_brouillon.includes(:entreprise, :etablissement, :champs, :champs_private) }
|
||||
scope :en_cours, -> { not_archived.state_en_construction_ou_instruction }
|
||||
scope :without_followers, -> { includes(:follows).where(follows: { id: nil }) }
|
||||
scope :with_unread_notifications, -> { where(notifications: { already_read: false }) }
|
||||
|
||||
|
@ -330,6 +330,29 @@ class Dossier < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def get_value(table, column)
|
||||
case table
|
||||
when 'self'
|
||||
self.send(column)
|
||||
when 'user'
|
||||
self.user.send(column)
|
||||
when 'france_connect_information'
|
||||
self.user.france_connect_information&.send(column)
|
||||
when 'entreprise'
|
||||
self.entreprise&.send(column)
|
||||
when 'etablissement'
|
||||
self.etablissement&.send(column)
|
||||
when 'type_de_champ'
|
||||
self.champs.find {|c| c.type_de_champ_id == column.to_i }.value
|
||||
when 'type_de_champ_private'
|
||||
self.champs_private.find {|c| c.type_de_champ_id == column.to_i }.value
|
||||
end
|
||||
end
|
||||
|
||||
def self.sanitize_for_order(order)
|
||||
sanitize_sql_for_order(order)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def build_attestation
|
||||
|
|
|
@ -40,6 +40,10 @@ class Gestionnaire < ActiveRecord::Base
|
|||
followed_dossiers << dossier
|
||||
end
|
||||
|
||||
def unfollow(dossier)
|
||||
followed_dossiers.delete(dossier)
|
||||
end
|
||||
|
||||
def follow?(dossier)
|
||||
followed_dossiers.include?(dossier)
|
||||
end
|
||||
|
@ -123,6 +127,10 @@ class Gestionnaire < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def procedure_presentation_for_procedure_id(procedure_id)
|
||||
assign_to.find_by(procedure_id: procedure_id).procedure_presentation_or_default
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def valid_couple_table_attr? table, column
|
||||
|
|
|
@ -184,4 +184,75 @@ class Procedure < ActiveRecord::Base
|
|||
def without_continuation_mail_template
|
||||
without_continuation_mail || Mails::WithoutContinuationMail.default
|
||||
end
|
||||
|
||||
def fields
|
||||
fields = [
|
||||
field_hash('Créé le', 'self', 'created_at'),
|
||||
field_hash('Mis à jour le', 'self', 'updated_at'),
|
||||
field_hash('Demandeur', 'user', 'email')
|
||||
]
|
||||
|
||||
fields << [
|
||||
field_hash('Civilité (FC)', 'france_connect_information', 'gender'),
|
||||
field_hash('Prénom (FC)', 'france_connect_information', 'given_name'),
|
||||
field_hash('Nom (FC)', 'france_connect_information', 'family_name')
|
||||
]
|
||||
|
||||
if !for_individual || (for_individual && individual_with_siret)
|
||||
fields << [
|
||||
field_hash('SIREN', 'entreprise', 'siren'),
|
||||
field_hash('Forme juridique', 'entreprise', 'forme_juridique'),
|
||||
field_hash('Nom commercial', 'entreprise', 'nom_commercial'),
|
||||
field_hash('Raison sociale', 'entreprise', 'raison_sociale'),
|
||||
field_hash('SIRET siège social', 'entreprise', 'siret_siege_social'),
|
||||
field_hash('Date de création', 'entreprise', 'date_creation')
|
||||
]
|
||||
|
||||
fields << [
|
||||
field_hash('SIRET', 'etablissement', 'siret'),
|
||||
field_hash('Nom établissement', 'etablissement', 'libelle_naf'),
|
||||
field_hash('Code postal', 'etablissement', 'code_postal')
|
||||
]
|
||||
end
|
||||
|
||||
types_de_champ
|
||||
.reject { |tdc| ['header_section', 'explication'].include?(tdc.type_champ ) }
|
||||
.each do |type_de_champ|
|
||||
|
||||
fields << field_hash(type_de_champ.libelle, 'type_de_champ', type_de_champ.id.to_s)
|
||||
end
|
||||
|
||||
types_de_champ_private
|
||||
.reject { |tdc| ['header_section', 'explication'].include?(tdc.type_champ ) }
|
||||
.each do |type_de_champ|
|
||||
|
||||
fields << field_hash(type_de_champ.libelle, 'type_de_champ_private', type_de_champ.id.to_s)
|
||||
end
|
||||
|
||||
fields.flatten
|
||||
end
|
||||
|
||||
def fields_for_select
|
||||
fields.map do |field|
|
||||
[field['label'], "#{field['table']}/#{field['column']}"]
|
||||
end
|
||||
end
|
||||
|
||||
def self.default_sort
|
||||
{
|
||||
'table' => 'self',
|
||||
'column' => 'id',
|
||||
'order' => 'desc'
|
||||
}.to_json
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def field_hash(label, table, column)
|
||||
{
|
||||
'label' => label,
|
||||
'table' => table,
|
||||
'column' => column
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
17
app/models/procedure_presentation.rb
Normal file
17
app/models/procedure_presentation.rb
Normal file
|
@ -0,0 +1,17 @@
|
|||
class ProcedurePresentation < ActiveRecord::Base
|
||||
belongs_to :assign_to
|
||||
|
||||
def displayed_fields
|
||||
read_attribute(:displayed_fields).map do |field|
|
||||
field = JSON.parse(field)
|
||||
end
|
||||
end
|
||||
|
||||
def sort
|
||||
JSON.parse(read_attribute(:sort))
|
||||
end
|
||||
|
||||
def filters
|
||||
JSON.parse(read_attribute(:filters))
|
||||
end
|
||||
end
|
|
@ -1,4 +1,5 @@
|
|||
class DossiersSerializer < ActiveModel::Serializer
|
||||
attributes :id,
|
||||
:updated_at
|
||||
:updated_at,
|
||||
:initiated_at
|
||||
end
|
||||
|
|
|
@ -20,7 +20,7 @@ class DossiersListGestionnaireService
|
|||
end
|
||||
|
||||
def all_state
|
||||
@all_state ||= filter_dossiers.all_state
|
||||
@all_state ||= filter_dossiers.all_state.order_by_updated_at('asc')
|
||||
end
|
||||
|
||||
def suivi
|
||||
|
@ -28,11 +28,11 @@ class DossiersListGestionnaireService
|
|||
end
|
||||
|
||||
def nouveaux
|
||||
@nouveaux ||= filter_dossiers.nouveaux
|
||||
@nouveaux ||= filter_dossiers.nouveaux.order_by_updated_at('asc')
|
||||
end
|
||||
|
||||
def a_instruire
|
||||
@a_instruire ||= filter_dossiers.en_instruction
|
||||
@a_instruire ||= filter_dossiers.en_instruction.order_by_updated_at('asc')
|
||||
end
|
||||
|
||||
def archive
|
||||
|
@ -40,7 +40,7 @@ class DossiersListGestionnaireService
|
|||
end
|
||||
|
||||
def termine
|
||||
@termine ||= filter_dossiers.termine
|
||||
@termine ||= filter_dossiers.termine.order_by_updated_at('asc')
|
||||
end
|
||||
|
||||
def filter_dossiers
|
||||
|
|
|
@ -8,6 +8,6 @@
|
|||
%li{ class: current_page?(avis_path(avis)) ? 'active' : nil }
|
||||
= link_to 'Demande', avis_path(avis)
|
||||
%li{ class: current_page?(instruction_avis_path(avis)) ? 'active' : nil }
|
||||
= link_to 'Instruction', instruction_avis_path(avis)
|
||||
= link_to 'Avis', instruction_avis_path(avis)
|
||||
%li{ class: current_page?(messagerie_avis_path(avis)) ? 'active' : nil }
|
||||
= link_to 'Messagerie', messagerie_avis_path(avis)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
.messagerie.container
|
||||
%ul
|
||||
- @dossier.commentaires.ordered.each do |commentaire|
|
||||
- @dossier.commentaires.each do |commentaire|
|
||||
%li
|
||||
= render partial: 'new_gestionnaire/dossiers/commentaire_icon', locals: { commentaire: commentaire, current_gestionnaire: current_gestionnaire }
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
- if c.type_champ == "header_section"
|
||||
%th.header-section{ colspan: 2 }
|
||||
= c.libelle
|
||||
- else
|
||||
- elsif c.type_champ != "explication"
|
||||
%th
|
||||
= "#{c.libelle} :"
|
||||
%td
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
%li
|
||||
= "Dossier nº #{dossier.id}"
|
||||
%div
|
||||
= render partial: "state_button", locals: { dossier: dossier }
|
||||
= render partial: "new_gestionnaire/procedures/dossier_actions", locals: { procedure: dossier.procedure, dossier: dossier, dossier_is_followed: current_gestionnaire&.follow?(dossier) }
|
||||
= render partial: "state_button", locals: { dossier: dossier }
|
||||
%ul.tabs
|
||||
- notifications_summary = dossier.notifications_summary
|
||||
%li{ class: current_page?(dossier_path(dossier.procedure, dossier)) ? 'active' : nil }
|
||||
|
@ -18,11 +18,11 @@
|
|||
%li{ class: current_page?(annotations_privees_dossier_path(dossier.procedure, dossier)) ? 'active' : nil }
|
||||
- if notifications_summary[:annotations_privees]
|
||||
%span.notifications{ 'aria-label': 'notifications' }
|
||||
= link_to "Annotations Privées", annotations_privees_dossier_path(dossier.procedure, dossier)
|
||||
= link_to "Annotations privées", annotations_privees_dossier_path(dossier.procedure, dossier)
|
||||
%li{ class: current_page?(avis_dossier_path(dossier.procedure, dossier)) ? 'active' : nil }
|
||||
- if notifications_summary[:avis]
|
||||
%span.notifications{ 'aria-label': 'notifications' }
|
||||
= link_to "Avis Externes", avis_dossier_path(dossier.procedure, dossier)
|
||||
= link_to "Avis externes", avis_dossier_path(dossier.procedure, dossier)
|
||||
%li{ class: current_page?(messagerie_dossier_path(dossier.procedure, dossier)) ? 'active' : nil }
|
||||
- if notifications_summary[:messagerie]
|
||||
%span.notifications{ 'aria-label': 'notifications' }
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
locals: { champ: champ, form: champ_form }
|
||||
|
||||
.send-wrapper
|
||||
= f.submit 'Sauvegarder', class: 'button send'
|
||||
= f.submit 'Sauvegarder', class: 'button send', data: { disable_with: "Envoi..." }
|
||||
|
||||
- else
|
||||
%h2.empty-text Aucune annotation privée
|
||||
|
|
|
@ -13,6 +13,6 @@
|
|||
= f.label :confidentiel, 'Cet avis est'
|
||||
= f.select :confidentiel, [['partagé avec les autres experts', false], ['confidentiel', true]]
|
||||
.send-wrapper
|
||||
= f.submit 'Demander un avis', class: 'button send'
|
||||
= f.submit 'Demander un avis', class: 'button send', data: { disable_with: "Envoi..." }
|
||||
|
||||
= render partial: 'new_gestionnaire/avis/avis_list', locals: { avis: @dossier.avis }
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
.messagerie.container
|
||||
%ul
|
||||
- @dossier.commentaires.ordered.each do |commentaire|
|
||||
- @dossier.commentaires.each do |commentaire|
|
||||
%li
|
||||
= render partial: 'commentaire_icon', locals: { commentaire: commentaire, current_gestionnaire: current_gestionnaire }
|
||||
|
||||
|
|
|
@ -2,18 +2,18 @@
|
|||
- if dossier_is_followed
|
||||
= link_to unfollow_dossier_path(procedure, dossier), method: :patch, class: 'button' do
|
||||
%i.unfollow>
|
||||
ne plus suivre
|
||||
Ne plus suivre
|
||||
- else
|
||||
= link_to follow_dossier_path(procedure, dossier), method: :patch, class: 'button' do
|
||||
%i.follow>
|
||||
suivre le dossier
|
||||
Suivre le dossier
|
||||
|
||||
- elsif dossier.termine?
|
||||
- if dossier.archived
|
||||
= link_to unarchive_dossier_path(procedure, dossier), method: :patch, class: 'button' do
|
||||
%i.unarchive>
|
||||
désarchiver le dossier
|
||||
Désarchiver le dossier
|
||||
- else
|
||||
= link_to archive_dossier_path(procedure, dossier), method: :patch, class: 'button' do
|
||||
%i.archive>
|
||||
archiver le dossier
|
||||
Archiver le dossier
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
%th{ class: classname }
|
||||
= link_to update_sort_procedure_path(@procedure, table: field['table'], column: field['column']) do
|
||||
= field['label']
|
||||
- if @procedure_presentation.sort['table'] == field['table'] && @procedure_presentation.sort['column'] == field['column']
|
||||
- if @procedure_presentation.sort['order'] == 'asc'
|
||||
%img.caret-icon{ src: image_url("table/up_caret.svg") }
|
||||
- else
|
||||
%img.caret-icon{ src: image_url("table/down_caret.svg") }
|
|
@ -51,14 +51,48 @@
|
|||
= link_to "Au format .ods", backoffice_download_dossiers_tps_path(format: :ods, procedure_id: @procedure.id), target: "_blank"
|
||||
|
||||
.container
|
||||
- if @dossiers.present?
|
||||
- if @dossiers.present? || @current_filters.count > 0
|
||||
%span.button.dropdown
|
||||
Filtrer
|
||||
.dropdown-content.left-aligned.fade-in-down
|
||||
= form_tag add_filter_procedure_path(@procedure), method: :post, class: 'dropdown-form large' do
|
||||
= label_tag :field, "Colonne"
|
||||
= select_tag :field, options_for_select(@available_fields_to_filters)
|
||||
%br
|
||||
= label_tag :value, "Valeur"
|
||||
= text_field_tag :value
|
||||
= hidden_field_tag :statut, @statut
|
||||
%br
|
||||
= submit_tag "Ajouter le filtre", class: 'button'
|
||||
|
||||
- @current_filters.each do |filter|
|
||||
%span.filter
|
||||
= "#{filter['label']} : #{filter['value']}"
|
||||
= link_to remove_filter_procedure_path(@procedure, statut: @statut, table: filter['table'], column: filter['column']) do
|
||||
%img.close-icon{ src: image_url("close.svg") }
|
||||
|
||||
%table.table.dossiers-table.hoverable
|
||||
%thead
|
||||
%tr
|
||||
%th.number-col Nº dossier
|
||||
%th Demandeur
|
||||
%th.status-col Statut
|
||||
= render partial: "header_field", locals: { field: { "label" => "Nº dossier", "table" => "self", "column" => "id" }, classname: "number-col" }
|
||||
|
||||
- @displayed_fields.each do |field|
|
||||
= render partial: "header_field", locals: { field: field, classname: "" }
|
||||
|
||||
= render partial: "header_field", locals: { field: { "label" => "Statut", "table" => "self", "column" => "state" }, classname: "status-col" }
|
||||
|
||||
%th.follow-col
|
||||
%span.button.dropdown
|
||||
Personnaliser
|
||||
.dropdown-content.fade-in-down
|
||||
= form_tag update_displayed_fields_procedure_path(@procedure), method: :patch, class: 'dropdown-form' do
|
||||
= select_tag :values,
|
||||
options_for_select(@procedure.fields_for_select,
|
||||
selected: @displayed_fields_values),
|
||||
multiple: true,
|
||||
class: 'select2-limited'
|
||||
= submit_tag "Enregistrer", class: 'button'
|
||||
|
||||
%tbody
|
||||
- @dossiers.each do |dossier|
|
||||
%tr
|
||||
|
@ -68,7 +102,12 @@
|
|||
- if @followed_dossiers.with_unread_notifications.include?(dossier)
|
||||
%span.notifications{ 'aria-label': 'notifications' }
|
||||
= dossier.id
|
||||
%td= link_to(dossier.user.email, dossier_path(@procedure, dossier), class: 'cell-link')
|
||||
|
||||
- @displayed_fields.each do |field|
|
||||
%td
|
||||
= link_to(dossier_path(@procedure, dossier), class: 'cell-link') do
|
||||
= dossier.get_value(field['table'], field['column'])
|
||||
|
||||
%td.status-col
|
||||
= link_to(dossier_path(@procedure, dossier), class: 'cell-link') do
|
||||
= render partial: 'status', locals: { dossier: dossier }
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
%p.feature-text
|
||||
%em.feature-text-em Gérer
|
||||
%br
|
||||
les demandes des usagers
|
||||
les demandes des usagers
|
||||
%br
|
||||
sur la plateforme
|
||||
%li.feature
|
||||
|
@ -42,7 +42,7 @@
|
|||
%p.feature-text
|
||||
%em.feature-text-em Collaborer
|
||||
%br
|
||||
pour instruire les demandes
|
||||
pour instruire les demandes
|
||||
%br
|
||||
à plusieurs
|
||||
|
||||
|
|
|
@ -33,5 +33,7 @@ module TPS
|
|||
else
|
||||
URL = "http://localhost:3000/"
|
||||
end
|
||||
|
||||
config.active_job.queue_adapter = :delayed_job
|
||||
end
|
||||
end
|
||||
|
|
|
@ -237,6 +237,11 @@ Rails.application.routes.draw do
|
|||
scope module: 'new_gestionnaire' do
|
||||
resources :procedures, only: [:index, :show], param: :procedure_id do
|
||||
member do
|
||||
patch 'update_displayed_fields'
|
||||
get 'update_sort/:table/:column' => 'procedures#update_sort', as: 'update_sort'
|
||||
post 'add_filter'
|
||||
get 'remove_filter/:statut/:table/:column' => 'procedures#remove_filter', as: 'remove_filter'
|
||||
|
||||
resources :dossiers, only: [:show], param: :dossier_id do
|
||||
member do
|
||||
get 'attestation'
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
auto_archive_procedure:
|
||||
cron: "* * * * *"
|
||||
class: "AutoArchiveProcedureWorker"
|
||||
weekly_overview_worker:
|
||||
cron: "0 8 * * 0"
|
||||
class: "WeeklyOverviewWorker"
|
10
db/migrate/20170915080151_create_procedure_presentations.rb
Normal file
10
db/migrate/20170915080151_create_procedure_presentations.rb
Normal file
|
@ -0,0 +1,10 @@
|
|||
class CreateProcedurePresentations < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
create_table :procedure_presentations do |t|
|
||||
t.references :assign_to, index: { unique: true }, foreign_key: true
|
||||
t.text :displayed_fields, array: true, default: [{ "label" => "Demandeur", "table" => "user", "column" => "email" }.to_json], null: false
|
||||
t.json :sort, default: { "table" => "self", "column" => "id", "order" => "desc" }.to_json, null: false
|
||||
t.json :filters, default: { "a-suivre" => [], "suivis" => [], "traites" => [], "tous" => [], "archives" => [] }.to_json, null: false
|
||||
end
|
||||
end
|
||||
end
|
11
db/schema.rb
11
db/schema.rb
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20170926092716) do
|
||||
ActiveRecord::Schema.define(version: 20170927092716) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
@ -382,6 +382,14 @@ ActiveRecord::Schema.define(version: 20170926092716) do
|
|||
t.index ["path"], name: "index_procedure_paths_on_path", using: :btree
|
||||
end
|
||||
|
||||
create_table "procedure_presentations", force: :cascade do |t|
|
||||
t.integer "assign_to_id"
|
||||
t.text "displayed_fields", default: ["{\"label\":\"Demandeur\",\"table\":\"user\",\"column\":\"email\"}"], null: false, array: true
|
||||
t.json "sort", default: "{\"table\":\"self\",\"column\":\"id\",\"order\":\"desc\"}", null: false
|
||||
t.json "filters", default: "{\"a-suivre\":[],\"suivis\":[],\"traites\":[],\"tous\":[],\"archives\":[]}", null: false
|
||||
t.index ["assign_to_id"], name: "index_procedure_presentations_on_assign_to_id", unique: true, using: :btree
|
||||
end
|
||||
|
||||
create_table "procedures", force: :cascade do |t|
|
||||
t.string "libelle"
|
||||
t.string "description"
|
||||
|
@ -503,6 +511,7 @@ ActiveRecord::Schema.define(version: 20170926092716) do
|
|||
add_foreign_key "initiated_mails", "procedures"
|
||||
add_foreign_key "procedure_paths", "administrateurs"
|
||||
add_foreign_key "procedure_paths", "procedures"
|
||||
add_foreign_key "procedure_presentations", "assign_tos"
|
||||
add_foreign_key "received_mails", "procedures"
|
||||
add_foreign_key "refused_mails", "procedures"
|
||||
add_foreign_key "without_continuation_mails", "procedures"
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
{
|
||||
"id": 2,
|
||||
"nom_projet": "Demande de subvention dans le cadre d'accompagnement d'enfant à l'étranger",
|
||||
"updated_at": "2008-09-01T08:05:00.000Z"
|
||||
"updated_at": "2008-09-01T08:05:00.000Z",
|
||||
"initiated_at": "2008-09-02T08:05:00.000Z"
|
||||
}
|
||||
],
|
||||
"pagination": {
|
||||
|
|
|
@ -25,7 +25,7 @@ describe API::V1::DossiersController do
|
|||
context 'when procedure is found and belongs to admin' do
|
||||
let(:procedure_id) { procedure.id }
|
||||
let(:date_creation) { Time.utc(2008, 9, 1, 10, 5, 0) }
|
||||
let!(:dossier) { Timecop.freeze(date_creation) { create(:dossier, :with_entreprise, procedure: procedure, state: 'initiated') } }
|
||||
let!(:dossier) { Timecop.freeze(date_creation) { create(:dossier, :with_entreprise, :initiated, procedure: procedure) } }
|
||||
let(:body) { JSON.parse(retour.body, symbolize_names: true) }
|
||||
|
||||
it 'return REST code 200', :show_in_doc do
|
||||
|
@ -53,7 +53,8 @@ describe API::V1::DossiersController do
|
|||
subject { super().first }
|
||||
it { expect(subject[:id]).to eq(dossier.id) }
|
||||
it { expect(subject[:updated_at]).to eq("2008-09-01T10:05:00.000Z") }
|
||||
it { expect(subject.keys.size).to eq(2) }
|
||||
it { expect(subject[:initiated_at]).to eq("2008-09-01T10:06:00.000Z") }
|
||||
it { expect(subject.keys.size).to eq(3) }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -55,12 +55,15 @@ describe NewGestionnaire::DossiersController, type: :controller do
|
|||
|
||||
describe '#archive' do
|
||||
before do
|
||||
gestionnaire.follow(dossier)
|
||||
patch :archive, params: { procedure_id: procedure.id, dossier_id: dossier.id }
|
||||
dossier.reload
|
||||
gestionnaire.reload
|
||||
end
|
||||
|
||||
it { expect(dossier.archived).to be true }
|
||||
it { expect(response).to redirect_to(procedures_url) }
|
||||
it { expect(gestionnaire.followed_dossiers).not_to include(dossier) }
|
||||
end
|
||||
|
||||
describe '#unarchive' do
|
||||
|
@ -121,6 +124,7 @@ describe NewGestionnaire::DossiersController, type: :controller do
|
|||
it { expect(saved_commentaire.email).to eq(gestionnaire.email) }
|
||||
it { expect(saved_commentaire.dossier).to eq(dossier) }
|
||||
it { expect(response).to redirect_to(messagerie_dossier_path(dossier.procedure, dossier)) }
|
||||
it { expect(gestionnaire.followed_dossiers).to include(dossier) }
|
||||
end
|
||||
|
||||
describe "#create_avis" do
|
||||
|
|
|
@ -172,15 +172,22 @@ describe NewGestionnaire::ProceduresController, type: :controller do
|
|||
context "when logged in" do
|
||||
before do
|
||||
sign_in(gestionnaire)
|
||||
get :show, params: { procedure_id: procedure.id }
|
||||
end
|
||||
|
||||
context "without anything" do
|
||||
before { get :show, params: { procedure_id: procedure.id } }
|
||||
|
||||
it { expect(response).to have_http_status(:ok) }
|
||||
it { expect(assigns(:procedure)).to eq(procedure) }
|
||||
end
|
||||
|
||||
context 'with a new draft dossier' do
|
||||
let!(:draft_dossier) { create(:dossier, procedure: procedure, state: 'draft') }
|
||||
|
||||
before do
|
||||
get :show, params: { procedure_id: procedure.id }
|
||||
end
|
||||
|
||||
it { expect(assigns(:a_suivre_dossiers)).to be_empty }
|
||||
it { expect(assigns(:followed_dossiers)).to be_empty }
|
||||
it { expect(assigns(:termines_dossiers)).to be_empty }
|
||||
|
@ -191,6 +198,10 @@ describe NewGestionnaire::ProceduresController, type: :controller do
|
|||
context 'with a new dossier without follower' do
|
||||
let!(:new_unfollow_dossier) { create(:dossier, procedure: procedure, state: 'received') }
|
||||
|
||||
before do
|
||||
get :show, params: { procedure_id: procedure.id }
|
||||
end
|
||||
|
||||
it { expect(assigns(:a_suivre_dossiers)).to match([new_unfollow_dossier]) }
|
||||
it { expect(assigns(:followed_dossiers)).to be_empty }
|
||||
it { expect(assigns(:termines_dossiers)).to be_empty }
|
||||
|
@ -201,7 +212,10 @@ describe NewGestionnaire::ProceduresController, type: :controller do
|
|||
context 'with a new dossier with a follower' do
|
||||
let!(:new_followed_dossier) { create(:dossier, procedure: procedure, state: 'received') }
|
||||
|
||||
before { gestionnaire.followed_dossiers << new_followed_dossier }
|
||||
before do
|
||||
gestionnaire.followed_dossiers << new_followed_dossier
|
||||
get :show, params: { procedure_id: procedure.id }
|
||||
end
|
||||
|
||||
it { expect(assigns(:a_suivre_dossiers)).to be_empty }
|
||||
it { expect(assigns(:followed_dossiers)).to match([new_followed_dossier]) }
|
||||
|
@ -213,6 +227,10 @@ describe NewGestionnaire::ProceduresController, type: :controller do
|
|||
context 'with a termine dossier with a follower' do
|
||||
let!(:termine_dossier) { create(:dossier, procedure: procedure, state: 'closed') }
|
||||
|
||||
before do
|
||||
get :show, params: { procedure_id: procedure.id }
|
||||
end
|
||||
|
||||
it { expect(assigns(:a_suivre_dossiers)).to be_empty }
|
||||
it { expect(assigns(:followed_dossiers)).to be_empty }
|
||||
it { expect(assigns(:termines_dossiers)).to match([termine_dossier]) }
|
||||
|
@ -223,6 +241,10 @@ describe NewGestionnaire::ProceduresController, type: :controller do
|
|||
context 'with an archived dossier' do
|
||||
let!(:archived_dossier) { create(:dossier, procedure: procedure, state: 'received', archived: true) }
|
||||
|
||||
before do
|
||||
get :show, params: { procedure_id: procedure.id }
|
||||
end
|
||||
|
||||
it { expect(assigns(:a_suivre_dossiers)).to be_empty }
|
||||
it { expect(assigns(:followed_dossiers)).to be_empty }
|
||||
it { expect(assigns(:termines_dossiers)).to be_empty }
|
||||
|
@ -235,6 +257,7 @@ describe NewGestionnaire::ProceduresController, type: :controller do
|
|||
let!(:new_followed_dossier) { Timecop.freeze(2.day.ago){ create(:dossier, procedure: procedure, state: 'received') } }
|
||||
let!(:termine_dossier) { Timecop.freeze(3.day.ago){ create(:dossier, procedure: procedure, state: 'closed') } }
|
||||
let!(:archived_dossier) { Timecop.freeze(4.day.ago){ create(:dossier, procedure: procedure, state: 'received', archived: true) } }
|
||||
|
||||
before do
|
||||
gestionnaire.followed_dossiers << new_followed_dossier
|
||||
get :show, params: { procedure_id: procedure.id, statut: statut }
|
||||
|
|
|
@ -9,5 +9,9 @@ FactoryGirl.define do
|
|||
trait :header_section do
|
||||
type_de_champ { FactoryGirl.create(:type_de_champ_public, :header_section) }
|
||||
end
|
||||
|
||||
trait :explication do
|
||||
type_de_champ { FactoryGirl.create(:type_de_champ_public, :explication) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -73,7 +73,20 @@ FactoryGirl.define do
|
|||
end
|
||||
|
||||
trait :initiated do
|
||||
state 'initiated'
|
||||
after(:create) do |dossier, _evaluator|
|
||||
dossier.state = 'initiated'
|
||||
dossier.initiated_at = dossier.created_at + 1.minute
|
||||
dossier.save!
|
||||
end
|
||||
end
|
||||
|
||||
trait :received do
|
||||
after(:create) do |dossier, _evaluator|
|
||||
dossier.state = 'received'
|
||||
dossier.initiated_at = dossier.created_at + 1.minute
|
||||
dossier.created_at = dossier.created_at + 2.minute
|
||||
dossier.save!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -44,12 +44,18 @@ FactoryGirl.define do
|
|||
end
|
||||
|
||||
trait :with_type_de_champ_private do
|
||||
after(:build) do |procedure, _evaluator|
|
||||
transient do
|
||||
types_de_champ_private_count 1
|
||||
end
|
||||
|
||||
after(:build) do |procedure, evaluator|
|
||||
evaluator.types_de_champ_private_count.times do
|
||||
type_de_champ = create(:type_de_champ_private)
|
||||
|
||||
procedure.types_de_champ_private << type_de_champ
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
trait :with_type_de_champ_mandatory do
|
||||
after(:build) do |procedure, _evaluator|
|
||||
|
|
|
@ -14,6 +14,10 @@ FactoryGirl.define do
|
|||
type_champ 'header_section'
|
||||
end
|
||||
|
||||
trait :explication do
|
||||
type_champ 'explication'
|
||||
end
|
||||
|
||||
trait :type_dossier_link do
|
||||
libelle 'Référence autre dossier'
|
||||
type_champ 'dossier_link'
|
||||
|
|
165
spec/features/new_gestionnaire/gestionnaire_spec.rb
Normal file
165
spec/features/new_gestionnaire/gestionnaire_spec.rb
Normal file
|
@ -0,0 +1,165 @@
|
|||
require 'spec_helper'
|
||||
|
||||
feature 'The gestionnaire part' do
|
||||
let(:password) { 'secret_password' }
|
||||
let!(:gestionnaire) { create(:gestionnaire, password: password) }
|
||||
|
||||
let!(:procedure) { create(:procedure, :published, gestionnaires: [gestionnaire]) }
|
||||
let!(:dossier) { create(:dossier, state: :initiated, procedure: procedure) }
|
||||
|
||||
scenario 'A gestionnaire can accept a dossier' do
|
||||
log_in(gestionnaire.email, password)
|
||||
|
||||
click_on 'nouvelle interface'
|
||||
expect(page).to have_current_path(procedures_path)
|
||||
|
||||
click_on procedure.libelle
|
||||
expect(page).to have_current_path(procedure_path(procedure))
|
||||
|
||||
click_on dossier.user.email
|
||||
expect(page).to have_current_path(dossier_path(procedure, dossier))
|
||||
|
||||
click_on 'Passer en instruction'
|
||||
dossier.reload
|
||||
expect(dossier.state).to eq('received')
|
||||
|
||||
fill_in('dossier_motivation', with: 'a good reason')
|
||||
click_on 'Valider la décision'
|
||||
|
||||
dossier.reload
|
||||
expect(dossier.state).to eq('closed')
|
||||
expect(dossier.motivation).to eq('a good reason')
|
||||
end
|
||||
|
||||
scenario 'A gestionnaire can follow/unfollow a dossier' do
|
||||
log_in(gestionnaire.email, password)
|
||||
|
||||
click_on 'nouvelle interface'
|
||||
|
||||
click_on procedure.libelle
|
||||
test_statut_bar(a_suivre: 1, tous_les_dossiers: 1)
|
||||
dossier_present?(dossier.id, 'en construction')
|
||||
|
||||
click_on 'Suivre le dossier'
|
||||
expect(page).to have_current_path(procedure_path(procedure))
|
||||
test_statut_bar(suivi: 1, tous_les_dossiers: 1)
|
||||
expect(page).to have_text('Aucun dossier')
|
||||
|
||||
click_on 'suivi'
|
||||
expect(page).to have_current_path(procedure_path(procedure, statut: 'suivis'))
|
||||
dossier_present?(dossier.id, 'en construction')
|
||||
|
||||
click_on 'Ne plus suivre'
|
||||
expect(page).to have_current_path(procedure_path(procedure, statut: 'suivis'))
|
||||
test_statut_bar(a_suivre: 1, tous_les_dossiers: 1)
|
||||
expect(page).to have_text('Aucun dossier')
|
||||
end
|
||||
|
||||
scenario 'A gestionnaire can use avis' do
|
||||
ActionMailer::Base.deliveries = []
|
||||
|
||||
log_in(gestionnaire.email, password)
|
||||
|
||||
click_on 'nouvelle interface'
|
||||
click_on procedure.libelle
|
||||
click_on dossier.user.email
|
||||
|
||||
click_on 'Avis externes'
|
||||
expect(page).to have_current_path(avis_dossier_path(procedure, dossier))
|
||||
|
||||
expert_email = 'expert@tps.com'
|
||||
ask_confidential_avis(expert_email, 'a good introduction')
|
||||
|
||||
log_out
|
||||
|
||||
avis = dossier.avis.first
|
||||
test_mail(expert_email, avis_sign_up_path(avis, expert_email))
|
||||
|
||||
avis_sign_up(avis, expert_email, 'a good password')
|
||||
|
||||
click_on 'nouvelle interface'
|
||||
expect(page).to have_current_path(avis_index_path)
|
||||
expect(page).to have_text('avis à donner 1')
|
||||
expect(page).to have_text('avis donnés 0')
|
||||
|
||||
click_on dossier.user.email
|
||||
expect(page).to have_current_path(avis_path(dossier.avis.first))
|
||||
|
||||
within(:css, '.tabs') do
|
||||
click_on 'Avis'
|
||||
end
|
||||
expect(page).to have_current_path(instruction_avis_path(dossier.avis.first))
|
||||
|
||||
within(:css, '.give-avis') do
|
||||
expect(page).to have_text("Demandeur : #{gestionnaire.email}")
|
||||
expect(page).to have_text('a good introduction')
|
||||
expect(page).to have_text('Cet avis est confidentiel')
|
||||
fill_in 'avis_answer', with: 'a great answer'
|
||||
click_on 'Envoyer votre avis'
|
||||
end
|
||||
|
||||
log_out
|
||||
|
||||
log_in(gestionnaire.email, password)
|
||||
|
||||
click_on 'nouvelle interface'
|
||||
click_on procedure.libelle
|
||||
click_on dossier.user.email
|
||||
click_on 'Avis externes'
|
||||
|
||||
expect(page).to have_text('a great answer')
|
||||
end
|
||||
|
||||
def log_in(email, password)
|
||||
visit '/'
|
||||
click_on 'Connexion'
|
||||
expect(page).to have_current_path(new_user_session_path)
|
||||
|
||||
fill_in 'user_email', with: email
|
||||
fill_in 'user_password', with: password
|
||||
click_on 'Se connecter'
|
||||
expect(page).to have_current_path(backoffice_dossiers_procedure_path(procedure))
|
||||
end
|
||||
|
||||
def log_out
|
||||
click_on 'Se déconnecter'
|
||||
end
|
||||
|
||||
def ask_confidential_avis(to, introduction)
|
||||
fill_in 'avis_email', with: to
|
||||
fill_in 'avis_introduction', with: introduction
|
||||
select 'confidentiel', from: 'avis_confidentiel'
|
||||
click_on 'Demander un avis'
|
||||
end
|
||||
|
||||
def test_mail(to, content)
|
||||
mail = ActionMailer::Base.deliveries.first
|
||||
expect(mail.to).to match([to])
|
||||
expect(mail.body.raw_source).to include(content)
|
||||
end
|
||||
|
||||
def test_statut_bar(a_suivre: 0, suivi: 0, traite: 0, tous_les_dossiers: 0, archive: 0)
|
||||
texts = [
|
||||
"à suivre #{a_suivre}",
|
||||
"suivi #{suivi}",
|
||||
"traité #{traite}",
|
||||
"tous les dossiers #{tous_les_dossiers}",
|
||||
"archivé #{archive}"]
|
||||
|
||||
texts.each { |text| expect(page).to have_text(text) }
|
||||
end
|
||||
|
||||
def avis_sign_up(avis, email, password)
|
||||
visit avis_sign_up_path(avis, email)
|
||||
fill_in 'gestionnaire_password', with: 'a good password'
|
||||
click_on 'Créer un compte'
|
||||
expect(page).to have_current_path(backoffice_dossier_path(dossier))
|
||||
end
|
||||
|
||||
def dossier_present?(id, statut)
|
||||
within(:css, '.dossiers-table') do
|
||||
expect(page).to have_text(id)
|
||||
expect(page).to have_text(statut)
|
||||
end
|
||||
end
|
||||
end
|
104
spec/features/new_gestionnaire/procedure_filters_spec.rb
Normal file
104
spec/features/new_gestionnaire/procedure_filters_spec.rb
Normal file
|
@ -0,0 +1,104 @@
|
|||
require "spec_helper"
|
||||
|
||||
feature "procedure filters" do
|
||||
let(:procedure) { create(:procedure, :published, :with_type_de_champ) }
|
||||
let(:gestionnaire) { create(:gestionnaire, procedures: [procedure]) }
|
||||
let!(:type_de_champ) { procedure.types_de_champ.first }
|
||||
let!(:new_unfollow_dossier) { create(:dossier, procedure: procedure, state: "received") }
|
||||
let!(:champ) { Champ.find_by(type_de_champ_id: type_de_champ.id, dossier_id: new_unfollow_dossier.id) }
|
||||
let!(:new_unfollow_dossier_2) { create(:dossier, procedure: procedure, state: "received") }
|
||||
|
||||
before do
|
||||
champ.update_attributes(value: "Mon champ rempli")
|
||||
login_as gestionnaire, scope: :gestionnaire
|
||||
visit procedure_path(procedure)
|
||||
end
|
||||
|
||||
scenario "should display demandeur by default" do
|
||||
within ".dossiers-table" do
|
||||
expect(page).to have_link("Demandeur")
|
||||
expect(page).to have_link(new_unfollow_dossier.user.email)
|
||||
end
|
||||
end
|
||||
|
||||
scenario "should list all dossiers" do
|
||||
within ".dossiers-table" do
|
||||
expect(page).to have_link(new_unfollow_dossier.id)
|
||||
expect(page).to have_link(new_unfollow_dossier.user.email)
|
||||
|
||||
expect(page).to have_link(new_unfollow_dossier_2.id)
|
||||
expect(page).to have_link(new_unfollow_dossier_2.user.email)
|
||||
end
|
||||
end
|
||||
|
||||
scenario "should add be able to add created_at column", js: true do
|
||||
add_column("Créé le")
|
||||
within ".dossiers-table" do
|
||||
expect(page).to have_link("Créé le")
|
||||
expect(page).to have_link(new_unfollow_dossier.created_at)
|
||||
end
|
||||
end
|
||||
|
||||
scenario "should add be able to add and remove custom type_de_champ column", js: true do
|
||||
add_column(type_de_champ.libelle)
|
||||
within ".dossiers-table" do
|
||||
expect(page).to have_link(type_de_champ.libelle)
|
||||
expect(page).to have_link(champ.value)
|
||||
end
|
||||
|
||||
remove_column(type_de_champ.libelle)
|
||||
within ".dossiers-table" do
|
||||
expect(page).not_to have_link(type_de_champ.libelle)
|
||||
expect(page).not_to have_link(champ.value)
|
||||
end
|
||||
end
|
||||
|
||||
scenario "should be able to add and remove filter", js: true do
|
||||
add_filter(type_de_champ.libelle, champ.value)
|
||||
|
||||
expect(page).to have_content("#{type_de_champ.libelle} : #{champ.value}")
|
||||
|
||||
within ".dossiers-table" do
|
||||
expect(page).to have_link(new_unfollow_dossier.id)
|
||||
expect(page).to have_link(new_unfollow_dossier.user.email)
|
||||
|
||||
expect(page).not_to have_link(new_unfollow_dossier_2.id)
|
||||
expect(page).not_to have_link(new_unfollow_dossier_2.user.email)
|
||||
end
|
||||
|
||||
remove_filter
|
||||
|
||||
within ".dossiers-table" do
|
||||
expect(page).to have_link(new_unfollow_dossier.id)
|
||||
expect(page).to have_link(new_unfollow_dossier.user.email)
|
||||
|
||||
expect(page).to have_link(new_unfollow_dossier_2.id)
|
||||
expect(page).to have_link(new_unfollow_dossier_2.user.email)
|
||||
end
|
||||
end
|
||||
|
||||
def remove_filter
|
||||
find(:xpath, "//span[contains(@class, 'filter')]/a").click
|
||||
end
|
||||
|
||||
def add_filter(column_name, filter_value)
|
||||
find(:xpath, "//span[contains(text(), 'Filtrer')]").click
|
||||
select column_name, from: "Colonne"
|
||||
fill_in "Valeur", with: filter_value
|
||||
click_button "Ajouter le filtre"
|
||||
end
|
||||
|
||||
def add_column(column_name)
|
||||
find(:xpath, "//span[contains(text(), 'Personnaliser')]").click
|
||||
find("span.select2-container").click
|
||||
find(:xpath, "//li[text()='#{column_name}']").click
|
||||
click_button "Enregistrer"
|
||||
end
|
||||
|
||||
def remove_column(column_name)
|
||||
find(:xpath, "//span[contains(text(), 'Personnaliser')]").click
|
||||
find(:xpath, "//li[contains(@title, '#{column_name}')]/span[contains(text(), '×')]").click
|
||||
find(:xpath, "//span[contains(text(), 'Personnaliser')]//span[contains(@class, 'select2-container')]").click
|
||||
click_button "Enregistrer"
|
||||
end
|
||||
end
|
16
spec/jobs/application_job_spec.rb
Normal file
16
spec/jobs/application_job_spec.rb
Normal file
|
@ -0,0 +1,16 @@
|
|||
require 'rails_helper'
|
||||
include ActiveJob::TestHelper
|
||||
|
||||
RSpec.describe ApplicationJob, type: :job do
|
||||
describe 'perform' do
|
||||
it do
|
||||
expect(Rails.logger).to receive(:info).with(/.+started at.+/)
|
||||
expect(Rails.logger).to receive(:info).with(/.+ended at.+/)
|
||||
perform_enqueued_jobs { ChildJob.perform_later }
|
||||
end
|
||||
end
|
||||
|
||||
class ChildJob < ApplicationJob
|
||||
def perform; end
|
||||
end
|
||||
end
|
|
@ -1,15 +1,12 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe AutoArchiveProcedureWorker, type: :worker do
|
||||
before { Delayed::Worker.delay_jobs = false }
|
||||
after { Delayed::Worker.delay_jobs = true }
|
||||
|
||||
RSpec.describe AutoArchiveProcedureJob, type: :job do
|
||||
let!(:procedure) { create(:procedure, published_at: Time.now, archived_at: nil, auto_archive_on: nil )}
|
||||
let!(:procedure_hier) { create(:procedure, published_at: Time.now, archived_at: nil, auto_archive_on: 1.day.ago )}
|
||||
let!(:procedure_aujourdhui) { create(:procedure, published_at: Time.now, archived_at: nil, auto_archive_on: Date.today )}
|
||||
let!(:procedure_demain) { create(:procedure, published_at: Time.now, archived_at: nil, auto_archive_on: 1.day.from_now )}
|
||||
|
||||
subject { AutoArchiveProcedureWorker.new.perform }
|
||||
subject { AutoArchiveProcedureJob.new.perform }
|
||||
|
||||
context "when procedures have no auto_archive_on" do
|
||||
before do
|
34
spec/jobs/auto_receive_dossiers_for_procedure_job_spec.rb
Normal file
34
spec/jobs/auto_receive_dossiers_for_procedure_job_spec.rb
Normal file
|
@ -0,0 +1,34 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe AutoReceiveDossiersForProcedureJob, type: :job do
|
||||
describe "perform" do
|
||||
let(:date) { Time.utc(2017, 9, 1, 10, 5, 0) }
|
||||
|
||||
before { Timecop.freeze(date) }
|
||||
|
||||
subject { AutoReceiveDossiersForProcedureJob.new.perform(procedure_id) }
|
||||
|
||||
context "with some dossiers" do
|
||||
let(:nouveau_dossier1) { create(:dossier, :initiated) }
|
||||
let(:nouveau_dossier2) { create(:dossier, :initiated, procedure: nouveau_dossier1.procedure) }
|
||||
let(:dossier_recu) { create(:dossier, :received, procedure: nouveau_dossier2.procedure) }
|
||||
let(:dossier_draft) { create(:dossier, procedure: dossier_recu.procedure) }
|
||||
let(:procedure_id) { dossier_draft.procedure_id }
|
||||
|
||||
it do
|
||||
subject
|
||||
expect(nouveau_dossier1.reload.received?).to be true
|
||||
expect(nouveau_dossier1.reload.received_at).to eq(date)
|
||||
|
||||
expect(nouveau_dossier2.reload.received?).to be true
|
||||
expect(nouveau_dossier2.reload.received_at).to eq(date)
|
||||
|
||||
expect(dossier_recu.reload.received?).to be true
|
||||
expect(dossier_recu.reload.received_at).to eq(date)
|
||||
|
||||
expect(dossier_draft.reload.draft?).to be true
|
||||
expect(dossier_draft.reload.received_at).to eq(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,9 +1,6 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe WeeklyOverviewWorker, type: :worker do
|
||||
before { Delayed::Worker.delay_jobs = false }
|
||||
after { Delayed::Worker.delay_jobs = true }
|
||||
|
||||
RSpec.describe WeeklyOverviewJob, type: :job do
|
||||
describe 'perform' do
|
||||
let!(:gestionnaire) { create(:gestionnaire) }
|
||||
let(:overview) { double('overview') }
|
||||
|
@ -16,7 +13,7 @@ RSpec.describe WeeklyOverviewWorker, type: :worker do
|
|||
before :each do
|
||||
expect_any_instance_of(Gestionnaire).to receive(:last_week_overview).and_return(overview)
|
||||
allow(GestionnaireMailer).to receive(:last_week_overview).and_return(mailer_double)
|
||||
WeeklyOverviewWorker.new.perform
|
||||
WeeklyOverviewJob.new.perform
|
||||
end
|
||||
|
||||
it { expect(GestionnaireMailer).to have_received(:last_week_overview).with(gestionnaire, overview) }
|
||||
|
@ -27,7 +24,7 @@ RSpec.describe WeeklyOverviewWorker, type: :worker do
|
|||
before :each do
|
||||
expect_any_instance_of(Gestionnaire).to receive(:last_week_overview).and_return(nil)
|
||||
allow(GestionnaireMailer).to receive(:last_week_overview)
|
||||
WeeklyOverviewWorker.new.perform
|
||||
WeeklyOverviewJob.new.perform
|
||||
end
|
||||
|
||||
it { expect(GestionnaireMailer).not_to have_received(:last_week_overview) }
|
||||
|
@ -38,7 +35,7 @@ RSpec.describe WeeklyOverviewWorker, type: :worker do
|
|||
before { allow(Features).to receive(:weekly_overview).and_return(false) }
|
||||
before :each do
|
||||
allow(Gestionnaire).to receive(:all)
|
||||
WeeklyOverviewWorker.new.perform
|
||||
WeeklyOverviewJob.new.perform
|
||||
end
|
||||
|
||||
it { expect(Gestionnaire).not_to receive(:all) }
|
16
spec/models/assign_to_spec.rb
Normal file
16
spec/models/assign_to_spec.rb
Normal file
|
@ -0,0 +1,16 @@
|
|||
describe AssignTo, type: :model do
|
||||
describe '#procedure_presentation_or_default' do
|
||||
context "without a procedure_presentation" do
|
||||
let!(:assign_to) { AssignTo.create }
|
||||
|
||||
it { expect(assign_to.procedure_presentation_or_default.persisted?).to be_falsey }
|
||||
end
|
||||
|
||||
context "with a procedure_presentation" do
|
||||
let!(:assign_to) { AssignTo.create }
|
||||
let!(:procedure_presentation) { ProcedurePresentation.create(assign_to: assign_to) }
|
||||
|
||||
it { expect(assign_to.procedure_presentation_or_default).to eq(procedure_presentation) }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -835,4 +835,28 @@ describe Dossier do
|
|||
it { expect(Dossier.count).to eq(0) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#get_value" do
|
||||
let(:dossier) { create(:dossier, :with_entreprise, user: user) }
|
||||
|
||||
before do
|
||||
FranceConnectInformation.create(france_connect_particulier_id: 123, user: user, gender: 'male')
|
||||
|
||||
@champ_public = dossier.champs.first
|
||||
@champ_public.value = "kiwi"
|
||||
@champ_public.save
|
||||
|
||||
@champ_private = dossier.champs_private.first
|
||||
@champ_private.value = "banane"
|
||||
@champ_private.save
|
||||
end
|
||||
|
||||
it { expect(dossier.get_value('self', 'created_at')).to eq(dossier.created_at) }
|
||||
it { expect(dossier.get_value('user', 'email')).to eq(user.email) }
|
||||
it { expect(dossier.get_value('france_connect_information', 'gender')).to eq(user.france_connect_information.gender) }
|
||||
it { expect(dossier.get_value('entreprise', 'siren')).to eq(dossier.entreprise.siren) }
|
||||
it { expect(dossier.get_value('etablissement', 'siret')).to eq(dossier.etablissement.siret) }
|
||||
it { expect(dossier.get_value('type_de_champ', @champ_public.type_de_champ.id.to_s)).to eq(dossier.champs.first.value) }
|
||||
it { expect(dossier.get_value('type_de_champ_private', @champ_private.type_de_champ.id.to_s)).to eq(dossier.champs_private.first.value) }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -32,6 +32,20 @@ describe Gestionnaire, type: :model do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#unfollow' do
|
||||
let(:already_followed_dossier) { create(:dossier) }
|
||||
before { gestionnaire.followed_dossiers << already_followed_dossier }
|
||||
|
||||
context 'when a gestionnaire unfollow a dossier already followed' do
|
||||
before do
|
||||
gestionnaire.unfollow(already_followed_dossier)
|
||||
already_followed_dossier.reload
|
||||
end
|
||||
|
||||
it { expect(gestionnaire.follow?(already_followed_dossier)).to be false }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#follow?' do
|
||||
let!(:dossier) { create :dossier, procedure: procedure }
|
||||
|
||||
|
@ -382,4 +396,12 @@ describe Gestionnaire, type: :model do
|
|||
it { is_expected.to eq({ }) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "procedure_presentation_for_procedure_id" do
|
||||
let!(:procedure_assign_2) { create :assign_to, gestionnaire: gestionnaire, procedure: procedure_2 }
|
||||
let!(:pp) { ProcedurePresentation.create(assign_to: procedure_assign) }
|
||||
|
||||
it { expect(gestionnaire.procedure_presentation_for_procedure_id(procedure.id)).to eq(pp)}
|
||||
it { expect(gestionnaire.procedure_presentation_for_procedure_id(procedure_2.id).persisted?).to be_falsey}
|
||||
end
|
||||
end
|
||||
|
|
26
spec/models/procedure_presentation_spec.rb
Normal file
26
spec/models/procedure_presentation_spec.rb
Normal file
|
@ -0,0 +1,26 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe ProcedurePresentation do
|
||||
let (:procedure_presentation_id) {
|
||||
ProcedurePresentation.create(
|
||||
displayed_fields: [
|
||||
{ "label" => "test1", "table" => "user" }.to_json,
|
||||
{ "label" => "test2", "table" => "champs" }.to_json],
|
||||
sort: { "table" => "user","column" => "email","order" => "asc" }.to_json,
|
||||
filters: { "a-suivre" => [], "suivis" => [{ "label" => "label1", "table" => "table1", "column" => "column1" }] }.to_json
|
||||
).id
|
||||
}
|
||||
let (:procedure_presentation) { ProcedurePresentation.find(procedure_presentation_id) }
|
||||
|
||||
describe "#displayed_fields" do
|
||||
it { expect(procedure_presentation.displayed_fields).to eq([{"label" => "test1", "table" => "user"}, {"label" => "test2", "table" => "champs"}]) }
|
||||
end
|
||||
|
||||
describe "#sort" do
|
||||
it { expect(procedure_presentation.sort).to eq({ "table" => "user","column" => "email","order" => "asc" }) }
|
||||
end
|
||||
|
||||
describe "#filters" do
|
||||
it { expect(procedure_presentation.filters).to eq({ "a-suivre" => [], "suivis" => [{ "label" => "label1", "table" => "table1", "column" => "column1" }] }) }
|
||||
end
|
||||
end
|
|
@ -408,17 +408,83 @@ describe Procedure do
|
|||
let(:procedure) { create(:procedure) }
|
||||
let!(:dossier) { create(:dossier, procedure: procedure) }
|
||||
let!(:dossier2) { create(:dossier, procedure: procedure) }
|
||||
let(:gestionnaire) { create(:gestionnaire) }
|
||||
|
||||
it { expect(Dossier.count).to eq(2) }
|
||||
it { expect(Dossier.all).to include(dossier, dossier2) }
|
||||
|
||||
context "when hidding procedure" do
|
||||
before do
|
||||
gestionnaire.followed_dossiers << dossier
|
||||
procedure.hide!
|
||||
gestionnaire.reload
|
||||
end
|
||||
|
||||
it { expect(procedure.dossiers.count).to eq(0) }
|
||||
it { expect(Dossier.count).to eq(0) }
|
||||
it { expect(gestionnaire.followed_dossiers).not_to include(dossier) }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#fields" do
|
||||
subject { create(:procedure, :with_type_de_champ, :with_type_de_champ_private, :types_de_champ_count => 4, :types_de_champ_private_count => 4) }
|
||||
let(:tdc_1) { subject.types_de_champ[0] }
|
||||
let(:tdc_2) { subject.types_de_champ[1] }
|
||||
let(:tdc_private_1) { subject.types_de_champ_private[0] }
|
||||
let(:tdc_private_2) { subject.types_de_champ_private[1] }
|
||||
let(:expected) {
|
||||
[
|
||||
{ "label" => 'Créé le', "table" => 'self', "column" => 'created_at' },
|
||||
{ "label" => 'Mis à jour le', "table" => 'self', "column" => 'updated_at' },
|
||||
{ "label" => 'Demandeur', "table" => 'user', "column" => 'email' },
|
||||
{ "label" => 'Civilité (FC)', "table" => 'france_connect_information', "column" => 'gender' },
|
||||
{ "label" => 'Prénom (FC)', "table" => 'france_connect_information', "column" => 'given_name' },
|
||||
{ "label" => 'Nom (FC)', "table" => 'france_connect_information', "column" => 'family_name' },
|
||||
{ "label" => 'SIREN', "table" => 'entreprise', "column" => 'siren' },
|
||||
{ "label" => 'Forme juridique', "table" => 'entreprise', "column" => 'forme_juridique' },
|
||||
{ "label" => 'Nom commercial', "table" => 'entreprise', "column" => 'nom_commercial' },
|
||||
{ "label" => 'Raison sociale', "table" => 'entreprise', "column" => 'raison_sociale' },
|
||||
{ "label" => 'SIRET siège social', "table" => 'entreprise', "column" => 'siret_siege_social' },
|
||||
{ "label" => 'Date de création', "table" => 'entreprise', "column" => 'date_creation' },
|
||||
{ "label" => 'SIRET', "table" => 'etablissement', "column" => 'siret' },
|
||||
{ "label" => 'Nom établissement', "table" => 'etablissement', "column" => 'libelle_naf' },
|
||||
{ "label" => 'Code postal', "table" => 'etablissement', "column" => 'code_postal' },
|
||||
{ "label" => tdc_1.libelle, "table" => 'type_de_champ', "column" => tdc_1.id.to_s },
|
||||
{ "label" => tdc_2.libelle, "table" => 'type_de_champ', "column" => tdc_2.id.to_s },
|
||||
{ "label" => tdc_private_1.libelle, "table" => 'type_de_champ_private', "column" => tdc_private_1.id.to_s },
|
||||
{ "label" => tdc_private_2.libelle, "table" => 'type_de_champ_private', "column" => tdc_private_2.id.to_s }
|
||||
]
|
||||
}
|
||||
|
||||
before do
|
||||
subject.types_de_champ[2].update_attribute(:type_champ, 'header_section')
|
||||
subject.types_de_champ[3].update_attribute(:type_champ, 'explication')
|
||||
subject.types_de_champ_private[2].update_attribute(:type_champ, 'header_section')
|
||||
subject.types_de_champ_private[3].update_attribute(:type_champ, 'explication')
|
||||
end
|
||||
|
||||
it { expect(subject.fields).to eq(expected) }
|
||||
end
|
||||
|
||||
describe "#fields_for_select" do
|
||||
subject { create(:procedure) }
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:fields).and_return([{
|
||||
"label" => "label1",
|
||||
"table" => "table1",
|
||||
"column" => "column1"
|
||||
}, {
|
||||
"label" => "label2",
|
||||
"table" => "table2",
|
||||
"column" => "column2"
|
||||
}])
|
||||
end
|
||||
|
||||
it { expect(subject.fields_for_select).to eq([["label1", "table1/column1"], ["label2", "table2/column2"]]) }
|
||||
end
|
||||
|
||||
describe ".default_sort" do
|
||||
it { expect(Procedure.default_sort).to eq("{\"table\":\"self\",\"column\":\"id\",\"order\":\"desc\"}") }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -24,6 +24,8 @@ require 'rspec/rails'
|
|||
# If you are not using ActiveRecord, you can remove this line.
|
||||
ActiveRecord::Migration.maintain_test_schema!
|
||||
|
||||
ActiveJob::Base.queue_adapter = :test
|
||||
|
||||
RSpec.configure do |config|
|
||||
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
|
||||
config.fixture_path = "#{::Rails.root}/spec/fixtures"
|
||||
|
|
|
@ -89,7 +89,9 @@ RSpec.configure do |config|
|
|||
|
||||
config.infer_base_class_for_anonymous_controllers = false
|
||||
|
||||
config.run_all_when_everything_filtered = true
|
||||
config.filter_run :show_in_doc => true if ENV['APIPIE_RECORD']
|
||||
config.filter_run :focus => true
|
||||
|
||||
config.order = 'random'
|
||||
|
||||
|
|
|
@ -4,12 +4,16 @@ describe 'new_gestionnaire/dossiers/champs.html.haml', type: :view do
|
|||
context "there is some champs" do
|
||||
let(:champ1) { create(:champ, :checkbox, value: "true") }
|
||||
let(:champ2) { create(:champ, :header_section, value: "Section") }
|
||||
let(:champs) { [champ1, champ2] }
|
||||
let(:champ3) { create(:champ, :explication, value: "mazette") }
|
||||
let(:champs) { [champ1, champ2, champ3] }
|
||||
|
||||
it { expect(rendered).to include(champ1.libelle) }
|
||||
it { expect(rendered).to include(champ1.value) }
|
||||
|
||||
it { expect(rendered).to have_css(".header-section") }
|
||||
it { expect(rendered).to include(champ2.libelle) }
|
||||
|
||||
it { expect(rendered).not_to include(champ3.libelle) }
|
||||
it { expect(rendered).not_to include(champ3.value) }
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue