Files
Sony MathewandGitHub 66cfb26c77 feat: Add unread count filters feature flag (1/6) (#14885)
## Description

Adds the account-level `unread_count_for_filters` feature flag as the
dark-launch gate for filtered sidebar unread counts. This reuses the
deprecated `quoted_email_reply` flag slot, resets the reused bit for
existing accounts, and removes stale defaults so new accounts do not
reference the old flag.

This also adds the feature where we are now calculating the unread counts for built in filters like mentions, participating and unattended along with unread count for saved filters/folders.

Closes
[CW-7262](https://linear.app/chatwoot/issue/CW-7262/unread-counts-for-filters-folders)

## Type of change

- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality not to work as expected)
- [ ] This change requires a documentation update
2026-07-08 23:50:40 +05:30

90 lines
2.7 KiB
Ruby

# == Schema Information
#
# Table name: teams
#
# id :bigint not null, primary key
# allow_auto_assign :boolean default(TRUE)
# description :text
# icon :string default("")
# icon_color :string default("")
# name :string not null
# created_at :datetime not null
# updated_at :datetime not null
# account_id :bigint not null
#
# Indexes
#
# index_teams_on_account_id (account_id)
# index_teams_on_name_and_account_id (name,account_id) UNIQUE
#
class Team < ApplicationRecord
include AccountCacheRevalidator
belongs_to :account
has_many :team_members, dependent: :destroy_async
has_many :members, through: :team_members, source: :user
has_many :conversations, dependent: :nullify
before_destroy :capture_filtered_unread_count_member_ids, prepend: true
after_destroy_commit :invalidate_filtered_unread_counts_after_destroy
validates :name,
presence: { message: I18n.t('errors.validations.presence') },
uniqueness: { scope: :account_id }
before_validation do
self.name = name.gsub(/[[:cntrl:]]/, '').strip.downcase if attribute_present?('name')
end
# Adds multiple members to the team
# @param user_ids [Array<Integer>] Array of user IDs to add as members
# @return [Array<User>] Array of newly added members
def add_members(user_ids)
team_members_to_create = user_ids.map { |user_id| { user_id: user_id } }
created_members = team_members.create(team_members_to_create)
added_users = created_members.filter_map(&:user)
update_account_cache
added_users
end
# Removes multiple members from the team
# @param user_ids [Array<Integer>] Array of user IDs to remove
# @return [void]
def remove_members(user_ids)
team_members.where(user_id: user_ids).destroy_all
update_account_cache
end
def messages
account.messages.where(conversation_id: conversations.pluck(:id))
end
def reporting_events
account.reporting_events.where(conversation_id: conversations.pluck(:id))
end
def push_event_data
{
id: id,
name: name,
icon: icon,
icon_color: icon_color
}
end
private
def capture_filtered_unread_count_member_ids
@filtered_unread_count_member_ids = team_members.pluck(:user_id)
end
def invalidate_filtered_unread_counts_after_destroy
invalidator = ::Conversations::UnreadCounts::FilteredCountInvalidator.new(account)
invalidator.conversation_changed!
invalidator.users_visibility_changed!(user_ids: @filtered_unread_count_member_ids)
end
end
Team.include_mod_with('Audit::Team')