[Fix #196] Attestation: building logic from template
This commit is contained in:
parent
b443b5cefd
commit
602527a09d
4 changed files with 282 additions and 8 deletions
|
@ -20,6 +20,10 @@ class AttestationTemplate < ApplicationRecord
|
|||
identity_tags + dossier_tags + procedure_type_de_champ_public_private_tags
|
||||
end
|
||||
|
||||
def attestation_for(dossier)
|
||||
Attestation.new(title: replace_tags(title, dossier), pdf: build_pdf(dossier))
|
||||
end
|
||||
|
||||
def dup
|
||||
result = AttestationTemplate.new(title: title, body: body, footer: footer, activated: activated)
|
||||
|
||||
|
@ -58,19 +62,82 @@ class AttestationTemplate < ApplicationRecord
|
|||
end
|
||||
|
||||
def individual_tags
|
||||
[{ libelle: 'civilité', description: 'M., Mme' },
|
||||
{ libelle: 'nom', description: "nom de l'usager" },
|
||||
{ libelle: 'prénom', description: "prénom de l'usager" }]
|
||||
[{ libelle: 'civilité', description: 'M., Mme', target: 'gender' },
|
||||
{ libelle: 'nom', description: "nom de l'usager", target: 'nom' },
|
||||
{ libelle: 'prénom', description: "prénom de l'usager", target: 'prenom' }]
|
||||
end
|
||||
|
||||
def entreprise_tags
|
||||
[{ libelle: 'SIREN', description: '' },
|
||||
{ libelle: 'numéro de TVA intracommunautaire', description: '' },
|
||||
{ libelle: 'SIRET du siège social', description: '' },
|
||||
{ libelle: 'raison sociale', description: '' }]
|
||||
[{ libelle: 'SIREN', description: '', target: 'siren' },
|
||||
{ libelle: 'numéro de TVA intracommunautaire', description: '', target: 'numero_tva_intracommunautaire' },
|
||||
{ libelle: 'SIRET du siège social', description: '', target: 'siret_siege_social' },
|
||||
{ libelle: 'raison sociale', description: '', target: 'raison_sociale' }]
|
||||
end
|
||||
|
||||
def etablissement_tags
|
||||
[{ libelle: 'adresse', description: '' }]
|
||||
[{ libelle: 'adresse', description: '', target: 'adresse' }]
|
||||
end
|
||||
|
||||
def build_pdf(dossier)
|
||||
action_view = ActionView::Base.new(ActionController::Base.view_paths,
|
||||
logo: logo,
|
||||
title: replace_tags(title, dossier),
|
||||
body: replace_tags(body, dossier),
|
||||
signature: signature,
|
||||
footer: footer,
|
||||
created_at: Time.now)
|
||||
|
||||
attestation_view = action_view.render(file: 'admin/attestation_templates/show',
|
||||
formats: [:pdf])
|
||||
|
||||
view_to_memory_file(attestation_view)
|
||||
end
|
||||
|
||||
def view_to_memory_file(view)
|
||||
pdf = StringIO.new(view)
|
||||
|
||||
def pdf.original_filename
|
||||
'attestation'
|
||||
end
|
||||
|
||||
pdf
|
||||
end
|
||||
|
||||
def replace_tags(text, dossier)
|
||||
if text.nil?
|
||||
return ''
|
||||
end
|
||||
|
||||
text = replace_type_de_champ_tags(text, procedure.types_de_champ, dossier.champs)
|
||||
text = replace_type_de_champ_tags(text, procedure.types_de_champ_private, dossier.champs_private)
|
||||
|
||||
tags_and_datas = [
|
||||
[dossier_tags, dossier],
|
||||
[individual_tags, dossier.individual],
|
||||
[entreprise_tags, dossier.entreprise],
|
||||
[etablissement_tags, dossier.entreprise&.etablissement]]
|
||||
|
||||
tags_and_datas.inject(text) { |acc, (tags, data)| replace_tags_with_values_from_data(acc, tags, data) }
|
||||
end
|
||||
|
||||
def replace_type_de_champ_tags(text, types_de_champ, dossier_champs)
|
||||
types_de_champ.inject(text) do |acc, tag|
|
||||
value = dossier_champs
|
||||
.select { |champ| champ.libelle == tag[:libelle] }
|
||||
.first
|
||||
.value
|
||||
|
||||
acc.gsub("--#{tag[:libelle]}--", value.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
def replace_tags_with_values_from_data(text, tags, data)
|
||||
if data.present?
|
||||
tags.inject(text) do |acc, tag|
|
||||
acc.gsub("--#{tag[:libelle]}--", data.send(tag[:target].to_sym).to_s)
|
||||
end
|
||||
else
|
||||
text
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -170,6 +170,9 @@ class Dossier < ActiveRecord::Base
|
|||
end
|
||||
when 'close'
|
||||
if received?
|
||||
self.attestation = build_attestation
|
||||
save
|
||||
|
||||
closed!
|
||||
|
||||
if motivation
|
||||
|
@ -306,6 +309,12 @@ class Dossier < ActiveRecord::Base
|
|||
|
||||
private
|
||||
|
||||
def build_attestation
|
||||
if procedure.attestation_template.present? && procedure.attestation_template.activated?
|
||||
procedure.attestation_template.attestation_for(self)
|
||||
end
|
||||
end
|
||||
|
||||
def update_state_dates
|
||||
if initiated? && !self.initiated_at
|
||||
self.initiated_at = DateTime.now
|
||||
|
|
|
@ -73,4 +73,172 @@ describe AttestationTemplate, type: :model do
|
|||
it { expect(subject.signature.file.read).to eq(attestation_template.signature.file.read) }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'attestation_for' do
|
||||
let(:procedure) do
|
||||
create(:procedure,
|
||||
types_de_champ: types_de_champ,
|
||||
types_de_champ_private: types_de_champ_private,
|
||||
for_individual: for_individual)
|
||||
end
|
||||
let(:for_individual) { false }
|
||||
let(:individual) { nil }
|
||||
let(:etablissement) { nil }
|
||||
let(:entreprise) { create(:entreprise, etablissement: etablissement) }
|
||||
let(:types_de_champ) { [] }
|
||||
let(:types_de_champ_private) { [] }
|
||||
let(:dossier) { create(:dossier, procedure: procedure, individual: individual, entreprise: entreprise) }
|
||||
let(:template_title) { 'title' }
|
||||
let(:template_body) { 'body' }
|
||||
let(:attestation_template) do
|
||||
AttestationTemplate.new(procedure: procedure,
|
||||
title: template_title,
|
||||
body: template_body,
|
||||
logo: @logo,
|
||||
signature: @signature)
|
||||
end
|
||||
|
||||
before do
|
||||
@logo = File.open('spec/fixtures/white.png')
|
||||
@signature = File.open('spec/fixtures/black.png')
|
||||
Timecop.freeze(Time.now)
|
||||
end
|
||||
|
||||
after do
|
||||
@logo.close
|
||||
@signature.close
|
||||
end
|
||||
|
||||
let(:view_args) do
|
||||
original_new = ActionView::Base.method(:new)
|
||||
arguments = nil
|
||||
|
||||
allow(ActionView::Base).to receive(:new) do |paths, args|
|
||||
arguments = args
|
||||
original_new.call(paths, args)
|
||||
end
|
||||
|
||||
attestation_template.attestation_for(dossier)
|
||||
|
||||
arguments
|
||||
end
|
||||
|
||||
let(:attestation) { attestation_template.attestation_for(dossier) }
|
||||
|
||||
it 'provides a pseudo file' do
|
||||
expect(attestation.pdf.file).to exist
|
||||
expect(attestation.pdf.filename).to eq('attestation')
|
||||
end
|
||||
|
||||
context 'when the dossier and the procedure has an individual' do
|
||||
let(:for_individual) { true }
|
||||
let(:individual) { Individual.create(nom: 'nom', prenom: 'prenom', gender: 'Mme') }
|
||||
|
||||
context 'and the template title use the individual tags' do
|
||||
let(:template_title) { '--civilité-- --nom-- --prénom--' }
|
||||
|
||||
it { expect(view_args[:title]).to eq('Mme nom prenom') }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the dossier and the procedure has an entreprise' do
|
||||
let(:for_individual) { false }
|
||||
|
||||
context 'and the template title use the entreprise tags' do
|
||||
let(:template_title) do
|
||||
'--SIREN-- --numéro de TVA intracommunautaire-- --SIRET du siège social-- --raison sociale-- --adresse--'
|
||||
end
|
||||
|
||||
let(:expected_title) do
|
||||
"#{entreprise.siren} #{entreprise.numero_tva_intracommunautaire} #{entreprise.siret_siege_social} #{entreprise.raison_sociale} --adresse--"
|
||||
end
|
||||
|
||||
it { expect(view_args[:title]).to eq(expected_title) }
|
||||
|
||||
context 'and the entreprise has a etablissement with an adresse' do
|
||||
let(:etablissement) { create(:etablissement, adresse: 'adresse') }
|
||||
let(:template_title) { '--adresse--' }
|
||||
|
||||
it { expect(view_args[:title]).to eq('adresse') }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the procedure has a type de champ named libelleA et libelleB' do
|
||||
let(:types_de_champ) do
|
||||
[create(:type_de_champ_public, libelle: 'libelleA'),
|
||||
create(:type_de_champ_public, libelle: 'libelleB')]
|
||||
end
|
||||
|
||||
context 'and the template title is nil' do
|
||||
let(:template_title) { nil }
|
||||
|
||||
it { expect(view_args[:title]).to eq('') }
|
||||
end
|
||||
|
||||
context 'and it is not used in the template title nor body' do
|
||||
it { expect(view_args[:title]).to eq('title') }
|
||||
it { expect(view_args[:body]).to eq('body') }
|
||||
it { expect(view_args[:created_at]).to eq(Time.now) }
|
||||
it { expect(view_args[:logo]).to eq(attestation_template.logo) }
|
||||
it { expect(view_args[:signature]).to eq(attestation_template.signature) }
|
||||
end
|
||||
|
||||
context 'and the are used in the template title and body' do
|
||||
let(:template_title) { 'title --libelleA--' }
|
||||
let(:template_body) { 'body --libelleB--' }
|
||||
|
||||
context 'and their value in the dossier are nil' do
|
||||
it { expect(view_args[:title]).to eq('title ') }
|
||||
end
|
||||
|
||||
context 'and their value in the dossier are not nil' do
|
||||
before :each do
|
||||
dossier.champs
|
||||
.select { |champ| champ.libelle == 'libelleA' }
|
||||
.first
|
||||
.value = 'libelle1'
|
||||
|
||||
dossier.champs
|
||||
.select { |champ| champ.libelle == 'libelleB' }
|
||||
.first
|
||||
.value = 'libelle2'
|
||||
end
|
||||
|
||||
it { expect(view_args[:title]).to eq('title libelle1') }
|
||||
it { expect(view_args[:body]).to eq('body libelle2') }
|
||||
it { expect(attestation.title).to eq('title libelle1') }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the dossier has a motivation' do
|
||||
let(:dossier) { create(:dossier, motivation: 'motivation') }
|
||||
|
||||
context 'and the title has the motivation tag' do
|
||||
let(:template_title) { 'title --motivation--' }
|
||||
|
||||
it { expect(view_args[:title]).to eq('title motivation') }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the procedure has a type de champ prive named libelleA' do
|
||||
let(:types_de_champ_private) { [create(:type_de_champ_private, libelle: 'libelleA')] }
|
||||
|
||||
context 'and the are used in the template title' do
|
||||
let(:template_title) { 'title --libelleA--' }
|
||||
|
||||
context 'and its value in the dossier are not nil' do
|
||||
before :each do
|
||||
dossier.champs_private
|
||||
.select { |champ| champ.libelle == 'libelleA' }
|
||||
.first
|
||||
.value = 'libelle1'
|
||||
end
|
||||
|
||||
it { expect(view_args[:title]).to eq('title libelle1') }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -886,4 +886,34 @@ describe Dossier do
|
|||
expect(ActionMailer::Base.deliveries.size).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.build_attestation' do
|
||||
let(:attestation_template) { nil }
|
||||
let(:procedure) { create(:procedure, attestation_template: attestation_template) }
|
||||
|
||||
before :each do
|
||||
dossier.next_step!('gestionnaire', 'close')
|
||||
dossier.reload
|
||||
end
|
||||
|
||||
context 'when the dossier is in received state ' do
|
||||
let!(:dossier) { create(:dossier, procedure: procedure, state: :received) }
|
||||
|
||||
context 'when the procedure has no attestation' do
|
||||
it { expect(dossier.attestation).to be_nil }
|
||||
end
|
||||
|
||||
context 'when the procedure has an unactivated attestation' do
|
||||
let(:attestation_template) { AttestationTemplate.new(activated: false) }
|
||||
|
||||
it { expect(dossier.attestation).to be_nil }
|
||||
end
|
||||
|
||||
context 'when the procedure attached has an activated attestation' do
|
||||
let(:attestation_template) { AttestationTemplate.new(activated: true) }
|
||||
|
||||
it { expect(dossier.attestation).not_to be_nil }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue