commit
58221c8e8a
38 changed files with 1154 additions and 19 deletions
12
Gemfile
12
Gemfile
|
@ -52,6 +52,7 @@ gem 'rest-client'
|
|||
gem 'clamav-client', require: 'clamav/client'
|
||||
|
||||
gem 'carrierwave'
|
||||
gem 'copy_carrierwave_file'
|
||||
gem 'fog'
|
||||
gem 'fog-openstack'
|
||||
|
||||
|
@ -101,6 +102,12 @@ gem 'sinatra', git: 'https://github.com/sinatra/sinatra.git', require: false
|
|||
|
||||
gem 'select2-rails'
|
||||
|
||||
# PDF Generation
|
||||
gem 'prawn', '~> 2.0.1'
|
||||
gem 'prawn_rails', '~> 0.0.11'
|
||||
|
||||
gem 'sentry-raven'
|
||||
|
||||
group :test do
|
||||
gem 'capybara'
|
||||
gem 'launchy'
|
||||
|
@ -143,8 +150,3 @@ group :development, :test do
|
|||
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
|
||||
gem 'dotenv-rails'
|
||||
end
|
||||
|
||||
group :production, :staging do
|
||||
gem 'sentry-raven'
|
||||
end
|
||||
|
||||
|
|
13
Gemfile.lock
13
Gemfile.lock
|
@ -120,6 +120,8 @@ GEM
|
|||
coffee-script-source (1.12.2)
|
||||
concurrent-ruby (1.0.5)
|
||||
connection_pool (2.2.1)
|
||||
copy_carrierwave_file (1.3.0)
|
||||
carrierwave (>= 0.9)
|
||||
crack (0.4.3)
|
||||
safe_yaml (~> 1.0.0)
|
||||
database_cleaner (1.5.3)
|
||||
|
@ -420,12 +422,19 @@ GEM
|
|||
parallel (1.11.2)
|
||||
parser (2.4.0.0)
|
||||
ast (~> 2.2)
|
||||
pdf-core (0.6.1)
|
||||
pg (0.19.0)
|
||||
poltergeist (1.14.0)
|
||||
capybara (~> 2.1)
|
||||
cliver (~> 0.3.1)
|
||||
websocket-driver (>= 0.2.0)
|
||||
powerpack (0.1.1)
|
||||
prawn (2.0.2)
|
||||
pdf-core (~> 0.6.0)
|
||||
ttfunk (~> 1.4.0)
|
||||
prawn_rails (0.0.11)
|
||||
prawn (>= 0.11.1)
|
||||
railties (>= 3.0.0)
|
||||
pry (0.10.4)
|
||||
coderay (~> 1.1.0)
|
||||
method_source (~> 0.8.1)
|
||||
|
@ -611,6 +620,7 @@ GEM
|
|||
tilt (2.0.5)
|
||||
timecop (0.8.1)
|
||||
trollop (2.1.2)
|
||||
ttfunk (1.4.0)
|
||||
turbolinks (5.0.1)
|
||||
turbolinks-source (~> 5)
|
||||
turbolinks-source (5.0.0)
|
||||
|
@ -677,6 +687,7 @@ DEPENDENCIES
|
|||
carrierwave
|
||||
chartkick
|
||||
clamav-client
|
||||
copy_carrierwave_file
|
||||
database_cleaner
|
||||
deep_cloneable (~> 2.2.1)
|
||||
devise
|
||||
|
@ -706,6 +717,8 @@ DEPENDENCIES
|
|||
openstack
|
||||
pg
|
||||
poltergeist
|
||||
prawn (~> 2.0.1)
|
||||
prawn_rails (~> 0.0.11)
|
||||
pry-byebug
|
||||
rack-handlers
|
||||
rails (= 5.0.0.1)
|
||||
|
|
1
app/assets/images/pdf.svg
Normal file
1
app/assets/images/pdf.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="550.801" height="550.801" viewBox="0 0 550.801 550.801"><path d="M160.381 282.225c0-14.832-10.299-23.684-28.474-23.684-7.414 0-12.437.715-15.071 1.432V307.6c3.114.707 6.942.949 12.192.949 19.391 0 31.353-9.809 31.353-26.324zM272.875 259.019c-8.145 0-13.397.717-16.519 1.435v105.523c3.116.729 8.142.729 12.69.729 33.017.231 54.554-17.946 54.554-56.474.242-33.513-19.385-51.213-50.725-51.213z"/><path d="M488.426 197.019H475.2v-63.816c0-.398-.063-.799-.116-1.202-.021-2.534-.827-5.023-2.562-6.995L366.325 3.694c-.032-.031-.063-.042-.085-.076-.633-.707-1.371-1.295-2.151-1.804a9.495 9.495 0 0 0-.706-.419 11.131 11.131 0 0 0-2.131-.896c-.2-.056-.38-.138-.58-.19A10.774 10.774 0 0 0 358.193 0H97.2C85.282 0 75.6 9.693 75.6 21.601v175.413H62.377c-17.049 0-30.873 13.818-30.873 30.873v160.545c0 17.043 13.824 30.87 30.873 30.87h13.224V529.2c0 11.907 9.682 21.601 21.6 21.601h356.4c11.907 0 21.6-9.693 21.6-21.601V419.302h13.226c17.044 0 30.871-13.827 30.871-30.87v-160.54c-.001-17.054-13.828-30.873-30.872-30.873zM97.2 21.605h250.193v110.513c0 5.967 4.841 10.8 10.8 10.8H453.6v54.108H97.2V21.605zm265.159 287.418c0 30.876-11.243 52.165-26.82 65.333-16.971 14.117-42.82 20.814-74.396 20.814-18.9 0-32.297-1.197-41.401-2.389V234.365c13.399-2.149 30.878-3.346 49.304-3.346 30.612 0 50.478 5.508 66.039 17.226 16.743 12.445 27.274 32.302 27.274 60.778zM80.7 393.499V234.365c11.241-1.904 27.042-3.346 49.296-3.346 22.491 0 38.527 4.308 49.291 12.928 10.292 8.131 17.215 21.534 17.215 37.328 0 15.799-5.25 29.198-14.829 38.285-12.442 11.728-30.865 16.996-52.407 16.996-4.778 0-9.1-.243-12.435-.723v57.67H80.7v-.004zm372.901 129.854H97.2V419.302h356.4v104.051zm31.297-261.226h-61.989v36.851h57.913v29.674h-57.913V393.5h-36.593V232.216h98.582v29.911z"/></svg>
|
After Width: | Height: | Size: 1.8 KiB |
|
@ -44,6 +44,8 @@
|
|||
// = require switch_menu
|
||||
// = require typeahead
|
||||
// = require users
|
||||
// = require attestation_template_edit
|
||||
// = require attestation_recapitulatif
|
||||
|
||||
// = require_self
|
||||
// = require bootstrap-datepicker3
|
||||
|
|
31
app/assets/stylesheets/attestation_recapitulatif.scss
Normal file
31
app/assets/stylesheets/attestation_recapitulatif.scss
Normal file
|
@ -0,0 +1,31 @@
|
|||
#attestation-recapitulatif {
|
||||
margin-top: 40px;
|
||||
|
||||
.details {
|
||||
padding: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-color: #FFFFFF;
|
||||
|
||||
.left {
|
||||
position: relative;
|
||||
padding-left: 30px;
|
||||
|
||||
img {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 15px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.delivery {
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
30
app/assets/stylesheets/attestation_template_edit.scss
Normal file
30
app/assets/stylesheets/attestation_template_edit.scss
Normal file
|
@ -0,0 +1,30 @@
|
|||
#attestation-template-edit {
|
||||
.notice {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.image-upload {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
input {
|
||||
margin: 10px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
width: 90px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.balises {
|
||||
max-height: 180px;
|
||||
overflow-y: scroll;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.table {
|
||||
border: 1px solid #DDDDDD;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
}
|
74
app/controllers/admin/attestation_templates_controller.rb
Normal file
74
app/controllers/admin/attestation_templates_controller.rb
Normal file
|
@ -0,0 +1,74 @@
|
|||
class Admin::AttestationTemplatesController < AdminController
|
||||
before_action :retrieve_procedure
|
||||
|
||||
def show
|
||||
attestation_template = @procedure.attestation_template
|
||||
@logo = attestation_template.logo
|
||||
@title = attestation_template.title
|
||||
@body = attestation_template.body
|
||||
@signature = attestation_template.signature
|
||||
@footer = attestation_template.footer
|
||||
@created_at = DateTime.now
|
||||
end
|
||||
|
||||
def edit
|
||||
@attestation_template = @procedure.attestation_template || AttestationTemplate.new(procedure: @procedure)
|
||||
end
|
||||
|
||||
def update
|
||||
attestation_template = @procedure.attestation_template
|
||||
|
||||
if attestation_template.update_attributes(activated_attestation_params)
|
||||
flash.notice = "L'attestation a bien été modifiée"
|
||||
else
|
||||
flash.alert = attestation_template.errors.full_messages.join('<br>')
|
||||
end
|
||||
|
||||
redirect_to edit_admin_procedure_attestation_template_path(@procedure)
|
||||
end
|
||||
|
||||
def create
|
||||
attestation_template = AttestationTemplate.new(activated_attestation_params.merge(procedure_id: @procedure.id))
|
||||
|
||||
if attestation_template.save
|
||||
flash.notice = "L'attestation a bien été sauvegardée"
|
||||
else
|
||||
flash.alert = attestation_template.errors.full_messages.join('<br>')
|
||||
end
|
||||
|
||||
redirect_to edit_admin_procedure_attestation_template_path(@procedure)
|
||||
end
|
||||
|
||||
def disactivate
|
||||
attestation_template = @procedure.attestation_template
|
||||
attestation_template.activated = false
|
||||
attestation_template.save
|
||||
|
||||
flash.notice = "L'attestation a bien été désactivée"
|
||||
|
||||
redirect_to edit_admin_procedure_attestation_template_path(@procedure)
|
||||
end
|
||||
|
||||
def preview
|
||||
@title = activated_attestation_params[:title]
|
||||
@body = activated_attestation_params[:body]
|
||||
@footer = activated_attestation_params[:footer]
|
||||
@created_at = DateTime.now
|
||||
|
||||
# In a case of a preview, when the user does not change its images,
|
||||
# the images are not uploaded and thus should be retrieved from previous
|
||||
# attestation_template
|
||||
@logo = activated_attestation_params[:logo] || @procedure.attestation_template&.logo
|
||||
@signature = activated_attestation_params[:signature] || @procedure.attestation_template&.signature
|
||||
|
||||
render 'admin/attestation_templates/show', formats: [:pdf]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def activated_attestation_params
|
||||
params.require(:attestation_template)
|
||||
.permit(:title, :body, :footer, :logo, :signature)
|
||||
.merge(activated: true)
|
||||
end
|
||||
end
|
|
@ -1,4 +1,6 @@
|
|||
class Backoffice::DossiersController < Backoffice::DossiersListController
|
||||
include ActionView::Helpers::NumberHelper
|
||||
|
||||
respond_to :html, :xlsx, :ods, :csv
|
||||
|
||||
prepend_before_action :store_current_location, only: :show
|
||||
|
@ -112,6 +114,8 @@ class Backoffice::DossiersController < Backoffice::DossiersListController
|
|||
|
||||
dossier = @facade.dossier
|
||||
|
||||
attestation_pdf = nil
|
||||
|
||||
case params[:process_action]
|
||||
when "refuse"
|
||||
next_step = "refuse"
|
||||
|
@ -125,12 +129,15 @@ class Backoffice::DossiersController < Backoffice::DossiersListController
|
|||
next_step = "close"
|
||||
notice = "Dossier traité avec succès."
|
||||
template = dossier.procedure.closed_mail_template
|
||||
if check_attestation_emailable(dossier)
|
||||
attestation_pdf = dossier.attestation.pdf.read
|
||||
end
|
||||
end
|
||||
|
||||
dossier.next_step! 'gestionnaire', next_step, motivation
|
||||
flash.notice = notice
|
||||
|
||||
NotificationMailer.send_notification(dossier, template).deliver_now!
|
||||
NotificationMailer.send_notification(dossier, template, attestation_pdf).deliver_now!
|
||||
|
||||
redirect_to backoffice_dossier_path(id: dossier.id)
|
||||
end
|
||||
|
@ -185,6 +192,16 @@ class Backoffice::DossiersController < Backoffice::DossiersListController
|
|||
|
||||
private
|
||||
|
||||
def check_attestation_emailable(dossier)
|
||||
if dossier&.attestation&.emailable? == false
|
||||
human_size = number_to_human_size(dossier.attestation.pdf.size)
|
||||
msg = "the attestation of the dossier #{dossier.id} cannot be mailed because it is too heavy: #{human_size}"
|
||||
capture_message(msg, level: 'error')
|
||||
end
|
||||
|
||||
dossier&.attestation&.emailable?
|
||||
end
|
||||
|
||||
def store_current_location
|
||||
if !gestionnaire_signed_in?
|
||||
store_location_for(:gestionnaire, request.url)
|
||||
|
|
|
@ -7,6 +7,10 @@ class Users::RecapitulatifController < UsersController
|
|||
create_dossier_facade
|
||||
end
|
||||
|
||||
def attestation
|
||||
send_data(current_user_dossier.attestation.pdf.read, filename: 'attestation.pdf', type: 'application/pdf')
|
||||
end
|
||||
|
||||
def initiate
|
||||
create_dossier_facade
|
||||
|
||||
|
|
|
@ -3,12 +3,16 @@ class NotificationMailer < ApplicationMailer
|
|||
|
||||
after_action :create_commentaire_for_notification, only: :send_notification
|
||||
|
||||
def send_notification(dossier, mail_template)
|
||||
def send_notification(dossier, mail_template, attestation = nil)
|
||||
vars_mailer(dossier)
|
||||
|
||||
@object = mail_template.object_for_dossier dossier
|
||||
@body = mail_template.body_for_dossier dossier
|
||||
|
||||
if attestation.present?
|
||||
attachments['attestation.pdf'] = attestation
|
||||
end
|
||||
|
||||
mail(subject: @object) { |format| format.html { @body } }
|
||||
end
|
||||
|
||||
|
|
11
app/models/attestation.rb
Normal file
11
app/models/attestation.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
class Attestation < ApplicationRecord
|
||||
belongs_to :dossier
|
||||
|
||||
mount_uploader :pdf, AttestationUploader
|
||||
|
||||
MAX_SIZE_EMAILABLE = 2.megabytes
|
||||
|
||||
def emailable?
|
||||
pdf.size <= MAX_SIZE_EMAILABLE
|
||||
end
|
||||
end
|
143
app/models/attestation_template.rb
Normal file
143
app/models/attestation_template.rb
Normal file
|
@ -0,0 +1,143 @@
|
|||
class AttestationTemplate < ApplicationRecord
|
||||
include ActionView::Helpers::NumberHelper
|
||||
|
||||
belongs_to :procedure
|
||||
|
||||
mount_uploader :logo, AttestationTemplateImageUploader
|
||||
mount_uploader :signature, AttestationTemplateImageUploader
|
||||
|
||||
validate :logo_signature_file_size
|
||||
|
||||
FILE_MAX_SIZE_IN_MB = 0.5
|
||||
|
||||
def tags
|
||||
if procedure.for_individual?
|
||||
identity_tags = individual_tags
|
||||
else
|
||||
identity_tags = entreprise_tags + etablissement_tags
|
||||
end
|
||||
|
||||
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)
|
||||
|
||||
if logo.present?
|
||||
CopyCarrierwaveFile::CopyFileService.new(self, result, :logo).set_file
|
||||
end
|
||||
|
||||
if signature.present?
|
||||
CopyCarrierwaveFile::CopyFileService.new(self, result, :signature).set_file
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def logo_signature_file_size
|
||||
%i[logo signature]
|
||||
.select { |file_name| send(file_name).present? }
|
||||
.each { |file_name| file_size_check(file_name) }
|
||||
end
|
||||
|
||||
def file_size_check(file_name)
|
||||
if send(file_name).file.size.to_f > FILE_MAX_SIZE_IN_MB.megabyte.to_f
|
||||
errors.add(file_name, " : vous ne pouvez pas charger une image de plus de #{number_with_delimiter(FILE_MAX_SIZE_IN_MB, locale: :fr)} Mo")
|
||||
end
|
||||
end
|
||||
|
||||
def procedure_type_de_champ_public_private_tags
|
||||
(procedure.types_de_champ + procedure.types_de_champ_private)
|
||||
.map { |tdc| { libelle: tdc.libelle, description: tdc.description } }
|
||||
end
|
||||
|
||||
def dossier_tags
|
||||
[{ libelle: 'motivation', description: '', target: 'motivation' }]
|
||||
end
|
||||
|
||||
def individual_tags
|
||||
[{ 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: '', 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: '', 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
|
|
@ -23,6 +23,7 @@ class Dossier < ActiveRecord::Base
|
|||
has_one :etablissement, dependent: :destroy
|
||||
has_one :entreprise, dependent: :destroy
|
||||
has_one :individual, dependent: :destroy
|
||||
has_one :attestation
|
||||
has_many :cerfa, dependent: :destroy
|
||||
|
||||
has_many :pieces_justificatives, dependent: :destroy
|
||||
|
@ -169,6 +170,9 @@ class Dossier < ActiveRecord::Base
|
|||
end
|
||||
when 'close'
|
||||
if received?
|
||||
self.attestation = build_attestation
|
||||
save
|
||||
|
||||
closed!
|
||||
|
||||
if motivation
|
||||
|
@ -305,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
|
||||
|
|
|
@ -7,6 +7,7 @@ class Procedure < ActiveRecord::Base
|
|||
has_one :procedure_path, dependent: :destroy
|
||||
|
||||
has_one :module_api_carto, dependent: :destroy
|
||||
has_one :attestation_template, dependent: :destroy
|
||||
|
||||
belongs_to :administrateur
|
||||
|
||||
|
@ -93,6 +94,7 @@ class Procedure < ActiveRecord::Base
|
|||
:types_de_champ,
|
||||
:types_de_champ_private,
|
||||
:module_api_carto,
|
||||
:attestation_template,
|
||||
types_de_champ: [:drop_down_list]
|
||||
])
|
||||
procedure.archived = false
|
||||
|
|
26
app/uploaders/attestation_template_image_uploader.rb
Normal file
26
app/uploaders/attestation_template_image_uploader.rb
Normal file
|
@ -0,0 +1,26 @@
|
|||
class AttestationTemplateImageUploader < BaseUploader
|
||||
def root
|
||||
File.join(Rails.root, 'public')
|
||||
end
|
||||
|
||||
# Choose what kind of storage to use for this uploader:
|
||||
if Features.remote_storage
|
||||
storage :fog
|
||||
else
|
||||
storage :file
|
||||
end
|
||||
|
||||
# Override the directory where uploaded files will be stored.
|
||||
# This is a sensible default for uploaders that are meant to be mounted:
|
||||
def store_dir
|
||||
unless Features.remote_storage
|
||||
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
|
||||
end
|
||||
end
|
||||
|
||||
# Add a white list of extensions which are allowed to be uploaded.
|
||||
# For images you might use something like this:
|
||||
def extension_white_list
|
||||
%w(jpg jpeg png)
|
||||
end
|
||||
end
|
20
app/uploaders/attestation_uploader.rb
Normal file
20
app/uploaders/attestation_uploader.rb
Normal file
|
@ -0,0 +1,20 @@
|
|||
class AttestationUploader < BaseUploader
|
||||
def root
|
||||
File.join(Rails.root, 'public')
|
||||
end
|
||||
|
||||
# Choose what kind of storage to use for this uploader:
|
||||
if Features.remote_storage
|
||||
storage :fog
|
||||
else
|
||||
storage :file
|
||||
end
|
||||
|
||||
# Override the directory where uploaded files will be stored.
|
||||
# This is a sensible default for uploaders that are meant to be mounted:
|
||||
def store_dir
|
||||
unless Features.remote_storage
|
||||
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
|
||||
end
|
||||
end
|
||||
end
|
73
app/views/admin/attestation_templates/edit.html.haml
Normal file
73
app/views/admin/attestation_templates/edit.html.haml
Normal file
|
@ -0,0 +1,73 @@
|
|||
#attestation-template-edit.row.white-back
|
||||
= form_for @attestation_template, url: admin_procedure_attestation_template_path do |f|
|
||||
.row
|
||||
.col-md-10
|
||||
%h1
|
||||
Attestation
|
||||
- if @attestation_template.activated?
|
||||
%small.text-success Activée
|
||||
- else
|
||||
%small Désactivée
|
||||
|
||||
%p.notice Les attestation, si elles sont activées, sont délivrées par email aux usagers lorsque leurs dossiers sont acceptés, et sont également disponibles au téléchargement sur leur espace personnel.
|
||||
|
||||
.image-upload
|
||||
- if @attestation_template.logo.present?
|
||||
= image_tag @attestation_template.logo.url, class: 'thumbnail'
|
||||
.form-group
|
||||
= f.label :logo, "Logo de l'attestation"
|
||||
= f.file_field :logo, accept: 'image/png, image/jpg, image/jpeg'
|
||||
%p.help-block
|
||||
Fichier accepté : JPG / JPEG / PNG
|
||||
%br
|
||||
Dimensions conseillées : au minimum 500 px de largeur ou de hauteur, poids maximum : 0,5 Mo.
|
||||
|
||||
.form-group
|
||||
= f.label :title, 'Titre'
|
||||
= f.text_field :title, class: 'form-control'
|
||||
|
||||
.form-group
|
||||
= f.label :body, 'Corps du document'
|
||||
~ f.text_area :body, class: 'form-control', rows: 10
|
||||
|
||||
.row
|
||||
.col-md-12.balises
|
||||
%table.table.table-striped
|
||||
%tr
|
||||
%th.col-md-3
|
||||
Balise
|
||||
%th
|
||||
Description
|
||||
- @attestation_template.tags.each do |tag|
|
||||
%tr
|
||||
%td
|
||||
= "--#{tag[:libelle]}--"
|
||||
%td
|
||||
= tag[:description]
|
||||
|
||||
.image-upload
|
||||
- if @attestation_template.signature.present?
|
||||
= image_tag @attestation_template.signature.url, class: 'thumbnail'
|
||||
.form-group
|
||||
= f.label :signature, "Tampon de l'attestation"
|
||||
= f.file_field :signature, accept: 'image/png, image/jpg, image/jpeg'
|
||||
%p.help-block
|
||||
Fichier accepté : JPG / JPEG / PNG
|
||||
%br
|
||||
Dimensions conseillées : au minimum 500 px de largeur ou de hauteur, poids maximum : 0,5 Mo.
|
||||
|
||||
.form-group
|
||||
= f.label :footer, 'Adresse en bas de page'
|
||||
~ f.text_area :footer, class: 'form-control', rows: 2,
|
||||
placeholder: "Direction interministérielle du numérique et du système d'information et de communication de l'Etat (DINSIC)"
|
||||
|
||||
%button.btn.btn-primary{ formaction: admin_procedure_attestation_template_preview_path, formtarget: '_blank' } Prévisualiser
|
||||
|
||||
.pull-right
|
||||
- if @attestation_template.activated
|
||||
%button.btn.btn-warning{ formaction: admin_procedure_attestation_template_disactivate_path } désactiver l'attestation
|
||||
|
||||
- if @attestation_template.id.nil? || !@attestation_template.activated
|
||||
%button.btn.btn-success Activer l'attestation
|
||||
- else
|
||||
%button.btn.btn-success Enregistrer
|
38
app/views/admin/attestation_templates/show.pdf.prawn
Normal file
38
app/views/admin/attestation_templates/show.pdf.prawn
Normal file
|
@ -0,0 +1,38 @@
|
|||
require 'prawn/measurement_extensions'
|
||||
|
||||
prawn_document(margin: [50, 100, 20, 100]) do |pdf|
|
||||
pdf.font_families.update( 'open sans' => { normal: './lib/prawn/fonts/OpenSans-Regular.ttf' })
|
||||
pdf.font 'open sans'
|
||||
|
||||
grey = '555555'
|
||||
black = '333333'
|
||||
max_logo_size = 40.mm
|
||||
max_signature_size = 40.mm
|
||||
|
||||
pdf.bounding_box([0, pdf.cursor], width: 400, height: 650) do
|
||||
if @logo.present?
|
||||
pdf.image StringIO.new(@logo.read), fit: [max_logo_size , max_logo_size], position: :center
|
||||
end
|
||||
|
||||
pdf.fill_color grey
|
||||
pdf.pad_top(40) { pdf.text "le #{l(@created_at, format: '%e %B %Y')}", size: 10, align: :right, character_spacing: -0.5 }
|
||||
|
||||
pdf.fill_color black
|
||||
pdf.pad_top(40) { pdf.text @title, size: 18, character_spacing: -0.2 }
|
||||
|
||||
pdf.fill_color grey
|
||||
pdf.pad_top(30) { pdf.text @body, size: 10, character_spacing: -0.2 }
|
||||
|
||||
if @signature.present?
|
||||
pdf.pad_top(40) do
|
||||
pdf.image StringIO.new(@signature.read), fit: [max_signature_size , max_signature_size], position: :right
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
pdf.repeat(:all) do
|
||||
pdf.move_cursor_to 20
|
||||
pdf.fill_color grey
|
||||
pdf.text @footer, align: :center, size: 8
|
||||
end
|
||||
end
|
14
app/views/dossiers/_attestation.html.haml
Normal file
14
app/views/dossiers/_attestation.html.haml
Normal file
|
@ -0,0 +1,14 @@
|
|||
- if dossier.attestation.present?
|
||||
#attestation-recapitulatif.default-data-block
|
||||
.row.show-block.clearfix
|
||||
.header
|
||||
.title
|
||||
.carret-right
|
||||
.carret-down
|
||||
ATTESTATION
|
||||
.details
|
||||
.left
|
||||
= image_tag('pdf.svg', width: '20px')
|
||||
%p.title= dossier.attestation.title
|
||||
%p.delivery Délivrée le #{l(dossier.attestation.created_at, format: '%d %B %Y')}
|
||||
%a.btn.btn-primary{ href: users_dossier_recapitulatif_attestation_path(dossier), target: '_blank' } Télécharger
|
|
@ -1,5 +1,7 @@
|
|||
= render partial: 'dossiers/edit_avis', locals: { dossier_facade: @facade }
|
||||
|
||||
= render partial: 'dossiers/attestation', locals: { dossier: @facade.dossier }
|
||||
|
||||
= render partial: 'dossiers/messagerie', locals: { dossier_facade: @facade }
|
||||
|
||||
= render partial: 'dossiers/motivation', locals: { dossier_facade: @facade }
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
= render partial: 'layouts/left_panels/left_panel_admin_procedurescontroller_navbar', locals: { active: 'Attestation' }
|
|
@ -45,6 +45,13 @@
|
|||
.procedure-list-element{ class: ('active' if active == 'Prévisualisation') }
|
||||
Prévisualisation
|
||||
|
||||
- if @procedure.locked?
|
||||
%a#onglet-attestation{ href: url_for(admin_procedure_attestation_template_path(@procedure, format: :pdf)), target: '_blank' }
|
||||
.procedure-list-element{ class: ('active' if active == 'Attestation') } Attestation
|
||||
- else
|
||||
%a#onglet-attestation{ href: url_for(edit_admin_procedure_attestation_template_path(@procedure)) }
|
||||
.procedure-list-element{ class: ('active' if active == 'Attestation') } Attestation
|
||||
|
||||
.split-hr-left
|
||||
|
||||
|
||||
|
|
|
@ -82,6 +82,8 @@ Rails.application.routes.draw do
|
|||
get '/recapitulatif' => 'recapitulatif#show'
|
||||
post '/recapitulatif/initiate' => 'recapitulatif#initiate'
|
||||
|
||||
get '/recapitulatif/attestation' => 'recapitulatif#attestation'
|
||||
|
||||
post '/commentaire' => 'commentaires#create'
|
||||
resources :commentaires, only: [:index]
|
||||
|
||||
|
@ -143,6 +145,14 @@ Rails.application.routes.draw do
|
|||
resource :accompagnateurs, only: [:show, :update]
|
||||
|
||||
resource :previsualisation, only: [:show]
|
||||
|
||||
resource :attestation_template, only: [:show, :edit, :update, :create]
|
||||
|
||||
post 'attestation_template/disactivate' => 'attestation_templates#disactivate'
|
||||
patch 'attestation_template/disactivate' => 'attestation_templates#disactivate'
|
||||
|
||||
post 'attestation_template/preview' => 'attestation_templates#preview'
|
||||
patch 'attestation_template/preview' => 'attestation_templates#preview'
|
||||
end
|
||||
|
||||
namespace :accompagnateurs do
|
||||
|
|
16
db/migrate/20170524140630_create_attestation_templates.rb
Normal file
16
db/migrate/20170524140630_create_attestation_templates.rb
Normal file
|
@ -0,0 +1,16 @@
|
|||
class CreateAttestationTemplates < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
create_table :attestation_templates do |t|
|
||||
t.text :title
|
||||
t.text :body
|
||||
t.text :footer
|
||||
t.string :logo
|
||||
t.string :signature
|
||||
t.boolean :activated
|
||||
|
||||
t.timestamps
|
||||
|
||||
t.references :procedure, index: { unique: true }, foreign_key: true
|
||||
end
|
||||
end
|
||||
end
|
11
db/migrate/20170601123221_create_attestations.rb
Normal file
11
db/migrate/20170601123221_create_attestations.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
class CreateAttestations < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
create_table :attestations do |t|
|
||||
t.string :pdf
|
||||
t.string :title
|
||||
t.references :dossier, foreign_key: true, null: false
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
27
db/schema.rb
27
db/schema.rb
|
@ -10,7 +10,8 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20170530141608) do
|
||||
ActiveRecord::Schema.define(version: 20170601123221) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
||||
|
@ -70,6 +71,28 @@ ActiveRecord::Schema.define(version: 20170530141608) do
|
|||
t.index ["procedure_id"], name: "index_assign_tos_on_procedure_id", using: :btree
|
||||
end
|
||||
|
||||
create_table "attestation_templates", force: :cascade do |t|
|
||||
t.text "title"
|
||||
t.text "body"
|
||||
t.text "footer"
|
||||
t.string "logo"
|
||||
t.string "signature"
|
||||
t.boolean "activated"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.integer "procedure_id"
|
||||
t.index ["procedure_id"], name: "index_attestation_templates_on_procedure_id", unique: true, using: :btree
|
||||
end
|
||||
|
||||
create_table "attestations", force: :cascade do |t|
|
||||
t.string "pdf"
|
||||
t.string "title"
|
||||
t.integer "dossier_id", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["dossier_id"], name: "index_attestations_on_dossier_id", using: :btree
|
||||
end
|
||||
|
||||
create_table "avis", force: :cascade do |t|
|
||||
t.string "email"
|
||||
t.text "introduction"
|
||||
|
@ -448,6 +471,8 @@ ActiveRecord::Schema.define(version: 20170530141608) do
|
|||
t.index ["procedure_id"], name: "index_without_continuation_mails_on_procedure_id", using: :btree
|
||||
end
|
||||
|
||||
add_foreign_key "attestation_templates", "procedures"
|
||||
add_foreign_key "attestations", "dossiers"
|
||||
add_foreign_key "avis", "gestionnaires", column: "claimant_id"
|
||||
add_foreign_key "cerfas", "dossiers"
|
||||
add_foreign_key "closed_mails", "procedures"
|
||||
|
|
BIN
lib/prawn/fonts/OpenSans-Regular.ttf
Normal file
BIN
lib/prawn/fonts/OpenSans-Regular.ttf
Normal file
Binary file not shown.
163
spec/controllers/admin/attestation_templates_controller_spec.rb
Normal file
163
spec/controllers/admin/attestation_templates_controller_spec.rb
Normal file
|
@ -0,0 +1,163 @@
|
|||
describe Admin::AttestationTemplatesController, type: :controller do
|
||||
let!(:attestation_template) { create(:attestation_template) }
|
||||
let(:admin) { create(:administrateur) }
|
||||
let!(:procedure) { create :procedure, administrateur: admin, attestation_template: attestation_template }
|
||||
let(:logo) { fixture_file_upload('spec/fixtures/white.png', 'image/png') }
|
||||
let(:signature) { fixture_file_upload('spec/fixtures/black.png', 'image/png') }
|
||||
|
||||
before do
|
||||
sign_in admin
|
||||
Timecop.freeze(Time.now)
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
before { get :show, params: { procedure_id: procedure.id, format: :pdf } }
|
||||
|
||||
it { expect(subject.status).to eq(200) }
|
||||
it { expect(assigns[:title]).to eq(attestation_template.title) }
|
||||
it { expect(assigns[:logo].read).to eq(attestation_template.logo.read) }
|
||||
it { expect(assigns[:body]).to eq(attestation_template.body) }
|
||||
it { expect(assigns[:signature].read).to eq(attestation_template.signature.read) }
|
||||
it { expect(assigns[:footer]).to eq(attestation_template.footer) }
|
||||
it { expect(assigns[:created_at]).to eq(DateTime.now) }
|
||||
end
|
||||
|
||||
describe 'POST #preview' do
|
||||
let(:upload_params) { { title: 't', body: 'b', footer: 'f' } }
|
||||
|
||||
before do
|
||||
post :preview,
|
||||
params: { procedure_id: procedure.id,
|
||||
attestation_template: upload_params }
|
||||
end
|
||||
|
||||
context 'if an attestation template does not exist on the procedure' do
|
||||
let(:attestation_template) { nil }
|
||||
it { expect(subject.status).to eq(200) }
|
||||
it { expect(assigns).to include(upload_params.stringify_keys) }
|
||||
end
|
||||
|
||||
context 'if an attestation template exists on the procedure' do
|
||||
context 'with logos' do
|
||||
let!(:attestation_template) do
|
||||
create(:attestation_template, logo: logo, signature: signature)
|
||||
end
|
||||
|
||||
it { expect(subject.status).to eq(200) }
|
||||
it { expect(assigns).to include(upload_params.stringify_keys) }
|
||||
it { expect(assigns[:created_at]).to eq(DateTime.now) }
|
||||
it { expect(assigns(:logo).read).to eq(logo.read) }
|
||||
it { expect(assigns(:signature).read).to eq(signature.read) }
|
||||
after { procedure.attestation_template.destroy }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #edit' do
|
||||
before { get :edit, params: { procedure_id: procedure.id } }
|
||||
|
||||
context 'if an attestation template exists on the procedure' do
|
||||
it { expect(subject.status).to eq(200) }
|
||||
it { expect(assigns(:attestation_template)).to eq(attestation_template) }
|
||||
end
|
||||
|
||||
context 'if an attestation template does not exist on the procedure' do
|
||||
let(:attestation_template) { nil }
|
||||
it { expect(subject.status).to eq(200) }
|
||||
it { expect(assigns(:attestation_template).id).to be_nil }
|
||||
it { expect(assigns(:attestation_template)).to be_an_instance_of(AttestationTemplate) }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
let(:attestation_template) { nil }
|
||||
let(:attestation_params) { { title: 't', body: 'b', footer: 'f' } }
|
||||
|
||||
context 'nominal' do
|
||||
before do
|
||||
post :create,
|
||||
params: { procedure_id: procedure.id,
|
||||
attestation_template: attestation_params.merge(logo: logo, signature: signature) }
|
||||
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.read).to eq(logo.read) }
|
||||
it { expect(procedure.attestation_template.signature.read).to eq(signature.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 }
|
||||
end
|
||||
|
||||
context 'when something wrong happens in the attestation template creation' do
|
||||
before do
|
||||
expect_any_instance_of(AttestationTemplate).to receive(:save)
|
||||
.and_return(false)
|
||||
expect_any_instance_of(AttestationTemplate).to receive(:errors)
|
||||
.and_return(double(full_messages: ['nop']))
|
||||
|
||||
post :create,
|
||||
params: { procedure_id: procedure.id,
|
||||
attestation_template: attestation_params }
|
||||
procedure.reload
|
||||
end
|
||||
|
||||
it { expect(response).to redirect_to edit_admin_procedure_attestation_template_path(procedure) }
|
||||
it { expect(flash.alert).to eq('nop') }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PATCH #update' do
|
||||
let(:attestation_params) { { title: 't', body: 'b', footer: 'f' } }
|
||||
let(:attestation_params_with_images) { attestation_params.merge(logo: logo, signature: signature) }
|
||||
|
||||
context 'nominal' do
|
||||
before do
|
||||
patch :update,
|
||||
params: { procedure_id: procedure.id,
|
||||
attestation_template: attestation_params_with_images }
|
||||
procedure.reload
|
||||
end
|
||||
|
||||
it { expect(procedure.attestation_template).to have_attributes(attestation_params) }
|
||||
it { expect(procedure.attestation_template.logo.read).to eq(logo.read) }
|
||||
it { expect(procedure.attestation_template.signature.read).to eq(signature.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 }
|
||||
end
|
||||
|
||||
context 'when something wrong happens in the attestation template creation' do
|
||||
before do
|
||||
expect_any_instance_of(AttestationTemplate).to receive(:update_attributes).and_return(false)
|
||||
expect_any_instance_of(AttestationTemplate).to receive(:errors)
|
||||
.and_return(double(full_messages: ['nop']))
|
||||
|
||||
patch :update,
|
||||
params: { procedure_id: procedure.id,
|
||||
attestation_template: attestation_params_with_images }
|
||||
procedure.reload
|
||||
end
|
||||
|
||||
it { expect(response).to redirect_to edit_admin_procedure_attestation_template_path(procedure) }
|
||||
it { expect(flash.alert).to eq('nop') }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'post #disactivate' do
|
||||
context 'when the attestation_template is activated' do
|
||||
let(:attestation_template) { create(:attestation_template, activated: true) }
|
||||
|
||||
before do
|
||||
post :disactivate, params: { procedure_id: procedure.id }
|
||||
attestation_template.reload
|
||||
end
|
||||
|
||||
it { expect(attestation_template.activated).to be false }
|
||||
it { expect(flash.notice).to eq("L'attestation a bien été désactivée") }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -268,7 +268,7 @@ describe Backoffice::DossiersController, type: :controller do
|
|||
|
||||
it 'Notification email is sent' do
|
||||
expect(NotificationMailer).to receive(:send_notification)
|
||||
.with(dossier, kind_of(Mails::RefusedMail)).and_return(NotificationMailer)
|
||||
.with(dossier, kind_of(Mails::RefusedMail), nil).and_return(NotificationMailer)
|
||||
expect(NotificationMailer).to receive(:deliver_now!)
|
||||
|
||||
subject
|
||||
|
@ -294,7 +294,7 @@ describe Backoffice::DossiersController, type: :controller do
|
|||
|
||||
it 'Notification email is sent' do
|
||||
expect(NotificationMailer).to receive(:send_notification)
|
||||
.with(dossier, kind_of(Mails::WithoutContinuationMail)).and_return(NotificationMailer)
|
||||
.with(dossier, kind_of(Mails::WithoutContinuationMail), nil).and_return(NotificationMailer)
|
||||
expect(NotificationMailer).to receive(:deliver_now!)
|
||||
|
||||
subject
|
||||
|
@ -304,9 +304,17 @@ describe Backoffice::DossiersController, type: :controller do
|
|||
end
|
||||
|
||||
context "with close" do
|
||||
let(:expected_attestation) { nil }
|
||||
|
||||
before do
|
||||
dossier.received!
|
||||
sign_in gestionnaire
|
||||
|
||||
expect(NotificationMailer).to receive(:send_notification)
|
||||
.with(dossier, kind_of(Mails::ClosedMail), expected_attestation)
|
||||
.and_return(NotificationMailer)
|
||||
|
||||
expect(NotificationMailer).to receive(:deliver_now!)
|
||||
end
|
||||
|
||||
subject { post :process_dossier, params: { process_action: "close", dossier_id: dossier_id} }
|
||||
|
@ -318,15 +326,42 @@ describe Backoffice::DossiersController, type: :controller do
|
|||
expect(dossier.state).to eq('closed')
|
||||
end
|
||||
|
||||
it 'Notification email is sent' do
|
||||
expect(NotificationMailer).to receive(:send_notification)
|
||||
.with(dossier, kind_of(Mails::ClosedMail)).and_return(NotificationMailer)
|
||||
expect(NotificationMailer).to receive(:deliver_now!)
|
||||
|
||||
subject
|
||||
context 'when the dossier does not have any attestation' do
|
||||
it 'Notification email is sent' do
|
||||
subject
|
||||
end
|
||||
end
|
||||
|
||||
it { is_expected.to redirect_to backoffice_dossier_path(id: dossier.id) }
|
||||
context 'when the dossier has an attestation' do
|
||||
let(:emailable) { false }
|
||||
|
||||
before do
|
||||
fake_attestation = double(pdf: double(read: 'pdf', size: 2.megabytes), emailable?: emailable)
|
||||
allow_any_instance_of(Dossier).to receive(:attestation).and_return(fake_attestation)
|
||||
end
|
||||
|
||||
context 'emailable' do
|
||||
let(:emailable) { true }
|
||||
let(:expected_attestation) { 'pdf' }
|
||||
|
||||
it 'Notification email is sent with the attestation' do
|
||||
subject
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the dossier has an attestation not emailable' do
|
||||
let(:emailable) { false }
|
||||
let(:expected_attestation) { nil }
|
||||
|
||||
it 'Notification email is sent without the attestation' do
|
||||
expect(controller).to receive(:capture_message)
|
||||
|
||||
subject
|
||||
end
|
||||
end
|
||||
|
||||
it { is_expected.to redirect_to backoffice_dossier_path(id: dossier.id) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -51,4 +51,22 @@ describe Users::RecapitulatifController, type: :controller do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Get #attestation' do
|
||||
context 'when a dossier has an attestation' do
|
||||
let(:fake_pdf) { double(read: 'pdf content') }
|
||||
let!(:dossier) { create(:dossier, attestation: Attestation.new) }
|
||||
|
||||
it 'returns the attestation pdf' do
|
||||
allow_any_instance_of(Attestation).to receive(:pdf).and_return(fake_pdf)
|
||||
|
||||
expect(controller).to receive(:send_data)
|
||||
.with('pdf content', filename: 'attestation.pdf', type: 'application/pdf') do
|
||||
controller.render nothing: true
|
||||
end
|
||||
|
||||
get :attestation, params: { dossier_id: dossier.id }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
8
spec/factories/attestation_template.rb
Normal file
8
spec/factories/attestation_template.rb
Normal file
|
@ -0,0 +1,8 @@
|
|||
FactoryGirl.define do
|
||||
factory :attestation_template do
|
||||
title 'title'
|
||||
body 'body'
|
||||
footer 'footer'
|
||||
activated true
|
||||
end
|
||||
end
|
BIN
spec/fixtures/black.png
vendored
Normal file
BIN
spec/fixtures/black.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 67 B |
BIN
spec/fixtures/white.png
vendored
Normal file
BIN
spec/fixtures/white.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 67 B |
|
@ -5,11 +5,25 @@ RSpec.describe NotificationMailer, type: :mailer do
|
|||
let(:user) { create(:user) }
|
||||
let(:dossier) { create(:dossier, user: user) }
|
||||
let(:email) { instance_double('email', object_for_dossier: 'object', body_for_dossier: 'body') }
|
||||
let (:notifications_count_before) { Notification.count }
|
||||
subject { described_class.send_notification(dossier, email) }
|
||||
let(:attestation) { nil }
|
||||
let(:notifications_count_before) { Notification.count }
|
||||
|
||||
subject { described_class.send_notification(dossier, email, attestation) }
|
||||
|
||||
it { expect(subject.subject).to eq(email.object_for_dossier) }
|
||||
it { expect(subject.body).to eq(email.body_for_dossier) }
|
||||
it { expect(subject.attachments['attestation.pdf']).to eq(nil) }
|
||||
|
||||
context 'when an attestation is provided' do
|
||||
let(:attestation) { 'attestation' }
|
||||
|
||||
it do
|
||||
expect(subject.attachments['attestation.pdf'].content_type)
|
||||
.to eq('application/pdf; filename=attestation.pdf')
|
||||
|
||||
expect(subject.attachments['attestation.pdf'].body).to eq('attestation')
|
||||
end
|
||||
end
|
||||
|
||||
it "creates a commentaire, which is not notified" do
|
||||
described_class.send_notification(dossier, email).deliver_now
|
||||
|
|
23
spec/models/attestation_spec.rb
Normal file
23
spec/models/attestation_spec.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
RSpec.describe Attestation, type: :model do
|
||||
describe 'emailable' do
|
||||
let(:attestation) do
|
||||
attestation = Attestation.new
|
||||
expect(attestation).to receive(:pdf).and_return(double(size: size))
|
||||
attestation
|
||||
end
|
||||
|
||||
subject { attestation.emailable? }
|
||||
|
||||
context 'when the pdf size is acceptable' do
|
||||
let(:size) { Attestation::MAX_SIZE_EMAILABLE }
|
||||
|
||||
it { is_expected.to be true }
|
||||
end
|
||||
|
||||
context 'when the pdf size is unacceptable' do
|
||||
let(:size) { Attestation::MAX_SIZE_EMAILABLE + 1 }
|
||||
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
end
|
||||
end
|
244
spec/models/attestation_template_spec.rb
Normal file
244
spec/models/attestation_template_spec.rb
Normal file
|
@ -0,0 +1,244 @@
|
|||
describe AttestationTemplate, type: :model do
|
||||
describe 'validate' do
|
||||
let(:logo_size) { AttestationTemplate::FILE_MAX_SIZE_IN_MB.megabyte }
|
||||
let(:signature_size) { AttestationTemplate::FILE_MAX_SIZE_IN_MB.megabyte }
|
||||
let(:fake_logo) { double(AttestationTemplateImageUploader, file: double(size: logo_size)) }
|
||||
let(:fake_signature) { double(AttestationTemplateImageUploader, file: double(size: signature_size)) }
|
||||
let(:attestation_template) { AttestationTemplate.new }
|
||||
|
||||
before do
|
||||
allow(attestation_template).to receive(:logo).and_return(fake_logo)
|
||||
allow(attestation_template).to receive(:signature).and_return(fake_signature)
|
||||
attestation_template.validate
|
||||
end
|
||||
|
||||
subject { attestation_template.errors.details }
|
||||
|
||||
context 'when no files are present' do
|
||||
let(:fake_logo) { nil }
|
||||
let(:fake_signature) { nil }
|
||||
|
||||
it { is_expected.to match({}) }
|
||||
end
|
||||
|
||||
context 'when the logo and the signature have the right size' do
|
||||
it { is_expected.to match({}) }
|
||||
end
|
||||
|
||||
context 'when the logo and the signature are too heavy' do
|
||||
let(:logo_size) { AttestationTemplate::FILE_MAX_SIZE_IN_MB.megabyte + 1 }
|
||||
let(:signature_size) { AttestationTemplate::FILE_MAX_SIZE_IN_MB.megabyte + 1 }
|
||||
|
||||
it do
|
||||
expected = {
|
||||
signature: [{ error: ' : vous ne pouvez pas charger une image de plus de 0,5 Mo' }],
|
||||
logo: [{ error: ' : vous ne pouvez pas charger une image de plus de 0,5 Mo' }]
|
||||
}
|
||||
|
||||
is_expected.to match(expected)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'dup' do
|
||||
before do
|
||||
@logo = File.open('spec/fixtures/white.png')
|
||||
@signature = File.open('spec/fixtures/black.png')
|
||||
end
|
||||
|
||||
after do
|
||||
@logo.close
|
||||
@signature.close
|
||||
subject.destroy
|
||||
end
|
||||
|
||||
let(:attestation_template) { AttestationTemplate.create(attributes) }
|
||||
subject { attestation_template.dup }
|
||||
|
||||
context 'with an attestation without images' do
|
||||
let(:attributes) { { title: 't', body: 'b', footer: 'f', activated: true } }
|
||||
|
||||
it { is_expected.to have_attributes(attributes) }
|
||||
it { is_expected.to have_attributes(id: nil) }
|
||||
it { expect(subject.logo.file).to be_nil }
|
||||
end
|
||||
|
||||
context 'with an attestation with images' do
|
||||
let(:attributes) { { logo: @logo, signature: @signature } }
|
||||
|
||||
it { expect(subject.logo.file.file).not_to eq(attestation_template.logo.file.file) }
|
||||
it { expect(subject.logo.file.read).to eq(attestation_template.logo.file.read) }
|
||||
|
||||
it { expect(subject.signature.file.file).not_to eq(attestation_template.signature.file.file) }
|
||||
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
|
||||
|
|
|
@ -153,6 +153,17 @@ describe Procedure do
|
|||
let!(:piece_justificative_1) { create(:type_de_piece_justificative, procedure: procedure, order_place: 1) }
|
||||
let(:received_mail){ create(:received_mail) }
|
||||
|
||||
before do
|
||||
@logo = File.open('spec/fixtures/white.png')
|
||||
@signature = File.open('spec/fixtures/black.png')
|
||||
@attestation_template = create(:attestation_template, procedure: procedure, logo: @logo, signature: @signature)
|
||||
end
|
||||
|
||||
after do
|
||||
@logo.close
|
||||
@signature.close
|
||||
end
|
||||
|
||||
subject { procedure.clone }
|
||||
|
||||
it 'should duplicate specific objects with different id' do
|
||||
|
@ -175,6 +186,8 @@ describe Procedure do
|
|||
subject.types_de_piece_justificative.zip(procedure.types_de_piece_justificative).each do |stc, ptc|
|
||||
expect(stc).to have_same_attributes_as(ptc)
|
||||
end
|
||||
|
||||
expect(subject.attestation_template.title).to eq(procedure.attestation_template.title)
|
||||
end
|
||||
|
||||
it 'should duplicate existing mail_templates' do
|
||||
|
|
Loading…
Reference in a new issue