Merge pull request #3209 from betagouv/dev

2018-12-20-01
This commit is contained in:
Frederic Merizen 2018-12-20 17:26:43 +01:00 committed by GitHub
commit a930032104
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
79 changed files with 408 additions and 535 deletions

View file

@ -439,19 +439,6 @@ $cta-panel-button-border-size: 2px;
} }
} }
.tour-de-france-banner {
padding-top: 15px;
padding-bottom: 15px;
background-color: $blue;
color: #FFFFFF;
text-align: center;
a {
color: #FFFFFF;
text-decoration: underline;
}
}
.half { .half {
width: 45%; width: 45%;
float: left; float: left;

View file

@ -18,20 +18,4 @@ class ChampDecorator < Draper::Decorator
object.value object.value
end end
end end
def date_for_input
if object.value.present?
if type_champ == TypeDeChamp.type_champs.fetch(:date)
object.value
elsif type_champ == TypeDeChamp.type_champs.fetch(:datetime) && object.value != ' 00:00'
Time.zone.strptime(object.value, "%Y-%m-%d %H:%M").strftime("%Y-%m-%d")
end
end
end
def description_with_links
if description
description.gsub(URI.regexp, '<a target="_blank" href="\0">\0</a>')
end
end
end end

View file

@ -90,13 +90,6 @@ module ApplicationHelper
end end
end end
def ensure_safe_json(json)
json.present? ? JSON.parse(json).to_json : '[]'
rescue Exception => e
Raven.capture_exception(e)
{}
end
def sentry_config def sentry_config
sentry = Rails.application.secrets.sentry sentry = Rails.application.secrets.sentry
if sentry if sentry

View file

@ -23,12 +23,16 @@ class Helpscout::FormAdapter
ADMIN_TYPE_RDV = 'admin demande rdv' ADMIN_TYPE_RDV = 'admin demande rdv'
ADMIN_TYPE_QUESTION = 'admin question' ADMIN_TYPE_QUESTION = 'admin question'
ADMIN_TYPE_SOUCIS = 'admin soucis' ADMIN_TYPE_SOUCIS = 'admin soucis'
ADMIN_TYPE_PRODUIT = 'admin suggestion produit'
ADMIN_TYPE_DEMANDE_COMPTE = 'admin demande compte'
ADMIN_TYPE_AUTRE = 'admin autre' ADMIN_TYPE_AUTRE = 'admin autre'
ADMIN_OPTIONS = [ ADMIN_OPTIONS = [
[I18n.t(ADMIN_TYPE_QUESTION, scope: [:supportadmin]), ADMIN_TYPE_QUESTION], [I18n.t(ADMIN_TYPE_QUESTION, scope: [:supportadmin]), ADMIN_TYPE_QUESTION],
[I18n.t(ADMIN_TYPE_RDV, scope: [:supportadmin]), ADMIN_TYPE_RDV], [I18n.t(ADMIN_TYPE_RDV, scope: [:supportadmin]), ADMIN_TYPE_RDV],
[I18n.t(ADMIN_TYPE_SOUCIS, scope: [:supportadmin]), ADMIN_TYPE_SOUCIS], [I18n.t(ADMIN_TYPE_SOUCIS, scope: [:supportadmin]), ADMIN_TYPE_SOUCIS],
[I18n.t(ADMIN_TYPE_PRODUIT, scope: [:supportadmin]), ADMIN_TYPE_PRODUIT],
[I18n.t(ADMIN_TYPE_DEMANDE_COMPTE, scope: [:supportadmin]), ADMIN_TYPE_DEMANDE_COMPTE],
[I18n.t(ADMIN_TYPE_AUTRE, scope: [:supportadmin]), ADMIN_TYPE_AUTRE] [I18n.t(ADMIN_TYPE_AUTRE, scope: [:supportadmin]), ADMIN_TYPE_AUTRE]
] ]

View file

@ -1,5 +1,7 @@
# Preview all emails at http://localhost:3000/rails/mailers/invite_mailer # Preview all emails at http://localhost:3000/rails/mailers/invite_mailer
class InviteMailer < ApplicationMailer class InviteMailer < ApplicationMailer
layout 'mailers/layout'
def invite_user(invite) def invite_user(invite)
subject = "Participez à l'élaboration d'un dossier" subject = "Participez à l'élaboration d'un dossier"

View file

@ -10,12 +10,13 @@ class Champ < ApplicationRecord
has_many :geo_areas, dependent: :destroy has_many :geo_areas, dependent: :destroy
belongs_to :etablissement, dependent: :destroy belongs_to :etablissement, dependent: :destroy
delegate :libelle, :type_champ, :order_place, :mandatory?, :description, :drop_down_list, to: :type_de_champ delegate :libelle, :type_champ, :order_place, :mandatory?, :description, :drop_down_list, :exclude_from_export?, :exclude_from_view?, to: :type_de_champ
scope :updated_since?, -> (date) { where('champs.updated_at > ?', date) } scope :updated_since?, -> (date) { where('champs.updated_at > ?', date) }
scope :public_only, -> { where(private: false) } scope :public_only, -> { where(private: false) }
scope :private_only, -> { where(private: true) } scope :private_only, -> { where(private: true) }
scope :ordered, -> { includes(:type_de_champ).order('types_de_champ.order_place') } scope :ordered, -> { includes(:type_de_champ).order(:row, 'types_de_champ.order_place') }
scope :root, -> { where(parent_id: nil) }
def public? def public?
!private? !private?

View file

@ -1,24 +1,12 @@
class Champs::DatetimeChamp < Champ class Champs::DatetimeChamp < Champ
before_save :format_before_save before_save :format_before_save
def same_hour?(num)
same_date?(num, '%H')
end
def same_minute?(num)
same_date?(num, '%M')
end
def search_terms def search_terms
# Text search is pretty useless for datetimes so were not including these champs # Text search is pretty useless for datetimes so were not including these champs
end end
private private
def same_date?(num, compare)
return value.present? && value.to_datetime.strftime(compare) == num
end
def format_before_save def format_before_save
if (value =~ /=>/).present? if (value =~ /=>/).present?
self.value = self.value =

View file

@ -0,0 +1,13 @@
class Champs::RepetitionChamp < Champ
has_many :champs, -> { ordered }, foreign_key: :parent_id, dependent: :destroy
accepts_nested_attributes_for :champs, allow_destroy: true
def rows
champs.group_by(&:row).values
end
def search_terms
# The user cannot enter any information here so it doesnt make much sense to search
end
end

View file

@ -18,8 +18,8 @@ class Dossier < ApplicationRecord
has_one :attestation, dependent: :destroy has_one :attestation, dependent: :destroy
has_many :pieces_justificatives, dependent: :destroy has_many :pieces_justificatives, dependent: :destroy
has_many :champs, -> { public_only.ordered }, dependent: :destroy has_many :champs, -> { root.public_only.ordered }, dependent: :destroy
has_many :champs_private, -> { private_only.ordered }, class_name: 'Champ', dependent: :destroy has_many :champs_private, -> { root.private_only.ordered }, class_name: 'Champ', dependent: :destroy
has_many :commentaires, dependent: :destroy has_many :commentaires, dependent: :destroy
has_many :invites, dependent: :destroy has_many :invites, dependent: :destroy
has_many :follows has_many :follows
@ -152,22 +152,10 @@ class Dossier < ApplicationRecord
update_columns(autorisation_donnees: false) update_columns(autorisation_donnees: false)
end end
def total_follow
follows.size
end
def read_only? def read_only?
en_instruction? || accepte? || refuse? || sans_suite? en_instruction? || accepte? || refuse? || sans_suite?
end end
def invite_for_user(user)
invites.find_by(user_id: user.id)
end
def can_be_en_construction?
!(procedure.archivee? && brouillon?)
end
def can_transition_to_en_construction? def can_transition_to_en_construction?
!procedure.archivee? && brouillon? !procedure.archivee? && brouillon?
end end

View file

@ -22,11 +22,6 @@ class Gestionnaire < ApplicationRecord
procedures.merge(Procedure.avec_lien.or(Procedure.archivees)) procedures.merge(Procedure.avec_lien.or(Procedure.archivees))
end end
def can_view_dossier?(dossier_id)
avis.where(dossier_id: dossier_id).any? ||
dossiers.where(id: dossier_id).any?
end
def follow(dossier) def follow(dossier)
if follow?(dossier) if follow?(dossier)
return return
@ -43,10 +38,6 @@ class Gestionnaire < ApplicationRecord
followed_dossiers.include?(dossier) followed_dossiers.include?(dossier)
end end
def assigned_on_procedure?(procedure_id)
procedures.find_by(id: procedure_id).present?
end
def assign_to_procedure(procedure) def assign_to_procedure(procedure)
begin begin
procedures << procedure procedures << procedure

View file

@ -3,9 +3,9 @@ require Rails.root.join('lib', 'percentile')
class Procedure < ApplicationRecord class Procedure < ApplicationRecord
MAX_DUREE_CONSERVATION = 36 MAX_DUREE_CONSERVATION = 36
has_many :types_de_piece_justificative, -> { order "order_place ASC" }, dependent: :destroy has_many :types_de_piece_justificative, -> { ordered }, dependent: :destroy
has_many :types_de_champ, -> { public_only }, dependent: :destroy has_many :types_de_champ, -> { public_only.ordered }, dependent: :destroy
has_many :types_de_champ_private, -> { private_only }, class_name: 'TypeDeChamp', dependent: :destroy has_many :types_de_champ_private, -> { private_only.ordered }, class_name: 'TypeDeChamp', dependent: :destroy
has_many :dossiers has_many :dossiers
has_many :deleted_dossiers, dependent: :destroy has_many :deleted_dossiers, dependent: :destroy
@ -137,13 +137,8 @@ class Procedure < ApplicationRecord
# Warning: dossier after_save build_default_champs must be removed # Warning: dossier after_save build_default_champs must be removed
# to save a dossier created from this method # to save a dossier created from this method
def new_dossier def new_dossier
champs = types_de_champ champs = types_de_champ.map { |tdc| tdc.champ.build }
.ordered champs_private = types_de_champ_private.map { |tdc| tdc.champ.build }
.map { |tdc| tdc.champ.build }
champs_private = types_de_champ_private
.ordered
.map { |tdc| tdc.champ.build }
Dossier.new(procedure: self, champs: champs, champs_private: champs_private) Dossier.new(procedure: self, champs: champs, champs_private: champs_private)
end end
@ -156,28 +151,16 @@ class Procedure < ApplicationRecord
service&.nom || organisation service&.nom || organisation
end end
def types_de_champ_ordered
types_de_champ.order(:order_place)
end
def types_de_champ_private_ordered
types_de_champ_private.order(:order_place)
end
def all_types_de_champ
types_de_champ + types_de_champ_private
end
def self.active(id) def self.active(id)
publiees.find(id) publiees.find(id)
end end
def switch_types_de_champ(index_of_first_element) def switch_types_de_champ(index_of_first_element)
switch_list_order(types_de_champ_ordered, index_of_first_element) switch_list_order(types_de_champ, index_of_first_element)
end end
def switch_types_de_champ_private(index_of_first_element) def switch_types_de_champ_private(index_of_first_element)
switch_list_order(types_de_champ_private_ordered, index_of_first_element) switch_list_order(types_de_champ_private, index_of_first_element)
end end
def switch_types_de_piece_justificative(index_of_first_element) def switch_types_de_piece_justificative(index_of_first_element)
@ -230,6 +213,8 @@ class Procedure < ApplicationRecord
if from_library if from_library
procedure.service = nil procedure.service = nil
elsif self.service.present? && (self.administrateur_id != admin.id)
procedure.service = self.service.clone_and_assign_to_administrateur(admin)
end end
procedure procedure

View file

@ -25,4 +25,10 @@ class Service < ApplicationRecord
validates :horaires, presence: { message: 'doivent être renseignés' }, allow_nil: false validates :horaires, presence: { message: 'doivent être renseignés' }, allow_nil: false
validates :adresse, presence: { message: 'doit être renseignée' }, allow_nil: false validates :adresse, presence: { message: 'doit être renseignée' }, allow_nil: false
validates :administrateur, presence: { message: 'doit être renseigné' }, allow_nil: false validates :administrateur, presence: { message: 'doit être renseigné' }, allow_nil: false
def clone_and_assign_to_administrateur(administrateur)
service_cloned = self.dup
service_cloned.administrateur = administrateur
service_cloned
end
end end

View file

@ -28,12 +28,36 @@ class TypeDeChamp < ApplicationRecord
dossier_link: 'dossier_link', dossier_link: 'dossier_link',
piece_justificative: 'piece_justificative', piece_justificative: 'piece_justificative',
siret: 'siret', siret: 'siret',
carte: 'carte' carte: 'carte',
repetition: 'repetition'
} }
belongs_to :procedure belongs_to :procedure
store :options, accessors: [:cadastres, :quartiers_prioritaires, :parcelles_agricoles] 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
# TODO simplify after migrating `options` column to (non YAML encoded) JSON
class MaybeYaml
def load(options)
case options
when String
YAML.safe_load(options, [ActiveSupport::HashWithIndifferentAccess])
when Hash
options.with_indifferent_access
else
options
end
end
def dump(options)
options
end
end
serialize :options, MaybeYaml.new
after_initialize :set_dynamic_type after_initialize :set_dynamic_type
after_create :populate_stable_id after_create :populate_stable_id
@ -105,7 +129,25 @@ class TypeDeChamp < ApplicationRecord
end end
def non_fillable? def non_fillable?
type_champ.in?([TypeDeChamp.type_champs.fetch(:header_section), TypeDeChamp.type_champs.fetch(:explication)]) type_champ.in?([
TypeDeChamp.type_champs.fetch(:header_section),
TypeDeChamp.type_champs.fetch(:explication)
])
end
def exclude_from_export?
type_champ.in?([
TypeDeChamp.type_champs.fetch(:header_section),
TypeDeChamp.type_champs.fetch(:explication),
TypeDeChamp.type_champs.fetch(:repetition)
])
end
def exclude_from_view?
type_champ.in?([
TypeDeChamp.type_champs.fetch(:explication),
TypeDeChamp.type_champs.fetch(:repetition)
])
end end
def public? def public?

View file

@ -6,4 +6,5 @@ class TypeDePieceJustificative < ApplicationRecord
validates :libelle, presence: true, allow_blank: false, allow_nil: false validates :libelle, presence: true, allow_blank: false, allow_nil: false
validates :lien_demarche, format: { with: URI.regexp }, allow_blank: true, allow_nil: true validates :lien_demarche, format: { with: URI.regexp }, allow_blank: true, allow_nil: true
scope :ordered, -> { order(order_place: :asc) }
end end

View file

@ -0,0 +1,2 @@
class TypesDeChamp::RepetitionTypeDeChamp < TypesDeChamp::TypeDeChampBase
end

View file

@ -28,21 +28,6 @@ class User < ApplicationRecord
link_invites! link_invites!
end end
def self.find_for_france_connect(email, siret)
user = User.find_by(email: email)
if user.nil?
User.create(email: email, password: Devise.friendly_token[0, 20], siret: siret)
else
user.update(siret: siret)
user
end
end
def loged_in_with_france_connect?
loged_in_with_france_connect.present?
end
def owns?(dossier) def owns?(dossier)
dossier.user_id == id dossier.user_id == id
end end

View file

@ -1,48 +0,0 @@
class ChampsService
class << self
def save_champs(champs, params)
fill_champs(champs, params)
champs.select(&:changed?).each(&:save)
end
def build_error_messages(champs)
champs.select(&:mandatory_and_blank?)
.map { |c| "Le champ #{c.libelle.truncate(200)} doit être rempli." }
end
def check_piece_justificative_files(champs)
champs.select do |champ|
champ.type_champ == TypeDeChamp.type_champs.fetch(:piece_justificative)
end.map(&:piece_justificative_file_errors).flatten
end
private
def fill_champs(champs, h)
datetimes, not_datetimes = champs.partition { |c| c.type_champ == TypeDeChamp.type_champs.fetch(:datetime) }
not_datetimes.each do |c|
if c.type_champ == TypeDeChamp.type_champs.fetch(:piece_justificative) && h["champs"]["'#{c.id}'"].present?
c.piece_justificative_file.attach(h["champs"]["'#{c.id}'"])
else
c.value = h[:champs]["'#{c.id}'"]
end
end
datetimes.each { |c| c.value = parse_datetime(c.id, h) }
end
def parse_datetime(champ_id, h)
"#{h[:champs]["'#{champ_id}'"]} #{extract_hour(champ_id, h)}:#{extract_minute(champ_id, h)}"
end
def extract_hour(champ_id, h)
h[:time_hour]["'#{champ_id}'"]
end
def extract_minute(champ_id, h)
h[:time_minute]["'#{champ_id}'"]
end
end
end

View file

@ -15,23 +15,6 @@ class PiecesJustificativesService
.compact() .compact()
end end
def self.upload_one!(dossier, user, params)
content = params[:piece_justificative][:content]
if ClamavService.safe_file?(content.path)
pj = PieceJustificative.new(content: content,
dossier: dossier,
type_de_piece_justificative: nil,
user: user)
pj.save
else
pj = PieceJustificative.new
pj.errors.add(:content, "#{content.original_filename} : <b>Virus détecté !!</b>")
end
pj
end
def self.save_pj(content, dossier, tpj, user) def self.save_pj(content, dossier, tpj, user)
pj = PieceJustificative.new(content: content, pj = PieceJustificative.new(content: content,
dossier: dossier, dossier: dossier,

View file

@ -142,10 +142,10 @@ class ProcedureExportService
headers = ATTRIBUTES.map do |key| headers = ATTRIBUTES.map do |key|
label_for_export(key.to_s) label_for_export(key.to_s)
end end
headers += @procedure.types_de_champ.ordered.map do |champ| headers += @procedure.types_de_champ.reject(&:exclude_from_export?).map do |champ|
label_for_export(champ.libelle) label_for_export(champ.libelle)
end end
headers += @procedure.types_de_champ_private.ordered.map do |champ| headers += @procedure.types_de_champ_private.reject(&:exclude_from_export?).map do |champ|
label_for_export(champ.libelle) label_for_export(champ.libelle)
end end
headers += ETABLISSEMENT_ATTRIBUTES.map do |key| headers += ETABLISSEMENT_ATTRIBUTES.map do |key|
@ -184,10 +184,10 @@ class ProcedureExportService
end end
end end
values = normalize_values(values) values = normalize_values(values)
values += dossier.champs.map do |champ| values += dossier.champs.reject(&:exclude_from_export?).map do |champ|
value_for_export(champ) value_for_export(champ)
end end
values += dossier.champs_private.map do |champ| values += dossier.champs_private.reject(&:exclude_from_export?).map do |champ|
value_for_export(champ) value_for_export(champ)
end end
values += etablissement_data(dossier.etablissement) values += etablissement_data(dossier.etablissement)

View file

@ -3,7 +3,8 @@ class TypesDeChampService
TOGGLES = { TOGGLES = {
TypeDeChamp.type_champs.fetch(:siret) => :champ_siret?, TypeDeChamp.type_champs.fetch(:siret) => :champ_siret?,
TypeDeChamp.type_champs.fetch(:integer_number) => :champ_integer_number? TypeDeChamp.type_champs.fetch(:integer_number) => :champ_integer_number?,
TypeDeChamp.type_champs.fetch(:repetition) => :champ_repetition?
} }
def options def options
@ -35,7 +36,7 @@ class TypesDeChampService
end end
def types_de_champ def types_de_champ
private? ? @procedure.types_de_champ_private_ordered.decorate : @procedure.types_de_champ_ordered.decorate private? ? @procedure.types_de_champ_private.decorate : @procedure.types_de_champ.decorate
end end
def new_type_de_champ def new_type_de_champ

View file

@ -14,8 +14,4 @@
Créateur : Créateur :
= @administration.email = @administration.email
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -14,8 +14,4 @@
= link_to("formulaire de contact", contact_url) = link_to("formulaire de contact", contact_url)
\. \.
%p = render partial: "layouts/mailers/signature"
Cordialement,
%p
L'équipe demarches-simplifiees.fr

View file

@ -2,6 +2,13 @@
- avis_link = @avis.gestionnaire.present? ? gestionnaire_avis_url(@avis) : sign_up_gestionnaire_avis_url(@avis.id, @avis.email) - avis_link = @avis.gestionnaire.present? ? gestionnaire_avis_url(@avis) : sign_up_gestionnaire_avis_url(@avis.id, @avis.email)
- content_for(:footer) do
Merci de ne pas répondre à cet email. Donnez votre avis
= link_to("sur demarches-simplifiees.fr", avis_link)
ou
= succeed '.' do
= mail_to(@avis.claimant.email, "contactez la personne qui vous a invité")
%p %p
Bonjour, Bonjour,
@ -24,17 +31,4 @@
%p %p
= link_to "Inscrivez-vous pour donner votre avis", avis_link = link_to "Inscrivez-vous pour donner votre avis", avis_link
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr
%hr
%p
Merci de ne pas répondre à cet email. Donnez votre avis
= link_to "sur notre site", avis_link
ou
= succeed '.' do
= mail_to @avis.claimant.email, "contactez la personne qui vous a invité"

View file

@ -30,9 +30,13 @@
= text_field_tag :name, nil, required: true = text_field_tag :name, nil, required: true
= label_tag :email do = label_tag :email do
Quelle est l'adresse email pour laquelle vous souhaitez un compte ? Quelle est l'adresse email professionnelle pour laquelle vous souhaitez un compte ?
%span.mandatory * %span.mandatory *
= email_field_tag :email, nil, required: true %p.intro{ :style => "font-weight: normal" }
Vous utilisez un email orange, wanadoo, free, gmail etc. ? Merci de nous
%a{ href: contact_admin_path, target:'_blank' }
contacter préalablement.
= email_field_tag :email, nil, placeholder: 'jean.martin@developpement-durable.gouv.fr', required: true
= label_tag :phone do = label_tag :phone do
Quel est votre numéro de téléphone (ligne directe) ? Quel est votre numéro de téléphone (ligne directe) ?

View file

@ -1,14 +1,10 @@
- content_for(:title, 'Activez votre compte') - content_for(:title, 'Activez votre compte')
%p %p
Bonjour #{@user.email}, Bonjour,
%p %p
Pour activer votre compte sur demarches-simplifiees.fr, veuillez cliquer sur le lien suivant : Pour activer votre compte sur demarches-simplifiees.fr, veuillez cliquer sur le lien suivant :
= link_to(confirmation_url(@user, confirmation_token: @token), confirmation_url(@user, confirmation_token: @token)) = link_to(confirmation_url(@user, confirmation_token: @token), confirmation_url(@user, confirmation_token: @token))
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -16,8 +16,4 @@
demarches-simplifiees.fr a bien été pris en compte. demarches-simplifiees.fr a bien été pris en compte.
Vous pouvez désormais vous connecter avec ladresse #{@resource.email}. Vous pouvez désormais vous connecter avec ladresse #{@resource.email}.
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -7,8 +7,4 @@
La demande de changement de mot de passe pour votre compte #{@resource.email} sur La demande de changement de mot de passe pour votre compte #{@resource.email} sur
demarches-simplifiees.fr a bien été prise en compte. demarches-simplifiees.fr a bien été prise en compte.
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -9,8 +9,4 @@
%p %p
Si vous n'avez pas effectué une telle demande, merci d'ignorer cet email. Votre mot de passe ne sera pas changé. Si vous n'avez pas effectué une telle demande, merci d'ignorer cet email. Votre mot de passe ne sera pas changé.
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -13,8 +13,4 @@
%p= link_to 'Déverrouiller mon compte', unlock_url(@resource, unlock_token: @token) %p= link_to 'Déverrouiller mon compte', unlock_url(@resource, unlock_token: @token)
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -1,14 +1,11 @@
- content_for(:title, "Suppression du dossier n° #{@deleted_dossier.dossier_id}") - content_for(:title, "Suppression du dossier n° #{@deleted_dossier.dossier_id}")
%h1 Bonjour, %p
Bonjour,
%p %p
À la demande de l'usager, le dossier n° #{@deleted_dossier.dossier_id} À la demande de l'usager, le dossier n° #{@deleted_dossier.dossier_id}
(sur la démarche «&nbsp;#{@deleted_dossier.procedure.libelle}&nbsp;») (sur la démarche «&nbsp;#{@deleted_dossier.procedure.libelle}&nbsp;»)
a été supprimé. a été supprimé.
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -1,14 +1,11 @@
- content_for(:title, "Suppression du dossier n° #{@deleted_dossier.dossier_id}") - content_for(:title, "Suppression du dossier n° #{@deleted_dossier.dossier_id}")
%h1 Bonjour, %p
Bonjour,
%p %p
Votre dossier n° #{@deleted_dossier.dossier_id} Votre dossier n° #{@deleted_dossier.dossier_id}
(«&nbsp;#{@deleted_dossier.procedure.libelle}&nbsp;») a bien été supprimé. («&nbsp;#{@deleted_dossier.procedure.libelle}&nbsp;») a bien été supprimé.
Une trace anonyme de ce traitement sera conservée pour ladministration. Une trace anonyme de ce traitement sera conservée pour ladministration.
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -8,8 +8,4 @@
Pour le consulter, merci de vous rendre sur Pour le consulter, merci de vous rendre sur
= link_to messagerie_dossier_url(@dossier), messagerie_dossier_url(@dossier), target: '_blank' = link_to messagerie_dossier_url(@dossier), messagerie_dossier_url(@dossier), target: '_blank'
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -7,8 +7,4 @@
à l'adresse suivante : à l'adresse suivante :
= link_to dossier_url(@dossier), dossier_url(@dossier), target: '_blank' = link_to dossier_url(@dossier), dossier_url(@dossier), target: '_blank'
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -8,8 +8,5 @@
sur la procédure «&nbsp;#{@dossier.procedure.libelle}&nbsp;» a été inaccessible pendant quelques jours. sur la procédure «&nbsp;#{@dossier.procedure.libelle}&nbsp;» a été inaccessible pendant quelques jours.
Laccès est à présent à nouveau possible. Nous vous présentons nos excuses pour toute gène occasionnée. Laccès est à présent à nouveau possible. Nous vous présentons nos excuses pour toute gène occasionnée.
%p
Bonne journée,
%p = render partial: "layouts/mailers/signature"
L'équipe demarches-simplifiees.fr

View file

@ -7,8 +7,4 @@
ayant commencé, il n'a pas pu être supprimé. ayant commencé, il n'a pas pu être supprimé.
Le dossier a été rétabli dans votre tableau de bord. Le dossier a été rétabli dans votre tableau de bord.
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -19,8 +19,4 @@
Nous avons pris des mesures pour nous assurer quun tel désagrément ne se reproduise pas, Nous avons pris des mesures pour nous assurer quun tel désagrément ne se reproduise pas,
et vous présentons nos excuses pour la gène occasionnée. et vous présentons nos excuses pour la gène occasionnée.
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -14,8 +14,4 @@
Par ailleurs, nous vous invitons à prendre quelques minutes pour consulter notre tutoriel à destination des nouveaux instructeurs : Par ailleurs, nous vous invitons à prendre quelques minutes pour consulter notre tutoriel à destination des nouveaux instructeurs :
= link_to(INSTRUCTEUR_TUTORIAL_URL, INSTRUCTEUR_TUTORIAL_URL) = link_to(INSTRUCTEUR_TUTORIAL_URL, INSTRUCTEUR_TUTORIAL_URL)
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -44,3 +44,5 @@
- if index != (@overview[:procedure_overviews].count - 1) - if index != (@overview[:procedure_overviews].count - 1)
.spacer{ style: 'border-bottom: 1px solid #CCC; margin: 25px 0 30px;' } .spacer{ style: 'border-bottom: 1px solid #CCC; margin: 25px 0 30px;' }
= render partial: "layouts/mailers/signature"

View file

@ -5,8 +5,4 @@
= "#{@sender.email} vous a envoyé le dossier nº #{@dossier.id}, cliquez sur le lien ci-dessous pour y accéder :" = "#{@sender.email} vous a envoyé le dossier nº #{@dossier.id}, cliquez sur le lien ci-dessous pour y accéder :"
= link_to(gestionnaire_dossier_url(@dossier.procedure, @dossier), gestionnaire_dossier_url(@dossier.procedure, @dossier)) = link_to(gestionnaire_dossier_url(@dossier.procedure, @dossier), gestionnaire_dossier_url(@dossier.procedure, @dossier))
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -5,8 +5,4 @@
Veuillez cliquer sur le lien suivant pour vous connecter sur le site demarches-simplifiees.fr :  Veuillez cliquer sur le lien suivant pour vous connecter sur le site demarches-simplifiees.fr : 
= link_to(sign_in_by_link_url(@gestionnaire_id, jeton: @login_token), sign_in_by_link_url(@gestionnaire_id, jeton: @login_token)) = link_to(sign_in_by_link_url(@gestionnaire_id, jeton: @login_token), sign_in_by_link_url(@gestionnaire_id, jeton: @login_token))
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -5,8 +5,4 @@
Vous venez d'être nommé instructeur sur demarches-simplifiees.fr. Vous venez d'être nommé instructeur sur demarches-simplifiees.fr.
= "Votre compte (#{@email}) vous donnera désormais aussi accès à lespace instructeur." = "Votre compte (#{@email}) vous donnera désormais aussi accès à lespace instructeur."
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -13,10 +13,7 @@
Afin de répondre à cette invitation, merci de vous inscrire avec l'adresse email Afin de répondre à cette invitation, merci de vous inscrire avec l'adresse email
= @invite.email = @invite.email
sur sur
= invite_url(@invite, params: { email: @invite.email }) - url_for_link = invite_url(@invite, params: { email: @invite.email })
= link_to url_for_link, url_for_link
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -8,10 +8,7 @@
%p %p
Pour le consulter, merci de suivre ce lien : Pour le consulter, merci de suivre ce lien :
= invite_url(@invite) - url_for_link = invite_url(@invite)
= link_to url_for_link, url_for_link
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -0,0 +1,5 @@
%p
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -116,6 +116,18 @@
</div> </div>
</td> </td>
</tr> </tr>
<% if content_for?(:footer) %>
<tr>
<td style="word-wrap:break-word;font-size:0px;padding:0px 25px 0px 25px;padding-top:0px;padding-bottom:0px;" align="left">
<p style="font-size:13px;text-align:left;">
</p>
<p style="cursor:auto;color:#55575d;font-family:Helvetica, Arial, sans-serif;font-size:12px;font-weight:bold;line-height:22px;text-align:left;">
<%= yield(:footer) %>
</p>
</td>
</tr>
<% end %>
</tbody> </tbody>
</table> </table>
</div> </div>

View file

@ -1,10 +1,7 @@
= yield - content_for :footer do
%strong
Merci de ne pas répondre à cet email. Pour vous adresser à votre administration, passez directement par votre
= succeed '.' do
= link_to 'messagerie', messagerie_dossier_url(@dossier), target: '_blank'
%footer = render template: 'layouts/mailers/layout'
%p
%br
%strong
Merci de ne pas répondre à cet email. Pour vous adresser à votre administration, passez directement par votre
= succeed '.' do
= link_to 'messagerie', messagerie_dossier_url(@dossier), target: '_blank'

View file

@ -7,8 +7,4 @@
%p %p
À tout moment, vous pouvez consulter votre dossier et les éventuels messages de l'administration à cette adresse : --lien dossier-- À tout moment, vous pouvez consulter votre dossier et les éventuels messages de l'administration à cette adresse : --lien dossier--
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -10,8 +10,4 @@
%p %p
À tout moment, vous pouvez consulter votre dossier et les éventuels messages de l'administration à cette adresse : --lien dossier-- À tout moment, vous pouvez consulter votre dossier et les éventuels messages de l'administration à cette adresse : --lien dossier--
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -7,8 +7,4 @@
%p %p
À tout moment, vous pouvez consulter votre dossier et les éventuels messages de l'administration à cette adresse : --lien dossier-- À tout moment, vous pouvez consulter votre dossier et les éventuels messages de l'administration à cette adresse : --lien dossier--
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -4,8 +4,4 @@
%p %p
Votre administration vous confirme la bonne réception de votre dossier nº --numéro du dossier--. Celui-ci sera instruit dans le délai légal déclaré par votre interlocuteur. Votre administration vous confirme la bonne réception de votre dossier nº --numéro du dossier--. Celui-ci sera instruit dans le délai légal déclaré par votre interlocuteur.
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -10,8 +10,4 @@
%p %p
Pour en savoir plus sur le motif du refus, vous pouvez consulter votre dossier et les éventuels messages de l'administration à cette adresse : --lien dossier-- Pour en savoir plus sur le motif du refus, vous pouvez consulter votre dossier et les éventuels messages de l'administration à cette adresse : --lien dossier--
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -10,8 +10,4 @@
%p %p
Pour en savoir plus sur les raisons de ce classement sans suite, vous pouvez consulter votre dossier et les éventuels messages de l'administration à cette adresse : --lien dossier-- Pour en savoir plus sur les raisons de ce classement sans suite, vous pouvez consulter votre dossier et les éventuels messages de l'administration à cette adresse : --lien dossier--
%p = render partial: "layouts/mailers/signature"
Bonne journée,
%p
L'équipe demarches-simplifiees.fr

View file

@ -1,6 +1,6 @@
%table.table.vertical.dossier-champs %table.table.vertical.dossier-champs
%tbody %tbody
- champs.reject { |c| c.type_champ == TypeDeChamp.type_champs.fetch(:explication) }.each do |c| - champs.reject(&:exclude_from_view?).each do |c|
%tr %tr
- case c.type_champ - case c.type_champ
- when TypeDeChamp.type_champs.fetch(:header_section) - when TypeDeChamp.type_champs.fetch(:header_section)

View file

@ -0,0 +1 @@
%h2.repetition-libelle= champ.libelle

View file

@ -1,6 +1,7 @@
- content_for(:title, @subject) - content_for(:title, @subject)
%h1 Bonjour %p
Bonjour,
%p %p
Une demande de création de compte a été réalisée sur le site demarches-simplifiees.fr pour l'email #{@user.email}. Une demande de création de compte a été réalisée sur le site demarches-simplifiees.fr pour l'email #{@user.email}.
@ -12,7 +13,4 @@
%p %p
Si vous n'êtes pas à l'origine de cette demande, vous pouvez ignorer ce mail. Si vous n'êtes pas à l'origine de cette demande, vous pouvez ignorer ce mail.
%p = render partial: "layouts/mailers/signature"
Cordialement,
%br
L'équipe demarches-simplifiees.fr

View file

@ -11,6 +11,8 @@ Flipflop.configure do
title: "Champ SIRET" title: "Champ SIRET"
feature :champ_integer_number, feature :champ_integer_number,
title: "Champ nombre entier" title: "Champ nombre entier"
feature :champ_repetition,
title: "Bloc répétable (NE MARCHE PAS NE PAS ACTIVER)"
end end
feature :web_hook feature :web_hook

View file

@ -65,6 +65,8 @@ fr:
admin demande rdv: Demande de RDV pour une présentation à distance de demarches-simplifiees.fr admin demande rdv: Demande de RDV pour une présentation à distance de demarches-simplifiees.fr
admin question: J'ai une question sur demarches-simplifiees.fr admin question: J'ai une question sur demarches-simplifiees.fr
admin soucis: J'ai un problème technique avec demarches-simplifiees.fr admin soucis: J'ai un problème technique avec demarches-simplifiees.fr
admin suggestion produit: J'ai une proposition d'évolution
admin demande compte: Je souhaite ouvrir un compte administrateur avec un email Orange, Wanadoo, etc.
admin autre: Autre sujet admin autre: Autre sujet
number: number:

View file

@ -31,3 +31,4 @@ fr:
piece_justificative: 'Pièce justificative' piece_justificative: 'Pièce justificative'
siret: 'SIRET' siret: 'SIRET'
carte: 'Carte' carte: 'Carte'
repetition: 'Bloc répétable'

View file

@ -0,0 +1,15 @@
class CreateChampGroups < ActiveRecord::Migration[5.2]
def change
add_column :types_de_champ, :parent_id, :bigint
add_index :types_de_champ, :parent_id
add_column :champs, :parent_id, :bigint
add_index :champs, :parent_id
add_column :champs, :row, :integer
add_index :champs, :row
add_foreign_key :types_de_champ, :types_de_champ, column: :parent_id
add_foreign_key :champs, :champs, column: :parent_id
end
end

View file

@ -153,8 +153,12 @@ ActiveRecord::Schema.define(version: 2018_12_18_204707) do
t.datetime "updated_at" t.datetime "updated_at"
t.boolean "private", default: false, null: false t.boolean "private", default: false, null: false
t.integer "etablissement_id" t.integer "etablissement_id"
t.bigint "parent_id"
t.integer "row"
t.index ["dossier_id"], name: "index_champs_on_dossier_id" t.index ["dossier_id"], name: "index_champs_on_dossier_id"
t.index ["parent_id"], name: "index_champs_on_parent_id"
t.index ["private"], name: "index_champs_on_private" t.index ["private"], name: "index_champs_on_private"
t.index ["row"], name: "index_champs_on_row"
t.index ["type_de_champ_id"], name: "index_champs_on_type_de_champ_id" t.index ["type_de_champ_id"], name: "index_champs_on_type_de_champ_id"
end end
@ -539,6 +543,8 @@ ActiveRecord::Schema.define(version: 2018_12_18_204707) do
t.datetime "updated_at" t.datetime "updated_at"
t.jsonb "options" t.jsonb "options"
t.bigint "stable_id" t.bigint "stable_id"
t.bigint "parent_id"
t.index ["parent_id"], name: "index_types_de_champ_on_parent_id"
t.index ["private"], name: "index_types_de_champ_on_private" t.index ["private"], name: "index_types_de_champ_on_private"
t.index ["stable_id"], name: "index_types_de_champ_on_stable_id" t.index ["stable_id"], name: "index_types_de_champ_on_stable_id"
end end
@ -600,6 +606,7 @@ ActiveRecord::Schema.define(version: 2018_12_18_204707) do
add_foreign_key "attestation_templates", "procedures" add_foreign_key "attestation_templates", "procedures"
add_foreign_key "attestations", "dossiers" add_foreign_key "attestations", "dossiers"
add_foreign_key "avis", "gestionnaires", column: "claimant_id" add_foreign_key "avis", "gestionnaires", column: "claimant_id"
add_foreign_key "champs", "champs", column: "parent_id"
add_foreign_key "closed_mails", "procedures" add_foreign_key "closed_mails", "procedures"
add_foreign_key "commentaires", "dossiers" add_foreign_key "commentaires", "dossiers"
add_foreign_key "dossier_operation_logs", "dossiers" add_foreign_key "dossier_operation_logs", "dossiers"
@ -613,5 +620,6 @@ ActiveRecord::Schema.define(version: 2018_12_18_204707) do
add_foreign_key "received_mails", "procedures" add_foreign_key "received_mails", "procedures"
add_foreign_key "refused_mails", "procedures" add_foreign_key "refused_mails", "procedures"
add_foreign_key "services", "administrateurs" add_foreign_key "services", "administrateurs"
add_foreign_key "types_de_champ", "types_de_champ", column: "parent_id"
add_foreign_key "without_continuation_mails", "procedures" add_foreign_key "without_continuation_mails", "procedures"
end end

View file

@ -0,0 +1,35 @@
namespace :after_party do
desc 'Deployment task: clone_service_for_transferred_procedures'
task clone_service_for_transferred_procedures: :environment do
puts "Running deploy task 'clone_service_for_transferred_procedures'"
procedures = Procedure.includes(:service).where.not(service_id: nil)
procedures_to_fix_in_array = procedures.select do |p|
p.administrateur_id != p.service.administrateur_id
end
procedures_to_fix = Procedure.where(id: procedures_to_fix_in_array.map(&:id))
service_and_admin_list = procedures_to_fix.group(:service_id, :administrateur_id).count.keys
progress = ProgressReport.new(service_and_admin_list.count)
service_and_admin_list.each do |service_id, administrateur_id|
cloned_service = Service.find(service_id).clone_and_assign_to_administrateur(Administrateur.find(administrateur_id))
if cloned_service.save
puts "Fixing Service #{service_id} for Administrateur #{administrateur_id}"
procedures_to_fix
.where(service_id: service_id, administrateur_id: administrateur_id)
.update_all(service_id: cloned_service.id)
else
puts "Cannot fix Service #{service_id} for Administrateur #{administrateur_id}, it should be fixed manually. Errors : #{cloned_service.errors.full_messages}"
end
progress.inc
end
progress.finish
# Update task as completed. If you remove the line below, the task will
# run with every deploy (or every time you call after_party:run).
AfterParty::TaskRecord.create version: '20181219164523'
end # task :clone_service_for_transferred_procedures
end # namespace :after_party

View file

@ -0,0 +1,17 @@
namespace :after_party do
desc 'Deployment task: migrate_types_de_champ_options_to_json'
task migrate_types_de_champ_options_to_json: :environment do
puts "Running deploy task 'migrate_types_de_champ_options_to_json'"
dirty_tdcs = TypeDeChamp.where.not(options: nil)
progress = ProgressReport.new(dirty_tdcs.count)
dirty_tdcs.find_each do |tdc|
tdc.options_will_change!
tdc.save
progress.inc
end
progress.finish
AfterParty::TaskRecord.create version: '20181219175043'
end
end

View file

@ -580,7 +580,7 @@ describe Admin::ProceduresController, type: :controller do
end end
describe 'POST #transfer' do describe 'POST #transfer' do
let!(:procedure) { create :procedure, administrateur: admin } let!(:procedure) { create :procedure, :with_service, administrateur: admin }
subject { post :transfer, params: { email_admin: email_admin, procedure_id: procedure.id } } subject { post :transfer, params: { email_admin: email_admin, procedure_id: procedure.id } }
@ -597,7 +597,12 @@ describe Admin::ProceduresController, type: :controller do
let(:email_admin) { 'new_admin@admin.com' } let(:email_admin) { 'new_admin@admin.com' }
it { expect(subject.status).to eq 200 } it { expect(subject.status).to eq 200 }
it { expect { subject }.to change(Procedure, :count).by(1) } it { expect { subject }.to change(new_admin.procedures, :count).by(1) }
it "should create a new service" do
subject
expect(new_admin.procedures.last.service_id).not_to eq(procedure.service_id)
end
end end
context 'when admin is know but its email was not downcased' do context 'when admin is know but its email was not downcased' do

View file

@ -17,7 +17,7 @@ describe Users::SessionsController, type: :controller do
user.reload user.reload
end end
subject { user.loged_in_with_france_connect? } subject { user.loged_in_with_france_connect.present? }
it { is_expected.to be_falsey } it { is_expected.to be_falsey }
end end
@ -141,7 +141,7 @@ describe Users::SessionsController, type: :controller do
it 'loged_in_with_france_connect current_user attribut is nil' do it 'loged_in_with_france_connect current_user attribut is nil' do
user.reload user.reload
expect(user.loged_in_with_france_connect?).to be_falsey expect(user.loged_in_with_france_connect.present?).to be_falsey
end end
context 'when user is connect with france connect particulier' do context 'when user is connect with france connect particulier' do

View file

@ -62,36 +62,4 @@ describe ChampDecorator do
end end
end end
end end
describe '#date_for_input' do
subject { decorator.date_for_input }
describe "for a date" do
let(:type_de_champ) { create(:type_de_champ_date) }
context "when value is an ISO date" do
before { champ.update value: "2017-12-31" }
it { is_expected.to eq "2017-12-31" }
end
context "when value is empty" do
before { champ.update value: nil }
it { is_expected.to eq nil }
end
end
describe "for a datetime" do
let(:type_de_champ) { create(:type_de_champ_date) }
context "when value is an formatted datetime" do
before { champ.update value: "2017-12-30 23:17" }
it { is_expected.to eq "2017-12-30" }
end
context "when value is empty" do
before { champ.update value: nil }
it { is_expected.to eq nil }
end
end
end
end end

View file

@ -165,4 +165,8 @@ FactoryBot.define do
champ.etablissement.signature = champ.etablissement.sign champ.etablissement.signature = champ.etablissement.sign
end end
end end
factory :champ_repetition, class: 'Champs::RepetitionChamp' do
type_de_champ { create(:type_de_champ_repetition) }
end
end end

View file

@ -93,6 +93,9 @@ FactoryBot.define do
factory :type_de_champ_carte do factory :type_de_champ_carte do
type_champ { TypeDeChamp.type_champs.fetch(:carte) } type_champ { TypeDeChamp.type_champs.fetch(:carte) }
end end
factory :type_de_champ_repetition do
type_champ { TypeDeChamp.type_champs.fetch(:repetition) }
end
trait :private do trait :private do
private { true } private { true }

View file

@ -17,18 +17,4 @@ describe ApplicationHelper do
it { is_expected.to be_nil } it { is_expected.to be_nil }
end end
end end
describe "#ensure_safe_json" do
subject { ensure_safe_json(json) }
context "with a dirty json" do
let(:json) { "alert('haha');" }
it { is_expected.to eq({}) }
end
context 'with a correct json' do
let(:json) { '[[{"lat": 2.0, "lng": 102.0}, {"lat": 3.0, "lng": 103.0}, {"lat": 2.0, "lng": 102.0}], [{"lat": 2.0, "lng": 102.0}, {"lat": 3.0, "lng": 103.0}, {"lat": 2.0, "lng": 102.0}]]' }
it { is_expected.to eq("[[{\"lat\":2.0,\"lng\":102.0},{\"lat\":3.0,\"lng\":103.0},{\"lat\":2.0,\"lng\":102.0}],[{\"lat\":2.0,\"lng\":102.0},{\"lat\":3.0,\"lng\":103.0},{\"lat\":2.0,\"lng\":102.0}]]") }
end
end
end end

View file

@ -0,0 +1,32 @@
describe '20181219164523_clone_service_for_transferred_procedures.rake' do
let(:rake_task) { Rake::Task['after_party:clone_service_for_transferred_procedures'] }
subject do
rake_task.invoke
end
after do
rake_task.reenable
end
context 'procedures from different admins share the same service' do
let(:admin1) { create(:administrateur) }
let(:admin2) { create(:administrateur) }
let(:service) { create(:service, administrateur: admin1) }
let!(:procedure1) { create(:procedure, service: service, administrateur: admin1) }
let!(:procedure2) { create(:procedure, service: service, administrateur: admin2) }
let!(:procedure3) { create(:procedure, service: service, administrateur: admin2) }
it 'clones service for procedure2 & procedure3' do
subject
expect(procedure1.reload.service).not_to eq(procedure2.reload.service)
expect(procedure1.reload.service).not_to eq(procedure3.reload.service)
expect(procedure2.reload.service).to eq(procedure3.reload.service)
end
it 'does nothing for procedure1' do
subject
expect(procedure1.reload.service).to eq(service)
end
end
end

View file

@ -23,7 +23,7 @@ RSpec.describe NotificationMailer, type: :mailer do
# Were testing the (private) method `NotificationMailer#send_notification`. # Were testing the (private) method `NotificationMailer#send_notification`.
# #
# The standard trick to test a private method would be to `send(:send_notification)`, but doesnt work here, # The standard trick to test a private method would be to `send(:send_notification)`, but doesnt work here,
# because ActionMailer does some magic to expose public instace methods as class methods. # because ActionMailer does some magic to expose public instance methods as class methods.
# So, we use inheritance instead to make the private method public for testing purposes. # So, we use inheritance instead to make the private method public for testing purposes.
def send_notification(dossier, template) def send_notification(dossier, template)
super super
@ -34,7 +34,7 @@ RSpec.describe NotificationMailer, type: :mailer do
it { expect(mail.subject).to eq(email_template.subject_for_dossier) } it { expect(mail.subject).to eq(email_template.subject_for_dossier) }
it { expect(mail.body).to include(email_template.body_for_dossier) } it { expect(mail.body).to include(email_template.body_for_dossier) }
it { expect(mail.body).to have_selector('footer') } it { expect(mail.body).to have_link('messagerie') }
it_behaves_like "create a commentaire not notified" it_behaves_like "create a commentaire not notified"
end end
@ -50,7 +50,7 @@ RSpec.describe NotificationMailer, type: :mailer do
it do it do
expect(mail.subject).to eq(email_template.subject) expect(mail.subject).to eq(email_template.subject)
expect(mail.body).to include(email_template.body) expect(mail.body).to include(email_template.body)
expect(mail.body).to have_selector('footer') expect(mail.body).to have_link('messagerie')
end end
it_behaves_like "create a commentaire not notified" it_behaves_like "create a commentaire not notified"

View file

@ -0,0 +1,33 @@
class InviteMailerPreview < ActionMailer::Preview
def invite_user
InviteMailer.invite_user(invite)
end
def invite_guest
InviteMailer.invite_guest(invite)
end
private
def invite
Invite.new(
id: 10,
dossier: dossier,
user: invited_user,
email: invited_user.email,
email_sender: 'sender@gouv.fr'
)
end
def dossier
Dossier.new(procedure: procedure)
end
def procedure
Procedure.new(libelle: 'Permis de construire en zone inondable')
end
def invited_user
User.new(email: 'Invité@gouv.fr')
end
end

View file

@ -399,4 +399,30 @@ describe Champ do
it { expect{ champ.save }.to_not change(VirusScan, :count) } it { expect{ champ.save }.to_not change(VirusScan, :count) }
end end
end end
describe "repetition" do
let(:champ) { create(:champ_repetition) }
let(:champ_text) { create(:champ_text, row: 0) }
let(:champ_integer_number) { create(:champ_integer_number, row: 0) }
let(:champ_text2) { create(:champ_text, row: 1) }
it {
expect(champ.rows.size).to eq(0)
champ.champs << champ_text2
expect(champ.rows.size).to eq(1)
champ.champs << champ_integer_number
row = champ.reload.rows.first
expect(row.size).to eq(1)
expect(row.first).to eq(champ_integer_number)
champ.champs << champ_text
row = champ.reload.rows.first
expect(row.size).to eq(2)
expect(row.second).to eq(champ_text)
expect(champ.rows.size).to eq(2)
}
end
end end

View file

@ -235,29 +235,6 @@ describe Dossier do
it { expect(dossier.champs_private.pluck(:libelle)).to match(['l1', 'l2', 'l3']) } it { expect(dossier.champs_private.pluck(:libelle)).to match(['l1', 'l2', 'l3']) }
end end
describe '#total_follow' do
let(:dossier) { create(:dossier, :with_entreprise, user: user) }
let(:dossier2) { create(:dossier, :with_entreprise, user: user) }
subject { dossier.total_follow }
context 'when no body follow dossier' do
it { expect(subject).to eq 0 }
end
context 'when 2 people follow dossier' do
before do
create :follow, dossier_id: dossier.id, gestionnaire_id: (create :gestionnaire).id
create :follow, dossier_id: dossier.id, gestionnaire_id: (create :gestionnaire).id
create :follow, dossier_id: dossier2.id, gestionnaire_id: (create :gestionnaire).id
create :follow, dossier_id: dossier2.id, gestionnaire_id: (create :gestionnaire).id
end
it { expect(subject).to eq 2 }
end
end
describe "#text_summary" do describe "#text_summary" do
let(:procedure) { create(:procedure, libelle: "Démarche", organisation: "Organisme") } let(:procedure) { create(:procedure, libelle: "Démarche", organisation: "Organisme") }

View file

@ -199,29 +199,6 @@ describe Gestionnaire, type: :model do
end end
end end
describe '#can_view_dossier?' do
subject{ gestionnaire.can_view_dossier?(dossier.id) }
context 'when gestionnaire is assigned on dossier' do
let!(:dossier){ create(:dossier, procedure: procedure, state: Dossier.states.fetch(:en_instruction)) }
it { expect(subject).to be true }
end
context 'when gestionnaire is invited on dossier' do
let(:dossier){ create(:dossier) }
let!(:avis){ create(:avis, dossier: dossier, gestionnaire: gestionnaire) }
it { expect(subject).to be true }
end
context 'when gestionnaire is neither assigned nor invited on dossier' do
let(:dossier){ create(:dossier) }
it { expect(subject).to be false }
end
end
describe "procedure_presentation_and_errors_for_procedure_id" do describe "procedure_presentation_and_errors_for_procedure_id" do
let(:procedure_presentation_and_errors) { gestionnaire.procedure_presentation_and_errors_for_procedure_id(procedure_id) } let(:procedure_presentation_and_errors) { gestionnaire.procedure_presentation_and_errors_for_procedure_id(procedure_id) }
let(:procedure_presentation) { procedure_presentation_and_errors.first } let(:procedure_presentation) { procedure_presentation_and_errors.first }

View file

@ -252,11 +252,11 @@ describe Procedure do
end end
end end
describe '#types_de_champ_ordered' do describe '#types_de_champ (ordered)' do
let(:procedure) { create(:procedure) } let(:procedure) { create(:procedure) }
let!(:type_de_champ_0) { create(:type_de_champ, procedure: procedure, order_place: 1) } let!(:type_de_champ_0) { create(:type_de_champ, procedure: procedure, order_place: 1) }
let!(:type_de_champ_1) { create(:type_de_champ, procedure: procedure, order_place: 0) } let!(:type_de_champ_1) { create(:type_de_champ, procedure: procedure, order_place: 0) }
subject { procedure.types_de_champ_ordered } subject { procedure.types_de_champ }
it { expect(subject.first).to eq(type_de_champ_1) } it { expect(subject.first).to eq(type_de_champ_1) }
it { expect(subject.last).to eq(type_de_champ_0) } it { expect(subject.last).to eq(type_de_champ_0) }
end end
@ -335,14 +335,15 @@ describe Procedure do
let!(:type_de_champ_private_2) { create(:type_de_champ_drop_down_list, :private, procedure: procedure, order_place: 2) } let!(:type_de_champ_private_2) { create(:type_de_champ_drop_down_list, :private, procedure: procedure, order_place: 2) }
let!(:piece_justificative_0) { create(:type_de_piece_justificative, procedure: procedure, order_place: 0) } let!(:piece_justificative_0) { create(:type_de_piece_justificative, procedure: procedure, order_place: 0) }
let!(:piece_justificative_1) { create(:type_de_piece_justificative, procedure: procedure, order_place: 1) } let!(:piece_justificative_1) { create(:type_de_piece_justificative, procedure: procedure, order_place: 1) }
let(:received_mail){ create(:received_mail) } let(:received_mail) { create(:received_mail) }
let(:from_library) { false } let(:from_library) { false }
let(:administrateur) { procedure.administrateur }
before do before do
@logo = File.open('spec/fixtures/files/white.png') @logo = File.open('spec/fixtures/files/white.png')
@signature = File.open('spec/fixtures/files/black.png') @signature = File.open('spec/fixtures/files/black.png')
@attestation_template = create(:attestation_template, procedure: procedure, logo: @logo, signature: @signature) @attestation_template = create(:attestation_template, procedure: procedure, logo: @logo, signature: @signature)
@procedure = procedure.clone(procedure.administrateur, from_library) @procedure = procedure.clone(administrateur, from_library)
@procedure.save @procedure.save
end end
@ -389,12 +390,26 @@ describe Procedure do
let(:from_library) { true } let(:from_library) { true }
it { expect(subject.cloned_from_library).to be(true) } it { expect(subject.cloned_from_library).to be(true) }
it 'should set service_id to nil' do
expect(subject.service).to eq(nil)
end
end end
it 'should keep service_id' do it 'should keep service_id' do
expect(subject.service).to eq(service) expect(subject.service).to eq(service)
end end
context 'when the procedure is cloned to another administrateur' do
let(:administrateur) { create(:administrateur) }
it 'should clone service' do
expect(subject.service.id).not_to eq(service.id)
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
end
it 'should duplicate existing mail_templates' do it 'should duplicate existing mail_templates' do
expect(subject.received_mail.attributes.except("id", "procedure_id", "created_at", "updated_at")).to eq procedure.received_mail.attributes.except("id", "procedure_id", "created_at", "updated_at") expect(subject.received_mail.attributes.except("id", "procedure_id", "created_at", "updated_at")).to eq procedure.received_mail.attributes.except("id", "procedure_id", "created_at", "updated_at")
expect(subject.received_mail.id).not_to eq procedure.received_mail.id expect(subject.received_mail.id).not_to eq procedure.received_mail.id
@ -432,8 +447,8 @@ describe Procedure do
end end
it 'should keep types_de_champ ids stable' do it 'should keep types_de_champ ids stable' do
expect(subject.types_de_champ_ordered.first.id).not_to eq(procedure.types_de_champ_ordered.first.id) expect(subject.types_de_champ.first.id).not_to eq(procedure.types_de_champ.first.id)
expect(subject.types_de_champ_ordered.first.stable_id).to eq(procedure.types_de_champ_ordered.first.id) expect(subject.types_de_champ.first.stable_id).to eq(procedure.types_de_champ.first.id)
end end
end end

View file

@ -110,4 +110,20 @@ shared_examples 'type_de_champ_spec' do
end end
end end
end end
describe "repetition" do
let(:type_de_champ) { create(:type_de_champ_repetition) }
let(:type_de_champ_text) { create(:type_de_champ_text) }
let(:type_de_champ_integer_number) { create(:type_de_champ_integer_number) }
it {
expect(type_de_champ.types_de_champ.size).to eq(0)
type_de_champ.types_de_champ << type_de_champ_integer_number
expect(type_de_champ.types_de_champ.size).to eq(1)
type_de_champ.types_de_champ << type_de_champ_text
expect(type_de_champ.types_de_champ.size).to eq(2)
expect(type_de_champ_integer_number.parent).to eq(type_de_champ)
expect(type_de_champ_text.parent).to eq(type_de_champ)
}
end
end end

View file

@ -20,36 +20,6 @@ describe User, type: :model do
end end
end end
describe '#find_for_france_connect' do
let(:siret) { '00000000000000' }
context 'when user exist' do
let!(:user) { create(:user) }
subject { described_class.find_for_france_connect(user.email, siret) }
it 'retrieves user' do
expect(subject).to eq(user)
end
it 'saves siret in user' do
expect(subject.siret).to eq(siret)
end
it 'does not create new user' do
expect { subject }.not_to change(User, :count)
end
end
context 'when user does not exist' do
let(:email) { 'super-m@n.com' }
subject { described_class.find_for_france_connect(email, siret) }
it 'returns user' do
expect(subject).to be_an_instance_of(User)
end
it 'creates new user' do
expect { subject }.to change(User, :count).by(1)
end
it 'saves siret' do
expect(subject.siret).to eq(siret)
end
end
end
describe '#owns?' do describe '#owns?' do
let(:owner) { create(:user) } let(:owner) { create(:user) }
let(:dossier) { create(:dossier, user: owner) } let(:dossier) { create(:dossier, user: owner) }

View file

@ -1,40 +0,0 @@
require 'spec_helper'
describe ChampsService do
let(:type_de_champ) { create(:type_de_champ) }
let(:type_de_champ_mandatory) { create(:type_de_champ, libelle: 'mandatory', mandatory: true) }
let(:type_de_champ_datetime) { create(:type_de_champ_datetime) }
let!(:champ) { type_de_champ.champ.create(value: 'toto') }
let!(:champ_mandatory_empty) { type_de_champ_mandatory.champ.create }
let!(:champ_datetime) { type_de_champ_datetime.champ.create }
let!(:champs) { [champ, champ_mandatory_empty, champ_datetime] }
describe 'save_champs' do
before :each do
params_hash = {
champs: {
"'#{champ.id}'" => 'yop',
"'#{champ_datetime.id}'" => 'd'
},
time_hour: { "'#{champ_datetime.id}'" => '12' },
time_minute: { "'#{champ_datetime.id}'" => '24' }
}
ChampsService.save_champs(champs, params_hash)
champs.each(&:reload)
end
it 'saves the changed champ' do
expect(champ.value).to eq('yop')
end
it 'parses and save the date' do
expect(champ_datetime.value).to eq(nil)
end
end
describe 'build_error_message' do
it 'adds error for the missing mandatory champ' do
expect(ChampsService.build_error_messages(champs)).to match(['Le champ mandatory doit être rempli.'])
end
end
end

View file

@ -11,10 +11,11 @@ describe ProcedureExportService do
before do before do
# change one tdc place to check if the header is ordered # change one tdc place to check if the header is ordered
tdc_first = procedure.types_de_champ.ordered.first tdc_first = procedure.types_de_champ.first
tdc_last = procedure.types_de_champ.ordered.last tdc_last = procedure.types_de_champ.last
tdc_first.update(order_place: tdc_last.order_place + 1) tdc_first.update(order_place: tdc_last.order_place + 1)
procedure.reload
end end
context 'dossiers' do context 'dossiers' do
@ -55,8 +56,6 @@ describe ProcedureExportService do
:regions, :regions,
:departements, :departements,
:engagement, :engagement,
:header_section,
:explication,
:dossier_link, :dossier_link,
:piece_justificative, :piece_justificative,
:siret, :siret,
@ -123,7 +122,7 @@ describe ProcedureExportService do
} }
let(:champs_data) { let(:champs_data) {
dossier.champs.ordered.map(&:for_export) dossier.reload.champs.reject(&:exclude_from_export?).map(&:for_export)
} }
let(:etablissement_data) { let(:etablissement_data) {
@ -132,8 +131,8 @@ describe ProcedureExportService do
it 'should have values' do it 'should have values' do
expect(data.first[0..14]).to eq(dossier_data) expect(data.first[0..14]).to eq(dossier_data)
expect(data.first[15..40]).to eq(champs_data) expect(data.first[15..38]).to eq(champs_data)
expect(data.first[41..64]).to eq(etablissement_data) expect(data.first[39..62]).to eq(etablissement_data)
expect(data).to eq([ expect(data).to eq([
dossier_data + champs_data + etablissement_data dossier_data + champs_data + etablissement_data
@ -178,8 +177,8 @@ describe ProcedureExportService do
it 'should have values' do it 'should have values' do
expect(data.first[0..14]).to eq(dossier_data) expect(data.first[0..14]).to eq(dossier_data)
expect(data.first[15..40]).to eq(champs_data) expect(data.first[15..38]).to eq(champs_data)
expect(data.first[41..64]).to eq(etablissement_data) expect(data.first[39..62]).to eq(etablissement_data)
expect(data).to eq([ expect(data).to eq([
dossier_data + champs_data + etablissement_data dossier_data + champs_data + etablissement_data