mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-11-04 04:57:51 +00:00 
			
		
		
		
	feat: Add WhatsApp profile for contact name resolution (#12123)
Fixes https://linear.app/chatwoot/issue/CW-4397/whatsapp-contacts-name-update-after-responsd-to-template
This commit is contained in:
		@@ -92,6 +92,9 @@ class Whatsapp::IncomingMessageBaseService
 | 
			
		||||
 | 
			
		||||
    @contact_inbox = contact_inbox
 | 
			
		||||
    @contact = contact_inbox.contact
 | 
			
		||||
 | 
			
		||||
    # Update existing contact name if ProfileName is available and current name is just phone number
 | 
			
		||||
    update_contact_with_profile_name(contact_params)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def set_conversation
 | 
			
		||||
@@ -171,4 +174,21 @@ class Whatsapp::IncomingMessageBaseService
 | 
			
		||||
      )
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def update_contact_with_profile_name(contact_params)
 | 
			
		||||
    profile_name = contact_params.dig(:profile, :name)
 | 
			
		||||
    return if profile_name.blank?
 | 
			
		||||
    return if @contact.name == profile_name
 | 
			
		||||
 | 
			
		||||
    # Only update if current name exactly matches the phone number or formatted phone number
 | 
			
		||||
    return unless contact_name_matches_phone_number?
 | 
			
		||||
 | 
			
		||||
    @contact.update!(name: profile_name)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def contact_name_matches_phone_number?
 | 
			
		||||
    phone_number = "+#{@processed_params[:messages].first[:from]}"
 | 
			
		||||
    formatted_phone_number = TelephoneNumber.parse(phone_number).international_number
 | 
			
		||||
    @contact.name == phone_number || @contact.name == formatted_phone_number
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -371,5 +371,100 @@ describe Whatsapp::IncomingMessageService do
 | 
			
		||||
        Redis::Alfred.delete(key)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'when profile name is available for contact updates' do
 | 
			
		||||
      let(:wa_id) { '1234567890' }
 | 
			
		||||
      let(:phone_number) { "+#{wa_id}" }
 | 
			
		||||
 | 
			
		||||
      it 'updates existing contact name when current name matches phone number' do
 | 
			
		||||
        # Create contact with phone number as name
 | 
			
		||||
        existing_contact = create(:contact,
 | 
			
		||||
                                  account: whatsapp_channel.inbox.account,
 | 
			
		||||
                                  name: phone_number,
 | 
			
		||||
                                  phone_number: phone_number)
 | 
			
		||||
        create(:contact_inbox,
 | 
			
		||||
               contact: existing_contact,
 | 
			
		||||
               inbox: whatsapp_channel.inbox,
 | 
			
		||||
               source_id: wa_id)
 | 
			
		||||
 | 
			
		||||
        params = {
 | 
			
		||||
          'contacts' => [{ 'profile' => { 'name' => 'Jane Smith' }, 'wa_id' => wa_id }],
 | 
			
		||||
          'messages' => [{ 'from' => wa_id, 'id' => 'message123', 'text' => { 'body' => 'Hello' },
 | 
			
		||||
                           'timestamp' => '1633034394', 'type' => 'text' }]
 | 
			
		||||
        }.with_indifferent_access
 | 
			
		||||
 | 
			
		||||
        described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
 | 
			
		||||
        existing_contact.reload
 | 
			
		||||
        expect(existing_contact.name).to eq('Jane Smith')
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'does not update contact name when current name is different from phone number' do
 | 
			
		||||
        # Create contact with human name
 | 
			
		||||
        existing_contact = create(:contact,
 | 
			
		||||
                                  account: whatsapp_channel.inbox.account,
 | 
			
		||||
                                  name: 'John Doe',
 | 
			
		||||
                                  phone_number: phone_number)
 | 
			
		||||
        create(:contact_inbox,
 | 
			
		||||
               contact: existing_contact,
 | 
			
		||||
               inbox: whatsapp_channel.inbox,
 | 
			
		||||
               source_id: wa_id)
 | 
			
		||||
 | 
			
		||||
        params = {
 | 
			
		||||
          'contacts' => [{ 'profile' => { 'name' => 'Jane Smith' }, 'wa_id' => wa_id }],
 | 
			
		||||
          'messages' => [{ 'from' => wa_id, 'id' => 'message123', 'text' => { 'body' => 'Hello' },
 | 
			
		||||
                           'timestamp' => '1633034394', 'type' => 'text' }]
 | 
			
		||||
        }.with_indifferent_access
 | 
			
		||||
 | 
			
		||||
        described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
 | 
			
		||||
        existing_contact.reload
 | 
			
		||||
        expect(existing_contact.name).to eq('John Doe') # Should not change
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'updates contact name when current name matches formatted phone number' do
 | 
			
		||||
        formatted_number = TelephoneNumber.parse(phone_number).international_number
 | 
			
		||||
 | 
			
		||||
        # Create contact with formatted phone number as name
 | 
			
		||||
        existing_contact = create(:contact,
 | 
			
		||||
                                  account: whatsapp_channel.inbox.account,
 | 
			
		||||
                                  name: formatted_number,
 | 
			
		||||
                                  phone_number: phone_number)
 | 
			
		||||
        create(:contact_inbox,
 | 
			
		||||
               contact: existing_contact,
 | 
			
		||||
               inbox: whatsapp_channel.inbox,
 | 
			
		||||
               source_id: wa_id)
 | 
			
		||||
 | 
			
		||||
        params = {
 | 
			
		||||
          'contacts' => [{ 'profile' => { 'name' => 'Alice Johnson' }, 'wa_id' => wa_id }],
 | 
			
		||||
          'messages' => [{ 'from' => wa_id, 'id' => 'message123', 'text' => { 'body' => 'Hello' },
 | 
			
		||||
                           'timestamp' => '1633034394', 'type' => 'text' }]
 | 
			
		||||
        }.with_indifferent_access
 | 
			
		||||
 | 
			
		||||
        described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
 | 
			
		||||
        existing_contact.reload
 | 
			
		||||
        expect(existing_contact.name).to eq('Alice Johnson')
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'does not update when profile name is blank' do
 | 
			
		||||
        # Create contact with phone number as name
 | 
			
		||||
        existing_contact = create(:contact,
 | 
			
		||||
                                  account: whatsapp_channel.inbox.account,
 | 
			
		||||
                                  name: phone_number,
 | 
			
		||||
                                  phone_number: phone_number)
 | 
			
		||||
        create(:contact_inbox,
 | 
			
		||||
               contact: existing_contact,
 | 
			
		||||
               inbox: whatsapp_channel.inbox,
 | 
			
		||||
               source_id: wa_id)
 | 
			
		||||
 | 
			
		||||
        params = {
 | 
			
		||||
          'contacts' => [{ 'profile' => { 'name' => '' }, 'wa_id' => wa_id }],
 | 
			
		||||
          'messages' => [{ 'from' => wa_id, 'id' => 'message123', 'text' => { 'body' => 'Hello' },
 | 
			
		||||
                           'timestamp' => '1633034394', 'type' => 'text' }]
 | 
			
		||||
        }.with_indifferent_access
 | 
			
		||||
 | 
			
		||||
        described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
 | 
			
		||||
        existing_contact.reload
 | 
			
		||||
        expect(existing_contact.name).to eq(phone_number) # Should not change
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user