Merge branch 'dev'

This commit is contained in:
gregoirenovel 2018-04-06 17:15:05 +02:00
commit 46cb8a7a92
18 changed files with 433 additions and 4 deletions

View file

@ -27,4 +27,21 @@
font-size: 11px;
margin-bottom: $default-spacer * 2;
}
.warning {
background-color: $orange-bg;
padding: $default-spacer;
margin-bottom: $default-spacer * 2;
border-radius: 3px;
h4 {
margin-top: $default-spacer;
font-weight: bold;
}
ul {
list-style: disc;
padding-left: $default-spacer * 1.5;
}
}
}

View file

@ -0,0 +1,19 @@
class EtablissementUpdateJob < ApplicationJob
queue_as :default
def perform(dossier, siret)
etablissement_attributes = SIRETService.fetch(siret, dossier.procedure_id, dossier)
if etablissement_attributes.present?
if dossier.entreprise.present?
dossier.entreprise.destroy
end
if dossier.etablissement.present?
dossier.etablissement.destroy
end
etablissement_attributes = ActionController::Parameters.new(etablissement_attributes).permit!
etablissement = dossier.build_etablissement(etablissement_attributes)
etablissement.save
end
end
end

View file

@ -17,6 +17,20 @@ class AttestationTemplate < ApplicationRecord
Attestation.new(title: replace_tags(title, dossier), pdf: build_pdf(dossier))
end
def unspecified_champs_for_dossier(dossier)
all_champs_with_libelle_index = (dossier.champs + dossier.champs_private)
.reduce({}) do |acc, champ|
acc[champ.libelle] = champ
acc
end
used_tags.map do |used_tag|
corresponding_champ = all_champs_with_libelle_index[used_tag]
corresponding_champ.value.blank? ? corresponding_champ : nil
end.compact
end
def dup
result = AttestationTemplate.new(title: title, body: body, footer: footer, activated: activated)
@ -33,6 +47,17 @@ class AttestationTemplate < ApplicationRecord
private
def used_tags
delimiters_regex = /--(?<capture>((?!--).)*)--/
# We can't use flat_map as scan will return 3 levels of array,
# using flat_map would give us 2, whereas flatten will
# give us 1, which is what we want
[title, body]
.map { |str| str.scan(delimiters_regex) }
.flatten
end
def logo_signature_file_size
%i[logo signature]
.select { |file_name| send(file_name).present? }

View file

@ -283,8 +283,18 @@ class Dossier < ApplicationRecord
end
end
def unspecified_attestation_champs
attestation_template = procedure.attestation_template
if attestation_template&.activated?
attestation_template.unspecified_champs_for_dossier(self)
else
[]
end
end
def build_attestation
if procedure.attestation_template.present? && procedure.attestation_template.activated?
if procedure.attestation_template&.activated?
procedure.attestation_template.attestation_for(self)
end
end

View file

@ -265,6 +265,18 @@ class Procedure < ApplicationRecord
update_attribute('whitelisted_at', DateTime.now)
end
def closed_mail_template_attestation_inconsistency_state
# As an optimization, dont check the predefined templates (they are presumed correct)
if closed_mail.present?
tag_present = closed_mail.body.include?("--lien attestation--")
if attestation_template&.activated? && !tag_present
:missing_tag
elsif !attestation_template&.activated? && tag_present
:extraneous_tag
end
end
end
private
def field_hash(label, table, column)

View file

@ -0,0 +1,22 @@
- case @procedure.closed_mail_template_attestation_inconsistency_state
- when :missing_tag
.center
.alert{ class: flash_class('alert') }
Cette procédure comporte une attestation, mais laccusé dacceptation ne la mentionne pas :
- if !@procedure.locked?
= link_to('désactivez lattestation', edit_admin_procedure_attestation_template_path(@procedure))
ou
= link_to('ajoutez la balise', edit_admin_procedure_mail_template_path(@procedure, Mails::ClosedMail::SLUG))
%code{ style: "white-space: pre-wrap;" }
\--lien attestation--
à laccusé dacceptation
- when :extraneous_tag
.center
.alert{ class: flash_class('alert') }
Cette procédure ne comporte pas dattestation, mais laccusé dacceptation en mentionne une :
= link_to('activez lattestation', edit_admin_procedure_attestation_template_path(@procedure))
ou
= link_to('enlevez la balise', edit_admin_procedure_mail_template_path(@procedure, Mails::ClosedMail::SLUG))
%code{ style: "white-space: pre-wrap;" }
\--lien attestation--
de laccusé dacceptation

View file

@ -1,3 +1,4 @@
= render partial: 'admin/closed_mail_template_attestation_inconsistency_alert'
#attestation-template-edit.row.white-back
= form_for @attestation_template, url: admin_procedure_attestation_template_path do |f|
.row

View file

@ -1,3 +1,5 @@
- if params[:id] == 'closed_mail'
= render partial: 'admin/closed_mail_template_attestation_inconsistency_alert'
.white-back
%h3
= @mail_template.class.const_get(:DISPLAYED_NAME)

View file

@ -1,3 +1,4 @@
= render partial: 'admin/closed_mail_template_attestation_inconsistency_alert'
#custom-mails
.wrapper
%h1 E-mails personnalisables

View file

@ -1,3 +1,4 @@
= render partial: 'admin/closed_mail_template_attestation_inconsistency_alert'
.row.white-back
#procedure_show
- if @facade.procedure.brouillon?

View file

@ -8,6 +8,25 @@
- if title == 'Accepter'
%p.help
L'acceptation du dossier envoie automatiquement une attestation à l'usager.
- unspecified_attestation_champs = dossier.unspecified_attestation_champs
- if unspecified_attestation_champs.present?
.warning
Attention, les valeurs suivantes n'ont pas été renseignées mais sont nécessaires pour pouvoir envoyer une attestation valide :
- unspecified_champs, unspecified_annotations_privees = unspecified_attestation_champs.partition(&:private)
- if unspecified_champs.present?
%h4 Champs de la demande
%ul
- unspecified_attestation_champs.each do |unspecified_champ|
%li= unspecified_champ.libelle
- if unspecified_annotations_privees.present?
%h4 Annotations privées
%ul
- unspecified_annotations_privees.each do |unspecified_annotations_privee|
%li= unspecified_annotations_privee.libelle
.text-right
%span.button{ onclick: 'DS.motivationCancel();' } Annuler
= button_tag 'Valider la décision', name: :process_action, value: process_action, class: 'button primary', title: title, data: { confirm: confirm }

View file

@ -4,9 +4,10 @@
%h1= @dossier.procedure.libelle
.container
%p
Pour vous aider à remplir votre dossier, vous pouvez consulter
= link_to 'le guide de cette démarche', @dossier.procedure.lien_notice, { target: '_blank' }
- if @dossier.procedure.lien_notice.present?
%p
Pour vous aider à remplir votre dossier, vous pouvez consulter
= link_to 'le guide de cette démarche', @dossier.procedure.lien_notice, { target: '_blank' }
%p.thanks Les champs avec une asterisque (*) sont obligatoires.

View file

@ -0,0 +1,83 @@
module Mailers
class AttestationClosedMailDiscrepancyMailer < ApplicationMailer
include Rails.application.routes.url_helpers
def missing_attestation_tag_email(admin, procedures)
procedures = procedures.sort_by(&:id)
mail(to: admin.email, subject: subject(procedures), body: body(procedures))
end
private
def subject(procedures)
if procedures.count == 1
procedure_ids = "votre procédure nº #{procedures.first.id}"
else
procedure_ids = 'vos procédures nº ' + procedures.map{ |p| p.id }.join(', ')
end
"demarches-simplifiees.fr mise à jour nécessaire de laccusé dacceptation de #{procedure_ids}"
end
def body(procedures)
<<~HEREDOC
Bonjour,
Pour des raisons de confidentialité, le mode de transmission des attestations aux usagers évolue.
À compter du 30 avril, les mails daccusé dacceptation émis par demarches-simplifiees.fr ne
comporteront plus dattestation en pièce jointe comme cest le cas aujourdhui.
À la place, le mail contiendra un lien permettant à lusager de télécharger son
attestation dirctement dans son espace sécurisé sur demarches-simplifiees.fr.
Ce lien de téléchargement est généré par la balise --lien attestation--.
#{detail_procedures(procedures)}
Pour toute question vous pouvez nous joindre par téléphone au 01 76 42 02 87
ou sur ladresse email contact@demarches-simplifiees.fr.
-- \nLéquipe demarches-simplifiees.fr
HEREDOC
end
def detail_procedures(procedures)
if procedures.count == 1
p = procedures.first
<<~HEREDOC.chomp
Vous êtes administrateur de la procédure suivante :
#{p.libelle} (nº #{p.id})
Cette procédure donne lieu à lémission dune attestation, et son accusé
dacceptation a é personnalisé. Pour respecter la rédaction de votre accusé
dacceptation, nous ne prendrons pas linitiative dy ajouter la balise --lien attestation--.
Afin que vos usagers puissent continuer à accéder facilement à leurs attestations
dans leurs démarches futures, nous vous invitons à ajouter à votre convenance la
balise --lien attestation-- dans votre accusé dacceptation. Vous pouvez le faire en
cliquant sur le lien suivant :
#{edit_admin_procedure_mail_template_url(p, Mails::ClosedMail::SLUG)}
HEREDOC
else
liste_procedures = procedures.map { |p| "- #{p.libelle} (nº #{p.id}) #{edit_admin_procedure_mail_template_url(p, Mails::ClosedMail::SLUG)}" }.join("\n")
<<~HEREDOC.chomp
Vous êtes administrateur sur plusieurs procédures qui donnent lieu à lémission
dune attestation, et dont laccusé dacceptation a é personnalisé. Pour respecter
la rédaction de vos accusés dacceptation, nous ne prendrons pas linitiative dy
ajouter de balise --lien attestation--.
Afin que vos usagers puissent continuer à accéder facilement à leurs attestations
dans leurs démarches futures, nous vous invitons à ajouter à votre convenance la
balise --lien attestation-- dans vos accusés dacceptation.
Vous trouverez ci-après la liste des démarches concernées, ainsi que les liens vous
permettant déditer les accusés dacceptation correspondants.
#{liste_procedures}
HEREDOC
end
end
end
end

View file

@ -0,0 +1,11 @@
namespace :'2018_04_03_attestation_closed_mail_discrepancy' do
task mail_adminstrators: :environment do
Administrateur.includes(:procedures).find_each(batch_size: 10) do |admin|
procedures = admin.procedures.where(archived_at: nil).select { |p| p.closed_mail_template_attestation_inconsistency_state == :missing_tag }
if procedures.any?
Mailers::AttestationClosedMailDiscrepancyMailer.missing_attestation_tag_email(admin, procedures).deliver_later
print "#{admin.email}\n"
end
end
end
end

View file

@ -0,0 +1,17 @@
namespace :'2018_04_04_fetch_etablissement_with_no_entreprise' do
task fetch: :environment do
dossiers = Entreprise.joins('LEFT JOIN etablissements et ON entreprises.id = et.entreprise_id')
.where('et.id IS NULL')
.map(&:dossier_id).map { |id| Dossier.unscoped.find_by(id: id) }.compact
dossiers.each do |dossier|
siret = dossier.entreprise.siret_siege_social
puts "Fetch siret: #{siret} for dossier: #{dossier.id}"
if siret
EtablissementUpdateJob.perform_later(dossier, siret)
end
end
end
end

View file

@ -643,6 +643,64 @@ describe Dossier do
end
end
describe "#unspecified_attestation_champs" do
let(:procedure) { create(:procedure, attestation_template: attestation_template) }
let(:dossier) { create(:dossier, procedure: procedure, state: :en_instruction) }
subject { dossier.unspecified_attestation_champs.map(&:libelle) }
context "without attestation template" do
let(:attestation_template) { nil }
it { is_expected.to eq([]) }
end
context "with attestation template" do
# Test all combinations:
# - with tag specified and unspecified
# - with tag in body and tag in title
# - with tag correponsing to a champ and an annotation privée
# - with a dash in the champ libelle / tag
let(:title) { "voici --specified champ-in-title-- un --unspecified champ-in-title-- beau --specified annotation privée-in-title-- titre --unspecified annotation privée-in-title-- non" }
let(:body) { "voici --specified champ-in-body-- un --unspecified champ-in-body-- beau --specified annotation privée-in-body-- body --unspecified annotation privée-in-body-- non ?" }
let(:attestation_template) { create(:attestation_template, title: title, body: body, activated: activated) }
context "which is disabled" do
let(:activated) { false }
it { is_expected.to eq([]) }
end
context "wich is enabled" do
let(:activated) { true }
let!(:tdc_1) { create(:type_de_champ, libelle: "specified champ-in-title", procedure: procedure) }
let!(:tdc_2) { create(:type_de_champ, libelle: "unspecified champ-in-title", procedure: procedure) }
let!(:tdc_3) { create(:type_de_champ, libelle: "specified champ-in-body", procedure: procedure) }
let!(:tdc_4) { create(:type_de_champ, libelle: "unspecified champ-in-body", procedure: procedure) }
let!(:tdc_5) { create(:type_de_champ, private: true, libelle: "specified annotation privée-in-title", procedure: procedure) }
let!(:tdc_6) { create(:type_de_champ, private: true, libelle: "unspecified annotation privée-in-title", procedure: procedure) }
let!(:tdc_7) { create(:type_de_champ, private: true, libelle: "specified annotation privée-in-body", procedure: procedure) }
let!(:tdc_8) { create(:type_de_champ, private: true, libelle: "unspecified annotation privée-in-body", procedure: procedure) }
before do
(dossier.champs + dossier.champs_private)
.select { |c| c.libelle.match?(/^specified/) }
.each { |c| c.update_attribute(:value, "specified") }
end
it do
is_expected.to eq([
"unspecified champ-in-title",
"unspecified annotation privée-in-title",
"unspecified champ-in-body",
"unspecified annotation privée-in-body"
])
end
end
end
end
describe '#build_attestation' do
let(:attestation_template) { nil }
let(:procedure) { create(:procedure, attestation_template: attestation_template) }

View file

@ -67,6 +67,90 @@ describe Procedure do
end
end
describe '#closed_mail_template_attestation_inconsistency_state' do
let(:procedure_without_attestation) { create(:procedure, closed_mail: closed_mail) }
let(:procedure_with_active_attestation) do
procedure = create(:procedure, closed_mail: closed_mail)
create(:attestation_template, procedure: procedure, activated: true)
procedure
end
let(:procedure_with_inactive_attestation) do
procedure = create(:procedure, closed_mail: closed_mail)
create(:attestation_template, procedure: procedure, activated: false)
procedure
end
subject { procedure.closed_mail_template_attestation_inconsistency_state }
context 'with a custom mail template' do
context 'that contains a lien attestation tag' do
let(:closed_mail) { create(:closed_mail, body: '--lien attestation--') }
context 'when the procedure doesnt have an attestation' do
let(:procedure) { procedure_without_attestation }
it { is_expected.to eq(:extraneous_tag) }
end
context 'when the procedure has an active attestation' do
let(:procedure) { procedure_with_active_attestation }
it { is_expected.to be(nil) }
end
context 'when the procedure has an inactive attestation' do
let(:procedure) { procedure_with_inactive_attestation }
it { is_expected.to eq(:extraneous_tag) }
end
end
context 'that doesnt contain a lien attestation tag' do
let(:closed_mail) { create(:closed_mail) }
context 'when the procedure doesnt have an attestation' do
let(:procedure) { procedure_without_attestation }
it { is_expected.to be(nil) }
end
context 'when the procedure has an active attestation' do
let(:procedure) { procedure_with_active_attestation }
it { is_expected.to eq(:missing_tag) }
end
context 'when the procedure has an inactive attestation' do
let(:procedure) { procedure_with_inactive_attestation }
it { is_expected.to be(nil) }
end
end
end
context 'with the default mail template' do
let(:closed_mail) { nil }
context 'when the procedure doesnt have an attestation' do
let(:procedure) { procedure_without_attestation }
it { is_expected.to be(nil) }
end
context 'when the procedure has an active attestation' do
let(:procedure) { procedure_with_active_attestation }
it { is_expected.to be(nil) }
end
context 'when the procedure has an inactive attestation' do
let(:procedure) { procedure_with_inactive_attestation }
it { is_expected.to be(nil) }
end
end
end
describe 'validation' do
context 'libelle' do
it { is_expected.not_to allow_value(nil).for(:libelle) }

View file

@ -0,0 +1,46 @@
require 'spec_helper'
describe 'admin/_closed_mail_template_attestation_inconsistency_alert.html.haml', type: :view do
let(:procedure) { create(:procedure, closed_mail: closed_mail, published_at: published_at) }
let(:published_at) { nil }
def alert
assign(:procedure, procedure)
render
rendered
end
context 'when there is no inconsistency' do
let(:closed_mail) { nil }
it { expect(alert).to be_empty }
end
context 'when there is no active attestation but the closed mail template mentions one' do
let(:closed_mail) { create(:closed_mail, body: '--lien attestation--') }
it { expect(alert).to include("Cette procédure ne comporte pas dattestation, mais laccusé dacceptation en mentionne une") }
it { expect(alert).to include(edit_admin_procedure_attestation_template_path(procedure)) }
it { expect(alert).to include(edit_admin_procedure_mail_template_path(procedure, Mails::ClosedMail::SLUG)) }
end
context 'when there is an active attestation but the closed mail template does not mention it' do
let(:closed_mail) { create(:closed_mail) }
let!(:attestation_template) { create(:attestation_template, procedure: procedure, activated: true) }
it { expect(alert).to include("Cette procédure comporte une attestation, mais laccusé dacceptation ne la mentionne pas") }
it { expect(alert).to include(edit_admin_procedure_mail_template_path(procedure, Mails::ClosedMail::SLUG)) }
context 'when the procedure has been published, the attestation cannot be deactivated' do
let(:published_at) { Time.now }
it { expect(procedure.locked?).to be_truthy }
it { expect(alert).not_to include(edit_admin_procedure_attestation_template_path(procedure)) }
end
context 'when the procedure is still a draft' do
it { expect(procedure.locked?).to be_falsey }
it { expect(alert).to include(edit_admin_procedure_attestation_template_path(procedure)) }
end
end
end