feat(attestation): revise attestations

This commit is contained in:
Paul Chavard 2022-01-12 16:23:29 +01:00
parent c1cb89bb44
commit e413872530
13 changed files with 94 additions and 44 deletions

View file

@ -3,12 +3,17 @@ module Administrateurs
before_action :retrieve_procedure
def edit
@attestation_template = @procedure.attestation_template || AttestationTemplate.new(procedure: @procedure)
@attestation_template = build_attestation
end
def update
attestation_template = @procedure.attestation_template
attestation_template = @procedure.draft_attestation_template.revise!
if attestation_template.update(activated_attestation_params)
AttestationTemplate
.where(id: @procedure.revisions.pluck(:attestation_template_id).compact)
.update_all(activated: attestation_template.activated?)
flash.notice = "L'attestation a bien été modifiée"
else
flash.alert = attestation_template.errors.full_messages.join('<br>')
@ -18,7 +23,7 @@ module Administrateurs
end
def create
attestation_template = AttestationTemplate.new(activated_attestation_params.merge(procedure_id: @procedure.id))
attestation_template = build_attestation(activated_attestation_params)
if attestation_template.save
flash.notice = "L'attestation a bien été sauvegardée"
@ -30,14 +35,19 @@ module Administrateurs
end
def preview
attestation = @procedure.attestation_template || AttestationTemplate.new
@attestation = attestation.render_attributes_for({})
@attestation = build_attestation.render_attributes_for({})
render 'administrateurs/attestation_templates/show', formats: [:pdf]
end
private
def build_attestation(attributes = {})
attestation_template = @procedure.draft_attestation_template || @procedure.draft_revision.build_attestation_template
attestation_template.attributes = attributes
attestation_template
end
def activated_attestation_params
# cache result to avoid multiple uninterlaced computations
if @activated_attestation_params.nil?

View file

@ -15,7 +15,8 @@ class AttestationTemplate < ApplicationRecord
include ActionView::Helpers::NumberHelper
include TagsSubstitutionConcern
belongs_to :procedure, optional: false
belongs_to :procedure, optional: true
has_many :revisions, class_name: 'ProcedureRevision', inverse_of: :attestation_template, dependent: :nullify
has_one_attached :logo
has_one_attached :signature
@ -103,6 +104,25 @@ class AttestationTemplate < ApplicationRecord
}
end
def revise!
if revisions.size > 1
attestation_template = dup
attestation_template.save!
revisions
.last
.procedure
.draft_revision
.update!(attestation_template: attestation_template)
attestation_template
else
self
end
end
def procedure
revisions.last&.procedure || super
end
private
def used_tags

View file

@ -720,9 +720,11 @@ class Dossier < ApplicationRecord
{ lon: lon, lat: lat, zoom: zoom }
end
def unspecified_attestation_champs
attestation_template = procedure.attestation_template
def attestation_template
revision.attestation_template
end
def unspecified_attestation_champs
if attestation_template&.activated?
attestation_template.unspecified_champs_for_dossier(self)
else
@ -731,8 +733,8 @@ class Dossier < ApplicationRecord
end
def build_attestation
if procedure.attestation_template&.activated?
procedure.attestation_template.attestation_for(self)
if attestation_template&.activated?
attestation_template.attestation_for(self)
end
end

View file

@ -77,12 +77,15 @@ class Procedure < ApplicationRecord
has_many :published_types_de_champ_private, through: :published_revision, source: :types_de_champ_private
has_many :draft_types_de_champ, through: :draft_revision, source: :types_de_champ
has_many :draft_types_de_champ_private, through: :draft_revision, source: :types_de_champ_private
has_one :draft_attestation_template, through: :draft_revision, source: :attestation_template
has_one :published_attestation_template, through: :published_revision, source: :attestation_template
has_many :experts_procedures, dependent: :destroy
has_many :experts, through: :experts_procedures
has_one :module_api_carto, dependent: :destroy
has_one :attestation_template, dependent: :destroy
has_many :attestation_templates, through: :revisions, source: :attestation_template
belongs_to :parent_procedure, class_name: 'Procedure', optional: true
belongs_to :canonical_procedure, class_name: 'Procedure', optional: true
@ -434,7 +437,8 @@ class Procedure < ApplicationRecord
},
revision_types_de_champ_private: {
type_de_champ: :types_de_champ
}
},
attestation_template: []
}
}
include_list[:groupe_instructeurs] = :instructeurs if !is_different_admin
@ -572,13 +576,17 @@ class Procedure < ApplicationRecord
touch(:whitelisted_at)
end
def active_attestation_template
published_attestation_template || draft_attestation_template
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.to_s.include?("--lien attestation--")
if attestation_template&.activated? && !tag_present
if active_attestation_template&.activated? && !tag_present
:missing_tag
elsif !attestation_template&.activated? && tag_present
elsif !active_attestation_template&.activated? && tag_present
:extraneous_tag
end
end

View file

@ -2,15 +2,17 @@
#
# Table name: procedure_revisions
#
# id :bigint not null, primary key
# published_at :datetime
# created_at :datetime not null
# updated_at :datetime not null
# procedure_id :bigint not null
# id :bigint not null, primary key
# published_at :datetime
# created_at :datetime not null
# updated_at :datetime not null
# attestation_template_id :bigint
# procedure_id :bigint not null
#
class ProcedureRevision < ApplicationRecord
self.implicit_order_column = :created_at
belongs_to :procedure, -> { with_discarded }, inverse_of: :revisions, optional: false
belongs_to :attestation_template, inverse_of: :revisions, optional: true, dependent: :destroy
has_many :dossiers, inverse_of: :revision, foreign_key: :revision_id
@ -125,6 +127,10 @@ class ProcedureRevision < ApplicationRecord
)
end
def attestation_template
super || procedure.attestation_template
end
private
def compare_types_de_champ(from_tdc, to_tdc)

View file

@ -138,7 +138,7 @@
.procedure-grid
= link_to edit_admin_procedure_attestation_template_path(@procedure), class: 'card-admin' do
- if @procedure.attestation_template.present? && @procedure.attestation_template.activated
- if @procedure.draft_attestation_template&.activated?
%div
%span.icon.accept
%p.card-admin-status-accept Activée

View file

@ -0,0 +1,5 @@
class AddAttestationTemplateIdToProcedureRevisions < ActiveRecord::Migration[6.1]
def change
add_reference :procedure_revisions, :attestation_template, foreign_key: { to_table: :attestation_templates }, null: true, index: true
end
end

View file

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2021_12_02_133139) do
ActiveRecord::Schema.define(version: 2022_01_10_133139) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -593,6 +593,8 @@ ActiveRecord::Schema.define(version: 2021_12_02_133139) do
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "published_at"
t.bigint "attestation_template_id"
t.index ["attestation_template_id"], name: "index_procedure_revisions_on_attestation_template_id"
t.index ["procedure_id"], name: "index_procedure_revisions_on_procedure_id"
end
@ -872,6 +874,7 @@ ActiveRecord::Schema.define(version: 2021_12_02_133139) do
add_foreign_key "procedure_revision_types_de_champ", "procedure_revision_types_de_champ", column: "parent_id"
add_foreign_key "procedure_revision_types_de_champ", "procedure_revisions", column: "revision_id"
add_foreign_key "procedure_revision_types_de_champ", "types_de_champ"
add_foreign_key "procedure_revisions", "attestation_templates"
add_foreign_key "procedure_revisions", "procedures"
add_foreign_key "procedures", "procedure_revisions", column: "draft_revision_id"
add_foreign_key "procedures", "procedure_revisions", column: "published_revision_id"

View file

@ -1,8 +1,8 @@
include ActionDispatch::TestProcess
describe Administrateurs::AttestationTemplatesController, type: :controller do
let!(:attestation_template) { create(:attestation_template) }
let(:admin) { create(:administrateur) }
let(:attestation_template) { build(:attestation_template) }
let!(:procedure) { create :procedure, administrateur: admin, attestation_template: attestation_template }
let(:logo) { fixture_file_upload('spec/fixtures/files/white.png', 'image/png') }
let(:logo2) { fixture_file_upload('spec/fixtures/files/white.png', 'image/png') }
@ -41,7 +41,7 @@ describe Administrateurs::AttestationTemplatesController, type: :controller do
end
context 'if an attestation template exists on the procedure' do
after { procedure.attestation_template.destroy }
after { procedure.draft_revision.attestation_template&.destroy }
context 'with images' do
let!(:attestation_template) do
@ -115,14 +115,14 @@ describe Administrateurs::AttestationTemplatesController, type: :controller do
procedure.reload
end
it { expect(procedure.attestation_template).to have_attributes(attestation_params) }
it { expect(procedure.attestation_template.activated).to be true }
it { expect(procedure.attestation_template.logo.download).to eq(logo2.read) }
it { expect(procedure.attestation_template.signature.download).to eq(signature2.read) }
it { expect(procedure.draft_attestation_template).to have_attributes(attestation_params) }
it { expect(procedure.draft_attestation_template.activated).to be true }
it { expect(procedure.draft_attestation_template.logo.download).to eq(logo2.read) }
it { expect(procedure.draft_attestation_template.signature.download).to eq(signature2.read) }
it { expect(response).to redirect_to edit_admin_procedure_attestation_template_path(procedure) }
it { expect(flash.notice).to eq("L'attestation a bien été sauvegardée") }
after { procedure.attestation_template.destroy }
after { procedure.draft_attestation_template.destroy }
end
context 'when something wrong happens in the attestation template creation' do
@ -140,7 +140,7 @@ describe Administrateurs::AttestationTemplatesController, type: :controller do
it { expect(response).to redirect_to edit_admin_procedure_attestation_template_path(procedure) }
it { expect(flash.alert).to be_present }
it { expect(procedure.attestation_template).to be nil }
it { expect(procedure.draft_attestation_template).to be nil }
end
end
@ -158,13 +158,13 @@ describe Administrateurs::AttestationTemplatesController, type: :controller do
procedure.reload
end
it { expect(procedure.attestation_template).to have_attributes(attestation_params) }
it { expect(procedure.attestation_template.logo.download).to eq(logo2.read) }
it { expect(procedure.attestation_template.signature.download).to eq(signature2.read) }
it { expect(procedure.draft_attestation_template).to have_attributes(attestation_params) }
it { expect(procedure.draft_attestation_template.logo.download).to eq(logo2.read) }
it { expect(procedure.draft_attestation_template.signature.download).to eq(signature2.read) }
it { expect(response).to redirect_to edit_admin_procedure_attestation_template_path(procedure) }
it { expect(flash.notice).to eq("L'attestation a bien été modifiée") }
after { procedure.attestation_template.destroy }
after { procedure.draft_attestation_template&.destroy }
end
context 'when something wrong happens in the attestation template creation' do

View file

@ -4,8 +4,6 @@ FactoryBot.define do
body { 'body' }
footer { 'footer' }
activated { true }
association :procedure
end
trait :with_files do

View file

@ -23,10 +23,11 @@ FactoryBot.define do
types_de_champ { [] }
types_de_champ_private { [] }
updated_at { nil }
attestation_template { }
end
after(:build) do |procedure, evaluator|
initial_revision = build(:procedure_revision, procedure: procedure)
initial_revision = build(:procedure_revision, procedure: procedure, attestation_template: evaluator.attestation_template)
add_types_de_champs(evaluator.types_de_champ, to: initial_revision, scope: :public)
add_types_de_champs(evaluator.types_de_champ_private, to: initial_revision, scope: :private)

View file

@ -66,16 +66,12 @@ describe Procedure do
end
describe '#closed_mail_template_attestation_inconsistency_state' do
let(:procedure_without_attestation) { create(:procedure, closed_mail: closed_mail) }
let(:procedure_without_attestation) { create(:procedure, closed_mail: closed_mail, attestation_template: nil) }
let(:procedure_with_active_attestation) do
procedure = create(:procedure, closed_mail: closed_mail)
create(:attestation_template, procedure: procedure, activated: true)
procedure
create(:procedure, closed_mail: closed_mail, attestation_template: build(:attestation_template, activated: true))
end
let(:procedure_with_inactive_attestation) do
procedure = create(:procedure, closed_mail: closed_mail)
create(:attestation_template, procedure: procedure, activated: false)
procedure
create(:procedure, closed_mail: closed_mail, attestation_template: build(:attestation_template, activated: false))
end
subject { procedure.closed_mail_template_attestation_inconsistency_state }

View file

@ -1,5 +1,6 @@
describe 'admin/_closed_mail_template_attestation_inconsistency_alert.html.haml', type: :view do
let(:procedure) { create(:procedure, closed_mail: closed_mail) }
let(:procedure) { create(:procedure, closed_mail: closed_mail, attestation_template: attestation_template) }
let(:attestation_template) { nil }
def alert
assign(:procedure, procedure)
@ -23,7 +24,7 @@ describe 'admin/_closed_mail_template_attestation_inconsistency_alert.html.haml'
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) }
let(:attestation_template) { build(:attestation_template) }
it { expect(alert).to include("Cette démarche 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)) }