commit
f00736d7b5
45 changed files with 733 additions and 103 deletions
1
app/assets/images/icons/trash.svg
Normal file
1
app/assets/images/icons/trash.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none" fill-rule="evenodd"><path d="M6 18.857C6 20.037 6.749 21 7.667 21h8.666C17.25 21 18 20.037 18 18.857V6H6v12.857zM4 6h16M9 11v5m3-5v5m3-5v5M8.5 4.889c0-.858.696-1.89 1.556-1.89h3.888c.86 0 1.556 1.032 1.556 1.89" stroke="#4393F3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/><path d="M0 0h24v24H0z"/></g></svg>
|
After Width: | Height: | Size: 427 B |
|
@ -60,6 +60,10 @@
|
|||
color: #FFFFFF;
|
||||
border-color: $medium-red;
|
||||
background-color: $medium-red;
|
||||
|
||||
> .icon {
|
||||
filter: brightness(100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
11
app/assets/stylesheets/new_design/commencer.scss
Normal file
11
app/assets/stylesheets/new_design/commencer.scss
Normal file
|
@ -0,0 +1,11 @@
|
|||
@import "constants";
|
||||
|
||||
.commencer {
|
||||
.button:first-of-type {
|
||||
margin-top: 4 * $default-spacer;
|
||||
}
|
||||
|
||||
.button {
|
||||
margin-bottom: 2 * $default-spacer;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
h1 {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
|
||||
@media (max-width: $two-columns-breakpoint) {
|
||||
font-size: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
hr {
|
||||
|
|
|
@ -105,4 +105,8 @@
|
|||
&.meh {
|
||||
background-image: image-url("icons/meh-regular.svg");
|
||||
}
|
||||
|
||||
&.delete {
|
||||
background-image: image-url("icons/trash.svg");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
end
|
||||
|
||||
def root_path_for_profile(nav_bar_profile)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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?
|
||||
}
|
||||
|
|
|
@ -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++}`
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 /^(?<original_description>.*?)(?:[\r\n]+)Récupérer le formulaire vierge pour mon dossier : (?<lien_demarche>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
|
||||
|
|
|
@ -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?
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
30
app/views/commencer/show.html.haml
Normal file
30
app/views/commencer/show.html.haml
Normal file
|
@ -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']
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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é
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
61
lib/tasks/2019_01_16_fix_automatic_dossier_logs.rake
Normal file
61
lib/tasks/2019_01_16_fix_automatic_dossier_logs.rake
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
end
|
||||
|
||||
describe '#commencer_test' do
|
||||
subject { get :commencer_test, params: { path: path } }
|
||||
let(:procedure) { create(:procedure, :with_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, brouillon: true) }
|
||||
context 'when the path is for a draft procedure' do
|
||||
let(:path) { draft_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 draft_procedure
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the path is for a published procedure' do
|
||||
let(:path) { published_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 '#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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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é"
|
||||
|
|
82
spec/lib/tasks/2019_01_16_fix_automatic_dossier_logs_spec.rb
Normal file
82
spec/lib/tasks/2019_01_16_fix_automatic_dossier_logs_spec.rb
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
76
spec/views/commencer/show.html.haml_spec.rb
Normal file
76
spec/views/commencer/show.html.haml_spec.rb
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue