chore: Merge contact copy over information (#2812)

fixes: #2767, #2773

Co-authored-by: Nithin David <1277421+nithindavid@users.noreply.github.com>
This commit is contained in:
Sojan Jose
2021-08-31 15:30:18 +05:30
committed by GitHub
parent 1ff9939a80
commit 5319af3dfc
6 changed files with 64 additions and 15 deletions

View File

@@ -1,4 +1,5 @@
class ContactMergeAction class ContactMergeAction
include Events::Types
pattr_initialize [:account!, :base_contact!, :mergee_contact!] pattr_initialize [:account!, :base_contact!, :mergee_contact!]
def perform def perform
@@ -11,7 +12,7 @@ class ContactMergeAction
merge_conversations merge_conversations
merge_messages merge_messages
merge_contact_inboxes merge_contact_inboxes
remove_mergee_contact merge_and_remove_mergee_contact
end end
@base_contact @base_contact
end end
@@ -40,7 +41,18 @@ class ContactMergeAction
ContactInbox.where(contact_id: @mergee_contact.id).update(contact_id: @base_contact.id) ContactInbox.where(contact_id: @mergee_contact.id).update(contact_id: @base_contact.id)
end end
def remove_mergee_contact def merge_and_remove_mergee_contact
mergable_attribute_keys = %w[identifier name email phone_number 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)
# retaining old pubsub token to notify the contacts that are listening
mergee_pubsub_token = mergee_contact.pubsub_token
@mergee_contact.destroy! @mergee_contact.destroy!
Rails.configuration.dispatcher.dispatch(CONTACT_MERGED, Time.zone.now, contact: @base_contact, tokens: [mergee_pubsub_token])
@base_contact.update!(merged_attributes)
end end
end end

View File

@@ -10,9 +10,22 @@ class ActionCableConnector extends BaseActionCableConnector {
'conversation.typing_off': this.onTypingOff, 'conversation.typing_off': this.onTypingOff,
'conversation.status_changed': this.onStatusChange, 'conversation.status_changed': this.onStatusChange,
'presence.update': this.onPresenceUpdate, 'presence.update': this.onPresenceUpdate,
'contact.merged': this.onContactMerge,
}; };
} }
static refreshConnector = pubsubToken => {
if (!pubsubToken || window.chatwootPubsubToken === pubsubToken) {
return;
}
window.chatwootPubsubToken = pubsubToken;
window.actionCable.disconnect();
window.actionCable = new ActionCableConnector(
window.WOOT_WIDGET,
window.chatwootPubsubToken
);
};
onStatusChange = data => { onStatusChange = data => {
this.app.$store.dispatch('conversationAttributes/update', data); this.app.$store.dispatch('conversationAttributes/update', data);
}; };
@@ -33,6 +46,11 @@ class ActionCableConnector extends BaseActionCableConnector {
this.app.$store.dispatch('agent/updatePresence', data.users); this.app.$store.dispatch('agent/updatePresence', data.users);
}; };
onContactMerge = data => {
const { pubsub_token: pubsubToken } = data;
ActionCableConnector.refreshConnector(pubsubToken);
};
onTypingOn = () => { onTypingOn = () => {
this.clearTimer(); this.clearTimer();
this.app.$store.dispatch('conversation/toggleAgentTyping', { this.app.$store.dispatch('conversation/toggleAgentTyping', {
@@ -63,16 +81,7 @@ class ActionCableConnector extends BaseActionCableConnector {
}; };
} }
export const refreshActionCableConnector = pubsubToken => { export const refreshActionCableConnector =
if (!pubsubToken || window.chatwootPubsubToken === pubsubToken) { ActionCableConnector.refreshConnector;
return;
}
window.chatwootPubsubToken = pubsubToken;
window.actionCable.disconnect();
window.actionCable = new ActionCableConnector(
window.WOOT_WIDGET,
window.chatwootPubsubToken
);
};
export default ActionCableConnector; export default ActionCableConnector;

View File

@@ -104,6 +104,13 @@ class ActionCableListener < BaseListener
broadcast(account, tokens, CONTACT_UPDATED, contact.push_event_data) broadcast(account, tokens, CONTACT_UPDATED, contact.push_event_data)
end end
def contact_merged(event)
contact, account = extract_contact_and_account(event)
tokens = event.data[:tokens]
broadcast(account, tokens, CONTACT_MERGED, contact.push_event_data)
end
private private
def typing_event_listener_tokens(account, conversation, user) def typing_event_listener_tokens(account, conversation, user)

View File

@@ -77,6 +77,8 @@ class Contact < ApplicationRecord
} }
end end
private
def ip_lookup def ip_lookup
return unless account.feature_enabled?('ip_lookup') return unless account.feature_enabled?('ip_lookup')

View File

@@ -34,6 +34,7 @@ module Events::Types
# contact events # contact events
CONTACT_CREATED = 'contact.created' CONTACT_CREATED = 'contact.created'
CONTACT_UPDATED = 'contact.updated' CONTACT_UPDATED = 'contact.updated'
CONTACT_MERGED = 'contact.merged'
# agent events # agent events
AGENT_ADDED = 'agent.added' AGENT_ADDED = 'agent.added'

View File

@@ -4,8 +4,14 @@ describe ::ContactMergeAction do
subject(:contact_merge) { described_class.new(account: account, base_contact: base_contact, mergee_contact: mergee_contact).perform } subject(:contact_merge) { described_class.new(account: account, base_contact: base_contact, mergee_contact: mergee_contact).perform }
let!(:account) { create(:account) } let!(:account) { create(:account) }
let!(:base_contact) { create(:contact, account: account) } let!(:base_contact) do
let!(:mergee_contact) { create(:contact, account: account) } create(:contact, identifier: 'base_contact', email: 'old@old.com', phone_number: '', custom_attributes: { val_test: 'old', val_empty_old: '' },
account: account)
end
let!(:mergee_contact) do
create(:contact, identifier: '', email: 'new@new.com', phone_number: '+12212345',
custom_attributes: { val_test: 'new', val_new: 'new', val_empty_new: '' }, account: account)
end
before do before do
2.times.each do 2.times.each do
@@ -21,6 +27,18 @@ describe ::ContactMergeAction do
expect { mergee_contact.reload }.to raise_error(ActiveRecord::RecordNotFound) expect { mergee_contact.reload }.to raise_error(ActiveRecord::RecordNotFound)
end end
it 'copies information from mergee contact to base contact' do
contact_merge
base_contact.reload
expect(base_contact.identifier).to eq('base_contact')
expect(base_contact.email).to eq('old@old.com')
expect(base_contact.phone_number).to eq('+12212345')
expect(base_contact.custom_attributes['val_test']).to eq('old')
expect(base_contact.custom_attributes['val_new']).to eq('new')
expect(base_contact.custom_attributes['val_empty_old']).to eq('')
expect(base_contact.custom_attributes['val_empty_new']).to eq('')
end
context 'when base contact and merge contact are same' do context 'when base contact and merge contact are same' do
it 'does not delete contact' do it 'does not delete contact' do
mergee_contact = base_contact mergee_contact = base_contact