Merge pull request #4769 from betagouv/dev

2020-02-12-01
This commit is contained in:
Pierre de La Morinerie 2020-02-12 13:32:17 +01:00 committed by GitHub
commit 13a8d45795
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 1383 additions and 101 deletions

View file

@ -3,6 +3,7 @@ $small-page-width: 840px;
$default-spacer: 8px; $default-spacer: 8px;
$default-padding: 2 * $default-spacer; $default-padding: 2 * $default-spacer;
$default-fields-spacer: 5 * $default-spacer;
// layouts // layouts
$two-columns-padding: 60px; $two-columns-padding: 60px;

View file

@ -20,7 +20,7 @@
} }
%outline { %outline {
&:active, &:active:not(:disabled),
&:focus { &:focus {
outline: 3px solid $blue; outline: 3px solid $blue;
} }

View file

@ -46,6 +46,18 @@
} }
} }
ul {
list-style-type: disc;
list-style-position: inside;
padding-left: $default-padding;
}
ol {
list-style-type: decimal;
list-style-position: inside;
padding-left: $default-padding;
}
p:not(:last-of-type) { p:not(:last-of-type) {
margin-bottom: $default-spacer; margin-bottom: $default-spacer;
} }

View file

@ -16,13 +16,13 @@
width: 100%; width: 100%;
height: 0; height: 0;
margin-top: $default-padding; margin-top: $default-padding;
margin-bottom: 2 * $default-padding; margin-bottom: $default-fields-spacer;
border: none; border: none;
border-bottom: 1px solid $border-grey; border-bottom: 2px solid $border-grey;
} }
@mixin notice-text-style { @mixin notice-text-style {
font-size: 14px; font-size: 16px;
color: $grey; color: $grey;
} }
@ -31,6 +31,7 @@
} }
label { label {
font-size: 18px;
margin-bottom: $default-padding; margin-bottom: $default-padding;
display: block; display: block;
font-weight: bold; font-weight: bold;
@ -45,7 +46,6 @@
.notice { .notice {
@include notice-text-style; @include notice-text-style;
font-weight: bold;
margin-top: - $default-spacer; margin-top: - $default-spacer;
margin-bottom: $default-padding; margin-bottom: $default-padding;
@ -70,32 +70,80 @@
visibility: visible; visibility: visible;
} }
// Align checkboxes on the top-left side of the label // Move checkbox to the top-left side of the label
&.editable-champ-checkbox, &.editable-champ-checkbox,
&.editable-champ-radio.vertical,
&.editable-champ-engagement { &.editable-champ-engagement {
p, p,
label { label {
padding-left: 28px; padding-left: 28px;
} }
input[type=checkbox], input[type=checkbox] {
input[type=radio] {
position: absolute; position: absolute;
top: 1px; top: 3px;
left: 0px; left: 0px;
} }
// When an (eventual) notice is displayed after the input, give it some bottom margin.
.notice {
margin-bottom: $default-fields-spacer;
}
} }
} }
.radios { .radios {
display: flex;
// Horizontal layout (default)
flex-direction: row;
align-items: flex-start;
label { label {
display: inline; margin-right: $default-padding;
margin-left: $default-padding; }
// Vertical layout
&.vertical {
flex-direction: column;
align-items: stretch;
label {
margin-right: 0;
}
}
label {
padding: $default-padding $default-padding $default-padding $default-spacer;
border: 1px solid $border-grey;
border-radius: 4px;
font-weight: normal;
background: $white;
user-select: none;
&:last-of-type {
margin-bottom: $default-fields-spacer;
}
&:hover {
background: $light-grey;
cursor: pointer;
}
&:active {
border-color: darken($border-grey, 10);
}
&:first-child { &:first-child {
margin-left: 0; margin-left: 0;
} }
input[type=radio] {
margin-bottom: 0;
}
.notice {
margin: 4px 0 0 27px;
}
} }
} }
@ -109,7 +157,7 @@
select, select,
.attachment { .attachment {
display: block; display: block;
margin-bottom: 2 * $default-padding; margin-bottom: $default-fields-spacer;
&.small-margin { &.small-margin {
margin-bottom: $default-padding / 2; margin-bottom: $default-padding / 2;
@ -117,7 +165,7 @@
} }
.add-row { .add-row {
margin-bottom: 2 * $default-padding; margin-bottom: $default-fields-spacer;
} }
input[type=checkbox] { input[type=checkbox] {
@ -182,16 +230,14 @@
input[type=radio] { input[type=radio] {
@extend %outline; @extend %outline;
margin-left: 5px; // Firefox tends to display some controls smaller than other browsers.
margin-right: 4px;
margin-bottom: 2 * $default-padding;
}
input[type=checkbox] {
// Firefox tends to display checkbox controls smaller than other browsers.
// Ensure a consistency of size between browsers. // Ensure a consistency of size between browsers.
width: 16px; width: 16px;
height: 16px; height: 16px;
margin-left: 5px;
margin-right: 4px;
margin-bottom: $default-fields-spacer;
} }
input[type=date] { input[type=date] {
@ -234,7 +280,7 @@
.select2-container { .select2-container {
display: block; display: block;
margin-bottom: 2 * $default-padding; margin-bottom: $default-fields-spacer;
&.select2-container--focus { &.select2-container--focus {
.select2-selection { .select2-selection {
@ -304,10 +350,17 @@
} }
.header-section { .header-section {
display: inline-block;
color: $blue; color: $blue;
font-weight: bold; font-size: 30px;
font-size: 20px; margin-bottom: 3 * $default-padding;
margin-bottom: 2 * $default-padding; border-bottom: 3px solid $blue;
}
.header-subsection {
font-size: 22px;
color: $blue;
margin-bottom: $default-padding;
} }
.explication-libelle { .explication-libelle {
@ -317,7 +370,7 @@
} }
.explication { .explication {
margin-bottom: $default-padding; margin-bottom: $default-fields-spacer;
padding: $default-padding / 2; padding: $default-padding / 2;
background-color: $light-grey; background-color: $light-grey;
@ -326,6 +379,13 @@
} }
} }
.siret-info {
margin-top: -$default-fields-spacer;
margin-bottom: $default-fields-spacer;
// Ensure the bottom-margin is not collapsed when the element is empty
min-height: 1px;
}
.send-wrapper { .send-wrapper {
display: flex; display: flex;
width: 100%; width: 100%;
@ -388,15 +448,4 @@
margin-right: 0; margin-right: 0;
} }
} }
.pj-input {
input[type=file] {
margin: $default-padding 0 (2 * $default-padding);
padding: 2px;
}
.piece-description {
margin-bottom: $default-padding;
}
}
} }

View file

@ -14,7 +14,7 @@ module CreateAvisConcern
allowed_dossiers = [dossier] allowed_dossiers = [dossier]
if create_avis_params[:invite_linked_dossiers].present? if create_avis_params[:invite_linked_dossiers].present?
allowed_dossiers += dossier.linked_dossiers allowed_dossiers += dossier.linked_dossiers_for(current_instructeur)
end end
create_results = Avis.create( create_results = Avis.create(

View file

@ -69,4 +69,27 @@ module DossierHelper
dossier.state dossier.state
end end
end end
# On the 22/01/2020, a technical error on the demarches-simplifees.fr
# instance caused some files attached to some dossiers to be deleted.
#
# This method returns true if the dossier contained attachments
# whose files were deleted during this incident.
def has_lost_attachments(dossier)
if dinum_instance?
dossiers_with_lost_attachments_ids.include?(dossier.id)
else
false
end
end
private
def dinum_instance?
ENV['APP_HOST']&.ends_with?('demarches-simplifiees.fr')
end
def dossiers_with_lost_attachments_ids
@@ids ||= YAML.load_file(Rails.root.join('config', 'dossiers-with-lost-attachments.yml'))
end
end end

View file

@ -2,4 +2,11 @@ class Champs::HeaderSectionChamp < Champ
def search_terms def search_terms
# The user cannot enter any information here so it doesnt make much sense to search # The user cannot enter any information here so it doesnt make much sense to search
end end
def section_index
dossier
.champs
.filter { |c| c.type_champ == TypeDeChamp.type_champs.fetch(:header_section) }
.index(self) + 1
end
end end

View file

@ -584,8 +584,9 @@ class Dossier < ApplicationRecord
!PiecesJustificativesService.liste_pieces_justificatives(self).empty? && PiecesJustificativesService.pieces_justificatives_total_size(self) < Dossier::TAILLE_MAX_ZIP !PiecesJustificativesService.liste_pieces_justificatives(self).empty? && PiecesJustificativesService.pieces_justificatives_total_size(self) < Dossier::TAILLE_MAX_ZIP
end end
def linked_dossiers def linked_dossiers_for(instructeur)
Dossier.where(id: champs.filter(&:dossier_link?).map(&:value).compact) dossier_ids = champs.filter(&:dossier_link?).map(&:value).compact
(instructeur.dossiers.where(id: dossier_ids) + instructeur.dossiers_from_avis.where(id: dossier_ids)).uniq
end end
def hash_for_deletion_mail def hash_for_deletion_mail

View file

@ -7,5 +7,6 @@
= render partial: "shared/dossiers/editable_champs/editable_champ", locals: { champ: champ, form: form } = render partial: "shared/dossiers/editable_champs/editable_champ", locals: { champ: champ, form: form }
= form.hidden_field :id = form.hidden_field :id
= form.hidden_field :_destroy, disabled: true = form.hidden_field :_destroy, disabled: true
.flex.row-reverse
%button.button.danger.remove-row %button.button.danger.remove-row
Supprimer Supprimer lélément

View file

@ -31,7 +31,7 @@
= f.submit 'Envoyer votre avis', class: 'button send' = f.submit 'Envoyer votre avis', class: 'button send'
- if !@dossier.termine? - if !@dossier.termine?
= render partial: "instructeurs/shared/avis/form", locals: { url: avis_instructeur_avis_path(@avis), linked_dossiers: @dossier.linked_dossiers, must_be_confidentiel: @avis.confidentiel?, avis: @new_avis } = render partial: "instructeurs/shared/avis/form", locals: { url: avis_instructeur_avis_path(@avis), linked_dossiers: @dossier.linked_dossiers_for(current_instructeur), must_be_confidentiel: @avis.confidentiel?, avis: @new_avis }
- if @dossier.avis_for(current_instructeur).present? - if @dossier.avis_for(current_instructeur).present?
= render partial: 'instructeurs/shared/avis/list', locals: { avis: @dossier.avis_for(current_instructeur), avis_seen_at: nil } = render partial: 'instructeurs/shared/avis/list', locals: { avis: @dossier.avis_for(current_instructeur), avis_seen_at: nil }

View file

@ -4,7 +4,7 @@
.container .container
- if !@dossier.termine? - if !@dossier.termine?
= render partial: "instructeurs/shared/avis/form", locals: { url: avis_instructeur_dossier_path(@dossier.procedure, @dossier), linked_dossiers: @dossier.linked_dossiers, must_be_confidentiel: false, avis: @avis } = render partial: "instructeurs/shared/avis/form", locals: { url: avis_instructeur_dossier_path(@dossier.procedure, @dossier), linked_dossiers: @dossier.linked_dossiers_for(current_instructeur), must_be_confidentiel: false, avis: @avis }
- if @dossier.avis.present? - if @dossier.avis.present?
= render partial: 'instructeurs/shared/avis/list', locals: { avis: @dossier.avis, avis_seen_at: @avis_seen_at } = render partial: 'instructeurs/shared/avis/list', locals: { avis: @dossier.avis, avis_seen_at: @avis_seen_at }

View file

@ -7,7 +7,7 @@
= f.text_area :introduction, rows: 3, value: avis.introduction || 'Bonjour, merci de me donner votre avis sur ce dossier.', required: true = f.text_area :introduction, rows: 3, value: avis.introduction || 'Bonjour, merci de me donner votre avis sur ce dossier.', required: true
- if linked_dossiers.present? - if linked_dossiers.present?
= f.check_box :invite_linked_dossiers, value: false = f.check_box :invite_linked_dossiers, {}, true, false
= f.label :invite_linked_dossiers, t('helpers.label.invite_linked_dossiers', count: linked_dossiers.length, ids: linked_dossiers.map(&:id).to_sentence) = f.label :invite_linked_dossiers, t('helpers.label.invite_linked_dossiers', count: linked_dossiers.length, ids: linked_dossiers.map(&:id).to_sentence)
.flex.justify-between.align-baseline .flex.justify-between.align-baseline

View file

@ -78,18 +78,17 @@
- if !@procedure.locked? - if !@procedure.locked?
%h2.header-section À qui sadresse ma démarche ? %h2.header-section À qui sadresse ma démarche ?
.editable-champ.editable-champ-radio.vertical .radios.vertical
= f.label :for_individual, value: true do = f.label :for_individual, value: true do
= f.radio_button :for_individual, true
Ma démarche sadresse à un particulier Ma démarche sadresse à un particulier
%p.notice En choisissant cette option, lusager devra renseigner son nom et prénom avant daccéder au formulaire %p.notice En choisissant cette option, lusager devra renseigner son nom et prénom avant daccéder au formulaire
= f.radio_button :for_individual, true
.editable-champ.editable-champ-radio.vertical
= f.label :for_individual, value: false do = f.label :for_individual, value: false do
= f.radio_button :for_individual, false
Ma démarche sadresse à une personne morale Ma démarche sadresse à une personne morale
%p.notice %p.notice
En choisissant cette option, lusager devra renseigner son n° SIRET.<br>Grâce à lAPI Entreprise, les informations sur la personne morale (raison sociale, adresse du siège, etc.) seront automatiquement renseignées. En choisissant cette option, lusager devra renseigner son n° SIRET.<br>Grâce à lAPI Entreprise, les informations sur la personne morale (raison sociale, adresse du siège, etc.) seront automatiquement renseignées.
= f.radio_button :for_individual, false
%p.explication %p.explication
Si votre démarche sadresse indifféremment à une personne morale ou un particulier, choisissez l'option « Particuliers ». Vous pourrez ajouter un champ SIRET directement dans le formulaire. Si votre démarche sadresse indifféremment à une personne morale ou un particulier, choisissez l'option « Particuliers ». Vous pourrez ajouter un champ SIRET directement dans le formulaire.

View file

@ -52,16 +52,16 @@
%label Mot de passe %label Mot de passe
%input{ type: "password", value: "12345678" } %input{ type: "password", value: "12345678" }
%h2.header-section Bouton radio verticaux %h3.header-subsection Bouton radio verticaux
.editable-champ.editable-champ-radio.vertical .radios.vertical
= f.label :archived, 'Option A', value: true = f.label :archived, value: true do
%p.notice Une option tout à fait valable.
= f.radio_button :archived, true = f.radio_button :archived, true
Option A
.editable-champ.editable-champ-radio.vertical %p.notice Une option tout à fait valable.
= f.label :archived, 'Option B', value: false = f.label :archived, value: false do
%p.notice Une autre option, pas mal non plus.
= f.radio_button :archived, false = f.radio_button :archived, false
Option B
%p.notice Une autre option, pas mal non plus.
.send-wrapper .send-wrapper
= f.submit 'Enregistrer un brouillon (formnovalidate)', formnovalidate: true, class: 'button send' = f.submit 'Enregistrer un brouillon (formnovalidate)', formnovalidate: true, class: 'button send'

View file

@ -24,5 +24,7 @@
.tab-title Formulaire .tab-title Formulaire
- champs = dossier.champs.includes(:type_de_champ) - champs = dossier.champs.includes(:type_de_champ)
- if champs.any? || dossier.procedure.routee? - if champs.any? || dossier.procedure.routee?
- if has_lost_attachments(dossier)
= render partial: "shared/dossiers/lost_attachments", locals: { dossier: dossier, profile: profile }
.card .card
= render partial: "shared/dossiers/champs", locals: { champs: champs, dossier: dossier, demande_seen_at: demande_seen_at, profile: profile } = render partial: "shared/dossiers/champs", locals: { champs: champs, dossier: dossier, demande_seen_at: demande_seen_at, profile: profile }

View file

@ -0,0 +1,54 @@
- post_mortem_url = 'https://demarches-simplifiees.gitbook.io/articles-demarches-simplifiees-fr/2020/incident-de-production-du-21-janvier-2020'
- if profile == 'usager'
/# Message for Usager
.card.warning
.card-title Des pièces jointes de votre dossier peuvent être manquantes.
%p
Suite à un
= link_to 'incident', post_mortem_url, target: '_blank'
survenu le 21 janvier, demarches-simplifiees.fr a perdu par erreur une partie des pièces jointes de votre dossier. Ladministration en charge de votre dossier a été prévenue.
- if dossier.read_only?
%p
Si nécessaire,
= succeed '.' do
%strong
ladministration vous contactera pour renvoyer les pièces jointes en question
- else
%p
Si une ou plusieurs pièces jointes manquent, nous vous invitons à
= link_to modifier_dossier_path(dossier) do
= succeed '.' do
%strong renvoyer les pièces jointes manquantes
%p Nous nous excusons pour la gêne occasionnée.
- else
/# Message for Instructeurs
.card.warning
.card-title Des pièces jointes de ce dossier peuvent être manquantes.
%p
Suite à un
= link_to 'incident', post_mortem_url, target: '_blank'
survenu le 21 janvier, demarches-simplifiees.fr a perdu par erreur une partie des pièces jointes de ce dossier.
- if dossier.read_only?
%p
Si une ou plusieurs pièces jointes essentielles manquent, nous vous invitons à :
%ol
%li repasser ce dossier en construction ;
%li<
= link_to 'contacter le demandeur ', messagerie_instructeur_dossier_path(dossier.procedure, dossier)
pour lui demander de
= succeed '.' do
%strong renvoyer les pièces jointes nécessaires
- else
%p
Si une ou plusieurs pièces jointes manquent, nous vous invitons à
= succeed ',' do
= link_to 'contacter le demandeur', messagerie_instructeur_dossier_path(dossier.procedure, dossier)
pour lui demander de
= succeed '.' do
%strong renvoyer les pièces jointes nécessaires
%p Le demandeur de ce dossier a également été prévenu. Nous nous excusons pour la gêne occasionnée.

View file

@ -1,9 +1,9 @@
.editable-champ{ class: "editable-champ-#{champ.type_champ}" } .editable-champ{ class: "editable-champ-#{champ.type_champ}" }
- if champ.repetition? - if champ.repetition?
= render partial: 'shared/dossiers/editable_champs/header_section', locals: { champ: champ } %h3.header-subsection= champ.libelle
- if champ.description.present? - if champ.description.present?
%p.notice= string_to_html(champ.description, false) %p.notice= string_to_html(champ.description, false)
- elsif has_label?(champ) - elsif has_label?(champ)
= render partial: 'shared/dossiers/editable_champs/champ_label', locals: { form: form, champ: champ, seen_at: defined?(seen_at) ? seen_at : nil } = render partial: 'shared/dossiers/editable_champs/champ_label', locals: { form: form, champ: champ, seen_at: defined?(seen_at) ? seen_at : nil }

View file

@ -1,2 +1,6 @@
- section_index = champ.section_index
%h2.header-section %h2.header-section
- if section_index
= "#{section_index}."
= champ.libelle = champ.libelle

View file

@ -8,16 +8,16 @@
.flex.row-reverse .flex.row-reverse
- if champ.persisted? - if champ.persisted?
%button.button.danger.remove-row{ type: :button } %button.button.danger.remove-row{ type: :button }
Supprimer Supprimer lélément
- else - else
%button.button.danger{ type: :button } %button.button.danger{ type: :button }
Supprimer Supprimer lélément
- if champ.persisted? - if champ.persisted?
= link_to champs_repetition_path(form.index), class: 'button add-row', data: { remote: true, method: 'POST', params: { champ_id: champ&.id }.to_query } do = link_to champs_repetition_path(form.index), class: 'button add-row', data: { remote: true, method: 'POST', params: { champ_id: champ&.id }.to_query } do
%span.icon.add %span.icon.add
Ajouter une ligne pour « #{champ.libelle} » Ajouter un élément pour « #{champ.libelle} »
- else - else
%a.button.add-row %a.button.add-row
%span.icon.add %span.icon.add
Ajouter une ligne pour « #{champ.libelle} » Ajouter un élément pour « #{champ.libelle} »

View file

@ -1,11 +1,10 @@
= form.text_field :value, = form.text_field :value,
placeholder: champ.libelle, placeholder: champ.libelle,
class: 'small-margin',
data: { remote: true, debounce: true, url: champs_siret_path(form.index), params: { champ_id: champ&.id }.to_query, spinner: true }, data: { remote: true, debounce: true, url: champs_siret_path(form.index), params: { champ_id: champ&.id }.to_query, spinner: true },
required: champ.mandatory?, required: champ.mandatory?,
pattern: "[0-9]{14}", pattern: "[0-9]{14}",
title: "Le numéro de SIRET doit comporter exactement 14 chiffres" title: "Le numéro de SIRET doit comporter exactement 14 chiffres"
.spinner.right.hidden .spinner.right.hidden
%div{ class: "siret-info-#{form.index}" } .siret-info{ class: "siret-info-#{form.index}" }
- if champ.etablissement.present? - if champ.etablissement.present?
= render partial: 'shared/dossiers/editable_champs/etablissement_titre', locals: { etablissement: champ.etablissement } = render partial: 'shared/dossiers/editable_champs/etablissement_titre', locals: { etablissement: champ.etablissement }

View file

@ -0,0 +1,946 @@
# On the 22/01/2020, a technical error on the demarches-simplifees.fr
# instance made us delete some files attached to some dossiers.
#
# This list contains the ids of all dossiers where some attached
# file was mistakenly deleted during this incident.
- 22
- 9224
- 9244
- 9489
- 9495
- 11045
- 14311
- 14530
- 14553
- 14569
- 14616
- 14619
- 15325
- 15331
- 16448
- 17848
- 18190
- 18308
- 18855
- 18929
- 18946
- 18965
- 19284
- 19697
- 19698
- 19872
- 20334
- 20663
- 20931
- 21015
- 21024
- 21620
- 21753
- 21782
- 21865
- 21871
- 21876
- 21938
- 21963
- 21971
- 22011
- 22042
- 22045
- 22063
- 22068
- 22108
- 22279
- 22434
- 22488
- 22523
- 24277
- 25275
- 26223
- 26228
- 27069
- 27213
- 29366
- 29386
- 29486
- 31179
- 31983
- 32004
- 32323
- 32325
- 32492
- 32497
- 35072
- 35074
- 35193
- 35232
- 35308
- 35323
- 35357
- 35442
- 35486
- 35496
- 35554
- 35644
- 36659
- 38984
- 39026
- 39099
- 39158
- 39287
- 39314
- 39352
- 39359
- 39371
- 39380
- 39390
- 39403
- 39493
- 39526
- 41106
- 41111
- 43566
- 43570
- 43571
- 43572
- 43578
- 43741
- 43785
- 43791
- 43884
- 43928
- 43935
- 43937
- 44013
- 44035
- 45123
- 48500
- 48690
- 52921
- 53029
- 53067
- 53097
- 53118
- 53147
- 53152
- 53153
- 53154
- 53155
- 53159
- 53171
- 53176
- 53178
- 53207
- 53208
- 53218
- 53472
- 53981
- 54002
- 56253
- 57216
- 57689
- 58003
- 58411
- 58721
- 59445
- 59925
- 61917
- 62547
- 62551
- 62552
- 62956
- 63035
- 63607
- 63615
- 65154
- 66268
- 66379
- 66963
- 67066
- 68688
- 68705
- 68710
- 68737
- 68929
- 68943
- 69023
- 69026
- 69510
- 69521
- 69546
- 70148
- 70224
- 72653
- 76114
- 79303
- 79863
- 79929
- 79951
- 79976
- 80032
- 84640
- 93404
- 98647
- 99294
- 101868
- 103748
- 104097
- 107096
- 109146
- 113137,
- 113690
- 113707
- 113711
- 113722
- 113743
- 117270
- 118003
- 119395
- 120824
- 121498
- 124009
- 125430
- 127024
- 130735
- 132389
- 132942
- 133317
- 133697
- 137347
- 137374
- 137427
- 137525
- 137900
- 138272
- 138436
- 138466
- 138515
- 138550
- 138631
- 138703
- 138990
- 139296
- 139371
- 140604
- 140811
- 141142
- 141227
- 148609
- 153917
- 156644
- 157401
- 184400
- 190035
- 191350
- 193213
- 193783
- 194088
- 198497
- 200002
- 200005
- 200017
- 200041
- 200048
- 200060
- 200061
- 200062
- 200081
- 200086
- 200089
- 200094
- 200098
- 200100
- 200108
- 200109
- 200113
- 200128
- 200138
- 200140
- 200143
- 200154
- 200158
- 200161
- 200163
- 200169
- 200182
- 200186
- 200195
- 200202
- 200208
- 200211
- 200263
- 200267
- 200448
- 200685
- 200757
- 200784
- 200787
- 201021
- 201315
- 201576
- 201921
- 201986
- 202015
- 203553
- 203630
- 204737
- 204866
- 204924
- 204982
- 205021
- 205265
- 205424
- 205655
- 205659
- 205847
- 205940
- 205954
- 205987
- 206013
- 206089
- 206108
- 206170
- 206179
- 206217
- 206237
- 206285
- 206288
- 206290
- 206300
- 206374
- 206472
- 206490
- 206494
- 206515
- 206532
- 206589
- 206612
- 206734
- 206741
- 206782
- 206807
- 206828
- 206835
- 206856
- 206887
- 206904
- 206909
- 206913
- 206931
- 206964
- 206972
- 206977
- 206979
- 206992
- 207004
- 207006
- 207032
- 207061
- 207078
- 207103
- 207104
- 207118
- 207181
- 207183
- 207197
- 207207
- 207236
- 207537
- 207734
- 207773
- 208009
- 208153
- 208186
- 208199
- 208379
- 208422
- 208545
- 208549
- 208873
- 208903
- 209151
- 209392
- 209397
- 209873
- 210103
- 210175
- 210959
- 211018
- 211144
- 211197
- 211852
- 212322
- 212359
- 212493
- 212503
- 212955
- 212986
- 213596
- 213598
- 213612
- 213625
- 213694
- 213712
- 213749
- 214123
- 214592
- 215503
- 215510
- 215742
- 215756
- 216263
- 216360
- 216620
- 217131
- 217159
- 217215
- 217320
- 217361
- 217373
- 217487
- 217507
- 217518
- 217587
- 217677
- 217714
- 217790
- 217796
- 217850
- 217859
- 217871
- 217875
- 218370
- 218419
- 219341
- 220675
- 221967
- 222266
- 222801
- 222868
- 222875
- 222946
- 222949
- 222965
- 223154
- 223303
- 223329
- 223368
- 224064
- 224290
- 225117
- 227153
- 227161
- 227816
- 227931
- 228074
- 228666
- 228703
- 228776
- 228918
- 228926
- 229050
- 229086
- 229109
- 229114
- 229553
- 230338
- 230353
- 230479
- 230539
- 230574
- 230582
- 231261
- 232521
- 232740
- 232916
- 232934
- 232958
- 233008
- 233047
- 233160
- 233197
- 233211
- 233556
- 233605
- 233712
- 235322
- 236625
- 237371
- 237439
- 237605
- 238276
- 239412
- 239500
- 239603
- 239777
- 239805
- 239829
- 239850
- 239858
- 241496
- 241557
- 241598
- 241788
- 241824
- 241858
- 241879
- 241910
- 241927
- 241934
- 241936
- 241939
- 241950
- 241952
- 241955
- 241956
- 241959
- 241969
- 241970
- 241985
- 241987
- 241991
- 241996
- 242414
- 242725
- 242800
- 242808
- 242814
- 242820
- 242840
- 242845
- 242937
- 242942
- 242972
- 242973
- 242975
- 242997
- 243133
- 243234
- 243237
- 243240
- 243273
- 243290
- 243335
- 243339
- 243429
- 245309
- 245460
- 247557
- 248202
- 248537
- 248567
- 248592
- 248726
- 248776
- 249018
- 249342
- 249352
- 249563
- 250149
- 250471
- 250489
- 250502
- 250504
- 250509
- 250511
- 250530
- 251386
- 252994
- 254055
- 254211
- 254972
- 255013
- 255078
- 255082
- 255329
- 255925
- 255990
- 256083
- 256084
- 256296
- 256472
- 257228
- 258640
- 258982
- 259131
- 259147
- 259204
- 261038
- 261117
- 261118
- 261170
- 261452
- 263654
- 264489
- 265036
- 265333
- 265983
- 266034
- 266057
- 266062
- 266069
- 266071
- 266205
- 267145
- 267322
- 267404
- 267708
- 268223
- 268652
- 268654
- 268678
- 268728
- 268731
- 268764
- 268885
- 269421
- 269444
- 269518
- 269560
- 269574
- 269575
- 270213
- 272346
- 272891
- 273169
- 274183
- 274478
- 274634
- 274730
- 275900
- 279329
- 279348
- 280975
- 281779
- 281804
- 282877
- 283362
- 283378
- 283392
- 283395
- 283495
- 283845
- 284616
- 284622
- 284675
- 284687
- 284774
- 284838
- 284880
- 285060
- 285230
- 285575
- 285603
- 287488
- 288210
- 289529
- 289530
- 289811
- 289844
- 289859
- 290754
- 291018
- 291621
- 293625
- 293634
- 296214
- 298172
- 298355
- 298942
- 299000
- 306186
- 310318
- 310544
- 310730
- 311019
- 311728
- 312509
- 312531
- 313699
- 330729
- 337282
- 344150
- 351128
- 360286
- 374944
- 386682
- 386850
- 409245
- 410749
- 429085
- 453060
- 473146
- 473183
- 477625
- 482733
- 485936
- 486996
- 501423
- 524299
- 525738
- 525916
- 525932
- 525936
- 529745
- 529870
- 542902
- 546362
- 546394
- 546406
- 546416
- 546519
- 551264
- 551276
- 552058
- 555081
- 571316
- 574190
- 574209
- 591896
- 600483
- 600501
- 600863
- 601157
- 619683
- 620774
- 627219
- 628388
- 628633
- 628675
- 628701
- 628743
- 628746
- 628763
- 631292
- 635784
- 639656
- 640229
- 642227
- 654699
- 656113
- 665439
- 666028
- 666790
- 670294
- 671241
- 671245
- 671259
- 671268
- 671458
- 677528
- 679414
- 690281
- 690749
- 692168
- 695653
- 695727
- 695768
- 695791
- 696013
- 696428
- 715997
- 719236
- 726969
- 726981
- 727014
- 727551
- 756386
- 756402
- 762500
- 766726
- 767963
- 771492
- 773982
- 775235
- 777837
- 780557
- 781158
- 781502
- 781503
- 784077
- 784298
- 784403
- 792304
- 794024
- 794606
- 795345
- 796814
- 798434
- 798893
- 799196
- 799200
- 800093
- 802666
- 802679
- 802707
- 802709
- 802716
- 808711
- 808740
- 808742
- 808766
- 808767
- 808784
- 808797
- 808876
- 808926
- 808935
- 808937
- 808939
- 808940
- 808943
- 808947
- 808958
- 808963
- 808967
- 808982
- 808983
- 808994
- 809002
- 809004
- 809007
- 811190
- 818427
- 818724
- 819171
- 819725
- 828064
- 828292
- 828535
- 828577
- 828607
- 828641
- 828705
- 828741
- 828778
- 828782
- 828788
- 828819
- 829128
- 829239
- 832186
- 839927
- 841809
- 842330
- 845358
- 846642
- 853954
- 855891
- 859844
- 860016
- 860043
- 860050
- 860059
- 860062
- 860067
- 860520
- 860555
- 861195
- 861222
- 863696
- 888447
- 898772
- 910362
- 916218
- 920528
- 924844
- 931770
- 933988
- 934004
- 934005
- 934008
- 934009
- 934010
- 934013
- 934014
- 934019
- 934029
- 934033
- 934046
- 934058
- 934060
- 938750
- 946941
- 949162
- 951110
- 951227
- 955534
- 959860
- 960038
- 962441
- 962443
- 962515
- 962547
- 962560
- 962664
- 963634
- 966627
- 969062
- 985102
- 990079
- 990281
- 991542
- 999193
- 1009535
- 1016896
- 1018675
- 1019395
- 1020295
- 1020509
- 1020960
- 1020969
- 1020982
- 1021109
- 1023811
- 1027181
- 1028190
- 1035967
- 1036338
- 1038182
- 1047230
- 1048403
- 1048429
- 1048938
- 1049968
- 1050075
- 1063901
- 1063941
- 1063942
- 1079027
- 1079344
- 1083246
- 1086139
- 1088337
- 1092801
- 1102942
- 1110614
- 1110620
- 1112775
- 1116822
- 1121711
- 1140138
- 1143324
- 1145406
- 1153823
- 1157409
- 1164993
- 1165566
- 1168238
- 1169529
- 1174555
- 1182043
- 1184647
- 1187042
- 1188538
- 1206673
- 1206824
- 1206939
- 1206954
- 1206967
- 1206969
- 1249330
- 1249377
- 1249815
- 1263647
- 1279054
- 1280300
- 1280341

View file

@ -187,27 +187,50 @@ describe Instructeurs::AvisController, type: :controller do
let(:previous_avis_confidentiel) { false } let(:previous_avis_confidentiel) { false }
let(:dossier) { create(:dossier, :en_construction, :with_dossier_link, procedure: procedure) } let(:dossier) { create(:dossier, :en_construction, :with_dossier_link, procedure: procedure) }
it do context 'when the expert doesnt share linked dossiers' do
let(:invite_linked_dossiers) { false }
it 'sends a single avis for the main dossier, but doesnt give access to the linked dossiers' do
expect(flash.notice).to eq("Une demande d'avis a été envoyée à a@b.com") expect(flash.notice).to eq("Une demande d'avis a été envoyée à a@b.com")
expect(Avis.count).to eq(old_avis_count + 1) expect(Avis.count).to eq(old_avis_count + 1)
expect(created_avis.email).to eq("a@b.com") expect(created_avis.email).to eq("a@b.com")
expect(created_avis.dossier).to eq(dossier) expect(created_avis.dossier).to eq(dossier)
end end
end
context 'checked' do context 'when the expert also shares the linked dossiers' do
let(:invite_linked_dossiers) { true } let(:invite_linked_dossiers) { true }
context 'and the expert can access the linked dossiers' do
let(:created_avis) { Avis.last(2).first } let(:created_avis) { Avis.last(2).first }
let(:linked_avis) { Avis.last } let(:linked_avis) { Avis.last }
let(:linked_dossier) { dossier.reload.linked_dossiers.first } let(:linked_dossier) { Dossier.find_by(id: dossier.reload.champs.filter(&:dossier_link?).map(&:value).compact) }
let(:invite_linked_dossiers) do
instructeur.assign_to_procedure(linked_dossier.procedure)
true
end
it do it 'sends one avis for the main dossier' do
expect(flash.notice).to eq("Une demande d'avis a été envoyée à a@b.com") expect(flash.notice).to eq("Une demande d'avis a été envoyée à a@b.com")
expect(Avis.count).to eq(old_avis_count + 2)
expect(created_avis.email).to eq("a@b.com") expect(created_avis.email).to eq("a@b.com")
expect(created_avis.dossier).to eq(dossier) expect(created_avis.dossier).to eq(dossier)
end
it 'sends another avis for the linked dossiers' do
expect(Avis.count).to eq(old_avis_count + 2)
expect(linked_avis.dossier).to eq(linked_dossier) expect(linked_avis.dossier).to eq(linked_dossier)
end end
end end
context 'but the expert cant access the linked dossier' do
it 'sends a single avis for the main dossier, but doesnt give access to the linked dossiers' do
expect(flash.notice).to eq("Une demande d'avis a été envoyée à a@b.com")
expect(Avis.count).to eq(old_avis_count + 1)
expect(created_avis.email).to eq("a@b.com")
expect(created_avis.dossier).to eq(dossier)
end
end
end
end end
end end
end end

View file

@ -430,6 +430,7 @@ describe Instructeurs::DossiersController, type: :controller do
end end
describe "#create_avis" do describe "#create_avis" do
let(:invite_linked_dossiers) { false }
let(:saved_avis) { dossier.avis.first } let(:saved_avis) { dossier.avis.first }
let!(:old_avis_count) { Avis.count } let!(:old_avis_count) { Avis.count }
@ -437,7 +438,7 @@ describe Instructeurs::DossiersController, type: :controller do
post :create_avis, params: { post :create_avis, params: {
procedure_id: procedure.id, procedure_id: procedure.id,
dossier_id: dossier.id, dossier_id: dossier.id,
avis: { emails: emails, introduction: 'intro', confidentiel: true } avis: { emails: emails, introduction: 'intro', confidentiel: true, invite_linked_dossiers: invite_linked_dossiers }
} }
end end
@ -471,6 +472,57 @@ describe Instructeurs::DossiersController, type: :controller do
it { expect(Avis.count).to eq(old_avis_count + 1) } it { expect(Avis.count).to eq(old_avis_count + 1) }
it { expect(saved_avis.email).to eq("titi@titimail.com") } it { expect(saved_avis.email).to eq("titi@titimail.com") }
end end
context 'with linked dossiers' do
let(:asked_confidentiel) { false }
let(:previous_avis_confidentiel) { false }
let(:dossier) { create(:dossier, :en_construction, :with_dossier_link, procedure: procedure) }
context 'when the expert doesnt share linked dossiers' do
let(:invite_linked_dossiers) { false }
it 'sends a single avis for the main dossier, but doesnt give access to the linked dossiers' do
expect(flash.notice).to eq("Une demande d'avis a été envoyée à email@a.com")
expect(Avis.count).to eq(old_avis_count + 1)
expect(saved_avis.email).to eq("email@a.com")
expect(saved_avis.dossier).to eq(dossier)
end
end
context 'when the expert also shares the linked dossiers' do
let(:invite_linked_dossiers) { true }
context 'and the expert can access the linked dossiers' do
let(:saved_avis) { Avis.last(2).first }
let(:linked_avis) { Avis.last }
let(:linked_dossier) { Dossier.find_by(id: dossier.reload.champs.filter(&:dossier_link?).map(&:value).compact) }
let(:invite_linked_dossiers) do
instructeur.assign_to_procedure(linked_dossier.procedure)
true
end
it 'sends one avis for the main dossier' do
expect(flash.notice).to eq("Une demande d'avis a été envoyée à email@a.com")
expect(saved_avis.email).to eq("email@a.com")
expect(saved_avis.dossier).to eq(dossier)
end
it 'sends another avis for the linked dossiers' do
expect(Avis.count).to eq(old_avis_count + 2)
expect(linked_avis.dossier).to eq(linked_dossier)
end
end
context 'but the expert cant access the linked dossier' do
it 'sends a single avis for the main dossier, but doesnt give access to the linked dossiers' do
expect(flash.notice).to eq("Une demande d'avis a été envoyée à email@a.com")
expect(Avis.count).to eq(old_avis_count + 1)
expect(saved_avis.email).to eq("email@a.com")
expect(saved_avis.dossier).to eq(dossier)
end
end
end
end
end end
describe "#show" do describe "#show" do

View file

@ -68,7 +68,7 @@ FactoryBot.define do
trait :with_dossier_link do trait :with_dossier_link do
after(:create) do |dossier, _evaluator| after(:create) do |dossier, _evaluator|
# create linked dossier # create linked dossier
linked_dossier = create(:dossier) linked_dossier = create(:dossier, :en_construction)
# find first type de champ dossier_link # find first type de champ dossier_link
type_de_champ = dossier.procedure.types_de_champ.find do |t| type_de_champ = dossier.procedure.types_de_champ.find do |t|

View file

@ -9,9 +9,13 @@ feature 'Inviting an expert:' do
let(:expert_password) { 'mot de passe dexpert' } let(:expert_password) { 'mot de passe dexpert' }
let(:procedure) { create(:procedure, :published, instructeurs: [instructeur]) } let(:procedure) { create(:procedure, :published, instructeurs: [instructeur]) }
let(:dossier) { create(:dossier, :en_construction, :with_dossier_link, procedure: procedure) } let(:dossier) { create(:dossier, :en_construction, :with_dossier_link, procedure: procedure) }
let(:linked_dossier) { Dossier.find_by(id: dossier.reload.champs.filter(&:dossier_link?).map(&:value).compact) }
context 'as an Instructeur' do context 'as an Instructeur' do
scenario 'I can invite an expert' do scenario 'I can invite an expert' do
# assign instructeur to linked dossier
instructeur.assign_to_procedure(linked_dossier.procedure)
login_as instructeur.user, scope: :user login_as instructeur.user, scope: :user
visit instructeur_dossier_path(procedure, dossier) visit instructeur_dossier_path(procedure, dossier)

View file

@ -107,7 +107,7 @@ feature 'The user' do
fill_in('text', with: 'super texte') fill_in('text', with: 'super texte')
expect(page).to have_field('text', with: 'super texte') expect(page).to have_field('text', with: 'super texte')
click_on 'Ajouter une ligne pour' click_on 'Ajouter un élément pour'
within '.row-1' do within '.row-1' do
fill_in('text', with: 'un autre texte') fill_in('text', with: 'un autre texte')
@ -120,7 +120,7 @@ feature 'The user' do
expect(page).to have_content('Supprimer', count: 2) expect(page).to have_content('Supprimer', count: 2)
within '.row-1' do within '.row-1' do
click_on 'Supprimer' click_on 'Supprimer lélément'
end end
click_on 'Enregistrer le brouillon' click_on 'Enregistrer le brouillon'

View file

@ -183,4 +183,33 @@ RSpec.describe DossierHelper, type: :helper do
it { is_expected.to eq('without_continuation') } it { is_expected.to eq('without_continuation') }
end end
end end
describe '.has_lost_attachments' do
let(:procedure) { create(:procedure, :published) }
let(:dossier_with_lost_attachments) { create(:dossier, procedure: procedure) }
let(:dossier_without_lost_attachments) { create(:dossier, procedure: procedure) }
before do
expect(ENV).to receive(:[]).with('APP_HOST').at_least(:once).and_return(app_host)
allow(helper).to receive(:dossiers_with_lost_attachments_ids).and_return([dossier_with_lost_attachments.id])
end
context 'on the DINUM instance' do
let(:app_host) { 'demarches-simplifiees.fr' }
it 'returns true for dossiers that lost attachments' do
expect(helper.has_lost_attachments(dossier_with_lost_attachments)).to be(true)
expect(helper.has_lost_attachments(dossier_without_lost_attachments)).to be(false)
end
end
context 'on another instance' do
let(:app_host) { 'polynesie-francaise.pref.gouv.fr' }
it 'returns false for all dossiers' do
expect(helper.has_lost_attachments(dossier_with_lost_attachments)).to be(false)
expect(helper.has_lost_attachments(dossier_without_lost_attachments)).to be(false)
end
end
end
end end

View file

@ -0,0 +1,26 @@
require 'spec_helper'
describe Champs::CheckboxChamp do
let(:types_de_champ) do
[
create(:type_de_champ_header_section, order_place: 1),
create(:type_de_champ_civilite, order_place: 2),
create(:type_de_champ_text, order_place: 3),
create(:type_de_champ_header_section, order_place: 4),
create(:type_de_champ_email, order_place: 5)
]
end
let(:procedure) { create(:procedure, types_de_champ: types_de_champ) }
let(:dossier) { create(:dossier, procedure: procedure) }
describe '#section_index' do
let(:first_header) { dossier.champs[0] }
let(:second_header) { dossier.champs[3] }
it 'returns the index of the section (starting from 1)' do
expect(first_header.section_index).to eq 1
expect(second_header.section_index).to eq 2
end
end
end

View file

@ -9,24 +9,24 @@ describe 'shared/dossiers/demande.html.haml', type: :view do
sign_in(current_instructeur.user) sign_in(current_instructeur.user)
end end
subject! { render 'shared/dossiers/demande.html.haml', dossier: dossier, demande_seen_at: nil, profile: 'usager' } subject { render 'shared/dossiers/demande.html.haml', dossier: dossier, demande_seen_at: nil, profile: 'usager' }
context 'when dossier was created by an etablissement' do context 'when dossier was created by an etablissement' do
let(:etablissement) { create(:etablissement) } let(:etablissement) { create(:etablissement) }
it 'renders the etablissement infos' do it 'renders the etablissement infos' do
expect(rendered).to include(etablissement.entreprise_raison_sociale) expect(subject).to include(etablissement.entreprise_raison_sociale)
expect(rendered).to include(etablissement.entreprise_siret_siege_social) expect(subject).to include(etablissement.entreprise_siret_siege_social)
expect(rendered).to include(etablissement.entreprise_forme_juridique) expect(subject).to include(etablissement.entreprise_forme_juridique)
end end
context 'and entreprise is an association' do context 'and entreprise is an association' do
let(:etablissement) { create(:etablissement, :is_association) } let(:etablissement) { create(:etablissement, :is_association) }
it 'renders the association infos' do it 'renders the association infos' do
expect(rendered).to include(etablissement.association_rna) expect(subject).to include(etablissement.association_rna)
expect(rendered).to include(etablissement.association_titre) expect(subject).to include(etablissement.association_titre)
expect(rendered).to include(etablissement.association_objet) expect(subject).to include(etablissement.association_objet)
end end
end end
end end
@ -35,10 +35,10 @@ describe 'shared/dossiers/demande.html.haml', type: :view do
let(:individual) { create(:individual) } let(:individual) { create(:individual) }
it 'renders the individual identity infos' do it 'renders the individual identity infos' do
expect(rendered).to include(individual.gender) expect(subject).to include(individual.gender)
expect(rendered).to include(individual.nom) expect(subject).to include(individual.nom)
expect(rendered).to include(individual.prenom) expect(subject).to include(individual.prenom)
expect(rendered).to include(I18n.l(individual.birthdate)) expect(subject).to include(I18n.l(individual.birthdate))
end end
end end
@ -47,7 +47,17 @@ describe 'shared/dossiers/demande.html.haml', type: :view do
it 'renders the champs' do it 'renders the champs' do
dossier.champs.each do |champ| dossier.champs.each do |champ|
expect(rendered).to include(champ.libelle) expect(subject).to include(champ.libelle)
end
end
context 'when the dossier lost some attachments' do
before do
expect(view).to receive(:has_lost_attachments).and_return(true)
end
it 'displays a warning message' do
expect(subject).to include('Des pièces jointes de votre dossier peuvent être manquantes.')
end end
end end
end end

View file

@ -0,0 +1,40 @@
describe 'shared/dossiers/lost_attachments.html.haml', type: :view do
let(:procedure) { create(:procedure, :published) }
let(:dossier) { create(:dossier, :en_construction, procedure: procedure) }
subject { render 'shared/dossiers/lost_attachments.html.haml', dossier: dossier, profile: profile }
context 'when viewed by an Usager' do
let(:profile) { 'usager' }
it 'displays a warning message' do
expect(subject).to include('Des pièces jointes de votre dossier peuvent être manquantes')
expect(subject).to have_link('renvoyer les pièces jointes manquantes', href: modifier_dossier_path(dossier))
end
context 'when the user cant edit the dossier' do
let(:dossier) { create(:dossier, :en_instruction, procedure: procedure) }
it 'suggest to wait' do
expect(subject).to include('ladministration vous contactera')
end
end
end
context 'when viewed by an Instructeur' do
let(:profile) { 'instructeur' }
it 'displays a warning message' do
expect(subject).to include('Des pièces jointes de ce dossier peuvent être manquantes')
expect(subject).to have_link('contacter le demandeur')
end
context 'when the user cant edit the dossier' do
let(:dossier) { create(:dossier, :en_instruction, procedure: procedure) }
it 'suggest to make the dossier editable again' do
expect(subject).to include('repasser ce dossier en construction')
end
end
end
end