diff --git a/app/assets/images/icons/trash.svg b/app/assets/images/icons/trash.svg
new file mode 100644
index 000000000..ea3e1ca31
--- /dev/null
+++ b/app/assets/images/icons/trash.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/assets/stylesheets/new_design/buttons.scss b/app/assets/stylesheets/new_design/buttons.scss
index d2c809c5b..5092221ff 100644
--- a/app/assets/stylesheets/new_design/buttons.scss
+++ b/app/assets/stylesheets/new_design/buttons.scss
@@ -60,6 +60,10 @@
color: #FFFFFF;
border-color: $medium-red;
background-color: $medium-red;
+
+ > .icon {
+ filter: brightness(100);
+ }
}
}
diff --git a/app/assets/stylesheets/new_design/commencer.scss b/app/assets/stylesheets/new_design/commencer.scss
new file mode 100644
index 000000000..5da4faf86
--- /dev/null
+++ b/app/assets/stylesheets/new_design/commencer.scss
@@ -0,0 +1,11 @@
+@import "constants";
+
+.commencer {
+ .button:first-of-type {
+ margin-top: 4 * $default-spacer;
+ }
+
+ .button {
+ margin-bottom: 2 * $default-spacer;
+ }
+}
diff --git a/app/assets/stylesheets/new_design/dossiers_table.scss b/app/assets/stylesheets/new_design/dossiers_table.scss
index b3cd92a4e..1f3468039 100644
--- a/app/assets/stylesheets/new_design/dossiers_table.scss
+++ b/app/assets/stylesheets/new_design/dossiers_table.scss
@@ -70,10 +70,17 @@
width: 110px;
}
- .follow-col {
- width: 200px;
+ .action-col {
text-align: right;
padding-left: $default-spacer;
padding-right: $default-spacer;
}
+
+ .follow-col {
+ width: 200px;
+ }
+
+ .delete-col {
+ width: 150px;
+ }
}
diff --git a/app/assets/stylesheets/new_design/forms.scss b/app/assets/stylesheets/new_design/forms.scss
index 95beff55e..a5edd446a 100644
--- a/app/assets/stylesheets/new_design/forms.scss
+++ b/app/assets/stylesheets/new_design/forms.scss
@@ -5,6 +5,10 @@
h1 {
text-align: center;
margin-bottom: 20px;
+
+ @media (max-width: $two-columns-breakpoint) {
+ font-size: 28px;
+ }
}
hr {
diff --git a/app/assets/stylesheets/new_design/icons.scss b/app/assets/stylesheets/new_design/icons.scss
index c2efb749a..fd3b8497c 100644
--- a/app/assets/stylesheets/new_design/icons.scss
+++ b/app/assets/stylesheets/new_design/icons.scss
@@ -105,4 +105,8 @@
&.meh {
background-image: image-url("icons/meh-regular.svg");
}
+
+ &.delete {
+ background-image: image-url("icons/trash.svg");
+ }
}
diff --git a/app/controllers/concerns/procedure_context_concern.rb b/app/controllers/concerns/procedure_context_concern.rb
index 307dba95e..d2d7b5a2c 100644
--- a/app/controllers/concerns/procedure_context_concern.rb
+++ b/app/controllers/concerns/procedure_context_concern.rb
@@ -5,8 +5,8 @@ module ProcedureContextConcern
include Devise::StoreLocationExtension
def restore_procedure_context
- if stored_procedure_id.present?
- @procedure = Procedure.publiees.find_by(id: stored_procedure_id)
+ if has_stored_procedure_path?
+ @procedure = find_procedure_in_context
if @procedure.blank?
invalid_procedure_context
@@ -16,11 +16,18 @@ module ProcedureContextConcern
private
- def stored_procedure_id
- stored_location = get_stored_location_for(:user)
+ def has_stored_procedure_path?
+ get_stored_location_for(:user)&.start_with?('/commencer/')
+ end
- if stored_location.present? && stored_location.include?('procedure_id=')
- stored_location.split('procedure_id=').second
+ def find_procedure_in_context
+ uri = URI(get_stored_location_for(:user))
+ path_components = uri.path.split('/')
+
+ if uri.path.start_with?('/commencer/test/')
+ Procedure.brouillon.find_by(path: path_components[3])
+ elsif uri.path.start_with?('/commencer/')
+ Procedure.publiee.find_by(path: path_components[2])
else
nil
end
diff --git a/app/controllers/new_user/commencer_controller.rb b/app/controllers/new_user/commencer_controller.rb
index b514544d1..325bf3706 100644
--- a/app/controllers/new_user/commencer_controller.rb
+++ b/app/controllers/new_user/commencer_controller.rb
@@ -1,25 +1,44 @@
module NewUser
class CommencerController < ApplicationController
- def commencer_test
- procedure = Procedure.brouillons.find_by(path: params[:path])
-
- if procedure.present?
- redirect_to new_dossier_path(procedure_id: procedure.id, brouillon: true)
- else
- flash.alert = "La démarche est inconnue."
- redirect_to root_path
- end
- end
+ layout 'procedure_context'
def commencer
- procedure = Procedure.publiees.find_by(path: params[:path])
+ @procedure = Procedure.publiees.find_by(path: params[:path])
- if procedure.present?
- redirect_to new_dossier_path(procedure_id: procedure.id)
- else
+ if @procedure.blank?
flash.alert = "La démarche est inconnue, ou la création de nouveaux dossiers pour cette démarche est terminée."
- redirect_to root_path
+ return redirect_to root_path
end
+
+ render 'commencer/show'
+ end
+
+ def commencer_test
+ @procedure = Procedure.brouillons.find_by(path: params[:path])
+
+ if @procedure.blank?
+ flash.alert = "La démarche est inconnue, ou cette démarche n’est maintenant plus en test."
+ return redirect_to root_path
+ end
+
+ render 'commencer/show'
+ end
+
+ def sign_in
+ store_user_location!
+ redirect_to new_user_session_path
+ end
+
+ def sign_up
+ store_user_location!
+ redirect_to new_user_registration_path
+ end
+
+ private
+
+ def store_user_location!
+ procedure = Procedure.find_by(path: params[:path])
+ store_location_for(:user, commencer_path(path: procedure.path))
end
end
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index b1bda2b01..d167a0609 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -85,13 +85,8 @@ module ApplicationHelper
tags, type, dossier_id = options.values_at(:tags, :type, :dossier_id)
options.except!(:tags, :type, :dossier_id)
- if Flipflop.support_form?
- params = { tags: tags, type: type, dossier_id: dossier_id }.compact
- link_to title, contact_url(params), options
- else
- mail_to CONTACT_EMAIL, title,
- options.merge(subject: "Question à propos de demarches-simplifiees.fr")
- end
+ params = { tags: tags, type: type, dossier_id: dossier_id }.compact
+ link_to title, contact_url(params), options
end
def root_path_for_profile(nav_bar_profile)
diff --git a/app/helpers/dossier_helper.rb b/app/helpers/dossier_helper.rb
index 53c759d5b..812eff956 100644
--- a/app/helpers/dossier_helper.rb
+++ b/app/helpers/dossier_helper.rb
@@ -23,6 +23,14 @@ module DossierHelper
end
end
+ def url_for_new_dossier(procedure)
+ if procedure.brouillon?
+ new_dossier_url(procedure_id: procedure.id, brouillon: true)
+ else
+ new_dossier_url(procedure_id: procedure.id)
+ end
+ end
+
def dossier_submission_is_closed?(dossier)
dossier.brouillon? && dossier.procedure.archivee?
end
diff --git a/app/helpers/procedure_helper.rb b/app/helpers/procedure_helper.rb
index bdedf9416..c6d6db847 100644
--- a/app/helpers/procedure_helper.rb
+++ b/app/helpers/procedure_helper.rb
@@ -64,7 +64,6 @@ module ProcedureHelper
private
TOGGLES = {
- TypeDeChamp.type_champs.fetch(:siret) => :champ_siret?,
TypeDeChamp.type_champs.fetch(:integer_number) => :champ_integer_number?,
TypeDeChamp.type_champs.fetch(:repetition) => :champ_repetition?
}
diff --git a/app/javascript/new_design/administrateur/DraggableItem.js b/app/javascript/new_design/administrateur/DraggableItem.js
index f9a55edbb..70dee126f 100644
--- a/app/javascript/new_design/administrateur/DraggableItem.js
+++ b/app/javascript/new_design/administrateur/DraggableItem.js
@@ -57,7 +57,7 @@ export default {
return this.typeChamp === 'header_section';
},
options() {
- const options = this.item.options;
+ const options = this.item.options || {};
for (let key of Object.keys(options)) {
options[key] = castBoolean(options[key]);
}
@@ -77,7 +77,7 @@ export default {
libelle: this.item.libelle,
mandatory: this.item.mandatory,
description: this.item.description,
- dropDownList: this.item.drop_down_list.value,
+ dropDownList: this.item.drop_down_list && this.item.drop_down_list.value,
deleted: false,
clientId: `id-${clientIds++}`
};
diff --git a/app/javascript/new_design/administrateur/champs-editor.js b/app/javascript/new_design/administrateur/champs-editor.js
index 6bfb9d43d..4b83af165 100644
--- a/app/javascript/new_design/administrateur/champs-editor.js
+++ b/app/javascript/new_design/administrateur/champs-editor.js
@@ -10,6 +10,12 @@ Vue.component('DraggableItem', DraggableItem);
addEventListener('DOMContentLoaded', () => {
const el = document.querySelector('#champs-editor');
+ if (el) {
+ initEditor(el);
+ }
+});
+
+function initEditor(el) {
const { directUploadsUrl, dragIconUrl } = el.dataset;
const state = {
@@ -48,7 +54,7 @@ addEventListener('DOMContentLoaded', () => {
this.updateAll = updateAll;
}
});
-});
+}
function createUpdateFunctions(app, isAnnotation) {
let isSaving = false;
diff --git a/app/models/procedure.rb b/app/models/procedure.rb
index b79d5ad47..276a90183 100644
--- a/app/models/procedure.rb
+++ b/app/models/procedure.rb
@@ -184,10 +184,11 @@ class Procedure < ApplicationRecord
end
def clone(admin, from_library)
+ is_different_admin = self.administrateur_id != admin.id
+
populate_champ_stable_ids
procedure = self.deep_clone(include:
{
- types_de_piece_justificative: nil,
attestation_template: nil,
types_de_champ: :drop_down_list,
types_de_champ_private: :drop_down_list
@@ -203,6 +204,11 @@ class Procedure < ApplicationRecord
[:notice, :deliberation].each { |attachment| clone_attachment(procedure, attachment) }
+ procedure.types_de_champ += PiecesJustificativesService.types_pj_as_types_de_champ(self)
+ if is_different_admin || from_library
+ procedure.types_de_champ.each { |tdc| tdc.options&.delete(:old_pj) }
+ end
+
procedure.administrateur = admin
procedure.initiated_mail = initiated_mail&.dup
procedure.received_mail = received_mail&.dup
@@ -215,7 +221,7 @@ class Procedure < ApplicationRecord
if from_library
procedure.service = nil
- elsif self.service.present? && (self.administrateur_id != admin.id)
+ elsif self.service.present? && is_different_admin
procedure.service = self.service.clone_and_assign_to_administrateur(admin)
end
diff --git a/app/models/type_de_champ.rb b/app/models/type_de_champ.rb
index 15927cf96..c801a4a56 100644
--- a/app/models/type_de_champ.rb
+++ b/app/models/type_de_champ.rb
@@ -37,7 +37,7 @@ class TypeDeChamp < ApplicationRecord
belongs_to :parent, class_name: 'TypeDeChamp'
has_many :types_de_champ, foreign_key: :parent_id, class_name: 'TypeDeChamp', dependent: :destroy
- store_accessor :options, :cadastres, :quartiers_prioritaires, :parcelles_agricoles
+ store_accessor :options, :cadastres, :quartiers_prioritaires, :parcelles_agricoles, :old_pj
# TODO simplify after migrating `options` column to (non YAML encoded) JSON
class MaybeYaml
diff --git a/app/serializers/dossier_serializer.rb b/app/serializers/dossier_serializer.rb
index 869aa727c..536c418cf 100644
--- a/app/serializers/dossier_serializer.rb
+++ b/app/serializers/dossier_serializer.rb
@@ -26,7 +26,7 @@ class DossierSerializer < ActiveModel::Serializer
has_many :champs, serializer: ChampSerializer
def champs
- champs = object.champs.to_a
+ champs = object.champs.reject { |c| c.type_de_champ.old_pj.present? }
if object.expose_legacy_carto_api?
champ_carte = champs.find do |champ|
@@ -47,6 +47,16 @@ class DossierSerializer < ActiveModel::Serializer
[]
end
+ def pieces_justificatives
+ ActiveModelSerializers::SerializableResource.new(object.pieces_justificatives).serializable_hash +
+ PiecesJustificativesService.serialize_champs_as_pjs(object)
+ end
+
+ def types_de_piece_justificative
+ ActiveModelSerializers::SerializableResource.new(object.types_de_piece_justificative).serializable_hash +
+ PiecesJustificativesService.serialize_types_de_champ_as_type_pj(object)
+ end
+
def email
object.user&.email
end
diff --git a/app/serializers/procedure_serializer.rb b/app/serializers/procedure_serializer.rb
index 674d8ab91..3d259bfc8 100644
--- a/app/serializers/procedure_serializer.rb
+++ b/app/serializers/procedure_serializer.rb
@@ -16,7 +16,7 @@ class ProcedureSerializer < ActiveModel::Serializer
has_one :geographic_information, serializer: ModuleApiCartoSerializer
has_many :types_de_champ, serializer: TypeDeChampSerializer
has_many :types_de_champ_private, serializer: TypeDeChampSerializer
- has_many :types_de_piece_justificative, serializer: TypeDePieceJustificativeSerializer
+ has_many :types_de_piece_justificative
def archived_at
object.archived_at&.in_time_zone('UTC')
@@ -43,4 +43,13 @@ class ProcedureSerializer < ActiveModel::Serializer
ModuleAPICarto.new(procedure: object)
end
end
+
+ def types_de_champ
+ object.types_de_champ.reject { |c| c.old_pj.present? }
+ end
+
+ def types_de_piece_justificative
+ ActiveModelSerializers::SerializableResource.new(object.types_de_piece_justificative).serializable_hash +
+ PiecesJustificativesService.serialize_types_de_champ_as_type_pj(object)
+ end
end
diff --git a/app/services/pieces_justificatives_service.rb b/app/services/pieces_justificatives_service.rb
index 6a68a0d7b..dd617b28b 100644
--- a/app/services/pieces_justificatives_service.rb
+++ b/app/services/pieces_justificatives_service.rb
@@ -31,4 +31,68 @@ class PiecesJustificativesService
missing_pjs.map { |pj| "La pièce jointe #{pj.libelle.truncate(200)} doit être fournie." }
end
+
+ def self.types_pj_as_types_de_champ(procedure)
+ order_place = procedure.types_de_champ.last&.order_place || 0
+ types_de_champ = [
+ TypeDeChamp.new(
+ libelle: "Pièces jointes",
+ type_champ: TypeDeChamp.type_champs.fetch(:header_section),
+ order_place: order_place
+ )
+ ]
+ types_de_champ += procedure.types_de_piece_justificative.map do |tpj|
+ order_place += 1
+ description = tpj.description
+ if tpj.lien_demarche.present?
+ if description.present?
+ description += "\n"
+ end
+ description += "Récupérer le formulaire vierge pour mon dossier : #{tpj.lien_demarche}"
+ end
+ TypeDeChamp.new(
+ libelle: tpj.libelle,
+ type_champ: TypeDeChamp.type_champs.fetch(:piece_justificative),
+ description: description,
+ order_place: order_place,
+ mandatory: tpj.mandatory,
+ old_pj: {
+ stable_id: tpj.id
+ }
+ )
+ end
+ if types_de_champ.count > 1
+ types_de_champ
+ else
+ []
+ end
+ end
+
+ def self.serialize_types_de_champ_as_type_pj(procedure)
+ tdcs = procedure.types_de_champ.select { |type_champ| type_champ.old_pj.present? }
+ tdcs.map.with_index do |type_champ, order_place|
+ description = type_champ.description
+ if /^(?.*?)(?:[\r\n]+)Récupérer le formulaire vierge pour mon dossier : (?http.*)$/m =~ description
+ description = original_description
+ end
+ {
+ id: type_champ.old_pj[:stable_id],
+ libelle: type_champ.libelle,
+ description: description,
+ order_place: order_place,
+ lien_demarche: lien_demarche
+ }
+ end
+ end
+
+ def self.serialize_champs_as_pjs(dossier)
+ dossier.champs.select { |champ| champ.type_de_champ.old_pj }.map do |champ|
+ {
+ created_at: champ.created_at&.in_time_zone('UTC'),
+ type_de_piece_justificative_id: champ.type_de_champ.old_pj[:stable_id],
+ content_url: champ.for_api,
+ user: champ.dossier.user
+ }
+ end
+ end
end
diff --git a/app/services/types_de_champ_service.rb b/app/services/types_de_champ_service.rb
index 288e30f59..411898f93 100644
--- a/app/services/types_de_champ_service.rb
+++ b/app/services/types_de_champ_service.rb
@@ -2,7 +2,6 @@ class TypesDeChampService
include Rails.application.routes.url_helpers
TOGGLES = {
- TypeDeChamp.type_champs.fetch(:siret) => :champ_siret?,
TypeDeChamp.type_champs.fetch(:integer_number) => :champ_integer_number?,
TypeDeChamp.type_champs.fetch(:repetition) => :champ_repetition?
}
diff --git a/app/views/admin/attestation_templates/edit.html.haml b/app/views/admin/attestation_templates/edit.html.haml
index 5dbc5b309..34b4572fe 100644
--- a/app/views/admin/attestation_templates/edit.html.haml
+++ b/app/views/admin/attestation_templates/edit.html.haml
@@ -66,6 +66,12 @@
= f.label :footer, 'Pied de page'
= f.text_field :footer, class: 'form-control', maxlength: 190
+ - if @attestation_template.activated && @procedure.locked?
+ .row
+ .col-md-12
+ .pull-right
+ %p.help-block L’attestation ne peut plus être désactivée car la démarche a déjà été publiée.
+
%button.btn.btn-primary{ formaction: admin_procedure_attestation_template_preview_path, formtarget: '_blank' } Prévisualiser
.pull-right
diff --git a/app/views/commencer/show.html.haml b/app/views/commencer/show.html.haml
new file mode 100644
index 000000000..5e71bbd19
--- /dev/null
+++ b/app/views/commencer/show.html.haml
@@ -0,0 +1,30 @@
+- content_for(:title, @procedure.libelle)
+
+.commencer.form
+ - if !user_signed_in?
+ %h1 Commencer la démarche
+ = link_to 'Créer un compte demarches-simplifiees.fr', commencer_sign_up_path(path: @procedure.path), class: ['button large expand primary']
+ = link_to 'J’ai déjà un compte', commencer_sign_in_path(path: @procedure.path), class: ['button large expand']
+
+ - else
+ - dossiers = current_user.dossiers.where(procedure: @procedure)
+ - drafts = dossiers.merge(Dossier.state_brouillon)
+ - not_drafts = dossiers.merge(Dossier.state_not_brouillon)
+
+ - if dossiers.count == 0
+ = link_to 'Commencer la démarche', url_for_new_dossier(@procedure), class: ['button large expand primary']
+
+ - elsif drafts.count == 1 && not_drafts.count == 0
+ %h1 Vous avez déjà commencé à remplir un dossier
+ = link_to 'Continuer à remplir mon dossier', brouillon_dossier_path(drafts.first), class: ['button large expand primary']
+ = link_to 'Commencer un nouveau dossier', url_for_new_dossier(@procedure), class: ['button large expand']
+
+ - elsif not_drafts.count == 1
+ %h1 Vous avez déjà déposé un dossier
+ = link_to 'Voir mon dossier', dossier_path(not_drafts.first), class: ['button large expand primary']
+ = link_to 'Commencer un nouveau dossier', url_for_new_dossier(@procedure), class: ['button large expand']
+
+ - else
+ %h1 Vous avez déjà des dossiers pour cette démarche
+ = link_to 'Voir mes dossiers en cours', dossiers_path, class: ['button large expand primary']
+ = link_to 'Commencer un nouveau dossier', url_for_new_dossier(@procedure), class: ['button large expand']
diff --git a/app/views/demandes/new.html.haml b/app/views/demandes/new.html.haml
index 40de202b1..14f0e3789 100644
--- a/app/views/demandes/new.html.haml
+++ b/app/views/demandes/new.html.haml
@@ -44,7 +44,7 @@
= text_field_tag :phone, nil, required: true
= label_tag :source do
- Comment avez-vous entendu parlé de demarches-simplifiees.fr ?
+ Comment avez-vous entendu parler de demarches-simplifiees.fr ?
%span.mandatory *
= text_field_tag :source, nil, required: true
diff --git a/app/views/new_gestionnaire/procedures/show.html.haml b/app/views/new_gestionnaire/procedures/show.html.haml
index ca1a06a13..11f17fc4f 100644
--- a/app/views/new_gestionnaire/procedures/show.html.haml
+++ b/app/views/new_gestionnaire/procedures/show.html.haml
@@ -77,7 +77,7 @@
= render partial: "header_field", locals: { field: { "label" => "Statut", "table" => "self", "column" => "state" }, classname: "status-col" }
- %th.follow-col
+ %th.action-col.follow-col
%span.dropdown
%button.button.dropdown-button
Personnaliser
@@ -112,7 +112,7 @@
%td.status-col
= link_to(gestionnaire_dossier_path(@procedure, dossier), class: 'cell-link') do
= render partial: 'shared/dossiers/status_badge', locals: { dossier: dossier }
- %td.follow-col= render partial: 'dossier_actions', locals: { procedure: @procedure, dossier: dossier, dossier_is_followed: @followed_dossiers_id.include?(dossier.id) }
+ %td.action-col.follow-col= render partial: 'dossier_actions', locals: { procedure: @procedure, dossier: dossier, dossier_is_followed: @followed_dossiers_id.include?(dossier.id) }
= paginate @dossiers
- else
%h2.empty-text Aucun dossier
diff --git a/app/views/new_gestionnaire/recherche/index.html.haml b/app/views/new_gestionnaire/recherche/index.html.haml
index 68e93156a..3af866a83 100644
--- a/app/views/new_gestionnaire/recherche/index.html.haml
+++ b/app/views/new_gestionnaire/recherche/index.html.haml
@@ -14,7 +14,7 @@
%th Démarche
%th Demandeur
%th.status-col Statut
- %th.follow-col
+ %th.action-col.follow-col
%tbody
- @dossiers.each do |dossier|
/ # FIXME: here we have a n+1, we fire a request
@@ -31,6 +31,6 @@
%td.status-col
= link_to(dossier_linked_path(current_gestionnaire, dossier), class: 'cell-link') do
= render partial: 'shared/dossiers/status_badge', locals: { dossier: dossier }
- %td.follow-col= render partial: 'new_gestionnaire/procedures/dossier_actions', locals: { procedure: dossier.procedure, dossier: dossier, dossier_is_followed: @followed_dossiers_id.include?(dossier.id) }
+ %td.action-col.follow-col= render partial: 'new_gestionnaire/procedures/dossier_actions', locals: { procedure: dossier.procedure, dossier: dossier, dossier_is_followed: @followed_dossiers_id.include?(dossier.id) }
- else
%h2 Aucun dossier correspondant à votre recherche n'a été trouvé
diff --git a/app/views/new_user/dossiers/index.html.haml b/app/views/new_user/dossiers/index.html.haml
index 80f6a9aff..347961d81 100644
--- a/app/views/new_user/dossiers/index.html.haml
+++ b/app/views/new_user/dossiers/index.html.haml
@@ -31,6 +31,7 @@
%th Démarche
%th.status-col Statut
%th.updated-at-col Mis à jour
+ %th
%tbody
- @dossiers.each do |dossier|
%tr
@@ -49,6 +50,11 @@
%td.updated-at-col
= link_to(url_for_dossier(dossier), class: 'cell-link') do
= dossier.updated_at.strftime("%d/%m/%Y")
+ %td.action-col.delete-col
+ - if dossier.brouillon?
+ = link_to(ask_deletion_dossier_path(dossier), method: :post, class: 'button danger', data: { disable: true, confirm: "En continuant, vous allez supprimer ce dossier ainsi que les informations qu’il contient. Toute suppression entraine l’annulation de la démarche en cours.\n\nConfirmer la suppression ?" }) do
+ %span.icon.delete
+ Supprimer
= paginate(@dossiers)
- if current_user.feedbacks.empty? || current_user.feedbacks.last.created_at < 1.month.ago
diff --git a/config/features.rb b/config/features.rb
index 6be7eecb5..2faf85f48 100644
--- a/config/features.rb
+++ b/config/features.rb
@@ -7,8 +7,6 @@ Flipflop.configure do
strategy :default
group :champs do
- feature :champ_siret,
- title: "Champ SIRET"
feature :champ_integer_number,
title: "Champ nombre entier"
feature :champ_repetition,
@@ -17,7 +15,6 @@ Flipflop.configure do
feature :web_hook
feature :publish_draft
- feature :support_form
feature :enable_email_login_token
feature :new_champs_editor
diff --git a/config/routes.rb b/config/routes.rb
index 5ad479ced..57ce1673c 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -265,6 +265,8 @@ Rails.application.routes.draw do
namespace :commencer do
get '/test/:path', action: 'commencer_test', as: :test
get '/:path', action: 'commencer'
+ get '/:path/sign_in', action: 'sign_in', as: :sign_in
+ get '/:path/sign_up', action: 'sign_up', as: :sign_up
end
resources :dossiers, only: [:index, :show, :new] do
diff --git a/lib/tasks/2019_01_16_fix_automatic_dossier_logs.rake b/lib/tasks/2019_01_16_fix_automatic_dossier_logs.rake
new file mode 100644
index 000000000..e4039fa77
--- /dev/null
+++ b/lib/tasks/2019_01_16_fix_automatic_dossier_logs.rake
@@ -0,0 +1,61 @@
+class FixAutomaticDossierLogs_2019_01_16
+ def find_handlers
+ # rubocop:disable Security/YAMLLoad
+ Delayed::Job.where(queue: 'cron')
+ .map { |job| YAML.load(job.handler) }
+ .select { |handler| handler.job_data['job_class'] == 'AutoReceiveDossiersForProcedureJob' }
+ # rubocop:enable Security/YAMLLoad
+ end
+
+ def run
+ handlers = find_handlers
+
+ handlers
+ .map { |handler| handler.job_data['arguments'] }
+ .each do |(procedure_id, state)|
+
+ procedure = Procedure
+ .includes(:administrateur, dossiers: [:dossier_operation_logs, :follows])
+ .find(procedure_id)
+
+ rake_puts "working on procedure #{procedure_id}, #{procedure.libelle} whose admin is #{procedure.administrateur.email}"
+
+ case state
+ when Dossier.states.fetch(:en_instruction)
+ dossiers = procedure.dossiers.state_en_instruction
+ operation = 'passer_en_instruction'
+ when Dossier.states.fetch(:accepte)
+ dossiers = procedure.dossiers.accepte
+ operation = 'accepter'
+ end
+
+ dossier_operation_logs = DossierOperationLog
+ .where(dossier: dossiers, operation: operation)
+
+ rake_puts "affecting #{dossier_operation_logs.count} dossier_operation_logs"
+
+ dossier_operation_logs
+ .update_all(gestionnaire_id: nil, automatic_operation: true)
+
+ # if the dossier is only followed by the procedure administrateur
+ # unfollow
+ if state == Dossier.states.fetch(:en_instruction)
+ dossier_to_unfollows = dossiers
+ .select { |d| d.follows.count == 1 && d.follows.first.gestionnaire.email == procedure.administrateur.email }
+
+ rake_puts "affecting #{dossier_to_unfollows.count} dossiers"
+
+ dossier_to_unfollows
+ .each { |d| d.follows.destroy_all }
+ end
+
+ rake_puts ""
+ end
+ end
+end
+
+namespace :'2019_01_16_fix_automatic_dossier_logs' do
+ task run: :environment do
+ FixAutomaticDossierLogs_2019_01_16.new.run
+ end
+end
diff --git a/spec/controllers/concerns/procedure_context_concern_spec.rb b/spec/controllers/concerns/procedure_context_concern_spec.rb
index 42e616305..5911e1686 100644
--- a/spec/controllers/concerns/procedure_context_concern_spec.rb
+++ b/spec/controllers/concerns/procedure_context_concern_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe ProcedureContextConcern, type: :controller do
end
end
- context 'when no procedure_id is present in the stored return location' do
+ context 'when the stored return location is not a procedure URL' do
before do
controller.store_location_for(:user, dossiers_path)
end
@@ -36,9 +36,9 @@ RSpec.describe ProcedureContextConcern, type: :controller do
end
context 'when a procedure location has been stored' do
- context 'when the stored procedure does not exist' do
+ context 'when the procedure path does not exist' do
before do
- controller.store_location_for(:user, new_dossier_path(procedure_id: '0'))
+ controller.store_location_for(:user, commencer_path(path: 'non-existent-path'))
end
it 'redirects with an error' do
@@ -47,11 +47,11 @@ RSpec.describe ProcedureContextConcern, type: :controller do
end
end
- context 'when the stored procedure is not published' do
- let(:procedure) { create :procedure }
+ context 'when the procedure path exists, but not with the same publication status' do
+ let(:published_procedure) { create :procedure, :published }
before do
- controller.store_location_for(:user, new_dossier_path(procedure_id: procedure.id))
+ controller.store_location_for(:user, commencer_test_path(path: published_procedure.path))
end
it 'redirects with an error' do
@@ -60,16 +60,29 @@ RSpec.describe ProcedureContextConcern, type: :controller do
end
end
- context 'when the stored procedure exists' do
- let(:procedure) { create :procedure, :published }
+ context 'when the stored procedure is in test' do
+ let(:test_procedure) { create :procedure, :with_path }
before do
- controller.store_location_for(:user, new_dossier_path(procedure_id: procedure.id))
+ controller.store_location_for(:user, commencer_test_path(path: test_procedure.path))
end
it 'succeeds, and assigns the procedure on the controller' do
expect(subject.status).to eq 200
- expect(assigns(:procedure)).to eq procedure
+ expect(assigns(:procedure)).to eq test_procedure
+ end
+ end
+
+ context 'when the stored procedure is published' do
+ let(:published_procedure) { create :procedure, :published }
+
+ before do
+ controller.store_location_for(:user, commencer_path(path: published_procedure.path))
+ end
+
+ it 'succeeds, and assigns the procedure on the controller' do
+ expect(subject.status).to eq 200
+ expect(assigns(:procedure)).to eq published_procedure
end
end
end
diff --git a/spec/controllers/new_user/commencer_controller_spec.rb b/spec/controllers/new_user/commencer_controller_spec.rb
index 3bede7f9b..7fbaea275 100644
--- a/spec/controllers/new_user/commencer_controller_spec.rb
+++ b/spec/controllers/new_user/commencer_controller_spec.rb
@@ -2,39 +2,88 @@ require 'spec_helper'
describe NewUser::CommencerController, type: :controller do
let(:user) { create(:user) }
- let(:procedure) { create(:procedure, :published) }
- let(:procedure_id) { procedure.id }
+ let(:published_procedure) { create(:procedure, :published) }
+ let(:draft_procedure) { create(:procedure, :with_path) }
- describe 'GET #commencer' do
+ describe '#commencer' do
subject { get :commencer, params: { path: path } }
- let(:path) { procedure.path }
- it { expect(subject.status).to eq 302 }
- it { expect(subject).to redirect_to new_dossier_path(procedure_id: procedure.id) }
+ context 'when the path is for a published procedure' do
+ let(:path) { published_procedure.path }
- context 'when procedure path does not exist' do
+ it 'renders the view' do
+ expect(subject.status).to eq(200)
+ expect(subject).to render_template('show')
+ expect(assigns(:procedure)).to eq published_procedure
+ end
+ end
+
+ context 'when the path is for a non-published procedure' do
+ let(:path) { draft_procedure.path }
+
+ it 'redirects with an error message' do
+ expect(subject).to redirect_to(root_path)
+ end
+ end
+
+ context 'when the path does not exist' do
let(:path) { 'hello' }
- it { expect(subject).to redirect_to(root_path) }
+ it 'redirects with an error message' do
+ expect(subject).to redirect_to(root_path)
+ end
end
end
- describe 'GET #commencer_test' do
- before do
- Flipflop::FeatureSet.current.test!.switch!(:publish_draft, true)
+ describe '#commencer_test' do
+ subject { get :commencer_test, params: { path: path } }
+
+ context 'when the path is for a draft procedure' do
+ let(:path) { draft_procedure.path }
+
+ it 'renders the view' do
+ expect(subject.status).to eq(200)
+ expect(subject).to render_template('show')
+ expect(assigns(:procedure)).to eq draft_procedure
+ end
end
- subject { get :commencer_test, params: { path: path } }
- let(:procedure) { create(:procedure, :with_path) }
- let(:path) { procedure.path }
+ context 'when the path is for a published procedure' do
+ let(:path) { published_procedure.path }
- it { expect(subject.status).to eq 302 }
- it { expect(subject).to redirect_to new_dossier_path(procedure_id: procedure.id, brouillon: true) }
+ it 'redirects with an error message' do
+ expect(subject).to redirect_to(root_path)
+ end
+ end
- context 'when procedure path does not exist' do
+ context 'when the path does not exist' do
let(:path) { 'hello' }
- it { expect(subject).to redirect_to(root_path) }
+ it 'redirects with an error message' do
+ expect(subject).to redirect_to(root_path)
+ end
end
end
+
+ describe '#sign_in' do
+ subject { get :sign_in, params: { path: published_procedure.path } }
+
+ it 'set the path to return after sign-in to the dossier creation path' do
+ subject
+ expect(controller.stored_location_for(:user)).to eq(commencer_path(path: published_procedure.path))
+ end
+
+ it { expect(subject).to redirect_to(new_user_session_path) }
+ end
+
+ describe '#sign_up' do
+ subject { get :sign_up, params: { path: published_procedure.path } }
+
+ it 'set the path to return after sign-up to the dossier creation path' do
+ subject
+ expect(controller.stored_location_for(:user)).to eq(commencer_path(path: published_procedure.path))
+ end
+
+ it { expect(subject).to redirect_to(new_user_registration_path) }
+ end
end
diff --git a/spec/controllers/users/registrations_controller_spec.rb b/spec/controllers/users/registrations_controller_spec.rb
index f1d8e036c..c5cbd2155 100644
--- a/spec/controllers/users/registrations_controller_spec.rb
+++ b/spec/controllers/users/registrations_controller_spec.rb
@@ -27,7 +27,7 @@ describe Users::RegistrationsController, type: :controller do
let(:procedure) { create :procedure, :published }
before do
- controller.store_location_for(:user, new_dossier_path(procedure_id: procedure.id))
+ controller.store_location_for(:user, commencer_path(path: procedure.path))
end
it 'makes the saved procedure available' do
diff --git a/spec/controllers/users/sessions_controller_spec.rb b/spec/controllers/users/sessions_controller_spec.rb
index e12521849..efa388790 100644
--- a/spec/controllers/users/sessions_controller_spec.rb
+++ b/spec/controllers/users/sessions_controller_spec.rb
@@ -179,7 +179,7 @@ describe Users::SessionsController, type: :controller do
let(:procedure) { create :procedure, :published }
before do
- controller.store_location_for(:user, new_dossier_path(procedure_id: procedure.id))
+ controller.store_location_for(:user, commencer_path(path: procedure.path))
end
it 'makes the saved procedure available' do
diff --git a/spec/features/new_gestionnaire/gestionnaire_spec.rb b/spec/features/new_gestionnaire/gestionnaire_spec.rb
index dd0aab750..d81906dc2 100644
--- a/spec/features/new_gestionnaire/gestionnaire_spec.rb
+++ b/spec/features/new_gestionnaire/gestionnaire_spec.rb
@@ -14,10 +14,16 @@ feature 'The gestionnaire part' do
scenario 'a gestionnaire can fill a dossier' do
visit commencer_path(path: procedure.path)
+ click_on 'J’ai déjà un compte'
expect(page).to have_current_path new_user_session_path
sign_in_with(gestionnaire.email, password, true)
+ expect(page).to have_current_path(commencer_path(path: procedure.path))
+ click_on 'Commencer la démarche'
+
+ expect(page).to have_content('Identifier votre établissement')
+ expect(page).to have_current_path(siret_dossier_path(procedure.reload.dossiers.last))
expect(page).to have_content(procedure.libelle)
end
end
diff --git a/spec/features/new_user/brouillon_spec.rb b/spec/features/new_user/brouillon_spec.rb
index 748572433..4cc1142e2 100644
--- a/spec/features/new_user/brouillon_spec.rb
+++ b/spec/features/new_user/brouillon_spec.rb
@@ -130,11 +130,15 @@ feature 'The user' do
def log_in(email, password, procedure)
visit "/commencer/#{procedure.path}"
- expect(page).to have_current_path(new_user_session_path)
+ click_on 'J’ai déjà un compte'
- fill_in 'user_email', with: email
- fill_in 'user_password', with: password
- click_on 'Se connecter'
+ expect(page).to have_current_path(new_user_session_path)
+ sign_in_with(email, password)
+
+ expect(page).to have_current_path("/commencer/#{procedure.path}")
+ click_on 'Commencer la démarche'
+
+ expect(page).to have_content("Données d'identité")
expect(page).to have_current_path(identite_dossier_path(user_dossier))
end
diff --git a/spec/features/new_user/dossier_creation_spec.rb b/spec/features/new_user/dossier_creation_spec.rb
index a45af4ba0..0944d7462 100644
--- a/spec/features/new_user/dossier_creation_spec.rb
+++ b/spec/features/new_user/dossier_creation_spec.rb
@@ -17,10 +17,10 @@ feature 'Creating a new dossier:' do
before do
visit commencer_path(path: procedure.path)
+ click_on 'Commencer la démarche'
- expect(page).to have_content(procedure.libelle)
- expect(page).to have_content(procedure.description)
- expect(page).to have_content(procedure.service.email)
+ expect(page).to have_current_path identite_dossier_path(user.reload.dossiers.last)
+ expect_page_to_have_procedure_description(procedure)
fill_in 'individual_nom', with: 'Nom'
fill_in 'individual_prenom', with: 'Prenom'
@@ -77,13 +77,12 @@ feature 'Creating a new dossier:' do
.to_return(status: 404, body: '')
end
- scenario 'the user can enter the SIRET of its etablissement and create a new draft', vcr: { cassette_name: 'api_adresse_search_paris_3' }, js: true do
+ scenario 'the user can enter the SIRET of its etablissement and create a new draft', vcr: { cassette_name: 'api_adresse_search_paris_3' } do
visit commencer_path(path: procedure.path)
+ click_on 'Commencer la démarche'
- expect(page).to have_current_path(siret_dossier_path(dossier))
- expect(page).to have_content(procedure.libelle)
- expect(page).to have_content(procedure.description)
- expect(page).to have_content(procedure.service.email)
+ expect(page).to have_current_path siret_dossier_path(dossier)
+ expect_page_to_have_procedure_description(procedure)
fill_in 'Numéro SIRET', with: siret
click_on 'Valider'
@@ -97,7 +96,10 @@ feature 'Creating a new dossier:' do
scenario 'the user is notified when its SIRET is invalid' do
visit commencer_path(path: procedure.path)
+ click_on 'Commencer la démarche'
+
expect(page).to have_current_path(siret_dossier_path(dossier))
+ expect_page_to_have_procedure_description(procedure)
fill_in 'Numéro SIRET', with: '0000'
click_on 'Valider'
diff --git a/spec/features/new_user/linked_dropdown_spec.rb b/spec/features/new_user/linked_dropdown_spec.rb
index a175f407a..769057fcd 100644
--- a/spec/features/new_user/linked_dropdown_spec.rb
+++ b/spec/features/new_user/linked_dropdown_spec.rb
@@ -48,11 +48,16 @@ feature 'linked dropdown lists' do
def log_in(email, password, procedure)
visit "/commencer/#{procedure.path}"
+ click_on 'J’ai déjà un compte'
+
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'
+ sign_in_with(email, password)
+
+ expect(page).to have_current_path(commencer_path(path: procedure.path))
+ click_on 'Commencer la démarche'
+
+ expect(page).to have_content("Données d'identité")
expect(page).to have_current_path(identite_dossier_path(user_dossier))
end
diff --git a/spec/features/new_user/list_dossiers_spec.rb b/spec/features/new_user/list_dossiers_spec.rb
index 999aef5d6..3e36e97d8 100644
--- a/spec/features/new_user/list_dossiers_spec.rb
+++ b/spec/features/new_user/list_dossiers_spec.rb
@@ -5,6 +5,7 @@ describe 'user access to the list of his dossier' do
let!(:last_updated_dossier) { create(:dossier, :with_entreprise, user: user, state: Dossier.states.fetch(:en_construction)) }
let!(:dossier1) { create(:dossier, :with_entreprise, user: user, state: Dossier.states.fetch(:en_construction)) }
let!(:dossier2) { create(:dossier, :with_entreprise) }
+ let!(:dossier_brouillon) { create(:dossier, :with_entreprise, user: user) }
let!(:dossier_archived) { create(:dossier, :with_entreprise, user: user, state: Dossier.states.fetch(:en_construction)) }
let(:dossiers_per_page) { 25 }
@@ -43,6 +44,21 @@ describe 'user access to the list of his dossier' do
expect(page).to have_content(dossier_archived.procedure.libelle)
end
+ it 'should have link to only delete brouillon' do
+ expect(page).to have_link(nil, href: ask_deletion_dossier_path(dossier_brouillon))
+ expect(page).not_to have_link(nil, href: ask_deletion_dossier_path(dossier1))
+ end
+
+ context 'when user clicks on delete brouillon list', js: true do
+ before do
+ find(:xpath, "//a[@href='#{ask_deletion_dossier_path(dossier_brouillon)}']").click
+ page.driver.browser.switch_to.alert.accept
+ end
+ scenario 'dossier is deleted' do
+ expect(page).not_to have_link("Supprimer", href: dossier_brouillon.procedure.libelle)
+ end
+ end
+
context 'when user clicks on a projet in list', js: true do
before do
page.click_on(dossier1.procedure.libelle)
diff --git a/spec/features/new_user/sign_up_spec.rb b/spec/features/new_user/sign_up_spec.rb
index 17063020d..516a9fb4f 100644
--- a/spec/features/new_user/sign_up_spec.rb
+++ b/spec/features/new_user/sign_up_spec.rb
@@ -41,15 +41,20 @@ feature 'Signing up:' do
end
scenario 'a new user can sign-up and fill the procedure' do
- expect(page).to have_current_path new_user_session_path
click_on 'Créer un compte'
+ expect(page).to have_current_path new_user_registration_path
expect_page_to_have_procedure_description(procedure)
sign_up_with user_email, user_password
expect(page).to have_content "nous avons besoin de vérifier votre adresse #{user_email}"
click_confirmation_link_for user_email
+
+ expect(page).to have_current_path(commencer_path(path: procedure.path))
expect(page).to have_content 'Votre compte a été activé'
+ click_on 'Commencer la démarche'
+
+ expect(page).to have_current_path identite_dossier_path(procedure.reload.dossiers.last)
expect_page_to_have_procedure_description(procedure)
end
end
diff --git a/spec/features/sessions/sign_in_spec.rb b/spec/features/sessions/sign_in_spec.rb
index 378d41dcb..3dc40531b 100644
--- a/spec/features/sessions/sign_in_spec.rb
+++ b/spec/features/sessions/sign_in_spec.rb
@@ -21,11 +21,15 @@ feature 'Signin in:' do
end
scenario 'an existing user can sign-in and fill the procedure' do
+ click_on 'J’ai déjà un compte'
expect(page).to have_current_path new_user_session_path
expect_page_to_have_procedure_description(procedure)
sign_in_with user.email, password
+ expect(page).to have_current_path(commencer_path(path: procedure.path))
+ click_on 'Commencer la démarche'
+
expect(page).to have_current_path identite_dossier_path(user.reload.dossiers.last)
expect_page_to_have_procedure_description(procedure)
expect(page).to have_content "Données d'identité"
diff --git a/spec/lib/tasks/2019_01_16_fix_automatic_dossier_logs_spec.rb b/spec/lib/tasks/2019_01_16_fix_automatic_dossier_logs_spec.rb
new file mode 100644
index 000000000..b41bafe81
--- /dev/null
+++ b/spec/lib/tasks/2019_01_16_fix_automatic_dossier_logs_spec.rb
@@ -0,0 +1,82 @@
+require 'spec_helper'
+
+load Rails.root.join('lib', 'tasks', '2019_01_16_fix_automatic_dossier_logs.rake')
+
+describe '2019_01_16_fix_automatic_dossier_logs' do
+ let!(:rake_task) { Rake::Task['2019_01_16_fix_automatic_dossier_logs:run'] }
+ let!(:administrateur) { create(:administrateur) }
+ let!(:another_gestionnaire) { create(:gestionnaire) }
+ let!(:procedure) { create(:procedure, administrateur: administrateur) }
+ let!(:dossier) { create(:dossier, procedure: procedure) }
+ let!(:fix_automatic_dossier_logs) { FixAutomaticDossierLogs_2019_01_16.new }
+
+ before do
+ allow(fix_automatic_dossier_logs).to receive(:find_handlers)
+ .and_return([double(job_data: { 'arguments' => [procedure.id, final_state] })])
+ end
+
+ subject do
+ fix_automatic_dossier_logs.run
+ dossier.reload
+ end
+
+ context 'when the dossiers are automatically moved to en_instruction' do
+ let(:final_state) { 'en_instruction' }
+
+ context 'and a dossier has been accidentally affected to an administrateur' do
+ before do
+ dossier.passer_en_instruction!(administrateur.gestionnaire)
+
+ control = DossierOperationLog.create(
+ gestionnaire: another_gestionnaire,
+ operation: 'refuser',
+ automatic_operation: false
+ )
+
+ dossier.dossier_operation_logs << control
+ subject
+ end
+
+ it { expect(dossier.follows.count).to eq(0) }
+
+ it do
+ expect(dossier_logs).to match_array([
+ [nil, 'passer_en_instruction', true],
+ [another_gestionnaire.id, "refuser", false]
+ ])
+ end
+ end
+
+ context ', followed anyway by another person and accidentally ...' do
+ before do
+ another_gestionnaire.follow(dossier)
+ dossier.passer_en_instruction!(administrateur.gestionnaire)
+
+ subject
+ end
+
+ it { expect(dossier.follows.count).to eq(2) }
+ it { expect(dossier_logs).to match([[nil, 'passer_en_instruction', true]]) }
+ end
+ end
+
+ context 'when the dossiers are automatically moved to accepte' do
+ let(:final_state) { 'accepte' }
+
+ context 'and a dossier has been accidentally affected to an administrateur' do
+ before do
+ dossier.accepter!(administrateur.gestionnaire, '')
+
+ subject
+ end
+
+ it { expect(dossier_logs).to match([[nil, 'accepter', true]]) }
+ end
+ end
+
+ private
+
+ def dossier_logs
+ dossier.dossier_operation_logs.pluck(:gestionnaire_id, :operation, :automatic_operation)
+ end
+end
diff --git a/spec/models/procedure_spec.rb b/spec/models/procedure_spec.rb
index 1e8d964cb..f69fffc46 100644
--- a/spec/models/procedure_spec.rb
+++ b/spec/models/procedure_spec.rb
@@ -336,6 +336,7 @@ describe Procedure do
let!(:type_de_champ_0) { create(:type_de_champ, procedure: procedure, order_place: 0) }
let!(:type_de_champ_1) { create(:type_de_champ, procedure: procedure, order_place: 1) }
let!(:type_de_champ_2) { create(:type_de_champ_drop_down_list, procedure: procedure, order_place: 2) }
+ let!(:type_de_champ_pj) { create(:type_de_champ_piece_justificative, procedure: procedure, order_place: 3, old_pj: { stable_id: 2713 }) }
let!(:type_de_champ_private_0) { create(:type_de_champ, :private, procedure: procedure, order_place: 0) }
let!(:type_de_champ_private_1) { create(:type_de_champ, :private, procedure: procedure, order_place: 1) }
let!(:type_de_champ_private_2) { create(:type_de_champ_drop_down_list, :private, procedure: procedure, order_place: 2) }
@@ -366,13 +367,12 @@ describe Procedure do
it 'should duplicate specific objects with different id' do
expect(subject.id).not_to eq(procedure.id)
- expect(subject.types_de_piece_justificative.size).to eq procedure.types_de_piece_justificative.size
- expect(subject.types_de_champ.size).to eq procedure.types_de_champ.size
+ expect(subject.types_de_champ.size).to eq(procedure.types_de_champ.size + 1 + procedure.types_de_piece_justificative.size)
expect(subject.types_de_champ_private.size).to eq procedure.types_de_champ_private.size
expect(subject.types_de_champ.map(&:drop_down_list).compact.size).to eq procedure.types_de_champ.map(&:drop_down_list).compact.size
expect(subject.types_de_champ_private.map(&:drop_down_list).compact.size).to eq procedure.types_de_champ_private.map(&:drop_down_list).compact.size
- subject.types_de_champ.zip(procedure.types_de_champ).each do |stc, ptc|
+ procedure.types_de_champ.zip(subject.types_de_champ).each do |ptc, stc|
expect(stc).to have_same_attributes_as(ptc)
end
@@ -380,10 +380,6 @@ describe Procedure do
expect(stc).to have_same_attributes_as(ptc)
end
- subject.types_de_piece_justificative.zip(procedure.types_de_piece_justificative).each do |stc, ptc|
- expect(stc).to have_same_attributes_as(ptc)
- end
-
expect(subject.attestation_template.title).to eq(procedure.attestation_template.title)
expect(subject.cloned_from_library).to be(false)
@@ -393,7 +389,19 @@ describe Procedure do
expect(cloned_procedure).to have_same_attributes_as(procedure)
end
- context 'when the procedure is clone from the library' do
+ it 'should not clone piece justificatives but create corresponding champs' do
+ expect(subject.types_de_piece_justificative.size).to eq(0)
+
+ champs_pj = subject.types_de_champ[procedure.types_de_champ.size + 1, procedure.types_de_piece_justificative.size]
+ champs_pj.zip(procedure.types_de_piece_justificative).each do |stc, ptpj|
+ expect(stc.libelle).to eq(ptpj.libelle)
+ expect(stc.description).to eq(ptpj.description)
+ expect(stc.mandatory).to eq(ptpj.mandatory)
+ expect(stc.old_pj[:stable_id]).to eq(ptpj.id)
+ end
+ end
+
+ context 'when the procedure is cloned from the library' do
let(:from_library) { true }
it { expect(subject.cloned_from_library).to be(true) }
@@ -401,6 +409,12 @@ describe Procedure do
it 'should set service_id to nil' do
expect(subject.service).to eq(nil)
end
+
+ it 'should discard old pj information' do
+ subject.types_de_champ.each do |stc|
+ expect(stc.old_pj).to be_nil
+ end
+ end
end
it 'should keep service_id' do
@@ -415,6 +429,12 @@ describe Procedure do
expect(subject.service.administrateur_id).not_to eq(service.administrateur_id)
expect(subject.service.attributes.except("id", "administrateur_id", "created_at", "updated_at")).to eq(service.attributes.except("id", "administrateur_id", "created_at", "updated_at"))
end
+
+ it 'should discard old pj information' do
+ subject.types_de_champ.each do |stc|
+ expect(stc.old_pj).to be_nil
+ end
+ end
end
it 'should duplicate existing mail_templates' do
diff --git a/spec/serializers/dossier_serializer_spec.rb b/spec/serializers/dossier_serializer_spec.rb
index aa9e51a28..681baeab7 100644
--- a/spec/serializers/dossier_serializer_spec.rb
+++ b/spec/serializers/dossier_serializer_spec.rb
@@ -45,4 +45,60 @@ describe DossierSerializer do
}
end
end
+
+ context 'when a type PJ was cloned to a type champ PJ' do
+ let(:original_procedure) do
+ p = create(:procedure, :published)
+ p.types_de_piece_justificative.create(
+ libelle: "Vidéo de votre demande de subvention",
+ description: "Pour optimiser vos chances, soignez la chorégraphie et privilégiez le chant polyphonique",
+ lien_demarche: "https://www.dance-academy.gouv.fr",
+ order_place: 0
+ )
+ p
+ end
+
+ let(:procedure) do
+ p = original_procedure.clone(original_procedure.administrateur, false)
+ p.save
+ p
+ end
+
+ let(:type_pj) { original_procedure.types_de_piece_justificative.first }
+ let(:migrated_type_champ) { procedure.types_de_champ.find_by(libelle: type_pj.libelle) }
+ let(:dossier) { create(:dossier, procedure: procedure) }
+ let(:champ_pj) { dossier.champs.last }
+
+ before do
+ champ_pj.piece_justificative_file.attach(io: StringIO.new("toto"), filename: "toto.txt", content_type: "text/plain")
+ end
+
+ subject { DossierSerializer.new(dossier).serializable_hash }
+
+ it "exposes the PJ in the legacy format" do
+ is_expected.to include(
+ types_de_piece_justificative: [
+ {
+ "id" => type_pj.id,
+ "libelle" => type_pj.libelle,
+ "description" => type_pj.description,
+ "lien_demarche" => type_pj.lien_demarche,
+ "order_place" => type_pj.order_place
+ }
+ ],
+ pieces_justificatives: [
+ {
+ "content_url" => champ_pj.for_api,
+ "created_at" => champ_pj.created_at.in_time_zone('UTC').iso8601(3),
+ "type_de_piece_justificative_id" => type_pj.id,
+ "user" => a_hash_including("id" => dossier.user.id)
+ }
+ ]
+ )
+ end
+
+ it "does not expose the PJ as a champ" do
+ expect(subject[:champs]).not_to include(a_hash_including(type_de_champ: a_hash_including(id: migrated_type_champ.id)))
+ end
+ end
end
diff --git a/spec/serializers/procedure_serializer_spec.rb b/spec/serializers/procedure_serializer_spec.rb
index 487866665..be0d83669 100644
--- a/spec/serializers/procedure_serializer_spec.rb
+++ b/spec/serializers/procedure_serializer_spec.rb
@@ -8,4 +8,42 @@ describe ProcedureSerializer do
is_expected.to include(state: "publiee")
}
end
+
+ context 'when a type PJ was cloned to a type champ PJ' do
+ let(:original_procedure) do
+ p = create(:procedure, :published)
+ p.types_de_piece_justificative.create(
+ libelle: "Vidéo de votre demande de subvention",
+ description: "Pour optimiser vos chances, soignez la chorégraphie et privilégiez le chant polyphonique",
+ lien_demarche: "https://www.dance-academy.gouv.fr",
+ order_place: 0
+ )
+ p
+ end
+
+ let(:procedure) { original_procedure.clone(original_procedure.administrateur, false) }
+
+ let(:type_pj) { original_procedure.types_de_piece_justificative.first }
+ let(:migrated_type_champ) { procedure.types_de_champ.find_by(libelle: type_pj.libelle) }
+
+ subject { ProcedureSerializer.new(procedure).serializable_hash }
+
+ it "is exposed as a legacy type PJ" do
+ is_expected.to include(
+ types_de_piece_justificative: [
+ {
+ "id" => type_pj.id,
+ "libelle" => type_pj.libelle,
+ "description" => type_pj.description,
+ "lien_demarche" => type_pj.lien_demarche,
+ "order_place" => type_pj.order_place
+ }
+ ]
+ )
+ end
+
+ it "is not exposed as a type de champ" do
+ expect(subject[:types_de_champ]).not_to include(a_hash_including(libelle: type_pj.libelle))
+ end
+ end
end
diff --git a/spec/views/commencer/show.html.haml_spec.rb b/spec/views/commencer/show.html.haml_spec.rb
new file mode 100644
index 000000000..274b55f45
--- /dev/null
+++ b/spec/views/commencer/show.html.haml_spec.rb
@@ -0,0 +1,76 @@
+require 'rails_helper'
+
+RSpec.describe 'commencer/show.html.haml', type: :view do
+ include Rails.application.routes.url_helpers
+
+ let(:procedure) { create(:procedure, :with_service, :published) }
+
+ before do
+ assign(:procedure, procedure)
+ if user
+ sign_in user
+ end
+ end
+
+ subject { render }
+
+ context 'when no user is signed in' do
+ let(:user) { nil }
+
+ it 'renders sign-in and sign-up links' do
+ subject
+ expect(rendered).to have_link('Créer un compte')
+ expect(rendered).to have_link('J’ai déjà un compte')
+ end
+ end
+
+ context 'when the user is already signed in' do
+ let(:user) { create :user }
+
+ shared_examples_for 'it renders a link to create a new dossier' do |button_label|
+ it 'renders a link to create a new dossier' do
+ subject
+ expect(rendered).to have_link(button_label, href: new_dossier_url(procedure_id: procedure.id))
+ end
+ end
+
+ context 'and they don’t have any dossier on this procedure' do
+ it_behaves_like 'it renders a link to create a new dossier', 'Commencer la démarche'
+ end
+
+ context 'and they have a pending draft' do
+ let!(:brouillon) { create(:dossier, user: user, procedure: procedure) }
+
+ it_behaves_like 'it renders a link to create a new dossier', 'Commencer un nouveau dossier'
+
+ it 'renders a link to resume the pending draft' do
+ subject
+ expect(rendered).to have_link('Continuer à remplir mon dossier', href: brouillon_dossier_path(brouillon))
+ end
+ end
+
+ context 'and they have a submitted dossier' do
+ let!(:brouillon) { create(:dossier, user: user, procedure: procedure) }
+ let!(:dossier) { create(:dossier, :en_construction, :for_individual, user: user, procedure: procedure) }
+
+ it_behaves_like 'it renders a link to create a new dossier', 'Commencer un nouveau dossier'
+
+ it 'renders a link to the submitted dossier' do
+ subject
+ expect(rendered).to have_link('Voir mon dossier', href: dossier_path(dossier))
+ end
+ end
+
+ context 'and they have several submitted dossiers' do
+ let!(:brouillon) { create(:dossier, user: user, procedure: procedure) }
+ let!(:dossiers) { create_list(:dossier, 2, :en_construction, :for_individual, user: user, procedure: procedure) }
+
+ it_behaves_like 'it renders a link to create a new dossier', 'Commencer un nouveau dossier'
+
+ it 'renders a link to the dossiers list' do
+ subject
+ expect(rendered).to have_link('Voir mes dossiers en cours', href: dossiers_path)
+ end
+ end
+ end
+end
diff --git a/spec/views/layouts/_new_header_spec.rb b/spec/views/layouts/_new_header_spec.rb
index 9c81e7118..17980f07e 100644
--- a/spec/views/layouts/_new_header_spec.rb
+++ b/spec/views/layouts/_new_header_spec.rb
@@ -3,7 +3,6 @@ require 'spec_helper'
describe 'layouts/_new_header.html.haml', type: :view do
describe 'logo link' do
before do
- Flipflop::FeatureSet.current.test!.switch!(:support_form, true)
sign_in user
allow(controller).to receive(:nav_bar_profile).and_return(profile)
render