commit
f13eed9123
39 changed files with 294 additions and 124 deletions
|
@ -139,7 +139,7 @@ GEM
|
||||||
carrierwave-i18n (0.2.0)
|
carrierwave-i18n (0.2.0)
|
||||||
case_transform (0.2)
|
case_transform (0.2)
|
||||||
activesupport
|
activesupport
|
||||||
chartkick (3.0.2)
|
chartkick (3.2.0)
|
||||||
childprocess (0.9.0)
|
childprocess (0.9.0)
|
||||||
ffi (~> 1.0, >= 1.0.11)
|
ffi (~> 1.0, >= 1.0.11)
|
||||||
chunky_png (1.3.11)
|
chunky_png (1.3.11)
|
||||||
|
|
|
@ -37,6 +37,8 @@ module Gestionnaires
|
||||||
|
|
||||||
def personnes_impliquees
|
def personnes_impliquees
|
||||||
@following_instructeurs_emails = dossier.followers_gestionnaires.pluck(:email)
|
@following_instructeurs_emails = dossier.followers_gestionnaires.pluck(:email)
|
||||||
|
previous_followers = dossier.previous_followers_gestionnaires - dossier.followers_gestionnaires
|
||||||
|
@previous_following_instructeurs_emails = previous_followers.pluck(:email)
|
||||||
@avis_emails = dossier.avis.includes(:gestionnaire).map(&:email_to_display)
|
@avis_emails = dossier.avis.includes(:gestionnaire).map(&:email_to_display)
|
||||||
@invites_emails = dossier.invites.map(&:email)
|
@invites_emails = dossier.invites.map(&:email)
|
||||||
@potential_recipients = procedure.gestionnaires.reject { |g| g == current_gestionnaire }
|
@potential_recipients = procedure.gestionnaires.reject { |g| g == current_gestionnaire }
|
||||||
|
|
|
@ -112,4 +112,12 @@ module ApplicationHelper
|
||||||
root_path
|
root_path
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def try_format_date(date)
|
||||||
|
date.present? ? I18n.l(date) : ''
|
||||||
|
end
|
||||||
|
|
||||||
|
def try_format_datetime(datetime)
|
||||||
|
datetime.present? ? I18n.l(datetime) : ''
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -34,7 +34,7 @@ class ApiEntreprise::API
|
||||||
|
|
||||||
if response.success?
|
if response.success?
|
||||||
JSON.parse(response.body, symbolize_names: true)
|
JSON.parse(response.body, symbolize_names: true)
|
||||||
elsif response.code == 404 || response.code == 422
|
elsif response.code&.between?(401, 499)
|
||||||
raise RestClient::ResourceNotFound
|
raise RestClient::ResourceNotFound
|
||||||
else
|
else
|
||||||
raise RestClient::RequestFailed
|
raise RestClient::RequestFailed
|
||||||
|
|
|
@ -6,7 +6,7 @@ class Champs::DateChamp < Champ
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
value.present? ? Date.parse(value).strftime('%d/%m/%Y') : ""
|
value.present? ? I18n.l(Date.parse(value)) : ""
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -5,6 +5,10 @@ class Champs::DatetimeChamp < Champ
|
||||||
# Text search is pretty useless for datetimes so we’re not including these champs
|
# Text search is pretty useless for datetimes so we’re not including these champs
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
value.present? ? I18n.l(Time.zone.parse(value)) : ""
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def format_before_save
|
def format_before_save
|
||||||
|
|
|
@ -26,8 +26,10 @@ class Dossier < ApplicationRecord
|
||||||
has_many :champs_private, -> { root.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, -> { active }
|
||||||
|
has_many :previous_follows, -> { inactive }, class_name: 'Follow'
|
||||||
has_many :followers_gestionnaires, through: :follows, source: :gestionnaire
|
has_many :followers_gestionnaires, through: :follows, source: :gestionnaire
|
||||||
|
has_many :previous_followers_gestionnaires, -> { distinct }, through: :previous_follows, source: :gestionnaire
|
||||||
has_many :avis, dependent: :destroy
|
has_many :avis, dependent: :destroy
|
||||||
|
|
||||||
has_many :dossier_operation_logs, dependent: :destroy
|
has_many :dossier_operation_logs, dependent: :destroy
|
||||||
|
|
|
@ -2,10 +2,13 @@ class Follow < ApplicationRecord
|
||||||
belongs_to :gestionnaire
|
belongs_to :gestionnaire
|
||||||
belongs_to :dossier
|
belongs_to :dossier
|
||||||
|
|
||||||
validates :gestionnaire_id, uniqueness: { scope: :dossier_id }
|
validates :gestionnaire_id, uniqueness: { scope: [:dossier_id, :unfollowed_at] }
|
||||||
|
|
||||||
before_create :set_default_date
|
before_create :set_default_date
|
||||||
|
|
||||||
|
scope :active, -> { where(unfollowed_at: nil) }
|
||||||
|
scope :inactive, -> { where.not(unfollowed_at: nil) }
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_default_date
|
def set_default_date
|
||||||
|
|
|
@ -16,8 +16,10 @@ class Gestionnaire < ApplicationRecord
|
||||||
has_many :procedures_with_email_notifications, through: :assign_to_with_email_notifications, source: :procedure
|
has_many :procedures_with_email_notifications, through: :assign_to_with_email_notifications, source: :procedure
|
||||||
|
|
||||||
has_many :dossiers, -> { state_not_brouillon }, through: :procedures
|
has_many :dossiers, -> { state_not_brouillon }, through: :procedures
|
||||||
has_many :follows
|
has_many :follows, -> { active }
|
||||||
|
has_many :previous_follows, -> { inactive }, class_name: 'Follow'
|
||||||
has_many :followed_dossiers, through: :follows, source: :dossier
|
has_many :followed_dossiers, through: :follows, source: :dossier
|
||||||
|
has_many :previously_followed_dossiers, -> { distinct }, through: :previous_follows, source: :dossier
|
||||||
has_many :avis
|
has_many :avis
|
||||||
has_many :dossiers_from_avis, through: :avis, source: :dossier
|
has_many :dossiers_from_avis, through: :avis, source: :dossier
|
||||||
has_many :trusted_device_tokens
|
has_many :trusted_device_tokens
|
||||||
|
@ -27,26 +29,23 @@ class Gestionnaire < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def follow(dossier)
|
def follow(dossier)
|
||||||
if follow?(dossier)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
followed_dossiers << dossier
|
followed_dossiers << dossier
|
||||||
|
# If the user tries to follow a dossier she already follows,
|
||||||
|
# we just fail silently: it means the goal is already reached.
|
||||||
rescue ActiveRecord::RecordNotUnique
|
rescue ActiveRecord::RecordNotUnique
|
||||||
# Altough we checked before the insertion that the gestionnaire wasn't
|
# Database uniqueness constraint
|
||||||
# already following this dossier, this was done at the Rails level:
|
rescue ActiveRecord::RecordInvalid => e
|
||||||
# at the database level, the dossier was already followed, and a
|
# ActiveRecord validation
|
||||||
# "invalid constraint" exception is raised.
|
raise unless e.record.errors.details.dig(:gestionnaire_id, 0, :error) == :taken
|
||||||
#
|
|
||||||
# We can ignore this safely, as it means the goal is already reached:
|
|
||||||
# the gestionnaire follows the dossier.
|
|
||||||
return
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def unfollow(dossier)
|
def unfollow(dossier)
|
||||||
followed_dossiers.delete(dossier)
|
f = follows.find_by(dossier: dossier)
|
||||||
|
if f.present?
|
||||||
|
f.update(unfollowed_at: Time.zone.now)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def follow?(dossier)
|
def follow?(dossier)
|
||||||
|
@ -94,23 +93,17 @@ class Gestionnaire < ApplicationRecord
|
||||||
.find_by(gestionnaire: self, dossier: dossier)
|
.find_by(gestionnaire: self, dossier: dossier)
|
||||||
|
|
||||||
if follow.present?
|
if follow.present?
|
||||||
# retirer le seen_at.present? une fois la contrainte de presence en base (et les migrations ad hoc)
|
champs_publiques = follow.dossier.champs.updated_since?(follow.demande_seen_at).any?
|
||||||
champs_publiques = follow.demande_seen_at.present? &&
|
|
||||||
follow.dossier.champs.updated_since?(follow.demande_seen_at).any?
|
|
||||||
|
|
||||||
pieces_justificatives = follow.demande_seen_at.present? &&
|
pieces_justificatives = follow.dossier.pieces_justificatives.updated_since?(follow.demande_seen_at).any?
|
||||||
follow.dossier.pieces_justificatives.updated_since?(follow.demande_seen_at).any?
|
|
||||||
|
|
||||||
demande = champs_publiques || pieces_justificatives
|
demande = champs_publiques || pieces_justificatives
|
||||||
|
|
||||||
annotations_privees = follow.annotations_privees_seen_at.present? &&
|
annotations_privees = follow.dossier.champs_private.updated_since?(follow.annotations_privees_seen_at).any?
|
||||||
follow.dossier.champs_private.updated_since?(follow.annotations_privees_seen_at).any?
|
|
||||||
|
|
||||||
avis_notif = follow.avis_seen_at.present? &&
|
avis_notif = follow.dossier.avis.updated_since?(follow.avis_seen_at).any?
|
||||||
follow.dossier.avis.updated_since?(follow.avis_seen_at).any?
|
|
||||||
|
|
||||||
messagerie = follow.messagerie_seen_at.present? &&
|
messagerie = dossier.commentaires
|
||||||
dossier.commentaires
|
|
||||||
.where.not(email: OLD_CONTACT_EMAIL)
|
.where.not(email: OLD_CONTACT_EMAIL)
|
||||||
.where.not(email: CONTACT_EMAIL)
|
.where.not(email: CONTACT_EMAIL)
|
||||||
.updated_since?(follow.messagerie_seen_at).any?
|
.updated_since?(follow.messagerie_seen_at).any?
|
||||||
|
|
|
@ -25,9 +25,16 @@ class PieceJustificativeToChampPieceJointeMigrationService
|
||||||
populate_champs_pjs!(procedure, types_de_champ_pj, &progress)
|
populate_champs_pjs!(procedure, types_de_champ_pj, &progress)
|
||||||
|
|
||||||
# Only destroy the old types PJ once everything has been safely migrated to
|
# Only destroy the old types PJ once everything has been safely migrated to
|
||||||
# champs PJs. Destroying the types PJ will cascade and destroy the PJs,
|
# champs PJs.
|
||||||
# and delete the linked objects from remote storage. This means that no other
|
|
||||||
# cleanup action is required.
|
# First destroy the individual PJ champs on all dossiers.
|
||||||
|
# It will cascade and destroy the PJs, and delete the linked objects from remote storage.
|
||||||
|
procedure.dossiers.unscope(where: :hidden_at).includes(:champs).find_each do |dossier|
|
||||||
|
destroy_pieces_justificatives(dossier)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Now we can destroy the type de champ themselves,
|
||||||
|
# without cascading the timestamp update on all attached dossiers.
|
||||||
procedure.types_de_piece_justificative.destroy_all
|
procedure.types_de_piece_justificative.destroy_all
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -40,32 +47,7 @@ class PieceJustificativeToChampPieceJointeMigrationService
|
||||||
|
|
||||||
# Unscope to make sure all dossiers are migrated, even the soft-deleted ones
|
# Unscope to make sure all dossiers are migrated, even the soft-deleted ones
|
||||||
procedure.dossiers.unscope(where: :hidden_at).includes(:champs).find_each do |dossier|
|
procedure.dossiers.unscope(where: :hidden_at).includes(:champs).find_each do |dossier|
|
||||||
# Add the new pieces justificatives champs to the dossier
|
migrate_dossier!(dossier, types_de_champ_pj, &progress)
|
||||||
champs_pj = types_de_champ_pj.map(&:build_champ)
|
|
||||||
dossier.champs += champs_pj
|
|
||||||
|
|
||||||
# Copy the dossier old pieces jointes to the new champs
|
|
||||||
# (even if the champs already existed, so that we ensure a clean state)
|
|
||||||
champs_pj.each do |champ|
|
|
||||||
type_pj_id = champ.type_de_champ.old_pj&.fetch('stable_id', nil)
|
|
||||||
pj = dossier.retrieve_last_piece_justificative_by_type(type_pj_id)
|
|
||||||
|
|
||||||
if pj.present?
|
|
||||||
convert_pj_to_champ!(pj, champ)
|
|
||||||
|
|
||||||
champ.update(
|
|
||||||
updated_at: pj.updated_at,
|
|
||||||
created_at: pj.created_at
|
|
||||||
)
|
|
||||||
else
|
|
||||||
champ.update(
|
|
||||||
updated_at: dossier.updated_at,
|
|
||||||
created_at: dossier.created_at
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
yield if block_given?
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
rescue StandardError, SignalException
|
rescue StandardError, SignalException
|
||||||
|
@ -74,8 +56,11 @@ class PieceJustificativeToChampPieceJointeMigrationService
|
||||||
rake_puts "Error received. Rolling back migration of procedure #{procedure.id}…"
|
rake_puts "Error received. Rolling back migration of procedure #{procedure.id}…"
|
||||||
|
|
||||||
types_de_champ_pj.each do |type_champ|
|
types_de_champ_pj.each do |type_champ|
|
||||||
type_champ.champ.each { |c| c.piece_justificative_file.purge }
|
# First destroy all the individual champs on dossiers
|
||||||
type_champ.destroy
|
type_champ.champ.each { |c| destroy_champ_pj(c.dossier.reload, c) }
|
||||||
|
# Now we can destroy the type de champ itself,
|
||||||
|
# without cascading the timestamp update on all attached dossiers.
|
||||||
|
type_champ.reload.destroy
|
||||||
end
|
end
|
||||||
|
|
||||||
rake_puts "Migration of procedure #{procedure.id} rolled back."
|
rake_puts "Migration of procedure #{procedure.id} rolled back."
|
||||||
|
@ -84,6 +69,39 @@ class PieceJustificativeToChampPieceJointeMigrationService
|
||||||
raise
|
raise
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def migrate_dossier!(dossier, types_de_champ_pj)
|
||||||
|
# Add the new pieces justificatives champs to the dossier
|
||||||
|
champs_pj = types_de_champ_pj.map(&:build_champ)
|
||||||
|
preserving_updated_at(dossier) do
|
||||||
|
dossier.champs += champs_pj
|
||||||
|
end
|
||||||
|
|
||||||
|
# Copy the dossier old pieces jointes to the new champs
|
||||||
|
# (even if the champs already existed, so that we ensure a clean state)
|
||||||
|
champs_pj.each do |champ|
|
||||||
|
type_pj_id = champ.type_de_champ.old_pj&.fetch('stable_id', nil)
|
||||||
|
pj = dossier.retrieve_last_piece_justificative_by_type(type_pj_id)
|
||||||
|
|
||||||
|
if pj.present?
|
||||||
|
preserving_updated_at(dossier) do
|
||||||
|
convert_pj_to_champ!(pj, champ)
|
||||||
|
end
|
||||||
|
|
||||||
|
champ.update_columns(
|
||||||
|
updated_at: pj.updated_at,
|
||||||
|
created_at: pj.created_at
|
||||||
|
)
|
||||||
|
else
|
||||||
|
champ.update_columns(
|
||||||
|
updated_at: dossier.updated_at,
|
||||||
|
created_at: dossier.created_at
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
yield if block_given?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def convert_pj_to_champ!(pj, champ)
|
def convert_pj_to_champ!(pj, champ)
|
||||||
actual_file_exists = pj.content.file.send(:file)
|
actual_file_exists = pj.content.file.send(:file)
|
||||||
if actual_file_exists
|
if actual_file_exists
|
||||||
|
@ -133,4 +151,26 @@ class PieceJustificativeToChampPieceJointeMigrationService
|
||||||
def make_empty_blob(pj)
|
def make_empty_blob(pj)
|
||||||
storage_service.make_empty_blob(pj.content, pj.updated_at.iso8601, filename: pj.original_filename)
|
storage_service.make_empty_blob(pj.content, pj.updated_at.iso8601, filename: pj.original_filename)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def preserving_updated_at(model)
|
||||||
|
original_modification_date = model.updated_at
|
||||||
|
begin
|
||||||
|
yield
|
||||||
|
ensure
|
||||||
|
model.update_column(:updated_at, original_modification_date)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy_pieces_justificatives(dossier)
|
||||||
|
preserving_updated_at(dossier) do
|
||||||
|
dossier.pieces_justificatives.destroy_all
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy_champ_pj(dossier, champ)
|
||||||
|
preserving_updated_at(dossier) do
|
||||||
|
champ.piece_justificative_file.purge
|
||||||
|
champ.destroy
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
- if procedure.publiee?
|
- if procedure.publiee?
|
||||||
%td.procedure-lien= link_to(procedure_lien(procedure), procedure_lien(procedure))
|
%td.procedure-lien= link_to(procedure_lien(procedure), procedure_lien(procedure))
|
||||||
- if procedure.publiee_ou_archivee?
|
- if procedure.publiee_ou_archivee?
|
||||||
%td= link_to(procedure.published_at.present? ? procedure.published_at.strftime('%d/%m/%Y %H:%M') : "", admin_procedure_href)
|
%td= link_to(procedure.published_at.present? ? try_format_datetime(procedure.published_at) : "", admin_procedure_href)
|
||||||
- else
|
- else
|
||||||
%td= link_to(procedure.created_at.strftime('%d/%m/%Y %H:%M'), admin_procedure_href)
|
%td= link_to(try_format_datetime(procedure.created_at), admin_procedure_href)
|
||||||
%td
|
%td
|
||||||
= link_to('Cloner', admin_procedure_clone_path(procedure.id), data: { method: :put }, class: 'btn-sm btn-primary clone-btn')
|
= link_to('Cloner', admin_procedure_clone_path(procedure.id), data: { method: :put }, class: 'btn-sm btn-primary clone-btn')
|
||||||
- if !procedure.publiee_ou_archivee?
|
- if !procedure.publiee_ou_archivee?
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
%p
|
%p
|
||||||
Vous avez fait la demande d’un compte administrateur sur demarches-simplifiees.fr.
|
Vous avez fait la demande d’un compte administrateur sur demarches-simplifiees.fr.
|
||||||
Votre compte a été créé mais reste inactif, il arrivera à expiration le #{@expiration_date.strftime("%d/%m/%Y")}
|
Votre compte a été créé mais reste inactif, il arrivera à expiration le #{try_format_date(@expiration_date)}
|
||||||
|
|
||||||
%p
|
%p
|
||||||
Afin d’activer votre compte, veuillez cliquer sur le lien ci-dessous :
|
Afin d’activer votre compte, veuillez cliquer sur le lien ci-dessous :
|
||||||
|
|
|
@ -5,7 +5,10 @@
|
||||||
.personnes-impliquees.container
|
.personnes-impliquees.container
|
||||||
= render partial: 'gestionnaires/dossiers/envoyer_dossier_block', locals: { dossier: @dossier, potential_recipients: @potential_recipients }
|
= render partial: 'gestionnaires/dossiers/envoyer_dossier_block', locals: { dossier: @dossier, potential_recipients: @potential_recipients }
|
||||||
|
|
||||||
= render partial: 'gestionnaires/dossiers/personnes_impliquees_block', locals: { emails_collection: @following_instructeurs_emails, title: "Instructeurs qui suivent le dossier", blank: "Aucun instructeur ne suit ce dossier" }
|
= render partial: 'gestionnaires/dossiers/personnes_impliquees_block', locals: { emails_collection: @following_instructeurs_emails, title: "Instructeurs qui suivent actuellement le dossier", blank: "Aucun instructeur ne suit ce dossier" }
|
||||||
|
|
||||||
|
- if @previous_following_instructeurs_emails.present?
|
||||||
|
= render partial: 'gestionnaires/dossiers/personnes_impliquees_block', locals: { emails_collection: @previous_following_instructeurs_emails, title: "Instructeurs ayant précédemment suivi le dossier", blank: " " }
|
||||||
|
|
||||||
= render partial: 'gestionnaires/dossiers/personnes_impliquees_block', locals: { emails_collection: @avis_emails, title: "Personnes à qui un avis a été demandé", blank: "Aucun avis n'a été demandé" }
|
= render partial: 'gestionnaires/dossiers/personnes_impliquees_block', locals: { emails_collection: @avis_emails, title: "Personnes à qui un avis a été demandé", blank: "Aucun avis n'a été demandé" }
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
= form_for procedure.administrateurs.new,
|
||||||
|
url: { controller: 'procedure_administrateurs' },
|
||||||
|
html: { class: 'form', id: "procedure-#{procedure.id}-new_administrateur" } ,
|
||||||
|
remote: true do |f|
|
||||||
|
= f.label :email do
|
||||||
|
Ajouter un administrateur
|
||||||
|
%span.notice= "Renseignez l’email d’un administrateur déjà enregistré sur demarches-simplifiees.fr pour lui permettre de modifier « #{procedure.libelle} »."
|
||||||
|
= f.email_field :email, placeholder: 'marie.dupont@exemple.fr', required: true
|
||||||
|
= f.submit 'Ajouter comme administrateur', class: 'button primary send'
|
|
@ -1,6 +1,6 @@
|
||||||
%tr{ id: "procedure-#{@procedure.id}-administrateur-#{administrateur.id}" }
|
%tr{ id: "procedure-#{@procedure.id}-administrateur-#{administrateur.id}" }
|
||||||
%td= administrateur.email
|
%td= administrateur.email
|
||||||
%td= administrateur.created_at.strftime('%d/%m/%Y %H:%M')
|
%td= try_format_datetime(administrateur.created_at)
|
||||||
%td= administrateur.registration_state
|
%td= administrateur.registration_state
|
||||||
%td
|
%td
|
||||||
- if administrateur == current_administrateur
|
- if administrateur == current_administrateur
|
||||||
|
|
|
@ -3,4 +3,7 @@
|
||||||
= append_to_element("#procedure-#{@procedure.id}-administrateurs",
|
= append_to_element("#procedure-#{@procedure.id}-administrateurs",
|
||||||
partial: 'administrateur',
|
partial: 'administrateur',
|
||||||
locals: { administrateur: @administrateur })
|
locals: { administrateur: @administrateur })
|
||||||
document.getElementById('procedure-#{@procedure.id}-new_administrateur').reset()
|
= render_to_element("#procedure-#{@procedure.id}-new_administrateur",
|
||||||
|
partial: 'add_admin_form',
|
||||||
|
outer: true,
|
||||||
|
locals: { procedure: @procedure })
|
||||||
|
|
|
@ -15,12 +15,4 @@
|
||||||
%tfoot
|
%tfoot
|
||||||
%tr
|
%tr
|
||||||
%th{ colspan: 4 }
|
%th{ colspan: 4 }
|
||||||
= form_for @procedure.administrateurs.new,
|
= render 'add_admin_form', procedure: @procedure
|
||||||
url: { controller: 'procedure_administrateurs' },
|
|
||||||
html: { class: 'form', id: "procedure-#{@procedure.id}-new_administrateur" } ,
|
|
||||||
remote: true do |f|
|
|
||||||
= f.label :email do
|
|
||||||
Ajouter un administrateur
|
|
||||||
%span.notice= "Renseignez l’email d’un administrateur déjà enregistré sur demarches-simplifiees.fr pour lui permettre de modifier « #{@procedure.libelle} »."
|
|
||||||
= f.email_field :email, placeholder: 'marie.dupont@exemple.fr', required: true
|
|
||||||
= f.submit 'Ajouter comme administrateur', class: 'button primary send'
|
|
||||||
|
|
|
@ -30,6 +30,10 @@
|
||||||
= render partial: "shared/champs/siret/show", locals: { champ: c, profile: profile }
|
= render partial: "shared/champs/siret/show", locals: { champ: c, profile: profile }
|
||||||
- when TypeDeChamp.type_champs.fetch(:textarea)
|
- when TypeDeChamp.type_champs.fetch(:textarea)
|
||||||
= render partial: "shared/champs/textarea/show", locals: { champ: c }
|
= render partial: "shared/champs/textarea/show", locals: { champ: c }
|
||||||
|
- when TypeDeChamp.type_champs.fetch(:date)
|
||||||
|
= c.to_s
|
||||||
|
- when TypeDeChamp.type_champs.fetch(:datetime)
|
||||||
|
= c.to_s
|
||||||
- else
|
- else
|
||||||
= sanitize(c.to_s)
|
= sanitize(c.to_s)
|
||||||
|
|
||||||
|
@ -37,4 +41,4 @@
|
||||||
%td.updated-at
|
%td.updated-at
|
||||||
%span{ class: highlight_if_unseen_class(demande_seen_at, c.updated_at) }
|
%span{ class: highlight_if_unseen_class(demande_seen_at, c.updated_at) }
|
||||||
modifié le
|
modifié le
|
||||||
= c.updated_at.strftime("%d/%m/%Y à %H:%M")
|
= try_format_datetime(c.updated_at)
|
||||||
|
|
|
@ -11,10 +11,12 @@
|
||||||
= form_for dossier, form_options do |f|
|
= form_for dossier, form_options do |f|
|
||||||
|
|
||||||
.prologue
|
.prologue
|
||||||
.mandatory-explanation
|
%p.mandatory-explanation
|
||||||
Les champs avec un astérisque (
|
Les champs avec un astérisque (
|
||||||
%span.mandatory> *
|
%span.mandatory> *
|
||||||
) sont obligatoires. Pour enregistrer les informations saisies, cliquez sur le bouton « enregistrer le brouillon » en bas à gauche du formulaire.
|
) sont obligatoires.
|
||||||
|
%p.mandatory-explanation
|
||||||
|
Pour enregistrer votre dossier et le reprendre plus tard, cliquez sur le bouton « Enregistrer le brouillon » en bas à gauche du formulaire.
|
||||||
|
|
||||||
- if notice_url(dossier.procedure).present?
|
- if notice_url(dossier.procedure).present?
|
||||||
= link_to notice_url(dossier.procedure), target: '_blank', rel: 'noopener', class: 'button notice', title: "Pour vous aider à remplir votre dossier, vous pouvez consulter le guide de cette démarche." do
|
= link_to notice_url(dossier.procedure), target: '_blank', rel: 'noopener', class: 'button notice', title: "Pour vous aider à remplir votre dossier, vous pouvez consulter le guide de cette démarche." do
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
%td= etablissement.naf
|
%td= etablissement.naf
|
||||||
%tr
|
%tr
|
||||||
%th.libelle Date de création :
|
%th.libelle Date de création :
|
||||||
%td= etablissement.entreprise.date_creation&.strftime("%d/%m/%Y")
|
%td= try_format_date(etablissement.entreprise.date_creation)
|
||||||
%tr
|
%tr
|
||||||
%th.libelle Effectif de l'organisation :
|
%th.libelle Effectif de l'organisation :
|
||||||
%td= effectif(etablissement)
|
%td= effectif(etablissement)
|
||||||
|
@ -64,10 +64,10 @@
|
||||||
%td= etablissement.association_objet
|
%td= etablissement.association_objet
|
||||||
%tr
|
%tr
|
||||||
%th.libelle Date de création :
|
%th.libelle Date de création :
|
||||||
%td= etablissement.association_date_creation&.strftime("%d/%m/%Y")
|
%td= try_format_date(etablissement.association_date_creation)
|
||||||
%tr
|
%tr
|
||||||
%th.libelle Date de publication :
|
%th.libelle Date de publication :
|
||||||
%td= etablissement.association_date_publication&.strftime("%d/%m/%Y")
|
%td= try_format_date(etablissement.association_date_publication)
|
||||||
%tr
|
%tr
|
||||||
%th.libelle Date de déclaration :
|
%th.libelle Date de déclaration :
|
||||||
%td= etablissement.association_date_declaration&.strftime("%d/%m/%Y")
|
%td= try_format_date(etablissement.association_date_declaration)
|
||||||
|
|
|
@ -12,4 +12,4 @@
|
||||||
- if individual.birthdate.present?
|
- if individual.birthdate.present?
|
||||||
%tr
|
%tr
|
||||||
%th.libelle Date de naissance :
|
%th.libelle Date de naissance :
|
||||||
%td= individual.birthdate&.strftime("%d/%m/%Y")
|
%td= try_format_date(individual.birthdate)
|
||||||
|
|
|
@ -23,11 +23,11 @@
|
||||||
= link_to pj.content_url, { target: :blank, rel: :noopener } do
|
= link_to pj.content_url, { target: :blank, rel: :noopener } do
|
||||||
%span.filename= display_pj_filename(pj)
|
%span.filename= display_pj_filename(pj)
|
||||||
%span
|
%span
|
||||||
ajoutée le #{pj.created_at.strftime('%d/%m/%Y à %H:%M')}
|
ajoutée le #{try_format_datetime(pj.created_at)}
|
||||||
- else
|
- else
|
||||||
%td Pièce non fournie
|
%td Pièce non fournie
|
||||||
%td.updated-at
|
%td.updated-at
|
||||||
- if pj
|
- if pj
|
||||||
%span{ class: highlight_if_unseen_class(demande_seen_at, pj.updated_at) }
|
%span{ class: highlight_if_unseen_class(demande_seen_at, pj.updated_at) }
|
||||||
modifié le
|
modifié le
|
||||||
= pj.updated_at.strftime("%d/%m/%Y à %H:%M")
|
= try_format_datetime(pj.updated_at)
|
||||||
|
|
|
@ -3,6 +3,6 @@
|
||||||
.card-title
|
.card-title
|
||||||
Le dépôt de dossier est fermé
|
Le dépôt de dossier est fermé
|
||||||
- if dossier.procedure.archived_at.present?
|
- if dossier.procedure.archived_at.present?
|
||||||
Il n'est plus possible de déposer de dossier pour cette démarche en ligne depuis le #{dossier.procedure.archived_at.strftime("%d/%m/%Y")}.
|
Il n'est plus possible de déposer de dossier pour cette démarche en ligne depuis le #{try_format_date(dossier.procedure.archived_at)}.
|
||||||
- else
|
- else
|
||||||
Il n'est plus possible de déposer de dossier pour cette démarche en ligne.
|
Il n'est plus possible de déposer de dossier pour cette démarche en ligne.
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
- if champ.updated_at.present? && seen_at.present?
|
- if champ.updated_at.present? && seen_at.present?
|
||||||
%span.updated-at{ class: highlight_if_unseen_class(seen_at, champ.updated_at) }
|
%span.updated-at{ class: highlight_if_unseen_class(seen_at, champ.updated_at) }
|
||||||
= "modifié le #{champ.updated_at.strftime('%d/%m/%Y à %H:%M')}"
|
= "modifié le #{try_format_datetime(champ.updated_at)}"
|
||||||
|
|
||||||
- if champ.description.present?
|
- if champ.description.present?
|
||||||
%span.notice= string_to_html(champ.description)
|
%span.notice= string_to_html(champ.description)
|
||||||
|
|
|
@ -13,12 +13,12 @@
|
||||||
|
|
||||||
%li
|
%li
|
||||||
Date de création :
|
Date de création :
|
||||||
= etablissement.association_date_creation&.strftime('%d/%m/%Y')
|
= try_format_date(etablissement.association_date_creation)
|
||||||
|
|
||||||
%li
|
%li
|
||||||
Date de déclaration :
|
Date de déclaration :
|
||||||
= etablissement.association_date_declaration&.strftime('%d/%m/%Y')
|
= try_format_date(etablissement.association_date_declaration)
|
||||||
|
|
||||||
%li
|
%li
|
||||||
Date de publication :
|
Date de publication :
|
||||||
= etablissement.association_date_publication&.strftime('%d/%m/%Y')
|
= try_format_date(etablissement.association_date_publication)
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
%li
|
%li
|
||||||
Date de création :
|
Date de création :
|
||||||
= etablissement.entreprise.date_creation&.strftime('%d/%m/%Y')
|
= try_format_date(etablissement.entreprise.date_creation)
|
||||||
|
|
||||||
%li
|
%li
|
||||||
Effectif organisation :
|
Effectif organisation :
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
= render partial: 'shared/dossiers/status_badge', locals: { dossier: dossier }
|
= render partial: 'shared/dossiers/status_badge', locals: { dossier: dossier }
|
||||||
%td.updated-at-col
|
%td.updated-at-col
|
||||||
= link_to(url_for_dossier(dossier), class: 'cell-link') do
|
= link_to(url_for_dossier(dossier), class: 'cell-link') do
|
||||||
= dossier.updated_at.strftime("%d/%m/%Y")
|
= try_format_date(dossier.updated_at)
|
||||||
%td.action-col.action-col
|
%td.action-col.action-col
|
||||||
= render partial: 'dossier_actions', locals: { dossier: dossier }
|
= render partial: 'dossier_actions', locals: { dossier: dossier }
|
||||||
= paginate(@dossiers)
|
= paginate(@dossiers)
|
||||||
|
|
|
@ -6,7 +6,7 @@ Rails.application.config.content_security_policy do |policy|
|
||||||
policy.report_uri "http://#{ENV['APP_HOST']}/csp/" # ne pas notifier report-uri en dev/test
|
policy.report_uri "http://#{ENV['APP_HOST']}/csp/" # ne pas notifier report-uri en dev/test
|
||||||
end
|
end
|
||||||
# Whitelist image
|
# Whitelist image
|
||||||
policy.img_src :self, "*.openstreetmap.org", "static.demarches-simplifiees.fr", "*.cloud.ovh.net", "stats.data.gouv.fr"
|
policy.img_src :self, "*.openstreetmap.org", "static.demarches-simplifiees.fr", "*.cloud.ovh.net", "stats.data.gouv.fr", "*"
|
||||||
# Whitelist JS: nous, sendinblue et matomo
|
# Whitelist JS: nous, sendinblue et matomo
|
||||||
# miniprofiler et nous avons quelques boutons inline :(
|
# miniprofiler et nous avons quelques boutons inline :(
|
||||||
policy.script_src :self, "*.sibautomation.com", "sibautomation.com", "stats.data.gouv.fr", "*.sendinblue.com", :unsafe_eval, :unsafe_inline
|
policy.script_src :self, "*.sibautomation.com", "sibautomation.com", "stats.data.gouv.fr", "*.sendinblue.com", :unsafe_eval, :unsafe_inline
|
||||||
|
@ -16,5 +16,5 @@ Rails.application.config.content_security_policy do |policy|
|
||||||
policy.style_src :self, :unsafe_inline
|
policy.style_src :self, :unsafe_inline
|
||||||
# Pour tout le reste, par défaut on accepte uniquement ce qui vient de chez nous
|
# Pour tout le reste, par défaut on accepte uniquement ce qui vient de chez nous
|
||||||
# et dans la notification on inclue la source de l'erreur
|
# et dans la notification on inclue la source de l'erreur
|
||||||
policy.default_src :self, :data, :report_sample, "fonts.gstatic.com", "in-automate.sendinblue.com", "player.vimeo.com", "app.franceconnect.gouv.fr", "sentry.io", "static.demarches-simplifiees.fr"
|
policy.default_src :self, :data, :report_sample, "fonts.gstatic.com", "in-automate.sendinblue.com", "player.vimeo.com", "app.franceconnect.gouv.fr", "sentry.io", "static.demarches-simplifiees.fr", "*.crisp.chat", "crisp.chat"
|
||||||
end
|
end
|
||||||
|
|
|
@ -249,7 +249,7 @@ fr:
|
||||||
- vendredi
|
- vendredi
|
||||||
- samedi
|
- samedi
|
||||||
formats:
|
formats:
|
||||||
default: "%d/%m/%Y"
|
default: "%d %B %Y"
|
||||||
short: "%e %b"
|
short: "%e %b"
|
||||||
long: "%e %B %Y"
|
long: "%e %B %Y"
|
||||||
datetime:
|
datetime:
|
||||||
|
@ -290,6 +290,9 @@ fr:
|
||||||
x_seconds:
|
x_seconds:
|
||||||
one: 1 seconde
|
one: 1 seconde
|
||||||
other: "%{count} secondes"
|
other: "%{count} secondes"
|
||||||
|
time:
|
||||||
|
formats:
|
||||||
|
default: "%d %B %Y %R"
|
||||||
pluralize:
|
pluralize:
|
||||||
case:
|
case:
|
||||||
zero: dossier
|
zero: dossier
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
class EnsureFollowDatesNotNull < ActiveRecord::Migration[5.2]
|
||||||
|
def change
|
||||||
|
change_column_null :follows, :demande_seen_at, false
|
||||||
|
change_column_null :follows, :annotations_privees_seen_at, false
|
||||||
|
change_column_null :follows, :avis_seen_at, false
|
||||||
|
change_column_null :follows, :messagerie_seen_at, false
|
||||||
|
end
|
||||||
|
end
|
17
db/migrate/20190607124156_add_follow_unfollowed_at.rb
Normal file
17
db/migrate/20190607124156_add_follow_unfollowed_at.rb
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
class AddFollowUnfollowedAt < ActiveRecord::Migration[5.2]
|
||||||
|
# We need up/down migrations because `remove_index` doesn’t allow `unique: true` and can’t be properly rolled back.
|
||||||
|
def up
|
||||||
|
add_column :follows, :unfollowed_at, :datetime
|
||||||
|
|
||||||
|
remove_index :follows, [:gestionnaire_id, :dossier_id]
|
||||||
|
add_index :follows, [:gestionnaire_id, :dossier_id, :unfollowed_at], unique: true,
|
||||||
|
name: :uniqueness_index # We need a custom name because the autogenerated name would be too long
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_column :follows, :unfollowed_at
|
||||||
|
# We don’t need to remove the index: dropping the column automatically deletes it.
|
||||||
|
|
||||||
|
add_index :follows, [:gestionnaire_id, :dossier_id], unique: true
|
||||||
|
end
|
||||||
|
end
|
13
db/schema.rb
13
db/schema.rb
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 2019_03_27_102360) do
|
ActiveRecord::Schema.define(version: 2019_06_07_124156) do
|
||||||
|
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
|
@ -327,14 +327,15 @@ ActiveRecord::Schema.define(version: 2019_03_27_102360) do
|
||||||
create_table "follows", id: :serial, force: :cascade do |t|
|
create_table "follows", id: :serial, force: :cascade do |t|
|
||||||
t.integer "gestionnaire_id", null: false
|
t.integer "gestionnaire_id", null: false
|
||||||
t.integer "dossier_id", null: false
|
t.integer "dossier_id", null: false
|
||||||
t.datetime "demande_seen_at"
|
t.datetime "demande_seen_at", null: false
|
||||||
t.datetime "annotations_privees_seen_at"
|
t.datetime "annotations_privees_seen_at", null: false
|
||||||
t.datetime "avis_seen_at"
|
t.datetime "avis_seen_at", null: false
|
||||||
t.datetime "messagerie_seen_at"
|
t.datetime "messagerie_seen_at", null: false
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
|
t.datetime "unfollowed_at"
|
||||||
t.index ["dossier_id"], name: "index_follows_on_dossier_id"
|
t.index ["dossier_id"], name: "index_follows_on_dossier_id"
|
||||||
t.index ["gestionnaire_id", "dossier_id"], name: "index_follows_on_gestionnaire_id_and_dossier_id", unique: true
|
t.index ["gestionnaire_id", "dossier_id", "unfollowed_at"], name: "uniqueness_index", unique: true
|
||||||
t.index ["gestionnaire_id"], name: "index_follows_on_gestionnaire_id"
|
t.index ["gestionnaire_id"], name: "index_follows_on_gestionnaire_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
6
spec/fixtures/files/api_entreprise/entreprises_private.json
vendored
Normal file
6
spec/fixtures/files/api_entreprise/entreprises_private.json
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"errors": [
|
||||||
|
"Le SIREN ou SIRET est non diffusable"
|
||||||
|
],
|
||||||
|
"gateway_error": true
|
||||||
|
}
|
|
@ -17,4 +17,42 @@ describe ApplicationHelper do
|
||||||
it { is_expected.to be_nil }
|
it { is_expected.to be_nil }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#try_format_date" do
|
||||||
|
subject { try_format_date(date) }
|
||||||
|
|
||||||
|
describe 'try formatting a date' do
|
||||||
|
let(:date) { Date.new(2019, 01, 24) }
|
||||||
|
it { is_expected.to eq("24 janvier 2019") }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'try formatting a blank string' do
|
||||||
|
let(:date) { "" }
|
||||||
|
it { is_expected.to eq("") }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'try formatting a nil string' do
|
||||||
|
let(:date) { nil }
|
||||||
|
it { is_expected.to eq("") }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#try_format_datetime" do
|
||||||
|
subject { try_format_datetime(datetime) }
|
||||||
|
|
||||||
|
describe 'try formatting 31/01/2019 11:25' do
|
||||||
|
let(:datetime) { Time.zone.local(2019, 01, 31, 11, 25, 00) }
|
||||||
|
it { is_expected.to eq("31 janvier 2019 11:25") }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'try formatting a blank string' do
|
||||||
|
let(:datetime) { "" }
|
||||||
|
it { is_expected.to eq("") }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'try formatting a nil string' do
|
||||||
|
let(:datetime) { nil }
|
||||||
|
it { is_expected.to eq("") }
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -31,7 +31,17 @@ describe ApiEntreprise::API do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when siret exist' do
|
context 'when siren infos are private' do
|
||||||
|
let(:siren) { '111111111' }
|
||||||
|
let(:status) { 403 }
|
||||||
|
let(:body) { File.read('spec/fixtures/files/api_entreprise/entreprises_private.json') }
|
||||||
|
|
||||||
|
it 'raises RestClient::ResourceNotFound' do
|
||||||
|
expect { subject }.to raise_error(RestClient::ResourceNotFound)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when siren exist' do
|
||||||
let(:siren) { '418166096' }
|
let(:siren) { '418166096' }
|
||||||
let(:status) { 200 }
|
let(:status) { 200 }
|
||||||
let(:body) { File.read('spec/fixtures/files/api_entreprise/entreprises.json') }
|
let(:body) { File.read('spec/fixtures/files/api_entreprise/entreprises.json') }
|
||||||
|
|
|
@ -238,7 +238,7 @@ describe TagsSubstitutionConcern, type: :model do
|
||||||
.update(value: '2017-09-13 09:00')
|
.update(value: '2017-09-13 09:00')
|
||||||
end
|
end
|
||||||
|
|
||||||
it { is_expected.to eq('15/04/2017 2017-09-13 09:00') }
|
it { is_expected.to eq('15 avril 2017 13 septembre 2017 09:00') }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -67,6 +67,7 @@ describe Gestionnaire, type: :model do
|
||||||
end
|
end
|
||||||
|
|
||||||
it { expect(gestionnaire.follow?(already_followed_dossier)).to be false }
|
it { expect(gestionnaire.follow?(already_followed_dossier)).to be false }
|
||||||
|
it { expect(gestionnaire.previously_followed_dossiers).to include(already_followed_dossier) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,18 @@ describe PieceJustificativeToChampPieceJointeMigrationService do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def timestamps(dossier)
|
||||||
|
# Reload dossier because the resolution of in-database timestamps is
|
||||||
|
# different from the resolution of in-memory timestamps, causing the
|
||||||
|
# tests to fail on fractional time differences.
|
||||||
|
dossier.reload
|
||||||
|
|
||||||
|
{
|
||||||
|
created_at: dossier.created_at,
|
||||||
|
updated_at: dossier.updated_at
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
def expect_storage_service_to_convert_object
|
def expect_storage_service_to_convert_object
|
||||||
expect(storage_service).to receive(:make_blob)
|
expect(storage_service).to receive(:make_blob)
|
||||||
expect(storage_service).to receive(:copy_from_carrierwave_to_active_storage!)
|
expect(storage_service).to receive(:copy_from_carrierwave_to_active_storage!)
|
||||||
|
@ -64,6 +76,8 @@ describe PieceJustificativeToChampPieceJointeMigrationService do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'no notifications are sent to instructeurs' do
|
context 'no notifications are sent to instructeurs' do
|
||||||
|
let!(:initial_dossier_timestamps) { timestamps(dossier) }
|
||||||
|
|
||||||
context 'when there is a PJ' do
|
context 'when there is a PJ' do
|
||||||
let(:pjs) { make_pjs }
|
let(:pjs) { make_pjs }
|
||||||
|
|
||||||
|
@ -80,24 +94,18 @@ describe PieceJustificativeToChampPieceJointeMigrationService do
|
||||||
dossier.reload
|
dossier.reload
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'the champ has the same created_at as the PJ' do
|
it 'the champ has the same timestamps as the PJ' do
|
||||||
expect(dossier.champs.last.created_at).to eq(pjs.last.created_at)
|
expect(dossier.champs.last.created_at).to eq(pjs.last.created_at)
|
||||||
|
expect(dossier.champs.last.updated_at).to eq(pjs.last.updated_at)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'the champ has the same updated_at as the PJ' do
|
it 'does not change the dossier timestamps' do
|
||||||
expect(dossier.champs.last.updated_at).to eq(pjs.last.updated_at)
|
expect(dossier.created_at).to eq(initial_dossier_timestamps[:created_at])
|
||||||
|
expect(dossier.updated_at).to eq(initial_dossier_timestamps[:updated_at])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when there is no PJ' do
|
context 'when there is no PJ' do
|
||||||
let!(:expected_updated_at) do
|
|
||||||
# Reload dossier because the resolution of in-database timestamps is
|
|
||||||
# different from the resolution of in-memory timestamps, causing the
|
|
||||||
# tests to fail on fractional time differences.
|
|
||||||
dossier.reload
|
|
||||||
dossier.updated_at
|
|
||||||
end
|
|
||||||
|
|
||||||
before do
|
before do
|
||||||
Timecop.travel(1.hour) { service.convert_procedure_pjs_to_champ_pjs(procedure) }
|
Timecop.travel(1.hour) { service.convert_procedure_pjs_to_champ_pjs(procedure) }
|
||||||
|
|
||||||
|
@ -105,12 +113,14 @@ describe PieceJustificativeToChampPieceJointeMigrationService do
|
||||||
dossier.reload
|
dossier.reload
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'the champ has the same created_at as the dossier' do
|
it 'the champ has the same timestamps as the dossier' do
|
||||||
expect(dossier.champs.last.created_at).to eq(dossier.created_at)
|
expect(dossier.champs.last.created_at).to eq(initial_dossier_timestamps[:created_at])
|
||||||
|
expect(dossier.champs.last.updated_at).to eq(initial_dossier_timestamps[:updated_at])
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'the champ has the same updated_at as the dossier' do
|
it 'does not change the dossier timestamps' do
|
||||||
expect(dossier.champs.last.updated_at).to eq(expected_updated_at)
|
expect(dossier.created_at).to eq(initial_dossier_timestamps[:created_at])
|
||||||
|
expect(dossier.updated_at).to eq(initial_dossier_timestamps[:updated_at])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -192,6 +202,9 @@ describe PieceJustificativeToChampPieceJointeMigrationService do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
let!(:initial_dossier_timestamps) { timestamps(dossier) }
|
||||||
|
let!(:initial_failing_dossier_timestamps) { timestamps(failing_dossier) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(storage_service).to receive(:checksum).and_return('cafe')
|
allow(storage_service).to receive(:checksum).and_return('cafe')
|
||||||
allow(storage_service).to receive(:fix_content_type)
|
allow(storage_service).to receive(:fix_content_type)
|
||||||
|
@ -204,8 +217,10 @@ describe PieceJustificativeToChampPieceJointeMigrationService do
|
||||||
end
|
end
|
||||||
|
|
||||||
def try_convert(procedure)
|
def try_convert(procedure)
|
||||||
service.convert_procedure_pjs_to_champ_pjs(procedure)
|
Timecop.travel(1.hour) { service.convert_procedure_pjs_to_champ_pjs(procedure) }
|
||||||
rescue StandardError, SignalException => e
|
rescue StandardError, SignalException => e
|
||||||
|
dossier.reload
|
||||||
|
failing_dossier.reload
|
||||||
e
|
e
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -234,6 +249,12 @@ describe PieceJustificativeToChampPieceJointeMigrationService do
|
||||||
.not_to change { procedure.types_de_piece_justificative.count }
|
.not_to change { procedure.types_de_piece_justificative.count }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'does not change the dossiers timestamps' do
|
||||||
|
try_convert(procedure)
|
||||||
|
expect(dossier.updated_at).to eq(initial_dossier_timestamps[:updated_at])
|
||||||
|
expect(failing_dossier.updated_at).to eq(initial_failing_dossier_timestamps[:updated_at])
|
||||||
|
end
|
||||||
|
|
||||||
it 'does not leave stale blobs behind' do
|
it 'does not leave stale blobs behind' do
|
||||||
expect { try_convert(procedure) }
|
expect { try_convert(procedure) }
|
||||||
.not_to change { ActiveStorage::Blob.count }
|
.not_to change { ActiveStorage::Blob.count }
|
||||||
|
|
|
@ -38,7 +38,7 @@ describe 'shared/dossiers/demande.html.haml', type: :view do
|
||||||
expect(rendered).to include(individual.gender)
|
expect(rendered).to include(individual.gender)
|
||||||
expect(rendered).to include(individual.nom)
|
expect(rendered).to include(individual.nom)
|
||||||
expect(rendered).to include(individual.prenom)
|
expect(rendered).to include(individual.prenom)
|
||||||
expect(rendered).to include(individual.birthdate.strftime("%d/%m/%Y"))
|
expect(rendered).to include(I18n.l(individual.birthdate))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue