From 1cb18e51ac036eb87508f7aa08d585b5f71103b6 Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Wed, 22 Apr 2020 11:46:42 +0200 Subject: [PATCH 01/22] champ: return the parent dossier even when discarded Dossier has a `default_scope { kept }`. Because of that, when the parent dossier is discarded, `champ.dossier` will return nil. We should kill the default scope. But meanwhile, ensure that `champ.dossier` returns even a discarded dossier. --- app/models/champ.rb | 2 +- spec/models/champ_spec.rb | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/app/models/champ.rb b/app/models/champ.rb index 7c21fdae2..9e2c2cf63 100644 --- a/app/models/champ.rb +++ b/app/models/champ.rb @@ -1,5 +1,5 @@ class Champ < ApplicationRecord - belongs_to :dossier, inverse_of: :champs, touch: true + belongs_to :dossier, -> { with_discarded }, inverse_of: :champs, touch: true belongs_to :type_de_champ, inverse_of: :champ belongs_to :parent, class_name: 'Champ' has_many :commentaires diff --git a/spec/models/champ_spec.rb b/spec/models/champ_spec.rb index f0368e424..119be869d 100644 --- a/spec/models/champ_spec.rb +++ b/spec/models/champ_spec.rb @@ -3,6 +3,17 @@ describe Champ do it_should_behave_like "champ_spec" + describe "associations" do + it { is_expected.to belong_to(:dossier) } + + context 'when the parent dossier is discarded' do + let(:discarded_dossier) { create(:dossier, :discarded) } + subject(:champ) { discarded_dossier.champs.first } + + it { expect(champ.reload.dossier).to eq discarded_dossier } + end + end + describe "validations" do let(:row) { 1 } let(:champ) { create(:champ, type_de_champ: create(:type_de_champ), row: row) } From 15645e11e356ab99c6c7dcc09e5bc149f076436c Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Wed, 22 Apr 2020 15:12:34 +0200 Subject: [PATCH 02/22] instructeur: improve InstructeurController#index test --- .../instructeurs/procedures_controller_spec.rb | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/spec/controllers/instructeurs/procedures_controller_spec.rb b/spec/controllers/instructeurs/procedures_controller_spec.rb index 75c75edae..a65184430 100644 --- a/spec/controllers/instructeurs/procedures_controller_spec.rb +++ b/spec/controllers/instructeurs/procedures_controller_spec.rb @@ -96,18 +96,22 @@ describe Instructeurs::ProceduresController, type: :controller do it { expect(response).to have_http_status(:ok) } context "with procedures assigned" do - let(:procedure1) { create(:procedure, :published) } - let(:procedure2) { create(:procedure, :closed) } - let(:procedure3) { create(:procedure) } + let(:procedure_draft) { create(:procedure) } + let(:procedure_published) { create(:procedure, :published) } + let(:procedure_closed) { create(:procedure, :closed) } + let(:procedure_not_assigned) { create(:procedure) } before do - instructeur.groupe_instructeurs << procedure1.defaut_groupe_instructeur - instructeur.groupe_instructeurs << procedure2.defaut_groupe_instructeur - instructeur.groupe_instructeurs << procedure3.defaut_groupe_instructeur + [procedure_draft, procedure_published, procedure_closed].each do |p| + instructeur.groupe_instructeurs << p.defaut_groupe_instructeur + end subject end - it { expect(assigns(:procedures)).to include(procedure1, procedure2) } + it 'assigns procedures visible to the instructeur' do + expect(assigns(:procedures)).to include(procedure_draft, procedure_published, procedure_closed) + expect(assigns(:procedures)).not_to include(procedure_not_assigned) + end end context "with dossiers" do From f29ec5c775d955f65abfbe0514d1bd33cf5e8b41 Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Wed, 22 Apr 2020 15:16:21 +0200 Subject: [PATCH 03/22] instucteurs: don't show discarded procedures in the list --- app/controllers/instructeurs/procedures_controller.rb | 1 + spec/controllers/instructeurs/procedures_controller_spec.rb | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/controllers/instructeurs/procedures_controller.rb b/app/controllers/instructeurs/procedures_controller.rb index 7a255186e..154c6f7c1 100644 --- a/app/controllers/instructeurs/procedures_controller.rb +++ b/app/controllers/instructeurs/procedures_controller.rb @@ -8,6 +8,7 @@ module Instructeurs def index @procedures = current_instructeur .procedures + .kept .with_attached_logo .includes(:defaut_groupe_instructeur) .order(closed_at: :desc, unpublished_at: :desc, published_at: :desc, created_at: :desc) diff --git a/spec/controllers/instructeurs/procedures_controller_spec.rb b/spec/controllers/instructeurs/procedures_controller_spec.rb index a65184430..392acc06d 100644 --- a/spec/controllers/instructeurs/procedures_controller_spec.rb +++ b/spec/controllers/instructeurs/procedures_controller_spec.rb @@ -99,10 +99,12 @@ describe Instructeurs::ProceduresController, type: :controller do let(:procedure_draft) { create(:procedure) } let(:procedure_published) { create(:procedure, :published) } let(:procedure_closed) { create(:procedure, :closed) } + let(:procedure_draft_discarded) { create(:procedure, :discarded) } + let(:procedure_closed_discarded) { create(:procedure, :discarded) } let(:procedure_not_assigned) { create(:procedure) } before do - [procedure_draft, procedure_published, procedure_closed].each do |p| + [procedure_draft, procedure_published, procedure_closed, procedure_draft_discarded, procedure_closed_discarded].each do |p| instructeur.groupe_instructeurs << p.defaut_groupe_instructeur end subject @@ -110,7 +112,7 @@ describe Instructeurs::ProceduresController, type: :controller do it 'assigns procedures visible to the instructeur' do expect(assigns(:procedures)).to include(procedure_draft, procedure_published, procedure_closed) - expect(assigns(:procedures)).not_to include(procedure_not_assigned) + expect(assigns(:procedures)).not_to include(procedure_draft_discarded, procedure_closed_discarded, procedure_not_assigned) end end From 50524fa640d94b8f462a4836104920056d0432c0 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 2 Apr 2020 15:02:40 +0200 Subject: [PATCH 04/22] Add termine_close_to_expiration_notice_sent_at to dossiers --- ...0331164240_add_termine_close_to_expiration_to_dossiers.rb | 5 +++++ db/schema.rb | 1 + 2 files changed, 6 insertions(+) create mode 100644 db/migrate/20200331164240_add_termine_close_to_expiration_to_dossiers.rb diff --git a/db/migrate/20200331164240_add_termine_close_to_expiration_to_dossiers.rb b/db/migrate/20200331164240_add_termine_close_to_expiration_to_dossiers.rb new file mode 100644 index 000000000..5e46cc2c1 --- /dev/null +++ b/db/migrate/20200331164240_add_termine_close_to_expiration_to_dossiers.rb @@ -0,0 +1,5 @@ +class AddTermineCloseToExpirationToDossiers < ActiveRecord::Migration[5.2] + def change + add_column :dossiers, :termine_close_to_expiration_notice_sent_at, :datetime + end +end diff --git a/db/schema.rb b/db/schema.rb index e7a2911e7..005470ef1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -258,6 +258,7 @@ ActiveRecord::Schema.define(version: 2020_04_21_174642) do t.index "to_tsvector('french'::regconfig, (search_terms || private_search_terms))", name: "index_dossiers_on_search_terms_private_search_terms", using: :gin t.index "to_tsvector('french'::regconfig, search_terms)", name: "index_dossiers_on_search_terms", using: :gin t.interval "en_construction_conservation_extension", default: "00:00:00" + t.datetime "termine_close_to_expiration_notice_sent_at" t.index ["archived"], name: "index_dossiers_on_archived" t.index ["groupe_instructeur_id"], name: "index_dossiers_on_groupe_instructeur_id" t.index ["hidden_at"], name: "index_dossiers_on_hidden_at" From bdbee38ff1f40a121304cb5b2cfeff4fc13bb778 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 2 Apr 2020 15:04:12 +0200 Subject: [PATCH 05/22] Add expired termine scopes to dossier --- app/models/dossier.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 0fdba3a50..b47cc927f 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -189,6 +189,11 @@ class Dossier < ApplicationRecord .joins(:procedure) .where("dossiers.en_instruction_at + (duree_conservation_dossiers_dans_ds * INTERVAL '1 month') - INTERVAL :expires_in < :now", { now: Time.zone.now, expires_in: INTERVAL_BEFORE_EXPIRATION }) end + scope :termine_close_to_expiration, -> do + state_termine + .joins(:procedure) + .where("dossiers.processed_at + (duree_conservation_dossiers_dans_ds * INTERVAL '1 month') - INTERVAL :expires_in < :now", { now: Time.zone.now, expires_in: INTERVAL_BEFORE_EXPIRATION }) + end scope :brouillon_expired, -> do state_brouillon @@ -198,9 +203,14 @@ class Dossier < ApplicationRecord state_en_construction .where("en_construction_close_to_expiration_notice_sent_at + INTERVAL :expires_in < :now", { now: Time.zone.now, expires_in: INTERVAL_EXPIRATION }) end + scope :termine_expired, -> do + state_termine + .where("termine_close_to_expiration_notice_sent_at + INTERVAL :expires_in < :now", { now: Time.zone.now, expires_in: INTERVAL_EXPIRATION }) + end scope :without_brouillon_expiration_notice_sent, -> { where(brouillon_close_to_expiration_notice_sent_at: nil) } scope :without_en_construction_expiration_notice_sent, -> { where(en_construction_close_to_expiration_notice_sent_at: nil) } + scope :without_termine_expiration_notice_sent, -> { where(termine_close_to_expiration_notice_sent_at: nil) } scope :discarded_brouillon_expired, -> do with_discarded From f1b531911b97e8e045312f92447065eb8e44357f Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 2 Apr 2020 15:05:16 +0200 Subject: [PATCH 06/22] Handle processed dossiers in deletion mailers --- app/mailers/dossier_mailer.rb | 3 +- ..._near_deletion_to_administration.html.haml | 7 +++- .../notify_near_deletion_to_user.html.haml | 5 ++- .../fr.yml | 9 +++++ .../notify_near_deletion_to_user/fr.yml | 6 +++ spec/mailers/dossier_mailer_spec.rb | 38 +++++++++++++++++++ .../previews/dossier_mailer_preview.rb | 12 ++++++ 7 files changed, 77 insertions(+), 3 deletions(-) diff --git a/app/mailers/dossier_mailer.rb b/app/mailers/dossier_mailer.rb index a217f4d16..36d4bd17d 100644 --- a/app/mailers/dossier_mailer.rb +++ b/app/mailers/dossier_mailer.rb @@ -134,7 +134,8 @@ class DossierMailer < ApplicationMailer def default_i18n_subject(interpolations = {}) if interpolations[:state] mailer_scope = self.class.mailer_name.tr('/', '.') - I18n.t("subject_#{interpolations[:state]}", interpolations.merge(scope: [mailer_scope, action_name])) + state = interpolations[:state].in?(Dossier::TERMINE) ? 'termine' : interpolations[:state] + I18n.t("subject_#{state}", interpolations.merge(scope: [mailer_scope, action_name])) else super end diff --git a/app/views/dossier_mailer/notify_near_deletion_to_administration.html.haml b/app/views/dossier_mailer/notify_near_deletion_to_administration.html.haml index 62b0156ff..485757f6d 100644 --- a/app/views/dossier_mailer/notify_near_deletion_to_administration.html.haml +++ b/app/views/dossier_mailer/notify_near_deletion_to_administration.html.haml @@ -4,7 +4,10 @@ Bonjour, %p - = t('.header_en_construction', count: @dossiers.count) + - if @state == Dossier.states.fetch(:en_construction) + = t('.header_en_construction', count: @dossiers.count) + - else + = t('.header_termine', count: @dossiers.count) %ul - @dossiers.each do |d| %li @@ -13,5 +16,7 @@ %p - if @state == Dossier.states.fetch(:en_construction) = sanitize(t('.footer_en_construction', count: @dossiers.count)) + - else + = sanitize(t('.footer_termine', count: @dossiers.count)) = render partial: "layouts/mailers/signature" diff --git a/app/views/dossier_mailer/notify_near_deletion_to_user.html.haml b/app/views/dossier_mailer/notify_near_deletion_to_user.html.haml index efe0c668d..83455024a 100644 --- a/app/views/dossier_mailer/notify_near_deletion_to_user.html.haml +++ b/app/views/dossier_mailer/notify_near_deletion_to_user.html.haml @@ -4,7 +4,10 @@ Bonjour, %p - = t('.header_en_construction', count: @dossiers.count) + - if @state == Dossier.states.fetch(:en_construction) + = t('.header_en_construction', count: @dossiers.count) + - else + = t('.header_termine', count: @dossiers.count) %ul - @dossiers.each do |d| %li diff --git a/config/locales/views/dossier_mailer/notify_near_deletion_to_administration/fr.yml b/config/locales/views/dossier_mailer/notify_near_deletion_to_administration/fr.yml index e3d24481c..c1bd54250 100644 --- a/config/locales/views/dossier_mailer/notify_near_deletion_to_administration/fr.yml +++ b/config/locales/views/dossier_mailer/notify_near_deletion_to_administration/fr.yml @@ -4,9 +4,18 @@ fr: subject_en_construction: one: Un dossier en construction va bientôt être supprimé other: Des dossiers en construction vont bientôt être supprimés + subject_termine: + one: Un dossier dont le traitement est terminé va bientôt être supprimé + other: Des dossiers dont le traitement est terminé vont bientôt être supprimés header_en_construction: one: "Le dossier en construction suivant sera bientôt automatiquement supprimé :" other: "Les dossiers en construction suivant seront bientôt automatiquement supprimés :" + header_termine: + one: "Le dossier suivant dont le traitement est terminé sera bientôt automatiquement supprimé :" + other: "Les dossiers suivant dont le traitement est terminé seront bientôt automatiquement supprimés :" footer_en_construction: one: "Vous avez un mois pour commencer l’instruction du dossier." other: "Vous avez un mois pour commencer l’instruction des dossiers." + footer_termine: + one: "Vous avez un mois pour archiver le dossier." + other: "Vous avez un mois pour archiver les dossiers." diff --git a/config/locales/views/dossier_mailer/notify_near_deletion_to_user/fr.yml b/config/locales/views/dossier_mailer/notify_near_deletion_to_user/fr.yml index e81cad44d..3a0098335 100644 --- a/config/locales/views/dossier_mailer/notify_near_deletion_to_user/fr.yml +++ b/config/locales/views/dossier_mailer/notify_near_deletion_to_user/fr.yml @@ -4,9 +4,15 @@ fr: subject_en_construction: one: Un dossier en construction va bientôt être supprimé other: Des dossiers en construction vont bientôt être supprimés + subject_termine: + one: Un dossier dont le traitement est terminé va bientôt être supprimé + other: Des dossiers dont le traitement est terminé vont bientôt être supprimés header_en_construction: one: "Afin de limiter la conservation de vos données personnelles, le dossier en construction suivant sera bientôt automatiquement supprimé :" other: "Afin de limiter la conservation de vos données personnelles, les dossiers en construction suivant seront bientôt automatiquement supprimés :" + header_termine: + one: "Afin de limiter la conservation de vos données personnelles, le dossier suivant dont le traitement est terminé sera bientôt automatiquement supprimé :" + other: "Afin de limiter la conservation de vos données personnelles, les dossiers suivant dont le traitement est terminé seront bientôt automatiquement supprimés :" footer: one: "Vous pouvez retrouver votre dossier pendant encore un mois. Vous n’avez rien à faire." other: "Vous pouvez retrouver vos dossiers pendant encore un mois. Vous n’avez rien à faire." diff --git a/spec/mailers/dossier_mailer_spec.rb b/spec/mailers/dossier_mailer_spec.rb index 7ba807f9a..d7ab78474 100644 --- a/spec/mailers/dossier_mailer_spec.rb +++ b/spec/mailers/dossier_mailer_spec.rb @@ -102,6 +102,19 @@ RSpec.describe DossierMailer, type: :mailer do it { expect(subject.body).to include(dossier.procedure.libelle) } it { expect(subject.body).to include("nous nous excusons de la gène occasionnée") } end + + describe 'termine' do + let(:dossier) { create(:dossier, :accepte) } + let(:deleted_dossier) { DeletedDossier.create_from_dossier(dossier, :expired) } + + subject { described_class.notify_automatic_deletion_to_user([deleted_dossier], dossier.user.email) } + + it { expect(subject.to).to eq([dossier.user.email]) } + it { expect(subject.subject).to eq("Un dossier a été supprimé automatiquement") } + it { expect(subject.body).to include("n° #{dossier.id} ") } + it { expect(subject.body).to include(dossier.procedure.libelle) } + it { expect(subject.body).not_to include("nous nous excusons de la gène occasionnée") } + end end describe '.notify_automatic_deletion_to_administration' do @@ -126,6 +139,18 @@ RSpec.describe DossierMailer, type: :mailer do it { expect(subject.body).to include("PDF") } it { expect(subject.body).to include("Vous avez un mois pour commencer l’instruction du dossier.") } end + + describe 'termine' do + let(:dossier) { create(:dossier, :accepte) } + + subject { described_class.notify_near_deletion_to_administration([dossier], dossier.user.email) } + + it { expect(subject.subject).to eq("Un dossier dont le traitement est terminé va bientôt être supprimé") } + it { expect(subject.body).to include("n° #{dossier.id} ") } + it { expect(subject.body).to include(dossier.procedure.libelle) } + it { expect(subject.body).to include("PDF") } + it { expect(subject.body).to include("Vous avez un mois pour archiver le dossier.") } + end end describe '.notify_near_deletion_to_user' do @@ -141,6 +166,19 @@ RSpec.describe DossierMailer, type: :mailer do it { expect(subject.body).to include("PDF") } it { expect(subject.body).to include("Vous pouvez retrouver votre dossier pendant encore un mois. Vous n’avez rien à faire.") } end + + describe 'termine' do + let(:dossier) { create(:dossier, :accepte) } + + subject { described_class.notify_near_deletion_to_user([dossier], dossier.user.email) } + + it { expect(subject.to).to eq([dossier.user.email]) } + it { expect(subject.subject).to eq("Un dossier dont le traitement est terminé va bientôt être supprimé") } + it { expect(subject.body).to include("n° #{dossier.id} ") } + it { expect(subject.body).to include(dossier.procedure.libelle) } + it { expect(subject.body).to include("PDF") } + it { expect(subject.body).to include("Vous pouvez retrouver votre dossier pendant encore un mois. Vous n’avez rien à faire.") } + end end describe '.notify_groupe_instructeur_changed_to_instructeur' do diff --git a/spec/mailers/previews/dossier_mailer_preview.rb b/spec/mailers/previews/dossier_mailer_preview.rb index fdda28d6c..c7e0a9e2d 100644 --- a/spec/mailers/previews/dossier_mailer_preview.rb +++ b/spec/mailers/previews/dossier_mailer_preview.rb @@ -28,6 +28,14 @@ class DossierMailerPreview < ActionMailer::Preview DossierMailer.notify_near_deletion_to_administration([dossier_en_construction, dossier_en_construction], administration_email) end + def notify_termine_near_deletion_to_user + DossierMailer.notify_near_deletion_to_user([dossier_accepte], usager_email) + end + + def notify_termine_near_deletion_to_administration + DossierMailer.notify_near_deletion_to_administration([dossier_accepte, dossier_accepte], administration_email) + end + def notify_brouillon_deletion DossierMailer.notify_brouillon_deletion([dossier.hash_for_deletion_mail], usager_email) end @@ -83,6 +91,10 @@ class DossierMailerPreview < ActionMailer::Preview Dossier.new(id: 47882, state: :en_construction, procedure: procedure, user: User.new(email: "usager@example.com")) end + def dossier_accepte + Dossier.new(id: 47882, state: :accepte, procedure: procedure, user: User.new(email: "usager@example.com")) + end + def procedure Procedure.new(id: 1234, libelle: 'Dotation d’Équipement des Territoires Ruraux - Exercice 2019', service: service, logo: Rack::Test::UploadedFile.new("./spec/fixtures/files/logo_test_procedure.png", 'image/png'), auto_archive_on: Time.zone.today + Dossier::REMAINING_DAYS_BEFORE_CLOSING.days) end From 31943f7d9ccca3f4a463310d392d7ecbfd2fa6af Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 2 Apr 2020 15:08:16 +0200 Subject: [PATCH 07/22] Add handeling of expired processed dossiers to deletion service --- .../expired_dossiers_deletion_service.rb | 19 +++ .../expired_dossiers_deletion_service_spec.rb | 137 ++++++++++++++++++ 2 files changed, 156 insertions(+) diff --git a/app/services/expired_dossiers_deletion_service.rb b/app/services/expired_dossiers_deletion_service.rb index 9b8efaa29..6ff7ed180 100644 --- a/app/services/expired_dossiers_deletion_service.rb +++ b/app/services/expired_dossiers_deletion_service.rb @@ -9,6 +9,11 @@ class ExpiredDossiersDeletionService delete_expired_en_construction_and_notify end + def self.process_expired_dossiers_termine + send_termine_expiration_notices + delete_expired_termine_and_notify + end + def self.send_brouillon_expiration_notices dossiers_close_to_expiration = Dossier .brouillon_close_to_expiration @@ -38,6 +43,16 @@ class ExpiredDossiersDeletionService dossiers_close_to_expiration.update_all(en_construction_close_to_expiration_notice_sent_at: Time.zone.now) end + def self.send_termine_expiration_notices + dossiers_close_to_expiration = Dossier + .termine_close_to_expiration + .without_termine_expiration_notice_sent + + send_expiration_notices(dossiers_close_to_expiration) + + dossiers_close_to_expiration.update_all(termine_close_to_expiration_notice_sent_at: Time.zone.now) + end + def self.delete_expired_brouillons_and_notify dossiers_to_remove = Dossier.brouillon_expired @@ -59,6 +74,10 @@ class ExpiredDossiersDeletionService delete_expired_and_notify(Dossier.en_construction_expired) end + def self.delete_expired_termine_and_notify + delete_expired_and_notify(Dossier.termine_expired) + end + private def self.send_expiration_notices(dossiers_close_to_expiration) diff --git a/spec/services/expired_dossiers_deletion_service_spec.rb b/spec/services/expired_dossiers_deletion_service_spec.rb index 3961bbd68..a040a2ebb 100644 --- a/spec/services/expired_dossiers_deletion_service_spec.rb +++ b/spec/services/expired_dossiers_deletion_service_spec.rb @@ -268,4 +268,141 @@ describe ExpiredDossiersDeletionService do it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([deleted_dossier_2], dossier_2.procedure.administrateurs.first.email) } end end + + describe '#send_termine_expiration_notices' do + before { Timecop.freeze(Time.zone.now) } + after { Timecop.return } + + before do + allow(DossierMailer).to receive(:notify_near_deletion_to_user).and_return(double(deliver_later: nil)) + allow(DossierMailer).to receive(:notify_near_deletion_to_administration).and_return(double(deliver_later: nil)) + end + + context 'with a single dossier' do + let!(:dossier) { create(:dossier, :accepte, :followed, procedure: procedure, processed_at: processed_at) } + + before { ExpiredDossiersDeletionService.send_termine_expiration_notices } + + context 'when the dossier is not near deletion' do + let(:processed_at) { (conservation_par_defaut - 1.month - 1.day).ago } + + it { expect(dossier.reload.termine_close_to_expiration_notice_sent_at).to be_nil } + it { expect(DossierMailer).not_to have_received(:notify_near_deletion_to_user) } + it { expect(DossierMailer).not_to have_received(:notify_near_deletion_to_administration) } + end + + context 'when the dossier is near deletion' do + let(:processed_at) { (conservation_par_defaut - 1.month + 1.day).ago } + + it { expect(dossier.reload.termine_close_to_expiration_notice_sent_at).not_to be_nil } + + it { expect(DossierMailer).to have_received(:notify_near_deletion_to_user).once } + it { expect(DossierMailer).to have_received(:notify_near_deletion_to_administration).twice } + it { expect(DossierMailer).to have_received(:notify_near_deletion_to_user).with([dossier], dossier.user.email) } + it { expect(DossierMailer).to have_received(:notify_near_deletion_to_administration).with([dossier], dossier.procedure.administrateurs.first.email) } + it { expect(DossierMailer).to have_received(:notify_near_deletion_to_administration).with([dossier], dossier.followers_instructeurs.first.email) } + end + end + + context 'with 2 dossiers to notice' do + let!(:dossier_1) { create(:dossier, :accepte, procedure: procedure, user: user, processed_at: (conservation_par_defaut - 1.month + 1.day).ago) } + let!(:dossier_2) { create(:dossier, :accepte, procedure: procedure_2, user: user, processed_at: (conservation_par_defaut - 1.month + 1.day).ago) } + + let!(:instructeur) { create(:instructeur) } + + before do + instructeur.followed_dossiers << dossier_1 << dossier_2 + ExpiredDossiersDeletionService.send_termine_expiration_notices + end + + it { expect(DossierMailer).to have_received(:notify_near_deletion_to_user).once } + it { expect(DossierMailer).to have_received(:notify_near_deletion_to_administration).exactly(3).times } + it { expect(DossierMailer).to have_received(:notify_near_deletion_to_user).with(match_array([dossier_1, dossier_2]), user.email) } + it { expect(DossierMailer).to have_received(:notify_near_deletion_to_administration).with(match_array([dossier_1, dossier_2]), instructeur.email) } + it { expect(DossierMailer).to have_received(:notify_near_deletion_to_administration).with([dossier_1], dossier_1.procedure.administrateurs.first.email) } + it { expect(DossierMailer).to have_received(:notify_near_deletion_to_administration).with([dossier_2], dossier_2.procedure.administrateurs.first.email) } + end + + context 'when an instructeur is also administrateur' do + let!(:administrateur) { procedure.administrateurs.first } + let!(:dossier) { create(:dossier, :accepte, procedure: procedure, processed_at: (conservation_par_defaut - 1.month + 1.day).ago) } + + before do + administrateur.instructeur.followed_dossiers << dossier + ExpiredDossiersDeletionService.send_termine_expiration_notices + end + + it { expect(DossierMailer).to have_received(:notify_near_deletion_to_user).once } + it { expect(DossierMailer).to have_received(:notify_near_deletion_to_user).with([dossier], dossier.user.email) } + it { expect(DossierMailer).to have_received(:notify_near_deletion_to_administration).with([dossier], administrateur.email) } + end + end + + describe '#delete_expired_termine_and_notify' do + before { Timecop.freeze(Time.zone.now) } + after { Timecop.return } + + before do + allow(DossierMailer).to receive(:notify_automatic_deletion_to_user).and_return(double(deliver_later: nil)) + allow(DossierMailer).to receive(:notify_automatic_deletion_to_administration).and_return(double(deliver_later: nil)) + end + + context 'with a single dossier' do + let!(:dossier) { create(:dossier, :accepte, :followed, procedure: procedure, termine_close_to_expiration_notice_sent_at: notice_sent_at) } + let(:deleted_dossier) { DeletedDossier.find_by(dossier_id: dossier.id) } + + before { ExpiredDossiersDeletionService.delete_expired_termine_and_notify } + + context 'when no notice has been sent' do + let(:notice_sent_at) { nil } + + it { expect { dossier.reload }.not_to raise_error } + it { expect(DossierMailer).not_to have_received(:notify_automatic_deletion_to_user) } + it { expect(DossierMailer).not_to have_received(:notify_automatic_deletion_to_administration) } + end + + context 'when a notice has been sent not so long ago' do + let(:notice_sent_at) { (warning_period - 4.days).ago } + + it { expect { dossier.reload }.not_to raise_error } + it { expect(DossierMailer).not_to have_received(:notify_automatic_deletion_to_user) } + it { expect(DossierMailer).not_to have_received(:notify_automatic_deletion_to_administration) } + end + + context 'when a notice has been sent a long time ago' do + let(:notice_sent_at) { (warning_period + 4.days).ago } + + it { expect { dossier.reload }.to raise_error(ActiveRecord::RecordNotFound) } + + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_user).once } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_user).with([deleted_dossier], dossier.user.email) } + + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).twice } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([deleted_dossier], dossier.procedure.administrateurs.first.email) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([deleted_dossier], dossier.followers_instructeurs.first.email) } + end + end + + context 'with 2 dossiers to delete' do + let!(:dossier_1) { create(:dossier, :accepte, procedure: procedure, user: user, termine_close_to_expiration_notice_sent_at: (warning_period + 1.day).ago) } + let!(:dossier_2) { create(:dossier, :refuse, procedure: procedure_2, user: user, termine_close_to_expiration_notice_sent_at: (warning_period + 1.day).ago) } + let(:deleted_dossier_1) { DeletedDossier.find_by(dossier_id: dossier_1.id) } + let(:deleted_dossier_2) { DeletedDossier.find_by(dossier_id: dossier_2.id) } + + let!(:instructeur) { create(:instructeur) } + + before do + instructeur.followed_dossiers << dossier_1 << dossier_2 + ExpiredDossiersDeletionService.delete_expired_termine_and_notify + end + + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_user).once } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_user).with(match_array([deleted_dossier_1, deleted_dossier_2]), user.email) } + + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).thrice } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with(match_array([deleted_dossier_1, deleted_dossier_2]), instructeur.email) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([deleted_dossier_1], dossier_1.procedure.administrateurs.first.email) } + it { expect(DossierMailer).to have_received(:notify_automatic_deletion_to_administration).with([deleted_dossier_2], dossier_2.procedure.administrateurs.first.email) } + end + end end From abe692ecc2393bd708cbc222e4a75bf3803509f7 Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Wed, 22 Apr 2020 13:52:28 +0000 Subject: [PATCH 08/22] specs: refactor instructeur procedures controller specs --- .../procedures_controller_spec.rb | 44 +++++++------------ 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/spec/controllers/instructeurs/procedures_controller_spec.rb b/spec/controllers/instructeurs/procedures_controller_spec.rb index 392acc06d..558312500 100644 --- a/spec/controllers/instructeurs/procedures_controller_spec.rb +++ b/spec/controllers/instructeurs/procedures_controller_spec.rb @@ -224,16 +224,20 @@ describe Instructeurs::ProceduresController, type: :controller do let!(:procedure) { create(:procedure, instructeurs: [instructeur]) } let!(:gi_2) { procedure.groupe_instructeurs.create(label: '2') } let!(:gi_3) { procedure.groupe_instructeurs.create(label: '3') } + let(:statut) { nil } + + subject do + get :show, params: { procedure_id: procedure.id, statut: statut } + end context "when logged in, and belonging to gi_1, gi_2" do before do sign_in(instructeur.user) - instructeur.groupe_instructeurs << gi_2 end - context "without anything" do - before { get :show, params: { procedure_id: procedure.id } } + context "without any dossier" do + before { subject } it { expect(response).to have_http_status(:ok) } it { expect(assigns(:procedure)).to eq(procedure) } @@ -242,9 +246,7 @@ describe Instructeurs::ProceduresController, type: :controller do context 'with a new brouillon dossier' do let!(:brouillon_dossier) { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:brouillon)) } - before do - get :show, params: { procedure_id: procedure.id } - end + before { subject } it { expect(assigns(:a_suivre_dossiers)).to be_empty } it { expect(assigns(:followed_dossiers)).to be_empty } @@ -256,9 +258,7 @@ describe Instructeurs::ProceduresController, type: :controller do context 'with a new dossier without follower' do let!(:new_unfollow_dossier) { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:en_instruction)) } - before do - get :show, params: { procedure_id: procedure.id } - end + before { subject } it { expect(assigns(:a_suivre_dossiers)).to match_array([new_unfollow_dossier]) } it { expect(assigns(:followed_dossiers)).to be_empty } @@ -270,9 +270,7 @@ describe Instructeurs::ProceduresController, type: :controller do let!(:new_unfollow_dossier_on_gi_2) { create(:dossier, groupe_instructeur: gi_2, state: Dossier.states.fetch(:en_instruction)) } let!(:new_unfollow_dossier_on_gi_3) { create(:dossier, groupe_instructeur: gi_3, state: Dossier.states.fetch(:en_instruction)) } - before do - get :show, params: { procedure_id: procedure.id } - end + before { subject } it { expect(assigns(:a_suivre_dossiers)).to match_array([new_unfollow_dossier, new_unfollow_dossier_on_gi_2]) } it { expect(assigns(:all_state_dossiers)).to match_array([new_unfollow_dossier, new_unfollow_dossier_on_gi_2]) } @@ -284,7 +282,7 @@ describe Instructeurs::ProceduresController, type: :controller do before do instructeur.followed_dossiers << new_followed_dossier - get :show, params: { procedure_id: procedure.id } + subject end it { expect(assigns(:a_suivre_dossiers)).to be_empty } @@ -299,7 +297,7 @@ describe Instructeurs::ProceduresController, type: :controller do before do instructeur.followed_dossiers << new_follow_dossier_on_gi_2 << new_follow_dossier_on_gi_3 - get :show, params: { procedure_id: procedure.id } + subject end # followed dossiers on another groupe should not be displayed @@ -311,9 +309,7 @@ describe Instructeurs::ProceduresController, type: :controller do context 'with a termine dossier with a follower' do let!(:termine_dossier) { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:accepte)) } - before do - get :show, params: { procedure_id: procedure.id } - end + before { subject } it { expect(assigns(:a_suivre_dossiers)).to be_empty } it { expect(assigns(:followed_dossiers)).to be_empty } @@ -325,9 +321,7 @@ describe Instructeurs::ProceduresController, type: :controller do let!(:termine_dossier_on_gi_2) { create(:dossier, groupe_instructeur: gi_2, state: Dossier.states.fetch(:accepte)) } let!(:termine_dossier_on_gi_3) { create(:dossier, groupe_instructeur: gi_3, state: Dossier.states.fetch(:accepte)) } - before do - get :show, params: { procedure_id: procedure.id } - end + before { subject } it { expect(assigns(:termines_dossiers)).to match_array([termine_dossier, termine_dossier_on_gi_2]) } it { expect(assigns(:all_state_dossiers)).to match_array([termine_dossier, termine_dossier_on_gi_2]) } @@ -337,9 +331,7 @@ describe Instructeurs::ProceduresController, type: :controller do context 'with an archived dossier' do let!(:archived_dossier) { create(:dossier, procedure: procedure, state: Dossier.states.fetch(:en_instruction), archived: true) } - before do - get :show, params: { procedure_id: procedure.id } - end + before { subject } it { expect(assigns(:a_suivre_dossiers)).to be_empty } it { expect(assigns(:followed_dossiers)).to be_empty } @@ -351,9 +343,7 @@ describe Instructeurs::ProceduresController, type: :controller do let!(:archived_dossier_on_gi_2) { create(:dossier, groupe_instructeur: gi_2, state: Dossier.states.fetch(:en_instruction), archived: true) } let!(:archived_dossier_on_gi_3) { create(:dossier, groupe_instructeur: gi_3, state: Dossier.states.fetch(:en_instruction), archived: true) } - before do - get :show, params: { procedure_id: procedure.id } - end + before { subject } it { expect(assigns(:archived_dossiers)).to match_array([archived_dossier, archived_dossier_on_gi_2]) } end @@ -367,7 +357,7 @@ describe Instructeurs::ProceduresController, type: :controller do before do instructeur.followed_dossiers << new_followed_dossier - get :show, params: { procedure_id: procedure.id, statut: statut } + subject end context 'when statut is empty' do From 32ad152347104d432b6b994b22ad760552a8b5fb Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Wed, 22 Apr 2020 15:53:54 +0200 Subject: [PATCH 09/22] specs: ensure that discarded procedures are not shown --- .../instructeurs/procedures_controller_spec.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/spec/controllers/instructeurs/procedures_controller_spec.rb b/spec/controllers/instructeurs/procedures_controller_spec.rb index 558312500..9b91ed178 100644 --- a/spec/controllers/instructeurs/procedures_controller_spec.rb +++ b/spec/controllers/instructeurs/procedures_controller_spec.rb @@ -236,6 +236,14 @@ describe Instructeurs::ProceduresController, type: :controller do instructeur.groupe_instructeurs << gi_2 end + context 'when the procedure is discarded' do + before do + procedure.discard! + end + + it { expect { subject }.to raise_error(ActiveRecord::RecordNotFound) } + end + context "without any dossier" do before { subject } From b849fc6fc3e374eb86e6b57e160457d76872a2da Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Wed, 22 Apr 2020 17:24:54 +0200 Subject: [PATCH 10/22] Mark as sent or destroy right after each notification is sent to enable a better recovery in case of mid loop failures --- .../expired_dossiers_deletion_service.rb | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/app/services/expired_dossiers_deletion_service.rb b/app/services/expired_dossiers_deletion_service.rb index 6ff7ed180..9e1aec31b 100644 --- a/app/services/expired_dossiers_deletion_service.rb +++ b/app/services/expired_dossiers_deletion_service.rb @@ -28,29 +28,27 @@ class ExpiredDossiersDeletionService dossiers, user.email ).deliver_later + + # mark as sent dossiers from current notification + Dossier.where(id: dossiers).update_all(brouillon_close_to_expiration_notice_sent_at: Time.zone.now) end + # mark as sent dossiers without notification dossiers_close_to_expiration.update_all(brouillon_close_to_expiration_notice_sent_at: Time.zone.now) end def self.send_en_construction_expiration_notices - dossiers_close_to_expiration = Dossier - .en_construction_close_to_expiration - .without_en_construction_expiration_notice_sent - - send_expiration_notices(dossiers_close_to_expiration) - - dossiers_close_to_expiration.update_all(en_construction_close_to_expiration_notice_sent_at: Time.zone.now) + send_expiration_notices( + Dossier.en_construction_close_to_expiration.without_en_construction_expiration_notice_sent, + :en_construction_close_to_expiration_notice_sent_at + ) end def self.send_termine_expiration_notices - dossiers_close_to_expiration = Dossier - .termine_close_to_expiration - .without_termine_expiration_notice_sent - - send_expiration_notices(dossiers_close_to_expiration) - - dossiers_close_to_expiration.update_all(termine_close_to_expiration_notice_sent_at: Time.zone.now) + send_expiration_notices( + Dossier.termine_close_to_expiration.without_termine_expiration_notice_sent, + :termine_close_to_expiration_notice_sent_at + ) end def self.delete_expired_brouillons_and_notify @@ -65,8 +63,12 @@ class ExpiredDossiersDeletionService dossiers.map(&:hash_for_deletion_mail), user.email ).deliver_later + + # destroy dossiers from current notification + Dossier.where(id: dossiers).destroy_all end + # destroy dossiers without notification dossiers_to_remove.destroy_all end @@ -80,7 +82,7 @@ class ExpiredDossiersDeletionService private - def self.send_expiration_notices(dossiers_close_to_expiration) + def self.send_expiration_notices(dossiers_close_to_expiration, close_to_expiration_flag) dossiers_close_to_expiration .with_notifiable_procedure .includes(:user) @@ -97,7 +99,13 @@ class ExpiredDossiersDeletionService dossiers.to_a, email ).deliver_later + + # mark as sent dossiers from current notification + Dossier.where(id: dossiers.to_a).update_all(close_to_expiration_flag => Time.zone.now) end + + # mark as sent dossiers without notification + dossiers_close_to_expiration.update_all(close_to_expiration_flag => Time.zone.now) end def self.delete_expired_and_notify(dossiers_to_remove) @@ -119,8 +127,12 @@ class ExpiredDossiersDeletionService DeletedDossier.where(dossier_id: dossiers.map(&:id)), email ).deliver_later + + # destroy dossiers from current notification + Dossier.where(id: dossiers.to_a).destroy_all end + # destroy dossiers without notification dossiers_to_remove.destroy_all end From a507359f5c3100577e015a1ee0a612c9565a0d1f Mon Sep 17 00:00:00 2001 From: Christophe Robillard Date: Wed, 22 Apr 2020 10:45:51 +0200 Subject: [PATCH 11/22] =?UTF-8?q?pr=C3=A9cise=20source=20pour=20effectifs?= =?UTF-8?q?=20mensuels?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/views/shared/dossiers/_identite_entreprise.html.haml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/views/shared/dossiers/_identite_entreprise.html.haml b/app/views/shared/dossiers/_identite_entreprise.html.haml index 51a5dc51f..af20dacc9 100644 --- a/app/views/shared/dossiers/_identite_entreprise.html.haml +++ b/app/views/shared/dossiers/_identite_entreprise.html.haml @@ -32,10 +32,13 @@ %th.libelle Effectif mensuel = try_format_mois_effectif(etablissement) + (URSSAF) %td= etablissement.entreprise_effectif_mensuel %tr %th.libelle Effectif de l'organisation : - %td= effectif(etablissement) + %td + = effectif(etablissement) + (INSEE) %tr %th.libelle Code effectif : %td= etablissement.entreprise.code_effectif_entreprise From 85d119fa4d536a42943ba3e9588aacf33c2d3fe3 Mon Sep 17 00:00:00 2001 From: Christophe Robillard Date: Wed, 22 Apr 2020 10:47:15 +0200 Subject: [PATCH 12/22] n'affiche plus le code effectif --- app/views/shared/dossiers/_identite_entreprise.html.haml | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/views/shared/dossiers/_identite_entreprise.html.haml b/app/views/shared/dossiers/_identite_entreprise.html.haml index af20dacc9..87370d0b2 100644 --- a/app/views/shared/dossiers/_identite_entreprise.html.haml +++ b/app/views/shared/dossiers/_identite_entreprise.html.haml @@ -39,9 +39,6 @@ %td = effectif(etablissement) (INSEE) - %tr - %th.libelle Code effectif : - %td= etablissement.entreprise.code_effectif_entreprise %tr %th.libelle Numéro de TVA intracommunautaire : %td= etablissement.entreprise.numero_tva_intracommunautaire From 453adf3c74bfebaefe18bbcbd08ff096f00f433d Mon Sep 17 00:00:00 2001 From: Christophe Robillard Date: Wed, 22 Apr 2020 17:53:45 +0200 Subject: [PATCH 13/22] instructeurs: affiche l'effectif moyen annuel n-1 --- app/lib/api_entreprise/api.rb | 5 ++++ .../effectifs_annuels_adapter.rb | 23 ++++++++++++++++++ app/services/api_entreprise_service.rb | 6 +++++ .../dossiers/_identite_entreprise.html.haml | 9 +++++-- ...422090426_add_effectif_annee_anterieure.rb | 6 +++++ db/schema.rb | 4 +++- .../users/dossiers_controller_spec.rb | 6 +++++ spec/features/users/dossier_creation_spec.rb | 2 ++ .../api_entreprise/effectifs_annuels.json | 5 ++++ .../effectifs_annuels_adapter_spec.rb | 24 +++++++++++++++++++ spec/services/api_entreprise_service_spec.rb | 7 ++++++ 11 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 app/lib/api_entreprise/effectifs_annuels_adapter.rb create mode 100644 db/migrate/20200422090426_add_effectif_annee_anterieure.rb create mode 100644 spec/fixtures/files/api_entreprise/effectifs_annuels.json create mode 100644 spec/lib/api_entreprise/effectifs_annuels_adapter_spec.rb diff --git a/app/lib/api_entreprise/api.rb b/app/lib/api_entreprise/api.rb index 8c5c66eb4..5d8443fea 100644 --- a/app/lib/api_entreprise/api.rb +++ b/app/lib/api_entreprise/api.rb @@ -4,6 +4,7 @@ class ApiEntreprise::API EXERCICES_RESOURCE_NAME = "exercices" RNA_RESOURCE_NAME = "associations" EFFECTIFS_RESOURCE_NAME = "effectifs_mensuels_acoss_covid" + EFFECTIFS_ANNUELS_RESOURCE_NAME = "effectifs_annuels_acoss_covid" TIMEOUT = 15 @@ -34,6 +35,10 @@ class ApiEntreprise::API call(endpoint, siren, procedure_id) end + def self.effectifs_annuels(siren, procedure_id) + call(EFFECTIFS_ANNUELS_RESOURCE_NAME, siren, procedure_id) + end + private def self.call(resource_name, siret_or_siren, procedure_id) diff --git a/app/lib/api_entreprise/effectifs_annuels_adapter.rb b/app/lib/api_entreprise/effectifs_annuels_adapter.rb new file mode 100644 index 000000000..2c56b41f6 --- /dev/null +++ b/app/lib/api_entreprise/effectifs_annuels_adapter.rb @@ -0,0 +1,23 @@ +class ApiEntreprise::EffectifsAnnuelsAdapter < ApiEntreprise::Adapter + def initialize(siren, procedure_id) + @siren = siren + @procedure_id = procedure_id + end + + private + + def get_resource + ApiEntreprise::API.effectifs_annuels(@siren, @procedure_id) + end + + def process_params + if data_source[:effectifs_annuels].present? + { + entreprise_effectif_annuel: data_source[:effectifs_annuels], + entreprise_effectif_annuel_annee: data_source[:annee] + } + else + {} + end + end +end diff --git a/app/services/api_entreprise_service.rb b/app/services/api_entreprise_service.rb index 2b48acf8a..3f5082765 100644 --- a/app/services/api_entreprise_service.rb +++ b/app/services/api_entreprise_service.rb @@ -29,6 +29,12 @@ class ApiEntrepriseService rescue ApiEntreprise::API::RequestFailed end + begin + effectifs_annuels_params = ApiEntreprise::EffectifsAnnuelsAdapter.new(entreprise_params[:entreprise_siren], procedure_id).to_params + etablissement_params.merge!(effectifs_annuels_params) + rescue ApiEntreprise::API::RequestFailed + end + etablissement_params.merge(entreprise_params) end end diff --git a/app/views/shared/dossiers/_identite_entreprise.html.haml b/app/views/shared/dossiers/_identite_entreprise.html.haml index 87370d0b2..a10cfdaf5 100644 --- a/app/views/shared/dossiers/_identite_entreprise.html.haml +++ b/app/views/shared/dossiers/_identite_entreprise.html.haml @@ -34,11 +34,16 @@ = try_format_mois_effectif(etablissement) (URSSAF) %td= etablissement.entreprise_effectif_mensuel + %tr + %th.libelle + Effectif moyen annuel + = etablissement.entreprise_effectif_annuel_annee + (URSSAF) + %td= etablissement.entreprise_effectif_annuel %tr - %th.libelle Effectif de l'organisation : + %th.libelle Effectif de l'organisation (INSEE) : %td = effectif(etablissement) - (INSEE) %tr %th.libelle Numéro de TVA intracommunautaire : %td= etablissement.entreprise.numero_tva_intracommunautaire diff --git a/db/migrate/20200422090426_add_effectif_annee_anterieure.rb b/db/migrate/20200422090426_add_effectif_annee_anterieure.rb new file mode 100644 index 000000000..62f55e3fc --- /dev/null +++ b/db/migrate/20200422090426_add_effectif_annee_anterieure.rb @@ -0,0 +1,6 @@ +class AddEffectifAnneeAnterieure < ActiveRecord::Migration[5.2] + def change + add_column :etablissements, :entreprise_effectif_annuel, :decimal + add_column :etablissements, :entreprise_effectif_annuel_annee, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 005470ef1..2f59b5fe7 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2020_04_21_174642) do +ActiveRecord::Schema.define(version: 2020_04_22_090426) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -314,6 +314,8 @@ ActiveRecord::Schema.define(version: 2020_04_21_174642) do t.string "entreprise_effectif_mois" t.string "entreprise_effectif_annee" t.decimal "entreprise_effectif_mensuel" + t.decimal "entreprise_effectif_annuel" + t.string "entreprise_effectif_annuel_annee" t.index ["dossier_id"], name: "index_etablissements_on_dossier_id" end diff --git a/spec/controllers/users/dossiers_controller_spec.rb b/spec/controllers/users/dossiers_controller_spec.rb index 5779e099a..c2990c13c 100644 --- a/spec/controllers/users/dossiers_controller_spec.rb +++ b/spec/controllers/users/dossiers_controller_spec.rb @@ -212,6 +212,9 @@ describe Users::DossiersController, type: :controller do let(:annee) { "2020" } let(:mois) { "02" } + let(:api_entreprise_effectifs_annuels_status) { 200 } + let(:api_entreprise_effectifs_annuels_body) { File.read('spec/fixtures/files/api_entreprise/effectifs_annuels.json') } + let(:api_exercices_status) { 200 } let(:api_exercices_body) { File.read('spec/fixtures/files/api_entreprise/exercices.json') } @@ -229,6 +232,8 @@ describe Users::DossiersController, type: :controller do .to_return(status: api_association_status, body: api_association_body) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_mensuels_acoss_covid\/#{annee}\/#{mois}\/entreprise\/#{siren}?.*token=/) .to_return(body: api_entreprise_effectifs_mensuels_body, status: api_entreprise_effectifs_mensuels_status) + stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_annuels_acoss_covid\/#{siren}?.*token=/) + .to_return(body: api_entreprise_effectifs_annuels_body, status: api_entreprise_effectifs_annuels_status) end before do @@ -328,6 +333,7 @@ describe Users::DossiersController, type: :controller do expect(dossier.etablissement.exercices).to be_present expect(dossier.etablissement.association?).to be(true) expect(dossier.etablissement.entreprise_effectif_mensuel).to be_present + expect(dossier.etablissement.entreprise_effectif_annuel).to be_present end end end diff --git a/spec/features/users/dossier_creation_spec.rb b/spec/features/users/dossier_creation_spec.rb index 5849cd1b4..4dec03889 100644 --- a/spec/features/users/dossier_creation_spec.rb +++ b/spec/features/users/dossier_creation_spec.rb @@ -76,6 +76,8 @@ feature 'Creating a new dossier:' do .to_return(status: 404, body: '') stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_mensuels_acoss_covid\/2020\/02\/entreprise\/#{siren}?.*token=/) .to_return(status: 404, body: '') + stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_annuels_acoss_covid\/#{siren}?.*token=/) + .to_return(status: 404, body: '') end before { Timecop.freeze(Time.zone.local(2020, 3, 14)) } after { Timecop.return } diff --git a/spec/fixtures/files/api_entreprise/effectifs_annuels.json b/spec/fixtures/files/api_entreprise/effectifs_annuels.json new file mode 100644 index 000000000..da299e40d --- /dev/null +++ b/spec/fixtures/files/api_entreprise/effectifs_annuels.json @@ -0,0 +1,5 @@ +{ + "siren": "418166096", + "annee": "2019", + "effectifs_annuels": 100.5 +} diff --git a/spec/lib/api_entreprise/effectifs_annuels_adapter_spec.rb b/spec/lib/api_entreprise/effectifs_annuels_adapter_spec.rb new file mode 100644 index 000000000..2c52cb00b --- /dev/null +++ b/spec/lib/api_entreprise/effectifs_annuels_adapter_spec.rb @@ -0,0 +1,24 @@ +describe ApiEntreprise::EffectifsAnnuelsAdapter do + let(:siren) { '418166096' } + let(:procedure_id) { 22 } + let(:adapter) { described_class.new(siren, procedure_id) } + subject { adapter.to_params } + + before do + stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_annuels_acoss_covid\/#{siren}?.*token=/) + .to_return(body: body, status: status) + end + + context "when the SIREN is valid" do + let(:body) { File.read('spec/fixtures/files/api_entreprise/effectifs_annuels.json') } + let(:status) { 200 } + + it '#to_params class est une Hash ?' do + expect(subject).to be_an_instance_of(Hash) + end + + it "renvoie les effectifs de l'année antérieure" do + expect(subject[:entreprise_effectif_annuel]).to eq(100.5) + end + end +end diff --git a/spec/services/api_entreprise_service_spec.rb b/spec/services/api_entreprise_service_spec.rb index ff6fec019..ca999d147 100644 --- a/spec/services/api_entreprise_service_spec.rb +++ b/spec/services/api_entreprise_service_spec.rb @@ -11,6 +11,8 @@ describe ApiEntrepriseService do .to_return(body: associations_body, status: associations_status) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_mensuels_acoss_covid\/#{annee}\/#{mois}\/entreprise\/#{siren}?.*token=/) .to_return(body: effectifs_mensuels_body, status: effectifs_mensuels_status) + stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_annuels_acoss_covid\/#{siren}?.*token=/) + .to_return(body: effectifs_annuels_body, status: effectifs_annuels_status) end before { Timecop.freeze(Time.zone.local(2020, 3, 14)) } @@ -32,6 +34,10 @@ describe ApiEntrepriseService do let(:mois) { "02" } let(:effectif_mensuel) { 100.5 } + let(:effectifs_annuels_status) { 200 } + let(:effectifs_annuels_body) { File.read('spec/fixtures/files/api_entreprise/effectifs_annuels.json') } + let(:effectif_annuel) { 100.5 } + let(:exercices_status) { 200 } let(:exercices_body) { File.read('spec/fixtures/files/api_entreprise/exercices.json') } @@ -47,6 +53,7 @@ describe ApiEntrepriseService do expect(result[:association_rna]).to eq(rna) expect(result[:exercices_attributes]).to_not be_empty expect(result[:entreprise_effectif_mensuel]).to eq(effectif_mensuel) + expect(result[:entreprise_effectif_annuel]).to eq(effectif_annuel) end end From 792e755af934ebba366ba7914305c606e486a8e3 Mon Sep 17 00:00:00 2001 From: Christophe Robillard Date: Wed, 22 Apr 2020 19:00:25 +0200 Subject: [PATCH 14/22] expose effectif_annuel dans api graphql --- app/graphql/schema.graphql | 21 +++++++------- app/graphql/types/personne_morale_type.rb | 28 +++++++++++-------- app/models/entreprise.rb | 2 ++ app/models/etablissement.rb | 2 ++ app/serializers/entreprise_serializer.rb | 2 ++ .../api/v1/dossiers_controller_spec.rb | 2 ++ 6 files changed, 36 insertions(+), 21 deletions(-) diff --git a/app/graphql/schema.graphql b/app/graphql/schema.graphql index 6b0b895f4..c1dea88f4 100644 --- a/app/graphql/schema.graphql +++ b/app/graphql/schema.graphql @@ -687,23 +687,24 @@ enum DossierState { } type Effectif { - """ - Année de l'effectif mensuel - """ - annee: String! - - """ - Mois de l'effectif mensuel - """ - mois: String! nb: Float! + periode: String! } type Entreprise { capitalSocial: BigInt! codeEffectifEntreprise: String! dateCreation: ISO8601Date! - effectifs: [Effectif!]! + + """ + effectif moyen d'une année + """ + effectifAnnuel: Effectif + + """ + effectif pour un mois donné + """ + effectifMensuel: Effectif formeJuridique: String! formeJuridiqueCode: String! inlineAdresse: String! diff --git a/app/graphql/types/personne_morale_type.rb b/app/graphql/types/personne_morale_type.rb index 5bc5f176b..627145cb0 100644 --- a/app/graphql/types/personne_morale_type.rb +++ b/app/graphql/types/personne_morale_type.rb @@ -2,8 +2,7 @@ module Types class PersonneMoraleType < Types::BaseObject class EntrepriseType < Types::BaseObject class EffectifType < Types::BaseObject - field :mois, String, null: false, description: "Mois de l'effectif mensuel" - field :annee, String, null: false, description: "Année de l'effectif mensuel" + field :periode, String, null: false field :nb, Float, null: false end @@ -16,21 +15,28 @@ module Types field :raison_sociale, String, null: false field :siret_siege_social, String, null: false field :code_effectif_entreprise, String, null: false - field :effectifs, [EffectifType], null: false + field :effectif_mensuel, EffectifType, null: true, description: "effectif pour un mois donné" + field :effectif_annuel, EffectifType, null: true, description: "effectif moyen d'une année" field :date_creation, GraphQL::Types::ISO8601Date, null: false field :nom, String, null: false field :prenom, String, null: false field :inline_adresse, String, null: false - def effectifs + def effectif_mensuel if object.effectif_mensuel.present? - [ - { - mois: object.effectif_mois, - annee: object.effectif_annee, - nb: object.effectif_mensuel - } - ] + { + periode: [object.effectif_mois, object.effectif_annee].join('/'), + nb: object.effectif_mensuel + } + end + end + + def effectif_annuel + if object.effectif_annuel.present? + { + periode: object.effectif_annuel_annee, + nb: object.effectif_annuel + } end end end diff --git a/app/models/entreprise.rb b/app/models/entreprise.rb index 5fb6cf719..5808b91e9 100644 --- a/app/models/entreprise.rb +++ b/app/models/entreprise.rb @@ -15,6 +15,8 @@ class Entreprise < Hashie::Dash property :effectif_mois property :effectif_annee property :effectif_mensuel + property :effectif_annuel + property :effectif_annuel_annee property :date_creation property :nom property :prenom diff --git a/app/models/etablissement.rb b/app/models/etablissement.rb index 4d3236e80..5b57331a2 100644 --- a/app/models/etablissement.rb +++ b/app/models/etablissement.rb @@ -105,6 +105,8 @@ class Etablissement < ApplicationRecord effectif_mensuel: entreprise_effectif_mensuel, effectif_mois: entreprise_effectif_mois, effectif_annee: entreprise_effectif_annee, + effectif_annuel: entreprise_effectif_annuel, + effectif_annuel_annee: entreprise_effectif_annuel_annee, date_creation: entreprise_date_creation, nom: entreprise_nom, prenom: entreprise_prenom, diff --git a/app/serializers/entreprise_serializer.rb b/app/serializers/entreprise_serializer.rb index 70437d8c8..602f9e69b 100644 --- a/app/serializers/entreprise_serializer.rb +++ b/app/serializers/entreprise_serializer.rb @@ -11,6 +11,8 @@ class EntrepriseSerializer < ActiveModel::Serializer :effectif_mois, :effectif_annee, :effectif_mensuel, + :effectif_annuel, + :effectif_annuel_annee, :date_creation, :nom, :prenom diff --git a/spec/controllers/api/v1/dossiers_controller_spec.rb b/spec/controllers/api/v1/dossiers_controller_spec.rb index a329464ac..1bc8b195b 100644 --- a/spec/controllers/api/v1/dossiers_controller_spec.rb +++ b/spec/controllers/api/v1/dossiers_controller_spec.rb @@ -200,6 +200,8 @@ describe API::V1::DossiersController do :effectif_mois, :effectif_annee, :effectif_mensuel, + :effectif_annuel, + :effectif_annuel_annee, :date_creation, :nom, :prenom From 9cb612bb3d1ce15f0c4172924229848e95ae5b31 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Wed, 15 Apr 2020 15:43:38 +0200 Subject: [PATCH 15/22] Show area and length on champ carto selections utilisateur --- Gemfile | 2 + Gemfile.lock | 5 ++ app/helpers/champ_helper.rb | 11 ++++ app/models/geo_area.rb | 32 +++++++++++- .../shared/champs/carte/_geo_areas.html.haml | 7 +++ spec/models/geo_area_spec.rb | 50 +++++++++++++++++++ 6 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 spec/models/geo_area_spec.rb diff --git a/Gemfile b/Gemfile index be4cfbaea..acc6af262 100644 --- a/Gemfile +++ b/Gemfile @@ -25,11 +25,13 @@ gem 'devise' # Gestion des comptes utilisateurs gem 'devise-async' gem 'discard' gem 'dotenv-rails', require: 'dotenv/rails-now' # dotenv should always be loaded before rails +gem 'ffi-geos' gem 'flipper' gem 'flipper-active_record' gem 'flipper-ui' gem 'font-awesome-rails' gem 'fugit' +gem 'geo_coord', require: "geo/coord" gem 'geocoder' gem 'gon' gem 'graphql' diff --git a/Gemfile.lock b/Gemfile.lock index 5544e433f..0958a8495 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -215,6 +215,8 @@ GEM faraday (0.15.4) multipart-post (>= 1.2, < 3) ffi (1.12.2) + ffi-geos (2.1.0) + ffi (>= 1.0.0) flipper (0.17.2) flipper-active_record (0.17.2) activerecord (>= 4.2, < 7) @@ -242,6 +244,7 @@ GEM fugit (1.3.3) et-orbi (~> 1.1, >= 1.1.8) raabro (~> 1.1) + geo_coord (0.1.0) geocoder (1.6.0) globalid (0.4.2) activesupport (>= 4.2.0) @@ -750,11 +753,13 @@ DEPENDENCIES discard dotenv-rails factory_bot + ffi-geos flipper flipper-active_record flipper-ui font-awesome-rails fugit + geo_coord geocoder gon graphql diff --git a/app/helpers/champ_helper.rb b/app/helpers/champ_helper.rb index b41d81fa2..36416f759 100644 --- a/app/helpers/champ_helper.rb +++ b/app/helpers/champ_helper.rb @@ -49,6 +49,17 @@ module ChampHelper "#{geo_area.commune} : #{geo_area.nom}" when GeoArea.sources.fetch(:parcelle_agricole) "Culture : #{geo_area.culture} - Surface : #{geo_area.surface} ha" + when GeoArea.sources.fetch(:selection_utilisateur) + if geo_area.polygon? + capture do + concat "Une aire de surface #{geo_area.area} m" + concat content_tag(:sup, "2") + end + elsif geo_area.line? + "Une ligne longue de #{geo_area.length} m" + elsif geo_area.point? + "Un point situé à #{geo_area.location}" + end end end end diff --git a/app/models/geo_area.rb b/app/models/geo_area.rb index ce89d7e03..60e59afd9 100644 --- a/app/models/geo_area.rb +++ b/app/models/geo_area.rb @@ -36,7 +36,7 @@ class GeoArea < ApplicationRecord { type: 'Feature', geometry: geometry, - properties: properties.merge(source: source) + properties: properties.merge(source: source, area: area, length: length).compact } end @@ -53,4 +53,34 @@ class GeoArea < ApplicationRecord ) end end + + def area + if polygon? + rgeo_geometry.area.round(1) + end + end + + def length + if line? + rgeo_geometry.length.round(1) + end + end + + def location + if point? + Geo::Coord.new(*rgeo_geometry.coordinates).to_s + end + end + + def line? + geometry['type'] == 'LineString' + end + + def polygon? + geometry['type'] == 'Polygon' + end + + def point? + geometry['type'] == 'Point' + end end diff --git a/app/views/shared/champs/carte/_geo_areas.html.haml b/app/views/shared/champs/carte/_geo_areas.html.haml index 6f3565e3d..6f5f24b13 100644 --- a/app/views/shared/champs/carte/_geo_areas.html.haml +++ b/app/views/shared/champs/carte/_geo_areas.html.haml @@ -1,3 +1,10 @@ +- if champ.selections_utilisateur.present? + .areas-title Sélections utilisateur + .areas + %ul + - champ.selections_utilisateur.each do |geo_area| + %li= geo_area_label(geo_area) + - if champ.quartiers_prioritaires? .areas-title Quartiers prioritaires .areas diff --git a/spec/models/geo_area_spec.rb b/spec/models/geo_area_spec.rb new file mode 100644 index 000000000..08ede4acd --- /dev/null +++ b/spec/models/geo_area_spec.rb @@ -0,0 +1,50 @@ +RSpec.describe GeoArea, type: :model do + describe '#area' do + let(:geo_area) do + create(:geo_area, geometry: { + "type": "Polygon", + "coordinates": [ + [ + [2.428439855575562, 46.538476837725796], + [2.4284291267395024, 46.53842148758162], + [2.4282521009445195, 46.53841410755813], + [2.42824137210846, 46.53847314771794], + [2.428284287452698, 46.53847314771794], + [2.428364753723145, 46.538487907747864], + [2.4284291267395024, 46.538491597754714], + [2.428439855575562, 46.538476837725796] + ] + ] + }) + end + + it { expect(geo_area.area).to eq(219.0) } + end + + describe '#length' do + let(:geo_area) do + create(:geo_area, geometry: { + "type": "LineString", + "coordinates": [ + [2.4282521009445195, 46.53841410755813], + [2.42824137210846, 46.53847314771794], + [2.428284287452698, 46.53847314771794], + [2.4284291267395024, 46.538491597754714] + ] + }) + end + + it { expect(geo_area.length).to eq(30.8) } + end + + describe '#location' do + let(:geo_area) do + create(:geo_area, geometry: { + "type": "Point", + "coordinates": [2.428439855575562, 46.538476837725796] + }) + end + + it { expect(geo_area.location).to eq("2°25'42\"N 46°32'19\"E") } + end +end From d591892380192cab7edeff99814280d2a4b74b15 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Wed, 22 Apr 2020 11:27:33 +0200 Subject: [PATCH 16/22] Add GEOS to circle CI --- .circleci/config.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index a7d5edd1e..17e827069 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -25,6 +25,11 @@ bundle_save_cache: &bundle_save_cache paths: - ~/vendor/bundle +aptget_install: &aptget_install + run: + name: Install GEOS + command: sudo apt-get install libgeos-dev + bundle_install: &bundle_install run: name: Install Ruby Dependencies @@ -78,6 +83,7 @@ jobs: <<: *defaults steps: - checkout + - *aptget_install - *bundle_restore_cache - *bundle_install - *bundle_save_cache @@ -89,6 +95,7 @@ jobs: parallelism: 3 steps: - checkout + - *aptget_install - *bundle_restore_cache - *bundle_install - *yarn_restore_cache @@ -123,6 +130,7 @@ jobs: <<: *defaults steps: - checkout + - *aptget_install - *bundle_restore_cache - *bundle_install - *yarn_restore_cache From 6f4075f38e34c215fff333e4983df9657e29cf06 Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Wed, 22 Apr 2020 16:21:33 +0000 Subject: [PATCH 17/22] javascript: fix FileUploadError stacktraces When subclassing a JS error, most browsers include the constructor stacktrace :/ This is an issue, because: - The stacktrace is deeper than it should be - The stacktrace reaches into a polyfill for which there is not source map, which causes Sentry to infer the issue grouping from the JS file name. And the fingerprinted name changes on each release. So for each release, the stacktrace is different ; and Sentry can't group issues properly. --- .../shared/activestorage/file-upload-error.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/javascript/shared/activestorage/file-upload-error.js b/app/javascript/shared/activestorage/file-upload-error.js index 9b8b4285a..ef4aa5ded 100644 --- a/app/javascript/shared/activestorage/file-upload-error.js +++ b/app/javascript/shared/activestorage/file-upload-error.js @@ -20,9 +20,19 @@ export const FAILURE_CONNECTIVITY = 'file-upload-failure-connectivity'; export default class FileUploadError extends Error { constructor(message, status, code) { super(message); + this.name = 'FileUploadError'; this.status = status; this.code = code; + + // Prevent the constructor stacktrace from being included. + // (it messes up with Sentry issues grouping) + if (Error.captureStackTrace) { + // V8-only + Error.captureStackTrace(this, this.constructor); + } else { + this.stack = new Error().stack; + } } /** From 339066778d7aeaa157b30b3987300bdcf3b45679 Mon Sep 17 00:00:00 2001 From: Christophe Robillard Date: Thu, 23 Apr 2020 11:52:21 +0200 Subject: [PATCH 18/22] send notif only to the right instructeurs after a dossier creation, only the instructeurs that belong to the group instructeur of the dossier, and who want notif will be notified by mail --- app/controllers/users/dossiers_controller.rb | 2 +- .../users/dossiers_controller_spec.rb | 22 +++++++++++++++++++ spec/factories/assign_to.rb | 8 +++++-- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index f94983007..88ea0db37 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -153,7 +153,7 @@ module Users if passage_en_construction? && errors.blank? @dossier.en_construction! NotificationMailer.send_initiated_notification(@dossier).deliver_later - @dossier.procedure.instructeurs.with_instant_email_dossier_notifications.each do |instructeur| + @dossier.groupe_instructeur.instructeurs.with_instant_email_dossier_notifications.each do |instructeur| DossierMailer.notify_new_dossier_depose_to_instructeur(@dossier, instructeur.email).deliver_later end return redirect_to(merci_dossier_path(@dossier)) diff --git a/spec/controllers/users/dossiers_controller_spec.rb b/spec/controllers/users/dossiers_controller_spec.rb index c2990c13c..8f56f1f38 100644 --- a/spec/controllers/users/dossiers_controller_spec.rb +++ b/spec/controllers/users/dossiers_controller_spec.rb @@ -454,6 +454,28 @@ describe Users::DossiersController, type: :controller do end end + context 'with procedure routee' do + let(:procedure) { create(:procedure, :routee, :with_type_de_champ) } + let(:dossier_group) { create(:groupe_instructeur, procedure: procedure) } + let(:another_group) { create(:groupe_instructeur, procedure: procedure) } + let(:instructeur_of_dossier) { create(:instructeur) } + let(:instructeur_in_another_group) { create(:instructeur) } + let!(:dossier) { create(:dossier, groupe_instructeur: dossier_group, user: user) } + + before do + allow(DossierMailer).to receive(:notify_new_dossier_depose_to_instructeur).and_return(double(deliver_later: nil)) + create(:assign_to, instructeur: instructeur_of_dossier, procedure: dossier.procedure, instant_email_dossier_notifications_enabled: true, groupe_instructeur: dossier_group) + create(:assign_to, instructeur: instructeur_in_another_group, procedure: dossier.procedure, instant_email_dossier_notifications_enabled: true, groupe_instructeur: another_group) + end + + it "sends notification mail to instructeurs in the correct group instructeur" do + subject + + expect(DossierMailer).to have_received(:notify_new_dossier_depose_to_instructeur).once.with(dossier, instructeur_of_dossier.email) + expect(DossierMailer).not_to have_received(:notify_new_dossier_depose_to_instructeur).with(dossier, instructeur_in_another_group.email) + end + end + context "on an closed procedure" do before { dossier.procedure.close! } diff --git a/spec/factories/assign_to.rb b/spec/factories/assign_to.rb index 759c32d52..64955c283 100644 --- a/spec/factories/assign_to.rb +++ b/spec/factories/assign_to.rb @@ -1,7 +1,11 @@ FactoryBot.define do factory :assign_to do - after(:build) do |assign_to, _evaluator| - assign_to.groupe_instructeur = assign_to.procedure.defaut_groupe_instructeur + after(:build) do |assign_to, evaluator| + if evaluator.groupe_instructeur.persisted? + assign_to.groupe_instructeur = evaluator.groupe_instructeur + else + assign_to.groupe_instructeur = assign_to.procedure.defaut_groupe_instructeur + end end end end From 04cf174039affb5f618ec0178d328f1c157bf7d7 Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Thu, 23 Apr 2020 18:31:59 +0200 Subject: [PATCH 19/22] Revert "app: add a warning about the file upload" This reverts commit 7f45c7d97bdc435b7bfe331c37b75506fea38d26. --- app/views/layouts/_pre_maintenance.html.haml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/layouts/_pre_maintenance.html.haml b/app/views/layouts/_pre_maintenance.html.haml index 00d0a9c9a..28327f13d 100644 --- a/app/views/layouts/_pre_maintenance.html.haml +++ b/app/views/layouts/_pre_maintenance.html.haml @@ -1,9 +1,9 @@ - if feature_enabled?(:pre_maintenance_mode) .site-banner.warning .container - .site-banner-icon 🛑 + .site-banner-icon 🕚 .site-banner-text %strong - L’envoi de fichiers est temporairement indisponible. + Une opération de maintenance est prévue sur demarches-simplifiees.fr à 23 h 00. %br - Si vous rencontrez des erreurs, merci de ré-essayer dans quelques heures. + La plateforme sera inaccessible pendant une vingtaine de minutes. From 2a3530738d6f4a2cbe866966a2bbbd82e2da3da9 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 23 Apr 2020 16:16:22 +0200 Subject: [PATCH 20/22] Do not crash on boot if geos is not installed --- Gemfile | 1 - Gemfile.lock | 3 --- app/models/geo_area.rb | 4 ++-- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Gemfile b/Gemfile index acc6af262..8ac290dc6 100644 --- a/Gemfile +++ b/Gemfile @@ -25,7 +25,6 @@ gem 'devise' # Gestion des comptes utilisateurs gem 'devise-async' gem 'discard' gem 'dotenv-rails', require: 'dotenv/rails-now' # dotenv should always be loaded before rails -gem 'ffi-geos' gem 'flipper' gem 'flipper-active_record' gem 'flipper-ui' diff --git a/Gemfile.lock b/Gemfile.lock index 0958a8495..622f366fb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -215,8 +215,6 @@ GEM faraday (0.15.4) multipart-post (>= 1.2, < 3) ffi (1.12.2) - ffi-geos (2.1.0) - ffi (>= 1.0.0) flipper (0.17.2) flipper-active_record (0.17.2) activerecord (>= 4.2, < 7) @@ -753,7 +751,6 @@ DEPENDENCIES discard dotenv-rails factory_bot - ffi-geos flipper flipper-active_record flipper-ui diff --git a/app/models/geo_area.rb b/app/models/geo_area.rb index 60e59afd9..510dc3b75 100644 --- a/app/models/geo_area.rb +++ b/app/models/geo_area.rb @@ -55,13 +55,13 @@ class GeoArea < ApplicationRecord end def area - if polygon? + if polygon? && RGeo::Geos.supported? rgeo_geometry.area.round(1) end end def length - if line? + if line? && RGeo::Geos.supported? rgeo_geometry.length.round(1) end end From 654793c2a70e06ba23846d173b214b42ea2c06d7 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 23 Apr 2020 16:19:04 +0200 Subject: [PATCH 21/22] Mention geos installation in the README --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 10bd59d5d..c294ee676 100644 --- a/README.md +++ b/README.md @@ -48,8 +48,11 @@ Les informations nécessaire à l'initialisation de la base doivent être pré-c Sous Ubuntu, certains packages doivent être installés au préalable : - sudo apt-get install libcurl3 libcurl3-gnutls libcurl4-openssl-dev libcurl4-gnutls-dev zlib1g-dev + sudo apt-get install libcurl3 libcurl3-gnutls libcurl4-openssl-dev libcurl4-gnutls-dev zlib1g-dev libgeos-dev +Sous Mac, certains packages doivent être installés au préalable : + + brew install geos Afin d'initialiser l'environnement de développement, exécutez la commande suivante : From 983cfad38f0398acde2974aa25467a73673f5962 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 23 Apr 2020 20:16:20 +0200 Subject: [PATCH 22/22] Bump bundler cache --- .circleci/config.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 17e827069..4615c88d8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -14,14 +14,14 @@ bundle_restore_cache: &bundle_restore_cache restore_cache: name: Restore Bundler Package Cache keys: - - bundle-install-v9-{{ arch }}-{{ checksum "Gemfile.lock" }} - - bundle-install-v9-{{ arch }} - - bundle-install-v9 + - bundle-install-v10-{{ arch }}-{{ checksum "Gemfile.lock" }} + - bundle-install-v10-{{ arch }} + - bundle-install-v10 bundle_save_cache: &bundle_save_cache save_cache: name: Save Bundler Package Cache - key: bundle-install-v9-{{ arch }}-{{ checksum "Gemfile.lock" }} + key: bundle-install-v10-{{ arch }}-{{ checksum "Gemfile.lock" }} paths: - ~/vendor/bundle