diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 1cca19ee4..9fe7a7242 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -289,30 +289,13 @@ class Dossier < ApplicationRecord scope :for_api_v2, -> { includes(procedure: [:administrateurs], etablissement: [], individual: [], traitements: []) } 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; - # it will fail otherwise - # rubocop:disable DS/ApplicationName - 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"') - .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"') - .joins('LEFT OUTER JOIN "avis" ON "avis" . "dossier_id" = "dossiers" . "id" AND avis.updated_at > follows.avis_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\'') - # 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 + joins(:follows) + .where('last_champ_updated_at > follows.demande_seen_at' \ + ' OR groupe_instructeur_updated_at > follows.demande_seen_at' \ + ' OR last_champ_private_updated_at > follows.annotations_privees_seen_at' \ + ' OR last_avis_updated_at > follows.avis_seen_at' \ + ' OR last_commentaire_updated_at > follows.messagerie_seen_at') + .distinct end accepts_nested_attributes_for :individual diff --git a/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb index 4a61017a0..ff6cffc32 100644 --- a/spec/models/dossier_spec.rb +++ b/spec/models/dossier_spec.rb @@ -112,9 +112,29 @@ describe Dossier do end 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 diff --git a/spec/models/instructeur_spec.rb b/spec/models/instructeur_spec.rb index e6db4ed56..c8ed17993 100644 --- a/spec/models/instructeur_spec.rb +++ b/spec/models/instructeur_spec.rb @@ -263,12 +263,20 @@ describe Instructeur, type: :model do 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(: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 procedure.groupe_instructeurs.last.instructeurs << instructeur instructeur_2.followed_dossiers << dossier + Timecop.freeze(now) end + after { Timecop.return } + subject { instructeur.notifications_for_procedure(procedure, :en_cours) } context 'when the instructeur has just followed the dossier' do @@ -276,7 +284,11 @@ describe Instructeur, type: :model do end 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 { expect(instructeur_2.notifications_for_procedure(procedure, :en_cours)).to match([dossier]) } @@ -289,9 +301,8 @@ describe Instructeur, type: :model do end context 'when instructeur update it s public champs last seen' do - let(:follow) { instructeur.follows.find_by(dossier: dossier) } - - before { follow.update_attribute('demande_seen_at', Time.zone.now) } + let(:seen_at_instructeur) { now + 1.hour } + let(:seen_at_instructeur2) { now - 1.hour } it { is_expected.to match([]) } it { expect(instructeur_2.notifications_for_procedure(procedure, :en_cours)).to match([dossier]) } @@ -305,20 +316,29 @@ describe Instructeur, type: :model do end 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]) } end 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]) } end context 'the messagerie' 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]) } end @@ -339,7 +359,7 @@ describe Instructeur, type: :model do subject { instructeur.procedures_with_notifications(:en_cours) } 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]) } end diff --git a/spec/models/procedure_presentation_spec.rb b/spec/models/procedure_presentation_spec.rb index 915ba52c3..6f9415bf2 100644 --- a/spec/models/procedure_presentation_spec.rb +++ b/spec/models/procedure_presentation_spec.rb @@ -262,7 +262,7 @@ describe ProcedurePresentation do let!(:older_dossier) { create(:dossier, :en_construction, procedure: procedure) } 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)) notified_dossier.touch(time: Time.zone.local(2018, 9, 20)) recent_dossier.touch(time: Time.zone.local(2018, 9, 25))