Merge pull request #7238 from betagouv/accuse-de-depot

Ajout d'un accusé de dépôt téléchargeable (derrière un feature-flag)
This commit is contained in:
Pierre de La Morinerie 2022-05-04 16:13:23 +02:00 committed by GitHub
commit e75276727f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 259 additions and 2 deletions

View file

@ -5,7 +5,7 @@ module Users
layout 'procedure_context', only: [:identite, :update_identite, :siret, :update_siret] layout 'procedure_context', only: [:identite, :update_identite, :siret, :update_siret]
ACTIONS_ALLOWED_TO_ANY_USER = [:index, :recherche, :new, :transferer_all] ACTIONS_ALLOWED_TO_ANY_USER = [:index, :recherche, :new, :transferer_all]
ACTIONS_ALLOWED_TO_OWNER_OR_INVITE = [:show, :demande, :messagerie, :brouillon, :update_brouillon, :modifier, :update, :create_commentaire] ACTIONS_ALLOWED_TO_OWNER_OR_INVITE = [:show, :demande, :messagerie, :brouillon, :update_brouillon, :modifier, :update, :create_commentaire, :papertrail]
ACTIONS_ALLOWED_TO_OWNER_OR_INVITE_HIDDEN = [:restore] ACTIONS_ALLOWED_TO_OWNER_OR_INVITE_HIDDEN = [:restore]
before_action :ensure_ownership!, except: ACTIONS_ALLOWED_TO_ANY_USER + ACTIONS_ALLOWED_TO_OWNER_OR_INVITE + ACTIONS_ALLOWED_TO_OWNER_OR_INVITE_HIDDEN before_action :ensure_ownership!, except: ACTIONS_ALLOWED_TO_ANY_USER + ACTIONS_ALLOWED_TO_OWNER_OR_INVITE + ACTIONS_ALLOWED_TO_OWNER_OR_INVITE_HIDDEN
@ -69,6 +69,11 @@ module Users
end end
end end
def papertrail
raise ActionController::BadRequest if dossier.brouillon?
@dossier = dossier
end
def identite def identite
@dossier = dossier @dossier = dossier
@user = current_user @user = current_user

View file

@ -0,0 +1,19 @@
module PapertrailHelper
def papertrail_requester_identity(dossier)
if dossier.etablissement.present?
raison_sociale_or_name(dossier.etablissement)
else
[dossier.individual.prenom, dossier.individual.nom.upcase].join(' ')
end
end
def papertrail_dossier_state(dossier)
raise "Dossiers in 'brouillon' state are not supported" if dossier.brouillon?
# i18n-tasks-use t('users.dossiers.papertrail.dossier_state.en_construction')
# i18n-tasks-use t('users.dossiers.papertrail.dossier_state.en_instruction')
# i18n-tasks-use t('users.dossiers.papertrail.dossier_state.accepte')
# i18n-tasks-use t('users.dossiers.papertrail.dossier_state.refuse')
# i18n-tasks-use t('users.dossiers.papertrail.dossier_state.sans_suite')
I18n.t("users.dossiers.papertrail.states.#{dossier.state}")
end
end

View file

@ -0,0 +1,99 @@
require 'prawn/measurement_extensions'
#----- A4 page size
page_size = 'A4'
page_width = 595
#----- margins
top_margin = 20
right_margin = 20
bottom_margin = 20
left_margin = 20
header_width = page_width - left_margin - right_margin
body_width = 400
body_left_margin = (page_width - body_width - left_margin - right_margin) / 2
prawn_document(margin: [top_margin, right_margin, bottom_margin, left_margin], page_size: page_size) do |pdf|
pdf.font_families.update('marianne' => {
normal: Rails.root.join('lib/prawn/fonts/marianne/marianne-regular.ttf'),
bold: Rails.root.join('lib/prawn/fonts/marianne/marianne-bold.ttf')
})
pdf.font 'marianne'
grey = '555555'
black = '333333'
pdf.float do
pdf.svg IO.read(DOSSIER_DEPOSIT_RECEIPT_LOGO_SRC), height: 64
end
pdf.bounding_box([110, pdf.cursor - 18], width: header_width - 200) do
pdf.fill_color black
pdf.text APPLICATION_NAME, size: 20, style: :bold
pdf.fill_color grey
pdf.text t('.receipt'), size: 14
end
pdf.bounding_box([body_left_margin, pdf.cursor - 20], width: body_width) do
pdf.fill_color black
pdf.pad_top(40) { pdf.text @dossier.procedure.libelle, size: 14, character_spacing: -0.2, align: :center }
pdf.fill_color grey
description = t('.description', user_name: papertrail_requester_identity(@dossier), procedure: @dossier.procedure.libelle, date: l(@dossier.created_at, format: '%e %B %Y'))
pdf.pad_top(30) { pdf.text description, size: 10, character_spacing: -0.2, align: :left }
pdf.fill_color black
pdf.pad_top(30) { pdf.text t('views.shared.dossiers.demande.requester_identity'), size: 14, character_spacing: -0.2, align: :justify }
if @dossier.individual.present?
pdf.pad_top(7) do
pdf.fill_color grey
pdf.text "#{Individual.human_attribute_name(:prenom)} : #{@dossier.individual.prenom}", size: 10, character_spacing: -0.2, align: :justify
pdf.text "#{Individual.human_attribute_name(:nom)} : #{@dossier.individual.nom.upcase}", size: 10, character_spacing: -0.2, align: :justify
end
end
if @dossier.etablissement.present?
pdf.pad_top(7) do
pdf.fill_color grey
pdf.text "Dénomination : " + raison_sociale_or_name(@dossier.etablissement), size: 10, character_spacing: -0.2, align: :justify
pdf.text "SIRET : " + @dossier.etablissement.siret, size: 10, character_spacing: -0.2, align: :justify
end
end
pdf.fill_color black
pdf.pad_top(30) { pdf.text Dossier.model_name.human, size: 14, character_spacing: -0.2, align: :justify }
pdf.fill_color grey
pdf.pad_top(7) do
pdf.text "#{Dossier.human_attribute_name(:id)} : #{@dossier.id.to_s}", size: 10, character_spacing: -0.2, align: :justify
pdf.text t('.file_submitted_at') + ' : ' + l(@dossier.en_construction_at, format: '%e %B %Y'), size: 10, character_spacing: -0.2, align: :justify
pdf.text t('.dossier_state') + ' : ' + papertrail_dossier_state(@dossier), size: 10, character_spacing: -0.2, align: :justify
end
service = @dossier.procedure.service
if service.present?
pdf.fill_color black
pdf.pad_top(30) { pdf.text t('.administrative_service'), size: 14, character_spacing: -0.2, align: :justify }
pdf.fill_color grey
pdf.pad_top(7) do
pdf.text "#{Service.model_name.human} : " + [service.nom, service.organisme].join(", "), size: 10, character_spacing: -0.2, align: :justify
pdf.text "#{Service.human_attribute_name(:adresse)} : #{service.adresse}", size: 10, character_spacing: -0.2, align: :justify
pdf.text "#{Service.human_attribute_name(:email)} : #{service.email}", size: 10, character_spacing: -0.2, align: :justify
if service.telephone.present?
pdf.text "#{Service.human_attribute_name(:telephone)} : #{service.telephone}", size: 10, character_spacing: -0.2, align: :justify
end
end
end
pdf.fill_color black
pdf.pad_top(100) do
pdf.text t('.generated_at', date: l(Time.zone.now.to_date, format: :long)), size: 10, character_spacing: -0.2, align: :right
pdf.text t('.signature', app_name: APPLICATION_NAME), size: 10, character_spacing: -0.2, align: :right
end
end
end

View file

@ -9,5 +9,8 @@
.container .container
= render partial: 'users/dossiers/show/status_overview', locals: { dossier: @dossier } = render partial: 'users/dossiers/show/status_overview', locals: { dossier: @dossier }
- if @dossier.procedure.feature_enabled?(:procedure_dossier_papertrail)
= render partial: 'users/dossiers/show/papertrail', locals: { dossier: @dossier }
- if !@dossier.termine? - if !@dossier.termine?
= render partial: 'users/dossiers/show/latest_message', locals: { dossier: @dossier } = render partial: 'users/dossiers/show/latest_message', locals: { dossier: @dossier }

View file

@ -0,0 +1,4 @@
.papertrail.mb-2
= link_to papertrail_dossier_url(dossier, format: :pdf), class: "button", download: t('.filename'), target: "_blank" do
%span.icon.justificatif
= t('.get_papertrail')

View file

@ -68,6 +68,9 @@ DS_ENV="staging"
# Instance customization: Procedure default logo ---> to be put in "app/assets/images" # Instance customization: Procedure default logo ---> to be put in "app/assets/images"
# PROCEDURE_DEFAULT_LOGO_SRC="republique-francaise-logo.svg" # PROCEDURE_DEFAULT_LOGO_SRC="republique-francaise-logo.svg"
# Instance customization: Deposit receipt logo ---> to be put in "app/assets/images"
# DOSSIER_DEPOSIT_RECEIPT_LOGO_SRC="app/assets/images/republique-francaise-logo.svg"
# Instance customization: PDF export logo ---> to be put in "app/assets/images" # Instance customization: PDF export logo ---> to be put in "app/assets/images"
# DOSSIER_PDF_EXPORT_LOGO_SRC="app/assets/images/header/logo-ds-wide.svg" # DOSSIER_PDF_EXPORT_LOGO_SRC="app/assets/images/header/logo-ds-wide.svg"

View file

@ -32,7 +32,8 @@ features = [
:hide_instructeur_email, :hide_instructeur_email,
:procedure_revisions, :procedure_revisions,
:procedure_routage_api, :procedure_routage_api,
:procedure_process_expired_dossiers_termine :procedure_process_expired_dossiers_termine,
:procedure_dossier_papertrail
] ]
def database_exists? def database_exists?

View file

@ -16,5 +16,8 @@ MAILER_FOOTER_LOGO_SRC = ENV.fetch("MAILER_FOOTER_LOGO_SRC", "mailer/instructeur
# Default logo of a procedure # Default logo of a procedure
PROCEDURE_DEFAULT_LOGO_SRC = ENV.fetch("PROCEDURE_DEFAULT_LOGO_SRC", "republique-francaise-logo.svg") PROCEDURE_DEFAULT_LOGO_SRC = ENV.fetch("PROCEDURE_DEFAULT_LOGO_SRC", "republique-francaise-logo.svg")
# Deposit receipt logo
DOSSIER_DEPOSIT_RECEIPT_LOGO_SRC = ENV.fetch("DOSSIER_DEPOSIT_RECEIPT_LOGO_SRC", "app/assets/images/republique-francaise-logo.svg")
# Logo in PDF export of a "Dossier" # Logo in PDF export of a "Dossier"
DOSSIER_PDF_EXPORT_LOGO_SRC = ENV.fetch("DOSSIER_PDF_EXPORT_LOGO_SRC", "app/assets/images/header/logo-ds-wide.svg") DOSSIER_PDF_EXPORT_LOGO_SRC = ENV.fetch("DOSSIER_PDF_EXPORT_LOGO_SRC", "app/assets/images/header/logo-ds-wide.svg")

View file

@ -453,6 +453,24 @@ en:
identity_saved: "Identity data is registred" identity_saved: "Identity data is registred"
attestation: attestation:
no_longer_available: "The certificate is no longer available on this file." no_longer_available: "The certificate is no longer available on this file."
show:
papertrail:
get_papertrail: "Get a deposit receipt"
filename: "deposit-receipt.pdf"
papertrail:
receipt: "Deposit receipt"
description: "This document attests that on the %{date}, %{user_name} submitted a file on the procedure “%{procedure}”."
file_submitted_at: "File submission date"
dossier_state: "File status"
states:
en_construction: "submitted, pending processing"
en_instruction: "processing"
accepte: "accepted"
refuse: "declined"
sans suite: "closed, no further action"
administrative_service: "Administrative department"
generated_at: "Made on %{date},"
signature: "%{app_name}"
instructeurs: instructeurs:
dossiers: dossiers:
deleted_by_instructeur: "The folder has been deleted" deleted_by_instructeur: "The folder has been deleted"

View file

@ -461,6 +461,24 @@ fr:
identity_saved: "Identité enregistrée" identity_saved: "Identité enregistrée"
attestation: attestation:
no_longer_available: "Lattestation n'est plus disponible sur ce dossier." no_longer_available: "Lattestation n'est plus disponible sur ce dossier."
papertrail:
receipt: "Accusé de dépôt"
description: "Ce document atteste que %{user_name} a déposé le %{date} un dossier sur la démarche « %{procedure} »."
file_submitted_at: "Dossier déposé le"
dossier_state: "État du dossier"
states:
en_construction: "déposé, en attente dexamen par ladministration"
en_instruction: "en cours dinstruction par ladministration"
accepte: "accepté"
refuse: "refusé"
sans suite: "classé sans suite"
administrative_service: "Service administratif"
generated_at: "Fait le %{date},"
signature: "La direction de %{app_name}"
show:
papertrail:
get_papertrail: "Obtenir une attestation de dépôt de dossier"
filename: "attestation-de-depot.pdf"
instructeurs: instructeurs:
dossiers: dossiers:
deleted_by_instructeur: "Le dossier a bien été supprimé de votre interface" deleted_by_instructeur: "Le dossier a bien été supprimé de votre interface"

View file

@ -6,6 +6,7 @@ en:
other: "Files" other: "Files"
attributes: attributes:
dossier: dossier:
id: "File number"
state: "State" state: "State"
dossier/state: &state dossier/state: &state
brouillon: "Draft" brouillon: "Draft"

View file

@ -6,6 +6,7 @@ fr:
other: "Dossiers" other: "Dossiers"
attributes: attributes:
dossier: dossier:
id: "Numéro de dossier"
montant_projet: 'Le montant du projet' montant_projet: 'Le montant du projet'
montant_aide_demande: "Le montant daide demandée" montant_aide_demande: "Le montant daide demandée"
date_previsionnelle: "La date de début prévisionnelle" date_previsionnelle: "La date de début prévisionnelle"

View file

@ -0,0 +1,11 @@
en:
activerecord:
models:
service:
one: 'Service'
other: 'Services'
attributes:
service:
adresse: 'Mail address'
email: 'Email'
telephone: 'Phone'

View file

@ -1,4 +1,14 @@
fr: fr:
activerecord:
models:
service:
one: 'Service'
other: 'Services'
attributes:
service:
adresse: 'Adresse postale'
email: 'Email de contact'
telephone: 'Téléphone'
type_organisme: type_organisme:
administration_centrale: 'Administration centrale' administration_centrale: 'Administration centrale'
association: 'Association' association: 'Association'

View file

@ -273,6 +273,7 @@ Rails.application.routes.draw do
patch 'restore', to: 'dossiers#restore' patch 'restore', to: 'dossiers#restore'
get 'attestation' get 'attestation'
get 'transferer', to: 'dossiers#transferer' get 'transferer', to: 'dossiers#transferer'
get 'papertrail', format: :pdf
end end
collection do collection do

View file

@ -1011,6 +1011,31 @@ describe Users::DossiersController, type: :controller do
end end
end end
describe "#papertrail" do
before { sign_in(user) }
subject do
get :papertrail, format: :pdf, params: { id: dossier.id }
end
context 'when the dossier has been submitted' do
let(:dossier) { create(:dossier, :en_construction, user: user) }
it 'renders a PDF document' do
subject
expect(response).to render_template(:papertrail)
end
end
context 'when the dossier is still a draft' do
let(:dossier) { create(:dossier, :brouillon, user: user) }
it 'raises an error' do
expect { subject }.to raise_error(ActionController::BadRequest)
end
end
end
describe '#delete_dossier' do describe '#delete_dossier' do
before { sign_in(user) } before { sign_in(user) }

View file

@ -16,6 +16,16 @@ describe 'Dossier details:' do
expect(page).to have_text(dossier.commentaires.last.body) expect(page).to have_text(dossier.commentaires.last.body)
end end
context 'when the deposit receipt feature is enabled' do
before { Flipper.enable(:procedure_dossier_papertrail, procedure) }
after { Flipper.disable(:procedure_dossier_papertrail, procedure) }
it 'displays a link to download a deposit receipt' do
visit dossier_path(dossier)
expect(page).to have_link("Obtenir une attestation de dépôt de dossier", href: %r{dossiers/#{dossier.id}/papertrail.pdf})
end
end
describe "the user can see the mean time they are expected to wait" do describe "the user can see the mean time they are expected to wait" do
let(:other_dossier) { create(:dossier, :accepte, :with_individual, procedure: procedure, depose_at: 10.days.ago, en_instruction_at: 9.days.ago, processed_at: Time.zone.now) } let(:other_dossier) { create(:dossier, :accepte, :with_individual, procedure: procedure, depose_at: 10.days.ago, en_instruction_at: 9.days.ago, processed_at: Time.zone.now) }

View file

@ -0,0 +1,25 @@
describe 'users/dossiers/papertrail.pdf.prawn', type: :view do
before do
assign(:dossier, dossier)
end
subject { render }
context 'for a dossier with an individual' do
let(:dossier) { create(:dossier, :en_construction, :with_service, :with_individual) }
it 'renders a PDF document with the dossier state' do
subject
expect(rendered).to be_present
end
end
context 'for a dossier with a SIRET' do
let(:dossier) { create(:dossier, :en_construction, :with_service, :with_entreprise) }
it 'renders a PDF document with the dossier state' do
subject
expect(rendered).to be_present
end
end
end