diff --git a/Gemfile b/Gemfile index fce678101..c6e525175 100644 --- a/Gemfile +++ b/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' diff --git a/Gemfile.lock b/Gemfile.lock index 9a6646416..5ff8a870a 100644 --- a/Gemfile.lock +++ b/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) @@ -685,6 +687,7 @@ DEPENDENCIES carrierwave chartkick clamav-client + copy_carrierwave_file database_cleaner deep_cloneable (~> 2.2.1) devise diff --git a/app/models/attestation_template.rb b/app/models/attestation_template.rb new file mode 100644 index 000000000..fd3ca4575 --- /dev/null +++ b/app/models/attestation_template.rb @@ -0,0 +1,40 @@ +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 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 +end diff --git a/app/models/procedure.rb b/app/models/procedure.rb index 99d44c77e..38c7200e3 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -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 diff --git a/app/uploaders/attestation_template_image_uploader.rb b/app/uploaders/attestation_template_image_uploader.rb new file mode 100644 index 000000000..4baa5fe54 --- /dev/null +++ b/app/uploaders/attestation_template_image_uploader.rb @@ -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 diff --git a/db/migrate/20170524140630_create_attestation_templates.rb b/db/migrate/20170524140630_create_attestation_templates.rb new file mode 100644 index 000000000..6517c72ea --- /dev/null +++ b/db/migrate/20170524140630_create_attestation_templates.rb @@ -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 diff --git a/db/schema.rb b/db/schema.rb index b24616cc2..10d5778c5 100644 --- a/db/schema.rb +++ b/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: 20170524140630) do + # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -70,6 +71,19 @@ 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 "avis", force: :cascade do |t| t.string "email" t.text "introduction" @@ -448,6 +462,7 @@ 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 "avis", "gestionnaires", column: "claimant_id" add_foreign_key "cerfas", "dossiers" add_foreign_key "closed_mails", "procedures" diff --git a/spec/factories/attestation_template.rb b/spec/factories/attestation_template.rb new file mode 100644 index 000000000..46eb4bee1 --- /dev/null +++ b/spec/factories/attestation_template.rb @@ -0,0 +1,8 @@ +FactoryGirl.define do + factory :attestation_template do + title 'title' + body 'body' + footer 'footer' + activated true + end +end diff --git a/spec/fixtures/black.png b/spec/fixtures/black.png new file mode 100644 index 000000000..17f1d2ed7 Binary files /dev/null and b/spec/fixtures/black.png differ diff --git a/spec/fixtures/white.png b/spec/fixtures/white.png new file mode 100644 index 000000000..7d3a386a2 Binary files /dev/null and b/spec/fixtures/white.png differ diff --git a/spec/models/attestation_template_spec.rb b/spec/models/attestation_template_spec.rb new file mode 100644 index 000000000..f5d7c62bb --- /dev/null +++ b/spec/models/attestation_template_spec.rb @@ -0,0 +1,76 @@ +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 +end diff --git a/spec/models/procedure_spec.rb b/spec/models/procedure_spec.rb index 067ca981e..d0f36ecea 100644 --- a/spec/models/procedure_spec.rb +++ b/spec/models/procedure_spec.rb @@ -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