Skip to content

Commit

Permalink
Fix newsletter recipients query
Browse files Browse the repository at this point in the history
  • Loading branch information
ahukkanen committed Dec 9, 2024
1 parent e253579 commit 390db05
Show file tree
Hide file tree
Showing 3 changed files with 217 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# frozen_string_literal: true

module Decidim
module Privacy
module AdminNewsletterRecipientsExtensions
extend ActiveSupport::Concern

included do
def query
recipients = recipients_base_query
recipients = recipients.interested_in_scopes(@form.scope_ids) if @form.scope_ids.present?

followers = recipients.where(id: user_id_of_followers) if @form.send_to_followers

participants = recipients.where(id: participant_ids) if @form.send_to_participants

recipients = participants if @form.send_to_participants
recipients = followers if @form.send_to_followers
recipients = (followers + participants).uniq if @form.send_to_followers && @form.send_to_participants

recipients
end
end

private

def recipients_base_query
Decidim::User
.entire_collection
.where(organization: @form.current_organization)
.where.not(newsletter_notifications_at: nil)
.where.not(email: nil)
.where.not(confirmed_at: nil)
.not_deleted
end
end
end
end
3 changes: 3 additions & 0 deletions lib/decidim/privacy/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,9 @@ class Engine < ::Rails::Engine
Decidim::StatsUsersCount.include(
Decidim::Privacy::StatsUsersCountExtensions
)
Decidim::Admin::NewsletterRecipients.include(
Decidim::Privacy::AdminNewsletterRecipientsExtensions
)

# Initialize concerns for each installed Decidim-module
if Decidim.module_installed? :budgets
Expand Down
176 changes: 176 additions & 0 deletions spec/queries/decidim/admin/newsletter_recipients_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
# frozen_string_literal: true

require "spec_helper"

describe Decidim::Admin::NewsletterRecipients do
subject { described_class.new(form) }

let(:newsletter) { create(:newsletter) }
let(:organization) { newsletter.organization }
let(:send_to_all_users) { true }
let(:send_to_followers) { false }
let(:send_to_participants) { false }
let(:participatory_space_types) { [] }
let(:scope_ids) { [] }

let(:form_params) do
{
send_to_all_users:,
send_to_followers:,
send_to_participants:,
participatory_space_types:,
scope_ids:
}
end

let(:form) do
Decidim::Admin::SelectiveNewsletterForm.from_params(
form_params
).with_context(
current_organization: organization
)
end

describe "querying recipients" do
context "when sending to all users" do
let!(:recipients) { create_list(:user, 5, :confirmed, newsletter_notifications_at: Time.current, organization:) }

it "returns all users" do
expect(subject.query).to match_array recipients
expect(recipients.count).to eq 5
end

context "with the scope_ids array containing an empty value" do
let(:scope_ids) { [""] }

it "returns all users" do
expect(subject.query).to match_array recipients
expect(recipients.count).to eq 5
end
end
end

context "when sending to followers" do
let!(:recipients) { create_list(:user, 3, :confirmed, newsletter_notifications_at: Time.current, organization:) }
let(:send_to_all_users) { false }
let(:send_to_followers) { true }
let(:participatory_processes) { create_list(:participatory_process, 2, organization:) }
let(:participatory_space_types) do
[
{ "id" => nil,
"manifest_name" => "participatory_processes",
"ids" => [participatory_processes.first.id.to_s] },
{ "id" => nil,
"manifest_name" => "assemblies",
"ids" => [] },
{ "id" => nil,
"manifest_name" => "conferences",
"ids" => [] },
{ "id" => nil,
"manifest_name" => "initiatives",
"ids" => [] }
]
end

context "when recipients follow the participatory space" do
before do
recipients.each do |follower|
create(:follow, followable: participatory_processes.first, user: follower)
end
end

it "returns all users" do
expect(subject.query).to match_array recipients
expect(recipients.count).to eq 3
end
end
end

context "when sending to participants" do
let(:send_to_all_users) { false }
let(:send_to_participants) { true }
let!(:component) { create(:dummy_component, organization:) }
let(:participatory_space_types) do
[
{ "id" => nil,
"manifest_name" => "participatory_processes",
"ids" => [component.participatory_space.id.to_s] },
{ "id" => nil,
"manifest_name" => "assemblies",
"ids" => [] },
{ "id" => nil,
"manifest_name" => "conferences",
"ids" => [] },
{ "id" => nil,
"manifest_name" => "initiatives",
"ids" => [] }
]
end

context "when recipients participate to the participatory space" do
let!(:authors) do
create_list(:user, 3, :confirmed, organization:, newsletter_notifications_at: Time.current)
end

before do
authors.each do |participant|
create(:dummy_resource, :published, component:, author: participant)
end
end

it "returns all users" do
expect(subject.query).to match_array authors
expect(authors.count).to eq 3
end

context "and other comment in other participatory spaces" do
# non participant commentator (comments into other spaces)
let!(:non_participant) { create(:user, :confirmed, newsletter_notifications_at: Time.current, organization:) }
let!(:component_out_of_newsletter) { create(:dummy_component, organization:) }
let!(:resource_out_of_newsletter) { create(:dummy_resource, :published, author: non_participant, component: component_out_of_newsletter) }
let!(:outlier_comment) { create(:comment, author: non_participant, commentable: resource_out_of_newsletter) }
# participant commentator
let!(:commentator_participant) { create(:user, :confirmed, newsletter_notifications_at: Time.current, organization:) }
let!(:resource_in_newsletter) { create(:dummy_resource, :published, author: authors.first, component:) }
let!(:comment_in_newsletter) { create(:comment, author: commentator_participant, commentable: resource_in_newsletter) }

let(:recipients) { authors + [commentator_participant] }

it "returns only commenters in the selected spaces" do
expect(subject.query).to match_array(recipients)
expect(recipients.count).to eq 4
end
end
end
end

context "with scopes segment" do
let(:scopes) do
create_list(:scope, 5, organization:)
end
let(:scope_ids) { scopes.pluck(:id) }

context "when recipients interested in scopes" do
let!(:recipients) do
create_list(:user, 3, :confirmed, organization:, newsletter_notifications_at: Time.current, extended_data: { "interested_scopes" => scopes.first.id })
end

it "returns all users" do
expect(subject.query).to match_array recipients
expect(recipients.count).to eq 3
end
end

context "when interest not match the selected scopes" do
let(:user_interset) { create(:scope, organization:) }
let!(:recipients) do
create_list(:user, 3, :confirmed, organization:, newsletter_notifications_at: Time.current, extended_data: { "interested_scopes" => user_interset.id })
end

it "do not return recipients" do
expect(subject.query).to be_empty
end
end
end
end
end

0 comments on commit 390db05

Please sign in to comment.