diff --git a/app/activity_notifications/chat_message_sent.rb b/app/activity_notifications/chat_message_sent.rb
index ab67709c7..faef6f402 100644
--- a/app/activity_notifications/chat_message_sent.rb
+++ b/app/activity_notifications/chat_message_sent.rb
@@ -3,7 +3,7 @@
class ChatMessageSent < Noticed::Base
deliver_by :database, format: :to_database, association: :notifications_as_recipient
- param :contributor_id, :request_id, :user_id, :message_id
+ param :contributor_id, :request_id, :user_id, :message_id, :organization_id
def to_database
{
@@ -11,7 +11,8 @@ def to_database
contributor_id: params[:contributor_id],
request_id: params[:request_id],
user_id: params[:user_id],
- message_id: params[:message_id]
+ message_id: params[:message_id],
+ organization_id: params[:organization_id]
}
end
diff --git a/app/activity_notifications/contributor_marked_inactive.rb b/app/activity_notifications/contributor_marked_inactive.rb
index 4375569cb..5d6f3a4a0 100644
--- a/app/activity_notifications/contributor_marked_inactive.rb
+++ b/app/activity_notifications/contributor_marked_inactive.rb
@@ -3,12 +3,13 @@
class ContributorMarkedInactive < Noticed::Base
deliver_by :database, format: :to_database, association: :notifications_as_recipient
- param :contributor_id
+ param :contributor_id, :organization_id
def to_database
{
type: self.class.name,
- contributor_id: params[:contributor_id]
+ contributor_id: params[:contributor_id],
+ organization_id: params[:organization_id]
}
end
diff --git a/app/activity_notifications/contributor_subscribed.rb b/app/activity_notifications/contributor_subscribed.rb
index 148a9e80c..83a018e2d 100644
--- a/app/activity_notifications/contributor_subscribed.rb
+++ b/app/activity_notifications/contributor_subscribed.rb
@@ -3,12 +3,13 @@
class ContributorSubscribed < Noticed::Base
deliver_by :database, format: :to_database, association: :notifications_as_recipient
- param :contributor_id
+ param :contributor_id, :organization_id
def to_database
{
type: self.class.name,
- contributor_id: params[:contributor_id]
+ contributor_id: params[:contributor_id],
+ organization_id: params[:organization_id]
}
end
diff --git a/app/activity_notifications/message_received.rb b/app/activity_notifications/message_received.rb
index 6dfc7884b..f5cb37a96 100644
--- a/app/activity_notifications/message_received.rb
+++ b/app/activity_notifications/message_received.rb
@@ -3,14 +3,15 @@
class MessageReceived < Noticed::Base
deliver_by :database, format: :to_database, association: :notifications_as_recipient
- param :contributor_id, :request_id, :message_id
+ param :contributor_id, :request_id, :message_id, :organization_id
def to_database
{
type: self.class.name,
contributor_id: params[:contributor_id],
request_id: params[:request_id],
- message_id: params[:message_id]
+ message_id: params[:message_id],
+ organization_id: params[:organization_id]
}
end
diff --git a/app/activity_notifications/onboarding_completed.rb b/app/activity_notifications/onboarding_completed.rb
index a2116ed2d..3398d8595 100644
--- a/app/activity_notifications/onboarding_completed.rb
+++ b/app/activity_notifications/onboarding_completed.rb
@@ -3,12 +3,13 @@
class OnboardingCompleted < Noticed::Base
deliver_by :database, format: :to_database, association: :notifications_as_recipient
- param :contributor_id
+ param :contributor_id, :organization_id
def to_database
{
type: self.class.name,
- contributor_id: params[:contributor_id]
+ contributor_id: params[:contributor_id],
+ organization_id: params[:organization_id]
}
end
diff --git a/app/activity_notifications/request_scheduled.rb b/app/activity_notifications/request_scheduled.rb
index 84af6be74..a2cfeaf00 100644
--- a/app/activity_notifications/request_scheduled.rb
+++ b/app/activity_notifications/request_scheduled.rb
@@ -3,12 +3,13 @@
class RequestScheduled < Noticed::Base
deliver_by :database, format: :to_database, association: :notifications_as_recipient
- param :request_id
+ param :request_id, :organization_id
def to_database
{
type: self.class.name,
- request_id: params[:request_id]
+ request_id: params[:request_id],
+ organization_id: params[:organization_id]
}
end
diff --git a/app/components/contributor_quick_edit_form/contributor_quick_edit_form.rb b/app/components/contributor_quick_edit_form/contributor_quick_edit_form.rb
index a963b5cd8..92f771df4 100644
--- a/app/components/contributor_quick_edit_form/contributor_quick_edit_form.rb
+++ b/app/components/contributor_quick_edit_form/contributor_quick_edit_form.rb
@@ -2,18 +2,19 @@
module ContributorQuickEditForm
class ContributorQuickEditForm < ApplicationComponent
- def initialize(contributor:)
+ def initialize(organization:, contributor:)
super
+ @organization = organization
@contributor = contributor
end
private
- attr_reader :contributor
+ attr_reader :organization, :contributor
def available_tags
- Contributor.all_tags_with_count.to_json
+ organization.contributors_tags_with_count.to_json
end
end
end
diff --git a/app/components/contributors_index/contributors_index.rb b/app/components/contributors_index/contributors_index.rb
index 06cc693e6..fc05ab37f 100644
--- a/app/components/contributors_index/contributors_index.rb
+++ b/app/components/contributors_index/contributors_index.rb
@@ -2,7 +2,7 @@
module ContributorsIndex
class ContributorsIndex < ApplicationComponent
- def initialize(organization:, contributors:, state:, active_count:, inactive_count:, unsubscribed_count:, filter_count:, tag_list: nil)
+ def initialize(organization:, contributors:, state:, active_count:, inactive_count:, unsubscribed_count:, filter_count:, available_tags:, tag_list: nil)
super
@organization = organization
@@ -13,15 +13,12 @@ def initialize(organization:, contributors:, state:, active_count:, inactive_cou
@inactive_count = inactive_count
@unsubscribed_count = unsubscribed_count
@filter_count = filter_count
+ @available_tags = available_tags
end
private
- attr_reader :organization, :contributors, :tag_list, :state, :active_count, :inactive_count, :unsubscribed_count, :filter_count
-
- def available_tags
- Contributor.all_tags_with_count.to_json
- end
+ attr_reader :organization, :contributors, :tag_list, :state, :active_count, :inactive_count, :unsubscribed_count, :filter_count, :available_tags
def active_contributors_count
tag_list.present? && state == :active ? filter_count : active_count
diff --git a/app/components/request_form/request_form.html.erb b/app/components/request_form/request_form.html.erb
index 3f2ff0115..79fca9290 100644
--- a/app/components/request_form/request_form.html.erb
+++ b/app/components/request_form/request_form.html.erb
@@ -135,7 +135,7 @@
<%= c 'device_frame', class: 'RequestForm-preview' do %>
- <%= c 'chat_preview', organization: organization do %>
+ <%= c 'chat_preview', organization: request.organization do %>
<% end %>
<% end %>
diff --git a/app/components/request_form/request_form.rb b/app/components/request_form/request_form.rb
index 2bd59d008..528419de3 100644
--- a/app/components/request_form/request_form.rb
+++ b/app/components/request_form/request_form.rb
@@ -2,20 +2,16 @@
module RequestForm
class RequestForm < ApplicationComponent
- def initialize(organization:, request:)
+ def initialize(request:, available_tags:)
super
- @organization = organization
@request = request
+ @available_tags = available_tags
end
private
- attr_reader :organization, :request
-
- def available_tags
- Contributor.all_tags_with_count.to_json
- end
+ attr_reader :request, :available_tags
def schedule_send_for_or_default
datetime = request.planned? ? request.schedule_send_for : Time.current
diff --git a/app/controllers/contributors_controller.rb b/app/controllers/contributors_controller.rb
index 188e1bb72..149299c2e 100644
--- a/app/controllers/contributors_controller.rb
+++ b/app/controllers/contributors_controller.rb
@@ -27,7 +27,7 @@ def index
@active_count = Contributor.active.count
@inactive_count = Contributor.inactive.count
@unsubscribed_count = Contributor.unsubscribed.count
- @available_tags = Contributor.all_tags_with_count.to_json
+ @available_tags = @organization.contributors_tags_with_count.to_json
@contributors = filtered_contributors
@contributors = @contributors.with_tags(tag_list_params)
diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index 8f8d3b5b1..2b69c0b8e 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -13,6 +13,7 @@ def index
def activity_notifications
grouped = current_user.notifications_as_recipient
+ .where(organization_id: @organization.id)
.newest_first
.includes({ contributor: { avatar_attachment: :blob } }, :request, :message, :user)
.last_four_weeks
diff --git a/app/controllers/requests_controller.rb b/app/controllers/requests_controller.rb
index 47b29ec8d..68f414915 100644
--- a/app/controllers/requests_controller.rb
+++ b/app/controllers/requests_controller.rb
@@ -5,6 +5,7 @@ class RequestsController < ApplicationController
before_action :notifications_params, only: :notifications
before_action :disallow_edit, only: %i[edit update]
before_action :disallow_destroy, only: :destroy
+ before_action :available_tags, only: %i[new edit]
def index
@filter = filter_param
@@ -34,7 +35,7 @@ def create
end
def new
- @request = Request.new
+ @request = Request.new(organization: @organization)
end
def edit; end
@@ -58,7 +59,7 @@ def update
def destroy
if @request.destroy
- redirect_to requests_url(filter: :planned), notice: t('request.destroy.successful', request_title: @request.title)
+ redirect_to requests_url(filter: :planned), flash: { notice: t('request.destroy.successful', request_title: @request.title) }
else
render :edit, status: :unprocessable_entity
end
@@ -111,6 +112,10 @@ def set_request
@request = Request.find(params[:id])
end
+ def available_tags
+ @available_tags ||= @organization.contributors_tags_with_count.to_json
+ end
+
def request_params
params.require(:request).permit(:title, :text, :tag_list, :schedule_send_for, files: [])
end
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index 131885813..c9d61b487 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -4,6 +4,8 @@ class SearchController < ApplicationController
def index
@results = []
query = params[:q]
- @results = PgSearch.multisearch(query).map(&:searchable) if query
+ return unless query
+
+ @results = PgSearch.multisearch(query).where(organization_id: @organization.id).map(&:searchable)
end
end
diff --git a/app/jobs/mark_inactive_contributor_inactive_job.rb b/app/jobs/mark_inactive_contributor_inactive_job.rb
index c36d67f4e..fc06e58f0 100644
--- a/app/jobs/mark_inactive_contributor_inactive_job.rb
+++ b/app/jobs/mark_inactive_contributor_inactive_job.rb
@@ -12,7 +12,10 @@ def perform(organization_id:, contributor_id:)
contributor.deactivated_at = Time.current
contributor.save(validate: false)
- ContributorMarkedInactive.with(contributor_id: contributor.id).deliver_later(User.all)
+ ContributorMarkedInactive.with(
+ contributor_id: contributor.id,
+ organization_id: organization.id
+ ).deliver_later(organization.users + User.admin.all)
User.admin.find_each do |admin|
PostmarkAdapter::Outbound.contributor_marked_as_inactive!(admin, contributor, organization)
end
diff --git a/app/jobs/resubscribe_contributor_job.rb b/app/jobs/resubscribe_contributor_job.rb
index c325191b0..b83cf65d4 100644
--- a/app/jobs/resubscribe_contributor_job.rb
+++ b/app/jobs/resubscribe_contributor_job.rb
@@ -24,7 +24,10 @@ def perform(organization_id, contributor_id, adapter)
contributor.update!(unsubscribed_at: nil)
adapter.send_welcome_message!(contributor, organization)
- ContributorSubscribed.with(contributor_id: contributor.id).deliver_later(User.all)
+ ContributorSubscribed.with(
+ contributor_id: contributor.id,
+ organization_id: organization.id
+ ).deliver_later(organization.users + User.admin.all)
User.admin.find_each do |admin|
PostmarkAdapter::Outbound.contributor_resubscribed!(admin, contributor, organization)
end
diff --git a/app/jobs/unsubscribe_contributor_job.rb b/app/jobs/unsubscribe_contributor_job.rb
index cf368bdc5..7d5c50596 100644
--- a/app/jobs/unsubscribe_contributor_job.rb
+++ b/app/jobs/unsubscribe_contributor_job.rb
@@ -13,7 +13,10 @@ def perform(organization_id, contributor_id, adapter)
contributor.update!(unsubscribed_at: Time.current)
adapter.send_unsubsribed_successfully_message!(contributor, organization)
- ContributorMarkedInactive.with(contributor_id: contributor.id).deliver_later(User.all)
+ ContributorMarkedInactive.with(
+ contributor_id: contributor.id,
+ organization_id: organization.id
+ ).deliver_later(organization.users + User.admin.all)
User.admin.find_each do |admin|
PostmarkAdapter::Outbound.contributor_unsubscribed!(admin, contributor, organization)
end
diff --git a/app/models/activity_notification.rb b/app/models/activity_notification.rb
index 489d64c75..03af43abd 100644
--- a/app/models/activity_notification.rb
+++ b/app/models/activity_notification.rb
@@ -7,6 +7,7 @@ class ActivityNotification < ApplicationRecord
belongs_to :request, optional: true
belongs_to :message, optional: true
belongs_to :user, optional: true
+ belongs_to :organization
scope :last_four_weeks, -> { where(created_at: 4.weeks.ago..Time.current) }
end
diff --git a/app/models/contributor.rb b/app/models/contributor.rb
index 44a6c213c..87c2220bf 100644
--- a/app/models/contributor.rb
+++ b/app/models/contributor.rb
@@ -9,7 +9,8 @@ class Contributor < ApplicationRecord
after_create_commit :notify_recipient
- multisearchable against: %i[first_name last_name username note]
+ multisearchable against: %i[first_name last_name username note],
+ additional_attributes: ->(contributor) { { organization_id: contributor.organization_id } }
has_many :replies, class_name: 'Message', as: :sender, dependent: :destroy
has_many :received_messages, class_name: 'Message', inverse_of: :recipient, foreign_key: 'recipient_id', dependent: :destroy
@@ -24,6 +25,7 @@ class Contributor < ApplicationRecord
accepts_nested_attributes_for :json_web_token
acts_as_taggable_on :tags
+ acts_as_taggable_tenant :organization_id
default_scope { order(:first_name, :last_name) }
scope :active, -> { where(deactivated_at: nil, unsubscribed_at: nil) }
@@ -66,28 +68,6 @@ def self.with_lowercased_email(email)
find_by('lower(email) in (?)', Array.wrap(email).map(&:downcase))
end
- def self.all_tags_with_count
- ActsAsTaggableOn::Tag
- .joins(:taggings)
- .select('tags.id, tags.name, count(taggings.id) as taggings_count')
- .group('tags.id')
- .where(taggings: { taggable_type: name })
- .all
- .map do |tag|
- {
- id: tag.id,
- name: tag.name,
- value: tag.name,
- count: tag.taggings_count,
- color: Contributor.tag_color_from_id(tag.id)
- }
- end
- end
-
- def self.tag_color_from_id(tag_id)
- ApplicationController.helpers.color_from_id(tag_id)
- end
-
def reply(message_decorator)
request = active_request or return nil
ActiveRecord::Base.transaction do
@@ -241,7 +221,7 @@ def stats
private
def notify_recipient
- OnboardingCompleted.with(contributor_id: id).deliver_later(User.all)
+ OnboardingCompleted.with(contributor_id: id, organization_id: organization.id).deliver_later(organization.users + User.admin.all)
end
end
# rubocop:enable Metrics/ClassLength
diff --git a/app/models/message.rb b/app/models/message.rb
index ac2d21d2d..c8891201a 100644
--- a/app/models/message.rb
+++ b/app/models/message.rb
@@ -5,7 +5,8 @@ class Message < ApplicationRecord
default_scope { order(created_at: :desc) }
- multisearchable against: :text, if: :reply?
+ multisearchable against: :text, if: :reply?,
+ additional_attributes: ->(message) { { organization_id: message.organization.id } }
belongs_to :sender, polymorphic: true, optional: true
belongs_to :recipient, class_name: 'Contributor', optional: true
@@ -63,14 +64,27 @@ def sent_from_contributor?
private
+ # rubocop:disable Metrics/AbcSize
def notify_recipient
+ # binding.pry
if reply?
- MessageReceived.with(contributor_id: sender_id, request_id: request.id, message_id: id).deliver_later(User.all)
+ MessageReceived.with(
+ contributor_id: sender_id,
+ request_id: request.id,
+ message_id: id,
+ organization_id: organization.id
+ ).deliver_later(organization.users + User.admin.all)
elsif !broadcasted?
- ChatMessageSent.with(contributor_id: recipient.id, request_id: request.id, user_id: sender_id,
- message_id: id).deliver_later(User.all)
+ ChatMessageSent.with(
+ contributor_id: recipient.id,
+ request_id: request.id,
+ user_id: sender_id,
+ message_id: id,
+ organization_id: organization.id
+ ).deliver_later(organization.users + User.admin.all)
end
end
+ # rubocop:enable Metrics/AbcSize
def send_if_outbound
return if manually_created? || reply?
diff --git a/app/models/organization.rb b/app/models/organization.rb
index aa22f6e59..5e2f002ed 100644
--- a/app/models/organization.rb
+++ b/app/models/organization.rb
@@ -12,6 +12,7 @@ class Organization < ApplicationRecord
has_many :users, class_name: 'User', dependent: :destroy
has_many :contributors, dependent: :destroy
has_many :requests, dependent: :destroy
+ has_many :notifications_as_mentioned, class_name: 'ActivityNotification', dependent: :destroy
has_one_attached :onboarding_logo
has_one_attached :onboarding_hero
@@ -93,6 +94,25 @@ def threema_instance
Threema.new(api_identity: threemarb_api_identity, api_secret: threemarb_api_secret, private_key: threemarb_private)
end
+ def contributors_tags_with_count
+ ActsAsTaggableOn::Tag
+ .for_tenant(id)
+ .joins(:taggings)
+ .where(taggings: { taggable_type: Contributor.name })
+ .select('tags.id, tags.name, count(taggings.id) as taggings_count')
+ .group('tags.id')
+ .all
+ .map do |tag|
+ {
+ id: tag.id,
+ name: tag.name,
+ value: tag.name,
+ count: tag.taggings_count,
+ color: ApplicationController.helpers.color_from_id(tag.id)
+ }
+ end
+ end
+
private
def notify_admin
diff --git a/app/models/request.rb b/app/models/request.rb
index edf2b9893..f18cdb12c 100644
--- a/app/models/request.rb
+++ b/app/models/request.rb
@@ -4,7 +4,8 @@ class Request < ApplicationRecord
include PlaceholderHelper
include PgSearch::Model
- multisearchable against: %i[title text]
+ multisearchable against: %i[title text],
+ additional_attributes: ->(request) { { organization_id: request.organization_id } }
belongs_to :user
belongs_to :organization
@@ -24,6 +25,7 @@ class Request < ApplicationRecord
validates :text, length: { maximum: 1500 }, presence: true, unless: -> { files.attached? }
acts_as_taggable_on :tags
+ acts_as_taggable_tenant :organization_id
after_create :broadcast_request
@@ -69,7 +71,7 @@ def messages_by_contributor
def self.broadcast!(request)
if request.planned?
BroadcastRequestJob.delay(run_at: request.schedule_send_for).perform_later(request.id)
- RequestScheduled.with(request_id: request.id).deliver_later(User.all)
+ RequestScheduled.with(request_id: request.id, organization_id: request.organization.id).deliver_later(User.all)
else
Contributor.active.with_tags(request.tag_list).each do |contributor|
message = Message.new(
diff --git a/app/views/contributors/index.html.erb b/app/views/contributors/index.html.erb
index 3f483b247..34d1ab28f 100644
--- a/app/views/contributors/index.html.erb
+++ b/app/views/contributors/index.html.erb
@@ -6,5 +6,6 @@
active_count: @active_count,
inactive_count: @inactive_count,
unsubscribed_count: @unsubscribed_count,
- filter_count: @filter_count
+ filter_count: @filter_count,
+ available_tags: @available_tags
%>
diff --git a/app/views/contributors/show.html.erb b/app/views/contributors/show.html.erb
index 777f69bf4..4f971bad4 100644
--- a/app/views/contributors/show.html.erb
+++ b/app/views/contributors/show.html.erb
@@ -16,7 +16,7 @@
<%= c 'section', styles: [:wide, :xlargeSpaceBetween, :noMarginTop] do %>
<%= c 'contributor_header', organization: @organization, contributor: @contributor %>
- <%= c 'contributor_quick_edit_form', contributor: @contributor %>
+ <%= c 'contributor_quick_edit_form', organization: @organization, contributor: @contributor %>
diff --git a/app/views/requests/edit.html.erb b/app/views/requests/edit.html.erb
index 4bf266529..01afaabaa 100644
--- a/app/views/requests/edit.html.erb
+++ b/app/views/requests/edit.html.erb
@@ -6,6 +6,6 @@
<% end %>
<%= c 'section' do %>
- <%= c 'request_form', organization: @organization, request: @request %>
+ <%= c 'request_form', request: @request, available_tags: @available_tags %>
<% end %>
<% end %>
diff --git a/app/views/requests/new.html.erb b/app/views/requests/new.html.erb
index b062f0ea5..65fc9f80b 100644
--- a/app/views/requests/new.html.erb
+++ b/app/views/requests/new.html.erb
@@ -7,6 +7,6 @@
<% end %>
<%= c 'section' do %>
- <%= c 'request_form', organization: @organization, request: @request %>
+ <%= c 'request_form', request: @request, available_tags: @available_tags %>
<% end %>
<% end %>
diff --git a/db/data/20240726061113_add_organization_id_to_activity_notifications.rb b/db/data/20240726061113_add_organization_id_to_activity_notifications.rb
new file mode 100644
index 000000000..06f348b66
--- /dev/null
+++ b/db/data/20240726061113_add_organization_id_to_activity_notifications.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class AddOrganizationIdToActivityNotifications < ActiveRecord::Migration[6.1]
+ def up
+ ActiveRecord::Base.transaction do
+ organization = Organization.singleton
+ return unless organization
+
+ ActivityNotification.find_each do |notification|
+ notification.organization_id = organization.id
+ notification.save!
+ Rails.logger.debug '.'
+ end
+ end
+ end
+
+ def down
+ ActiveRecord::Base.transaction do
+ organization = Organization.singleton
+ return unless organization
+
+ ActivityNotification.find_each do |notification|
+ notification.organization_id = nil
+ notification.save!
+ Rails.logger.debug '.'
+ end
+ end
+ end
+end
diff --git a/db/data/20240726063319_add_organization_id_to_taggings.rb b/db/data/20240726063319_add_organization_id_to_taggings.rb
new file mode 100644
index 000000000..a5bd95ad5
--- /dev/null
+++ b/db/data/20240726063319_add_organization_id_to_taggings.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class AddOrganizationIdToTaggings < ActiveRecord::Migration[6.1]
+ def up
+ ActiveRecord::Base.transaction do
+ organization = Organization.singleton
+ return unless organization
+
+ ActsAsTaggableOn::Tagging.find_each do |tag|
+ tag.tenant = organization.id
+ tag.save!
+ Rails.logger.debug '.'
+ end
+ end
+ end
+
+ def down
+ ActiveRecord::Base.transaction do
+ organization = Organization.singleton
+ return unless organization
+
+ ActsAsTaggableOn::Tagging.find_each do |tag|
+ tag.tenant = nil
+ tag.save!
+ Rails.logger.debug '.'
+ end
+ end
+ end
+end
diff --git a/db/data/20240730085839_rebuild_pg_search_multi_search.rb b/db/data/20240730085839_rebuild_pg_search_multi_search.rb
new file mode 100644
index 000000000..f1302a1d3
--- /dev/null
+++ b/db/data/20240730085839_rebuild_pg_search_multi_search.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class RebuildPgSearchMultiSearch < ActiveRecord::Migration[6.1]
+ def up
+ PgSearch::Multisearch.rebuild(Contributor)
+ PgSearch::Multisearch.rebuild(Message)
+ PgSearch::Multisearch.rebuild(Request)
+ end
+
+ def down
+ PgSearch::Multisearch.rebuild(Contributor)
+ PgSearch::Multisearch.rebuild(Message)
+ PgSearch::Multisearch.rebuild(Request)
+ end
+end
diff --git a/db/data_schema.rb b/db/data_schema.rb
index 72cc88a37..05ab7451c 100644
--- a/db/data_schema.rb
+++ b/db/data_schema.rb
@@ -1,3 +1,3 @@
# frozen_string_literal: true
-DataMigrate::Data.define(version: 20_240_722_092_527)
+DataMigrate::Data.define(version: 20_240_730_085_839)
diff --git a/db/migrate/20240528094251_add_organization_id_to_activity_notifications.rb b/db/migrate/20240528094251_add_organization_id_to_activity_notifications.rb
new file mode 100644
index 000000000..74278d2f0
--- /dev/null
+++ b/db/migrate/20240528094251_add_organization_id_to_activity_notifications.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddOrganizationIdToActivityNotifications < ActiveRecord::Migration[6.1]
+ def change
+ add_reference :activity_notifications, :organization, foreign_key: true
+ end
+end
diff --git a/db/migrate/20240726062741_add_tenant_to_taggings.acts_as_taggable_on_engine.rb b/db/migrate/20240726062741_add_tenant_to_taggings.acts_as_taggable_on_engine.rb
new file mode 100644
index 000000000..2aa74171d
--- /dev/null
+++ b/db/migrate/20240726062741_add_tenant_to_taggings.acts_as_taggable_on_engine.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+# This migration comes from acts_as_taggable_on_engine (originally 7)
+
+class AddTenantToTaggings < ActiveRecord::Migration[6.0]
+ def self.up
+ add_column ActsAsTaggableOn.taggings_table, :tenant, :string, limit: 128
+ add_index ActsAsTaggableOn.taggings_table, :tenant unless index_exists? ActsAsTaggableOn.taggings_table, :tenant
+ end
+
+ def self.down
+ remove_index ActsAsTaggableOn.taggings_table, :tenant
+ remove_column ActsAsTaggableOn.taggings_table, :tenant
+ end
+end
diff --git a/db/migrate/20240726065204_add_organization_id_to_pg_search_documents.rb b/db/migrate/20240726065204_add_organization_id_to_pg_search_documents.rb
new file mode 100644
index 000000000..01a09c92a
--- /dev/null
+++ b/db/migrate/20240726065204_add_organization_id_to_pg_search_documents.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddOrganizationIdToPgSearchDocuments < ActiveRecord::Migration[6.1]
+ def change
+ add_reference :pg_search_documents, :organization, foreign_key: true
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 01c71f1dd..4d882cf03 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: 2024_06_27_182314) do
+ActiveRecord::Schema.define(version: 2024_07_26_065204) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_trgm"
@@ -65,8 +65,10 @@
t.bigint "message_id"
t.bigint "request_id"
t.bigint "user_id"
+ t.bigint "organization_id"
t.index ["contributor_id"], name: "index_activity_notifications_on_contributor_id"
t.index ["message_id"], name: "index_activity_notifications_on_message_id"
+ t.index ["organization_id"], name: "index_activity_notifications_on_organization_id"
t.index ["read_at"], name: "index_activity_notifications_on_read_at"
t.index ["recipient_type", "recipient_id"], name: "index_activity_notifications_on_recipient"
t.index ["request_id"], name: "index_activity_notifications_on_request_id"
@@ -252,6 +254,8 @@
t.bigint "searchable_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
+ t.bigint "organization_id"
+ t.index ["organization_id"], name: "index_pg_search_documents_on_organization_id"
t.index ["searchable_type", "searchable_id"], name: "index_pg_search_documents_on_searchable_type_and_searchable_id"
end
@@ -292,6 +296,7 @@
t.integer "tagger_id"
t.string "context", limit: 128
t.datetime "created_at"
+ t.string "tenant", limit: 128
t.index ["context"], name: "index_taggings_on_context"
t.index ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "taggings_idx", unique: true
t.index ["tag_id"], name: "index_taggings_on_tag_id"
@@ -301,6 +306,7 @@
t.index ["taggable_type"], name: "index_taggings_on_taggable_type"
t.index ["tagger_id", "tagger_type"], name: "index_taggings_on_tagger_id_and_tagger_type"
t.index ["tagger_id"], name: "index_taggings_on_tagger_id"
+ t.index ["tenant"], name: "index_taggings_on_tenant"
end
create_table "tags", id: :serial, force: :cascade do |t|
@@ -334,6 +340,7 @@
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
add_foreign_key "activity_notifications", "contributors"
add_foreign_key "activity_notifications", "messages"
+ add_foreign_key "activity_notifications", "organizations"
add_foreign_key "activity_notifications", "requests"
add_foreign_key "activity_notifications", "users"
add_foreign_key "contributors", "organizations"
@@ -343,6 +350,7 @@
add_foreign_key "messages", "requests"
add_foreign_key "organizations", "business_plans"
add_foreign_key "organizations", "users", column: "contact_person_id"
+ add_foreign_key "pg_search_documents", "organizations"
add_foreign_key "photos", "messages"
add_foreign_key "requests", "organizations"
add_foreign_key "requests", "users"
diff --git a/db/seeds/multi_tenancy.rb b/db/seeds/multi_tenancy.rb
new file mode 100644
index 000000000..72c5997a6
--- /dev/null
+++ b/db/seeds/multi_tenancy.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+require 'factory_bot_rails'
+require 'faker'
+
+request_count = 20
+
+business_plan = BusinessPlan.find_by(name: 'Free')
+organizations = 3.times.collect do
+ Organization.create!(
+ name: Faker::Company.name,
+ upgrade_discount: rand(0..25),
+ business_plan: business_plan
+ )
+end
+users = 10.times.collect do
+ FactoryBot.create(:user, organization: organizations.sample)
+end
+
+# images = 10.times.map { URI(Faker::Avatar.image(size: '50x50', format: 'png', set: 'set5')) }
+
+FactoryBot.modify do
+ factory :contributor do
+ organization { organizations.sample }
+ # after(:build) do |contributor|
+ # image = images.sample
+ # contributor.avatar.attach(
+ # io: image.open,
+ # filename: File.basename(image.path)
+ # )
+ # end
+ end
+end
+
+FactoryBot.modify do
+ factory :request do
+ title { Faker::Lorem.question }
+ text { Faker::Lorem.paragraph }
+ user { users.sample }
+ end
+end
+
+Rails.logger.debug 'Seeding requests..'
+requests = request_count.times.collect do
+ created_at = Time.zone.at(rand(14.days.ago..Time.current))
+ broadcasted_at = Time.zone.at(rand(created_at..Time.current))
+ FactoryBot.build(:request,
+ created_at: created_at,
+ broadcasted_at: broadcasted_at,
+ organization: organizations.sample) do |request|
+ request.class.skip_callback(:create, :after, :broadcast_request, raise: false)
+ request.save!
+ end
+end
+
+Rails.logger.debug 'Seeding contributors..'
+
+FactoryBot.create_list(:contributor, 5)
+FactoryBot.create_list(:contributor, 20, :threema_contributor, :skip_validations)
+FactoryBot.create_list(:contributor, 30, :telegram_contributor)
+FactoryBot.create_list(:contributor, 40, :signal_contributor)
+FactoryBot.create_list(:contributor, 100, :whats_app_contributor)
+contributors = Contributor.all
+
+FactoryBot.modify do
+ factory :message do
+ sender_type { 'Contributor' }
+ text { Faker::Lorem.paragraph }
+ unknown_content { false }
+ broadcasted { false }
+ sender { contributors.sample }
+ recipient { nil }
+ end
+end
+
+Rails.logger.debug 'Seeding messages..'
+message_count = request_count * (contributors.count * 0.5).to_i
+message_count.times do
+ request = requests.sample
+ created_at = Time.zone.at(rand(request.broadcasted_at..Time.current))
+ FactoryBot.build(:message, request: request, created_at: created_at, updated_at: created_at) do |message|
+ message.class.skip_callback(:create, :after, :send_if_outbound, raise: false)
+ message.save!
+ end
+end
diff --git a/spec/components/contributors_index_spec.rb b/spec/components/contributors_index_spec.rb
index 145c77dc6..a5ecf2064 100644
--- a/spec/components/contributors_index_spec.rb
+++ b/spec/components/contributors_index_spec.rb
@@ -15,6 +15,7 @@
inactive_count: 1,
unsubscribed_count: 0,
filter_count: 0,
+ available_tags: [],
tag_list: []
}
end
diff --git a/spec/components/request_form_spec.rb b/spec/components/request_form_spec.rb
index 28e1acfd5..1c1047842 100644
--- a/spec/components/request_form_spec.rb
+++ b/spec/components/request_form_spec.rb
@@ -6,7 +6,7 @@
subject { render_inline(described_class.new(**params)) }
let(:organization) { create(:organization) }
- let(:params) { { organization: organization, request: build(:request) } }
+ let(:params) { { request: build(:request, organization: organization), available_tags: [] } }
it { should have_css('.RequestForm') }
it {
is_expected.not_to have_css('button[data-action="request-form#openModal"]',
@@ -14,7 +14,12 @@
}
context 'planned request' do
- let(:params) { { organization: organization, request: create(:request, broadcasted_at: nil, schedule_send_for: 1.day.from_now) } }
+ let(:params) do
+ {
+ request: create(:request, broadcasted_at: nil, schedule_send_for: 1.day.from_now, organization: organization),
+ available_tags: []
+ }
+ end
it 'renders a button to open a confirm destroy modal' do
expect(subject).to have_css('button[data-action="request-form#openModal"]',
diff --git a/spec/jobs/mark_inactive_contributor_inactive_job_spec.rb b/spec/jobs/mark_inactive_contributor_inactive_job_spec.rb
index 39877c7d0..263bc23fd 100644
--- a/spec/jobs/mark_inactive_contributor_inactive_job_spec.rb
+++ b/spec/jobs/mark_inactive_contributor_inactive_job_spec.rb
@@ -32,7 +32,10 @@
end
context 'that does belong to the organization' do
- before { contributor.update(organization_id: organization.id) }
+ before do
+ contributor.update(organization_id: organization.id)
+ non_admin_user.update(organization_id: organization.id)
+ end
it { is_expected.to change { contributor.reload.deactivated_at }.from(nil).to(kind_of(ActiveSupport::TimeWithZone)) }
it_behaves_like 'an ActivityNotification', 'ContributorMarkedInactive'
diff --git a/spec/jobs/resubscribe_contributor_job_spec.rb b/spec/jobs/resubscribe_contributor_job_spec.rb
index 7e213a006..4065e5cf1 100644
--- a/spec/jobs/resubscribe_contributor_job_spec.rb
+++ b/spec/jobs/resubscribe_contributor_job_spec.rb
@@ -4,7 +4,7 @@
RSpec.describe ResubscribeContributorJob do
describe '#perform_later(contributor_id, adapter)' do
- let(:user) { create(:user) }
+ let(:user) { create(:user, organization: organization) }
let(:organization) { create(:organization) }
subject { -> { described_class.new.perform(organization.id, contributor.id, adapter) } }
@@ -27,7 +27,7 @@
signal_onboarding_completed_at: 1.week.ago,
unsubscribed_at: 1.day.ago,
deactivated_at: Time.current,
- deactivated_by_user: create(:user),
+ deactivated_by_user: user,
organization: organization)
end
end
@@ -62,7 +62,7 @@
telegram_id: 123_456_789,
unsubscribed_at: 1.week.ago,
deactivated_at: Time.current,
- deactivated_by_user: create(:user),
+ deactivated_by_user: user,
organization: organization)
end
end
@@ -107,7 +107,7 @@
threema_id: threema_id,
unsubscribed_at: 1.month.ago,
deactivated_at: Time.current,
- deactivated_by_user: create(:user),
+ deactivated_by_user: user,
organization: organization)
end
end
@@ -147,7 +147,7 @@
whats_app_phone_number: '+491234567',
unsubscribed_at: 5.days.ago,
deactivated_at: Time.current,
- deactivated_by_user: create(:user),
+ deactivated_by_user: user,
organization: organization)
end
end
@@ -184,7 +184,7 @@
whats_app_phone_number: '+491234567',
unsubscribed_at: 5.days.ago,
deactivated_at: Time.current,
- deactivated_by_user: create(:user),
+ deactivated_by_user: user,
organization: organization)
end
end
diff --git a/spec/mailboxes/replies_mailbox_spec.rb b/spec/mailboxes/replies_mailbox_spec.rb
index 006bf8692..279f8d9e3 100644
--- a/spec/mailboxes/replies_mailbox_spec.rb
+++ b/spec/mailboxes/replies_mailbox_spec.rb
@@ -34,22 +34,29 @@
it { should_not(change { Message.count }) }
describe 'given an active request' do
- let(:request) { create(:request, title: 'Wie geht es euren Haustieren in Corona-Zeiten?') }
+ let(:request) { create(:request, title: 'Wie geht es euren Haustieren in Corona-Zeiten?', organization: organization) }
before(:each) { create(:message, request: request, sender: nil, recipient: contributor, broadcasted: true) }
+ let!(:admin) { create(:user, admin: true) }
it { should(change { Message.count }.from(1).to(2)) }
describe 'after email processing' do
let(:replies) { Message.where(sender: contributor).pluck(:text) }
- before(:each) { subject.call }
+ before do
+ organization.update!(users: create_list(:user, 5))
+ subject.call
+ end
it { should(change { Message.count }.from(2).to(3)) }
- describe 'MessageReceived ActivityNotification' do
- context 'creates an ActivityNotification' do
- it_behaves_like 'an ActivityNotification', 'MessageReceived'
- end
+ it 'it creates a MessageReceived notification for each user and admin' do
+ subject.call
+ recipient_ids = ActivityNotification.where(type: MessageReceived.name).pluck(:recipient_id).uniq.sort
+ user_ids = organization.users.pluck(:id)
+ admin_id = admin.id
+ ids = (user_ids << admin_id).sort
+ expect(recipient_ids).to eq(ids)
end
describe 'with matching from address' do
diff --git a/spec/models/contributor_spec.rb b/spec/models/contributor_spec.rb
index d31dcfdde..38876f54c 100644
--- a/spec/models/contributor_spec.rb
+++ b/spec/models/contributor_spec.rb
@@ -4,9 +4,11 @@
RSpec.describe Contributor, type: :model do
let(:the_request) do
- create(:request, title: 'Hitchhiker’s Guide', text: 'What is the answer to life, the universe, and everything?')
+ create(:request, title: 'Hitchhiker’s Guide', text: 'What is the answer to life, the universe, and everything?',
+ organization: organization, user: create(:user, organization: organization))
end
- let(:contributor) { create(:contributor, email: 'contributor@example.org') }
+ let(:organization) { create(:organization) }
+ let(:contributor) { create(:contributor, email: 'contributor@example.org', organization: organization) }
it 'is sorted in alphabetical order' do
zora = create(:contributor, first_name: 'Zora', last_name: 'Zimmermann')
@@ -328,20 +330,6 @@
end
end
- describe '.all_tags_with_count' do
- subject { Contributor.all_tags_with_count.pluck(:name, :count) }
-
- context 'given a contributor with a tag' do
- let!(:contributor) { create(:contributor, tag_list: %w[Homeowner]) }
- it { should eq([['Homeowner', 1]]) }
-
- context 'and a request with the same tag' do
- let!(:request) { create(:request, tag_list: %w[Homeowner]) }
- it { should eq([['Homeowner', 1]]) }
- end
- end
- end
-
describe '#conversations' do
let(:received_message) do
create(:message, text: 'Message with the contributor as recipient', recipient: contributor)
@@ -952,8 +940,22 @@
end
describe '#after_create_commit' do
- subject { create(:contributor) }
+ subject { create(:contributor, organization: organization) }
- it_behaves_like 'an ActivityNotification', 'OnboardingCompleted'
+ before do
+ users = create_list(:user, 5, organization: organization)
+ organization.update(users: users)
+ end
+
+ it 'behaves like an ActivityNotification' do
+ expect { subject }.to change(ActivityNotification.where(type: 'OnboardingCompleted'), :count).by(User.count)
+ end
+
+ it 'for each user' do
+ subject
+ recipient_ids = ActivityNotification.where(type: 'OnboardingCompleted').pluck(:recipient_id).uniq.sort
+ user_ids = User.pluck(:id).sort
+ expect(recipient_ids).to eq(user_ids)
+ end
end
end
diff --git a/spec/models/message_spec.rb b/spec/models/message_spec.rb
index 7f6d1b738..274616422 100644
--- a/spec/models/message_spec.rb
+++ b/spec/models/message_spec.rb
@@ -91,12 +91,13 @@
describe '#after_commit(on: :commit)' do
let!(:user) { create(:user) }
- let(:request) { create(:request, user: user, organization: organization) }
- let(:message) { create(:message, sender: user, recipient: recipient, broadcasted: true, request: request) }
+ let!(:request) { create(:request, user: user, organization: organization) }
+ let(:message) { create(:message, sender: user, recipient: recipient, broadcasted: broadcasted, request: request) }
let(:organization) do
create(:organization, name: '100eyes', telegram_bot_api_key: 'TELEGRAM_BOT_API_KEY', telegram_bot_username: 'USERNAME')
end
let(:recipient) { create(:contributor, organization: organization) }
+ let(:broadcasted) { true }
describe 'given a recipient with telegram' do
before do
@@ -123,14 +124,55 @@
end
end
- describe 'ActivityNotification' do
- subject { create(:message, request: request) }
+ describe '#notify_recipient' do
+ subject { message }
- it 'Message Received is not created for outbound messages' do
- expect { message }.not_to(change { ActivityNotification.where(type: 'MessageReceived').count })
+ let!(:admin) { create(:user, admin: true) }
+
+ before do
+ Contributor.skip_callback(:commit, :after, :notify_recipient, raise: false)
+ organization.update!(users: create_list(:user, 5, organization: organization))
+ end
+
+ after do
+ Contributor.set_callback(:commit, :after, :notify_recipient, raise: false)
+ end
+
+ context 'given an outbound message' do
+ it 'is broadcasted, it does not create an ActivityNotification' do
+ expect { subject }.not_to change(ActivityNotification, :count)
+ end
+
+ context 'is not broadcast' do
+ let(:broadcasted) { false }
+
+ it 'does not create a MessageReceived notification' do
+ expect { subject }.not_to(change { ActivityNotification.where(type: MessageReceived.name).count })
+ end
+
+ it 'it creates a ChatMessageSent notification for each user and admin' do
+ subject
+ recipient_ids = ActivityNotification.where(type: ChatMessageSent.name).pluck(:recipient_id).uniq.sort
+ user_ids = organization.users.pluck(:id)
+ admin_id = admin.id
+ ids = (user_ids << admin_id).sort
+ expect(recipient_ids).to eq(ids)
+ end
+ end
end
- it_behaves_like 'an ActivityNotification', 'MessageReceived'
+ context 'given an inbound message' do
+ subject { create(:message, :inbound, request: request) }
+
+ it 'it creates a MessageReceived for each user and admin' do
+ subject
+ recipient_ids = ActivityNotification.where(type: MessageReceived.name).pluck(:recipient_id).uniq.sort
+ user_ids = organization.users.pluck(:id)
+ admin_id = admin.id
+ ids = (user_ids << admin_id).sort
+ expect(recipient_ids).to eq(ids)
+ end
+ end
end
end
diff --git a/spec/models/organization_spec.rb b/spec/models/organization_spec.rb
index b1826111f..3bba635cc 100644
--- a/spec/models/organization_spec.rb
+++ b/spec/models/organization_spec.rb
@@ -53,4 +53,18 @@
end
end
end
+
+ describe '#contributors_tags_with_count' do
+ subject { organization.contributors_tags_with_count.pluck(:name, :count) }
+
+ context 'given a contributor with a tag' do
+ let!(:contributor) { create(:contributor, tag_list: %w[Homeowner], organization: organization) }
+ it { should eq([['Homeowner', 1]]) }
+
+ context 'and a request with the same tag' do
+ let!(:request) { create(:request, tag_list: %w[Homeowner], organization: organization) }
+ it { should eq([['Homeowner', 1]]) }
+ end
+ end
+ end
end
diff --git a/spec/requests/telegram/webhook_spec.rb b/spec/requests/telegram/webhook_spec.rb
index 05b7ba815..e1ce59762 100644
--- a/spec/requests/telegram/webhook_spec.rb
+++ b/spec/requests/telegram/webhook_spec.rb
@@ -138,7 +138,7 @@
it { expect { subject.call }.not_to(change { Message.count }) }
context 'given a recent request' do
- before { create(:request, organization: organization) }
+ before { create(:request, organization: organization, user: create(:user, organization: organization)) }
it { expect { subject.call }.to(change { Message.count }.from(0).to(1)) }
it { expect { subject.call }.not_to respond_with_message }
it_behaves_like 'an ActivityNotification', 'MessageReceived'
diff --git a/spec/requests/threema/webhook_spec.rb b/spec/requests/threema/webhook_spec.rb
index 7ddf341cd..d24d940a7 100644
--- a/spec/requests/threema/webhook_spec.rb
+++ b/spec/requests/threema/webhook_spec.rb
@@ -47,7 +47,7 @@
context 'With known contributor' do
let!(:contributor) { create(:contributor, :skip_validations, threema_id: 'V5EA564T', organization: organization) }
- let!(:request) { create(:request) }
+ let!(:request) { create(:request, organization: organization, user: create(:user, organization: organization)) }
before do
allow(threema_mock).to receive(:instance_of?).with(Threema::Receive::Text).and_return(true)
diff --git a/spec/support/shared_examples/activity_notifications.rb b/spec/support/shared_examples/activity_notifications.rb
index 21ebe5b82..c83e9a97e 100644
--- a/spec/support/shared_examples/activity_notifications.rb
+++ b/spec/support/shared_examples/activity_notifications.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
RSpec.shared_examples 'an ActivityNotification' do |event_type|
- let!(:users) { create_list(:user, 5) }
+ let!(:users) { create_list(:user, 5, organization: organization) }
context 'creates activity notifications' do
it " of type #{event_type}" do
diff --git a/spec/support/shared_examples/contributor_resubscribes.rb b/spec/support/shared_examples/contributor_resubscribes.rb
index 8735c79f7..21a50d976 100644
--- a/spec/support/shared_examples/contributor_resubscribes.rb
+++ b/spec/support/shared_examples/contributor_resubscribes.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: true
RSpec.shared_examples 'a Contributor resubscribes' do |adapter|
- let!(:request) { create(:request, organization: organization) }
+ let!(:request) { create(:request, organization: organization, user: non_admin_user) }
let!(:admin) { create_list(:user, 2, admin: true) }
- let!(:non_admin_user) { create(:user) }
+ let!(:non_admin_user) { create(:user, organization: organization) }
let(:welcome_message) do
organization.onboarding_success_text
end
diff --git a/spec/support/shared_examples/contributor_unsubscribes.rb b/spec/support/shared_examples/contributor_unsubscribes.rb
index d1e146548..d98aea60a 100644
--- a/spec/support/shared_examples/contributor_unsubscribes.rb
+++ b/spec/support/shared_examples/contributor_unsubscribes.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: true
RSpec.shared_examples 'a Contributor unsubscribes' do |adapter|
- let!(:request) { create(:request, organization: organization) }
+ let!(:request) { create(:request, organization: organization, user: non_admin_user) }
let!(:admin) { create_list(:user, 2, admin: true) }
- let!(:non_admin_user) { create(:user) }
+ let!(:non_admin_user) { create(:user, organization: organization) }
let(:unsubscribe_successful_message) do
[I18n.t('adapter.shared.unsubscribe.successful')].join("\n\n")
end
diff --git a/spec/system/contributors/filter_spec.rb b/spec/system/contributors/filter_spec.rb
index 1b5c79936..1fbcfaa56 100644
--- a/spec/system/contributors/filter_spec.rb
+++ b/spec/system/contributors/filter_spec.rb
@@ -4,9 +4,10 @@
RSpec.describe 'Filter contributors' do
let(:user) { create(:user) }
- let!(:active_contributor) { create(:contributor, tag_list: ['entwickler']) }
- let!(:inactive_contributor) { create(:contributor, :inactive, tag_list: ['entwickler']) }
- let!(:another_contributor) { create(:contributor) }
+ let(:organization) { create(:organization) }
+ let!(:active_contributor) { create(:contributor, tag_list: ['entwickler'], organization: organization) }
+ let!(:inactive_contributor) { create(:contributor, :inactive, tag_list: ['entwickler'], organization: organization) }
+ let!(:another_contributor) { create(:contributor, organization: organization) }
it 'Editor lists contributors' do
visit contributors_path(as: user)
diff --git a/spec/system/dashboard/activity_notifications_spec.rb b/spec/system/dashboard/activity_notifications_spec.rb
index d2d8acea5..90e606893 100644
--- a/spec/system/dashboard/activity_notifications_spec.rb
+++ b/spec/system/dashboard/activity_notifications_spec.rb
@@ -17,10 +17,11 @@
create(:user, first_name: 'Coworker', last_name: 'Extraordinaire', email: coworker_email, password: password,
otp_enabled: otp_enabled, organization: organization)
end
- let(:request) { create(:request) }
- let(:contributor_without_avatar) { create(:contributor) }
+ let(:request) { create(:request, user: user, organization: organization) }
+ let(:contributor_without_avatar) { create(:contributor, organization: organization) }
let(:another_contributor) { create(:contributor) }
+ before { organization.update(users: [user, coworker]) }
after { Timecop.return }
it 'displays the activity notifications on dashboard' do
@@ -32,7 +33,7 @@
expect(page).to have_text('Du hast im Moment keine neuen Benachrichtigungen.')
# OnboardingCompleted
- contributor = create(:contributor, :with_an_avatar)
+ contributor = create(:contributor, :with_an_avatar, organization: organization)
Timecop.travel(1.minute.from_now)
visit dashboard_path(as: user)
@@ -45,7 +46,7 @@
expect(page).to have_link('Zum Profil', href: contributor_path(contributor))
# I shouldn't be grouped
- contributor_two = create(:contributor, first_name: 'Timmy', last_name: 'Timmerson')
+ contributor_two = create(:contributor, first_name: 'Timmy', last_name: 'Timmerson', organization: organization)
visit dashboard_path(as: user)
expect(page).to have_css('svg.Avatar-initials')
diff --git a/spec/system/profile/index_spec.rb b/spec/system/profile/index_spec.rb
index bbf29fe23..42508de47 100644
--- a/spec/system/profile/index_spec.rb
+++ b/spec/system/profile/index_spec.rb
@@ -12,8 +12,9 @@
let(:user_to_be_deactivated) { create(:user, first_name: 'User', last_name: 'ToBeDeactivated') }
let(:current_plan) { business_plans[1] }
let(:contact_person) { create(:user, first_name: 'Isaac', last_name: 'Bonga') }
+ let!(:contributors_of_organization) { create_list(:contributor, 5, organization: organization) }
let(:organization) do
- create(:organization, business_plan: current_plan, contact_person: contact_person, contributors_count: 5,
+ create(:organization, business_plan: current_plan, contact_person: contact_person,
upgrade_discount: 15).tap do |org|
users = [user, contact_person, user_to_be_deactivated, create(:user)]
org.users << users
diff --git a/spec/system/requests/deleting_requests_spec.rb b/spec/system/requests/deleting_requests_spec.rb
index 35b3d1709..c217843d5 100644
--- a/spec/system/requests/deleting_requests_spec.rb
+++ b/spec/system/requests/deleting_requests_spec.rb
@@ -3,14 +3,15 @@
require 'rails_helper'
RSpec.describe 'Deleting requests' do
- let(:user) { create(:user) }
- let!(:broadcasted_request) { create(:request) }
- let!(:planned_request) { create(:request, schedule_send_for: 1.hour.from_now) }
- let!(:another_planned_request) { create(:request, schedule_send_for: 5.minutes.from_now) }
+ let(:organization) { create(:organization) }
+ let(:user) { create(:user, organization: organization) }
+ let!(:broadcasted_request) { create(:request, organization: organization, user: user) }
+ let!(:planned_request) { create(:request, schedule_send_for: 1.hour.from_now, organization: organization, user: user) }
+ let!(:another_planned_request) { create(:request, schedule_send_for: 5.minutes.from_now, organization: organization, user: user) }
before do
allow(Request).to receive(:broadcast!).and_call_original
- create(:contributor)
+ create(:contributor, organization: organization)
end
it 'conditonally allows deleting' do
@@ -42,8 +43,8 @@
expect(page).to have_content(I18n.t('components.destroy_planned_request_modal.heading', request_title: planned_request.title))
click_on 'löschen'
- expect(page).to have_content(I18n.t('request.destroy.successful', request_title: planned_request.title))
expect(page).to have_current_path(requests_path(filter: :planned))
+ expect(page).to have_content(I18n.t('request.destroy.successful', request_title: planned_request.title))
# Planned request, that was then sent out
@@ -55,13 +56,12 @@
expect(page).to have_current_path(edit_request_path(another_planned_request))
Timecop.travel(10.minutes.from_now)
another_planned_request.update(broadcasted_at: 5.minutes.ago)
-
click_on I18n.t('components.request_form.planned_request.destroy.button_text')
expect(page).to have_content(I18n.t('components.request_form.planned_request.destroy.button_text',
request_title: another_planned_request.title))
click_on 'löschen'
- expect(page).to have_content(I18n.t('request.destroy.broadcasted_request_unallowed', request_title: another_planned_request.title))
expect(page).to have_current_path(requests_path)
+ expect(page).to have_content(I18n.t('request.destroy.broadcasted_request_unallowed', request_title: another_planned_request.title))
end
end
diff --git a/spec/system/requests/editing_requests_spec.rb b/spec/system/requests/editing_requests_spec.rb
index cbeaff78e..09d4374c0 100644
--- a/spec/system/requests/editing_requests_spec.rb
+++ b/spec/system/requests/editing_requests_spec.rb
@@ -4,7 +4,7 @@
RSpec.describe 'Editing requests', js: true do
let(:organization) { create(:organization) }
- let(:user) { create(:user) }
+ let(:user) { create(:user, organization: organization) }
let(:sent_request) { create(:request, organization: organization) }
let(:request_scheduled_in_future) { create(:request, schedule_send_for: 2.minutes.from_now, organization: organization) }
@@ -37,8 +37,8 @@
formatted = I18n.l(scheduled_datetime, format: :long)
success_message = "Ihre Frage wurde erfolgreich geplant, um am #{formatted} an ein Community-Mitglied gesendet zu werden."
- expect(page).to have_content(success_message)
- expect(page).to have_content('Did you get my scheduled request?')
expect(page).to have_current_path(requests_path(filter: :planned))
+ expect(page).to have_content('Did you get my scheduled request?')
+ expect(page).to have_content(success_message)
end
end
diff --git a/spec/system/requests/scheduling_requests_spec.rb b/spec/system/requests/scheduling_requests_spec.rb
index 8d23802dc..3609dc561 100644
--- a/spec/system/requests/scheduling_requests_spec.rb
+++ b/spec/system/requests/scheduling_requests_spec.rb
@@ -25,9 +25,9 @@
formatted = I18n.l(scheduled_datetime, format: :long)
success_message = "Ihre Frage wurde erfolgreich geplant, um am #{formatted} an ein Community-Mitglied gesendet zu werden."
- expect(page).to have_content(success_message)
- expect(page).to have_content('Did you get my scheduled request?')
expect(page).to have_current_path(requests_path(filter: :planned))
+ expect(page).to have_content('Did you get my scheduled request?')
+ expect(page).to have_content(success_message)
end
end
end