make Dossier#with_notifications great again
Co-authored-by: Christophe Robillard <christophe.robillard@beta.gouv.fr>
This commit is contained in:
parent
8d87f60291
commit
52ea5ef89a
4 changed files with 58 additions and 35 deletions
|
@ -289,30 +289,13 @@ class Dossier < ApplicationRecord
|
||||||
scope :for_api_v2, -> { includes(procedure: [:administrateurs], etablissement: [], individual: [], traitements: []) }
|
scope :for_api_v2, -> { includes(procedure: [:administrateurs], etablissement: [], individual: [], traitements: []) }
|
||||||
|
|
||||||
scope :with_notifications, -> do
|
scope :with_notifications, -> do
|
||||||
# This scope is meant to be composed, typically with Instructeur.followed_dossiers, which means that the :follows table is already INNER JOINed;
|
joins(:follows)
|
||||||
# it will fail otherwise
|
.where('last_champ_updated_at > follows.demande_seen_at' \
|
||||||
# rubocop:disable DS/ApplicationName
|
' OR groupe_instructeur_updated_at > follows.demande_seen_at' \
|
||||||
joined_dossiers = joins('LEFT OUTER JOIN "champs" ON "champs" . "dossier_id" = "dossiers" . "id" AND "champs" . "parent_id" IS NULL AND "champs" . "private" = FALSE AND "champs"."updated_at" > "follows"."demande_seen_at"')
|
' OR last_champ_private_updated_at > follows.annotations_privees_seen_at' \
|
||||||
.joins('LEFT OUTER JOIN "champs" "champs_privates_dossiers" ON "champs_privates_dossiers" . "dossier_id" = "dossiers" . "id" AND "champs_privates_dossiers" . "parent_id" IS NULL AND "champs_privates_dossiers" . "private" = TRUE AND "champs_privates_dossiers"."updated_at" > "follows"."annotations_privees_seen_at"')
|
' OR last_avis_updated_at > follows.avis_seen_at' \
|
||||||
.joins('LEFT OUTER JOIN "avis" ON "avis" . "dossier_id" = "dossiers" . "id" AND avis.updated_at > follows.avis_seen_at')
|
' OR last_commentaire_updated_at > follows.messagerie_seen_at')
|
||||||
.joins('LEFT OUTER JOIN "commentaires" ON "commentaires" . "dossier_id" = "dossiers" . "id" and commentaires.updated_at > follows.messagerie_seen_at and "commentaires"."email" != \'contact@tps.apientreprise.fr\' AND "commentaires"."email" != \'contact@demarches-simplifiees.fr\'')
|
.distinct
|
||||||
# rubocop:enable DS/ApplicationName
|
|
||||||
|
|
||||||
updated_demandes = joined_dossiers
|
|
||||||
.where('champs.updated_at > follows.demande_seen_at OR groupe_instructeur_updated_at > follows.demande_seen_at')
|
|
||||||
|
|
||||||
updated_annotations = joined_dossiers
|
|
||||||
.where('champs_privates_dossiers.updated_at > follows.annotations_privees_seen_at')
|
|
||||||
|
|
||||||
updated_avis = joined_dossiers
|
|
||||||
.where('avis.updated_at > follows.avis_seen_at')
|
|
||||||
|
|
||||||
updated_messagerie = joined_dossiers
|
|
||||||
.where('commentaires.updated_at > follows.messagerie_seen_at')
|
|
||||||
.where.not(commentaires: { email: OLD_CONTACT_EMAIL })
|
|
||||||
.where.not(commentaires: { email: CONTACT_EMAIL })
|
|
||||||
|
|
||||||
updated_demandes.or(updated_annotations).or(updated_avis).or(updated_messagerie).distinct
|
|
||||||
end
|
end
|
||||||
|
|
||||||
accepts_nested_attributes_for :individual
|
accepts_nested_attributes_for :individual
|
||||||
|
|
|
@ -112,9 +112,29 @@ describe Dossier do
|
||||||
end
|
end
|
||||||
|
|
||||||
context('with changes') do
|
context('with changes') do
|
||||||
before { dossier.commentaires << create(:commentaire, email: 'test@exemple.fr') }
|
context 'when there is a new commentaire' do
|
||||||
|
before { dossier.update!(last_commentaire_updated_at: Time.zone.now) }
|
||||||
|
|
||||||
it { is_expected.to match([dossier]) }
|
it { is_expected.to match([dossier]) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when there is a new avis' do
|
||||||
|
before { dossier.update!(last_avis_updated_at: Time.zone.now) }
|
||||||
|
|
||||||
|
it { is_expected.to match([dossier]) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when a public champ is updated' do
|
||||||
|
before { dossier.update!(last_champ_updated_at: Time.zone.now) }
|
||||||
|
|
||||||
|
it { is_expected.to match([dossier]) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when a private champ is updated' do
|
||||||
|
before { dossier.update!(last_champ_private_updated_at: Time.zone.now) }
|
||||||
|
|
||||||
|
it { is_expected.to match([dossier]) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -263,12 +263,20 @@ describe Instructeur, type: :model do
|
||||||
|
|
||||||
let!(:dossier_on_procedure_2) { create(:dossier, :followed, state: Dossier.states.fetch(:en_construction)) }
|
let!(:dossier_on_procedure_2) { create(:dossier, :followed, state: Dossier.states.fetch(:en_construction)) }
|
||||||
let!(:instructeur_on_procedure_2) { dossier_on_procedure_2.follows.first.instructeur }
|
let!(:instructeur_on_procedure_2) { dossier_on_procedure_2.follows.first.instructeur }
|
||||||
|
let(:now) { Time.zone.parse("14/09/1867") }
|
||||||
|
let(:follow) { instructeur.follows.find_by(dossier: dossier) }
|
||||||
|
let(:follow2) { instructeur_2.follows.find_by(dossier: dossier) }
|
||||||
|
let(:seen_at_instructeur) { now - 1.hour }
|
||||||
|
let(:seen_at_instructeur2) { now - 1.hour }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
procedure.groupe_instructeurs.last.instructeurs << instructeur
|
procedure.groupe_instructeurs.last.instructeurs << instructeur
|
||||||
instructeur_2.followed_dossiers << dossier
|
instructeur_2.followed_dossiers << dossier
|
||||||
|
Timecop.freeze(now)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
after { Timecop.return }
|
||||||
|
|
||||||
subject { instructeur.notifications_for_procedure(procedure, :en_cours) }
|
subject { instructeur.notifications_for_procedure(procedure, :en_cours) }
|
||||||
|
|
||||||
context 'when the instructeur has just followed the dossier' do
|
context 'when the instructeur has just followed the dossier' do
|
||||||
|
@ -276,7 +284,11 @@ describe Instructeur, type: :model do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when there is a modification on public champs' do
|
context 'when there is a modification on public champs' do
|
||||||
before { dossier.champs.first.update_attribute('value', 'toto') }
|
before do
|
||||||
|
dossier.update!(last_champ_updated_at: now)
|
||||||
|
follow.update_attribute('demande_seen_at', seen_at_instructeur)
|
||||||
|
follow2.update_attribute('demande_seen_at', seen_at_instructeur2)
|
||||||
|
end
|
||||||
|
|
||||||
it { is_expected.to match([dossier]) }
|
it { is_expected.to match([dossier]) }
|
||||||
it { expect(instructeur_2.notifications_for_procedure(procedure, :en_cours)).to match([dossier]) }
|
it { expect(instructeur_2.notifications_for_procedure(procedure, :en_cours)).to match([dossier]) }
|
||||||
|
@ -289,9 +301,8 @@ describe Instructeur, type: :model do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when instructeur update it s public champs last seen' do
|
context 'when instructeur update it s public champs last seen' do
|
||||||
let(:follow) { instructeur.follows.find_by(dossier: dossier) }
|
let(:seen_at_instructeur) { now + 1.hour }
|
||||||
|
let(:seen_at_instructeur2) { now - 1.hour }
|
||||||
before { follow.update_attribute('demande_seen_at', Time.zone.now) }
|
|
||||||
|
|
||||||
it { is_expected.to match([]) }
|
it { is_expected.to match([]) }
|
||||||
it { expect(instructeur_2.notifications_for_procedure(procedure, :en_cours)).to match([dossier]) }
|
it { expect(instructeur_2.notifications_for_procedure(procedure, :en_cours)).to match([dossier]) }
|
||||||
|
@ -305,20 +316,29 @@ describe Instructeur, type: :model do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when there is a modification on private champs' do
|
context 'when there is a modification on private champs' do
|
||||||
before { dossier.champs_private.first.update_attribute('value', 'toto') }
|
before do
|
||||||
|
dossier.update!(last_champ_private_updated_at: now)
|
||||||
|
follow.update_attribute('annotations_privees_seen_at', seen_at_instructeur)
|
||||||
|
end
|
||||||
|
|
||||||
it { is_expected.to match([dossier]) }
|
it { is_expected.to match([dossier]) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when there is a modification on avis' do
|
context 'when there is a modification on avis' do
|
||||||
before { create(:avis, dossier: dossier) }
|
before do
|
||||||
|
dossier.update!(last_avis_updated_at: Time.zone.now)
|
||||||
|
follow.update_attribute('avis_seen_at', seen_at_instructeur)
|
||||||
|
end
|
||||||
|
|
||||||
it { is_expected.to match([dossier]) }
|
it { is_expected.to match([dossier]) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'the messagerie' do
|
context 'the messagerie' do
|
||||||
context 'when there is a new commentaire' do
|
context 'when there is a new commentaire' do
|
||||||
before { create(:commentaire, dossier: dossier, email: 'a@b.com') }
|
before do
|
||||||
|
dossier.update!(last_commentaire_updated_at: Time.zone.now)
|
||||||
|
follow.update_attribute('messagerie_seen_at', seen_at_instructeur)
|
||||||
|
end
|
||||||
|
|
||||||
it { is_expected.to match([dossier]) }
|
it { is_expected.to match([dossier]) }
|
||||||
end
|
end
|
||||||
|
@ -339,7 +359,7 @@ describe Instructeur, type: :model do
|
||||||
subject { instructeur.procedures_with_notifications(:en_cours) }
|
subject { instructeur.procedures_with_notifications(:en_cours) }
|
||||||
|
|
||||||
context 'when there is a modification on public champs' do
|
context 'when there is a modification on public champs' do
|
||||||
before { dossier.champs.first.update_attribute('value', 'toto') }
|
before { dossier.update!(last_champ_updated_at: Time.zone.now) }
|
||||||
|
|
||||||
it { is_expected.to match([procedure]) }
|
it { is_expected.to match([procedure]) }
|
||||||
end
|
end
|
||||||
|
|
|
@ -262,7 +262,7 @@ describe ProcedurePresentation do
|
||||||
let!(:older_dossier) { create(:dossier, :en_construction, procedure: procedure) }
|
let!(:older_dossier) { create(:dossier, :en_construction, procedure: procedure) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
notified_dossier.champs.first.touch(time: Time.zone.local(2018, 9, 20))
|
notified_dossier.update!(last_champ_updated_at: Time.zone.local(2018, 9, 20))
|
||||||
create(:follow, instructeur: instructeur, dossier: notified_dossier, demande_seen_at: Time.zone.local(2018, 9, 10))
|
create(:follow, instructeur: instructeur, dossier: notified_dossier, demande_seen_at: Time.zone.local(2018, 9, 10))
|
||||||
notified_dossier.touch(time: Time.zone.local(2018, 9, 20))
|
notified_dossier.touch(time: Time.zone.local(2018, 9, 20))
|
||||||
recent_dossier.touch(time: Time.zone.local(2018, 9, 25))
|
recent_dossier.touch(time: Time.zone.local(2018, 9, 25))
|
||||||
|
|
Loading…
Add table
Reference in a new issue