791d90c6b7
At present, the websocket pubsub tokens are present at the contact objects in chatwoot. A better approach would be to have these tokens at the contact_inbox object instead. This helps chatwoot to deliver the websocket events targetted to the specific widget connection, stop contact events from leaking into other chat sessions from the same contact. Fixes #1682 Fixes #1664 Co-authored-by: Pranav Raj S <pranav@chatwoot.com> Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
57 lines
2 KiB
Ruby
57 lines
2 KiB
Ruby
class ContactMergeAction
|
|
include Events::Types
|
|
pattr_initialize [:account!, :base_contact!, :mergee_contact!]
|
|
|
|
def perform
|
|
# This case happens when an agent updates a contact email in dashboard,
|
|
# while the contact also update his email via email collect box
|
|
return @base_contact if base_contact.id == mergee_contact.id
|
|
|
|
ActiveRecord::Base.transaction do
|
|
validate_contacts
|
|
merge_conversations
|
|
merge_messages
|
|
merge_contact_inboxes
|
|
merge_and_remove_mergee_contact
|
|
end
|
|
@base_contact
|
|
end
|
|
|
|
private
|
|
|
|
def validate_contacts
|
|
return if belongs_to_account?(@base_contact) && belongs_to_account?(@mergee_contact)
|
|
|
|
raise StandardError, 'contact does not belong to the account'
|
|
end
|
|
|
|
def belongs_to_account?(contact)
|
|
@account.id == contact.account_id
|
|
end
|
|
|
|
def merge_conversations
|
|
Conversation.where(contact_id: @mergee_contact.id).update(contact_id: @base_contact.id)
|
|
end
|
|
|
|
def merge_messages
|
|
Message.where(sender: @mergee_contact).update(sender: @base_contact)
|
|
end
|
|
|
|
def merge_contact_inboxes
|
|
ContactInbox.where(contact_id: @mergee_contact.id).update(contact_id: @base_contact.id)
|
|
end
|
|
|
|
def merge_and_remove_mergee_contact
|
|
mergable_attribute_keys = %w[identifier name email phone_number additional_attributes custom_attributes]
|
|
base_contact_attributes = base_contact.attributes.slice(*mergable_attribute_keys).compact_blank
|
|
mergee_contact_attributes = mergee_contact.attributes.slice(*mergable_attribute_keys).compact_blank
|
|
|
|
# attributes in base contact are given preference
|
|
merged_attributes = mergee_contact_attributes.deep_merge(base_contact_attributes)
|
|
|
|
@mergee_contact.destroy!
|
|
Rails.configuration.dispatcher.dispatch(CONTACT_MERGED, Time.zone.now, contact: @base_contact,
|
|
tokens: [@base_contact.contact_inboxes.filter_map(&:pubsub_token)])
|
|
@base_contact.update!(merged_attributes)
|
|
end
|
|
end
|