From 9bc5364ca242f208451bd4237484a36581f637c8 Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Wed, 4 May 2022 06:57:14 +0000 Subject: [PATCH] app: add controller and view to generate a deposit receipt --- app/controllers/users/dossiers_controller.rb | 7 +- app/helpers/papertrail_helper.rb | 19 ++++ app/views/users/dossiers/papertrail.pdf.prawn | 99 +++++++++++++++++++ app/views/users/dossiers/show.html.haml | 3 + config/env.example.optional | 3 + config/initializers/images.rb | 3 + config/locales/en.yml | 14 +++ config/locales/fr.yml | 14 +++ config/locales/models/dossier/en.yml | 1 + config/locales/models/dossier/fr.yml | 1 + config/locales/models/service/en.yml | 11 +++ config/locales/models/service/fr.yml | 10 ++ config/routes.rb | 1 + .../users/dossiers_controller_spec.rb | 25 +++++ .../dossiers/papertrail.pdf.prawl_spec.rb | 25 +++++ 15 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 app/helpers/papertrail_helper.rb create mode 100644 app/views/users/dossiers/papertrail.pdf.prawn create mode 100644 config/locales/models/service/en.yml create mode 100644 spec/views/users/dossiers/papertrail.pdf.prawl_spec.rb diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index 765b4b19b..856c110da 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -5,7 +5,7 @@ module Users layout 'procedure_context', only: [:identite, :update_identite, :siret, :update_siret] 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] 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 + def papertrail + raise ActionController::BadRequest if dossier.brouillon? + @dossier = dossier + end + def identite @dossier = dossier @user = current_user diff --git a/app/helpers/papertrail_helper.rb b/app/helpers/papertrail_helper.rb new file mode 100644 index 000000000..bbe8845d3 --- /dev/null +++ b/app/helpers/papertrail_helper.rb @@ -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 diff --git a/app/views/users/dossiers/papertrail.pdf.prawn b/app/views/users/dossiers/papertrail.pdf.prawn new file mode 100644 index 000000000..937c86b2b --- /dev/null +++ b/app/views/users/dossiers/papertrail.pdf.prawn @@ -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 diff --git a/app/views/users/dossiers/show.html.haml b/app/views/users/dossiers/show.html.haml index 2ec8ab29d..deeb7cd3b 100644 --- a/app/views/users/dossiers/show.html.haml +++ b/app/views/users/dossiers/show.html.haml @@ -9,5 +9,8 @@ .container = 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? = render partial: 'users/dossiers/show/latest_message', locals: { dossier: @dossier } diff --git a/config/env.example.optional b/config/env.example.optional index e19e0d6b5..2504fe14f 100644 --- a/config/env.example.optional +++ b/config/env.example.optional @@ -68,6 +68,9 @@ DS_ENV="staging" # Instance customization: Procedure default logo ---> to be put in "app/assets/images" # 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" # DOSSIER_PDF_EXPORT_LOGO_SRC="app/assets/images/header/logo-ds-wide.svg" diff --git a/config/initializers/images.rb b/config/initializers/images.rb index c488aa279..bfa9e34f3 100644 --- a/config/initializers/images.rb +++ b/config/initializers/images.rb @@ -16,5 +16,8 @@ MAILER_FOOTER_LOGO_SRC = ENV.fetch("MAILER_FOOTER_LOGO_SRC", "mailer/instructeur # Default logo of a procedure 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" DOSSIER_PDF_EXPORT_LOGO_SRC = ENV.fetch("DOSSIER_PDF_EXPORT_LOGO_SRC", "app/assets/images/header/logo-ds-wide.svg") diff --git a/config/locales/en.yml b/config/locales/en.yml index ee9040130..116227801 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -453,6 +453,20 @@ en: identity_saved: "Identity data is registred" attestation: no_longer_available: "The certificate is no longer available on this file." + 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: dossiers: deleted_by_instructeur: "The folder has been deleted" diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 177b44dd4..619b3c8dd 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -461,6 +461,20 @@ fr: identity_saved: "Identité enregistrée" attestation: no_longer_available: "L’attestation 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 d’examen par l’administration" + en_instruction: "en cours d’instruction par l’administration" + accepte: "accepté" + refuse: "refusé" + sans suite: "classé sans suite" + administrative_service: "Service administratif" + generated_at: "Fait le %{date}," + signature: "La direction de %{app_name}" instructeurs: dossiers: deleted_by_instructeur: "Le dossier a bien été supprimé de votre interface" diff --git a/config/locales/models/dossier/en.yml b/config/locales/models/dossier/en.yml index c9bb7d046..19fe8ff63 100644 --- a/config/locales/models/dossier/en.yml +++ b/config/locales/models/dossier/en.yml @@ -6,6 +6,7 @@ en: other: "Files" attributes: dossier: + id: "File number" state: "State" dossier/state: &state brouillon: "Draft" diff --git a/config/locales/models/dossier/fr.yml b/config/locales/models/dossier/fr.yml index 1fb503dff..7f9f119c7 100644 --- a/config/locales/models/dossier/fr.yml +++ b/config/locales/models/dossier/fr.yml @@ -6,6 +6,7 @@ fr: other: "Dossiers" attributes: dossier: + id: "Numéro de dossier" montant_projet: 'Le montant du projet' montant_aide_demande: "Le montant d’aide demandée" date_previsionnelle: "La date de début prévisionnelle" diff --git a/config/locales/models/service/en.yml b/config/locales/models/service/en.yml new file mode 100644 index 000000000..5d3012f12 --- /dev/null +++ b/config/locales/models/service/en.yml @@ -0,0 +1,11 @@ +en: + activerecord: + models: + service: + one: 'Service' + other: 'Services' + attributes: + service: + adresse: 'Mail address' + email: 'Email' + telephone: 'Phone' diff --git a/config/locales/models/service/fr.yml b/config/locales/models/service/fr.yml index c9792d965..c1e7fed72 100644 --- a/config/locales/models/service/fr.yml +++ b/config/locales/models/service/fr.yml @@ -1,4 +1,14 @@ fr: + activerecord: + models: + service: + one: 'Service' + other: 'Services' + attributes: + service: + adresse: 'Adresse postale' + email: 'Email de contact' + telephone: 'Téléphone' type_organisme: administration_centrale: 'Administration centrale' association: 'Association' diff --git a/config/routes.rb b/config/routes.rb index 34400251f..24d75f346 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -273,6 +273,7 @@ Rails.application.routes.draw do patch 'restore', to: 'dossiers#restore' get 'attestation' get 'transferer', to: 'dossiers#transferer' + get 'papertrail', format: :pdf end collection do diff --git a/spec/controllers/users/dossiers_controller_spec.rb b/spec/controllers/users/dossiers_controller_spec.rb index f8a1faf9e..8eb4013d3 100644 --- a/spec/controllers/users/dossiers_controller_spec.rb +++ b/spec/controllers/users/dossiers_controller_spec.rb @@ -1011,6 +1011,31 @@ describe Users::DossiersController, type: :controller do 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 before { sign_in(user) } diff --git a/spec/views/users/dossiers/papertrail.pdf.prawl_spec.rb b/spec/views/users/dossiers/papertrail.pdf.prawl_spec.rb new file mode 100644 index 000000000..c0b5483a5 --- /dev/null +++ b/spec/views/users/dossiers/papertrail.pdf.prawl_spec.rb @@ -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