fix: Duplicate contacts creating for Argentina numbers (#11173)

This commit is contained in:
Karim
2025-10-13 02:37:07 -03:00
committed by GitHub
parent 610495123e
commit cdd3b73fc9
4 changed files with 82 additions and 2 deletions

View File

@@ -47,6 +47,15 @@ module Whatsapp::IncomingMessageServiceHelpers
%w[reaction ephemeral unsupported request_welcome].include?(message_type) %w[reaction ephemeral unsupported request_welcome].include?(message_type)
end end
def argentina_phone_number?(phone_number)
phone_number.match(/^54/)
end
def normalised_argentina_mobil_number(phone_number)
# Remove 9 before country code
phone_number.sub(/^549/, '54')
end
def processed_waid(waid) def processed_waid(waid)
Whatsapp::PhoneNumberNormalizationService.new(inbox).normalize_and_find_contact(waid) Whatsapp::PhoneNumberNormalizationService.new(inbox).normalize_and_find_contact(waid)
end end

View File

@@ -0,0 +1,18 @@
# Handles Argentina phone number normalization
#
# Argentina phone numbers can appear with or without "9" after country code
# This normalizer removes the "9" when present to create consistent format: 54 + area + number
class Whatsapp::PhoneNormalizers::ArgentinaPhoneNormalizer < Whatsapp::PhoneNormalizers::BasePhoneNormalizer
def normalize(waid)
return waid unless handles_country?(waid)
# Remove "9" after country code if present (549 → 54)
waid.sub(/^549/, '54')
end
private
def country_code_pattern
/^54/
end
end

View File

@@ -1,5 +1,5 @@
# Service to handle phone number normalization for WhatsApp messages # Service to handle phone number normalization for WhatsApp messages
# Currently supports Brazil phone number format variations # Currently supports Brazil and Argentina phone number format variations
# Designed to be extensible for additional countries in future PRs # Designed to be extensible for additional countries in future PRs
# #
# Usage: Whatsapp::PhoneNumberNormalizationService.new(inbox).normalize_and_find_contact(waid) # Usage: Whatsapp::PhoneNumberNormalizationService.new(inbox).normalize_and_find_contact(waid)
@@ -34,6 +34,7 @@ class Whatsapp::PhoneNumberNormalizationService
end end
NORMALIZERS = [ NORMALIZERS = [
Whatsapp::PhoneNormalizers::BrazilPhoneNormalizer Whatsapp::PhoneNormalizers::BrazilPhoneNormalizer,
Whatsapp::PhoneNormalizers::ArgentinaPhoneNormalizer
].freeze ].freeze
end end

View File

@@ -341,6 +341,58 @@ describe Whatsapp::IncomingMessageService do
end end
end end
describe 'When the incoming waid is an Argentine number with 9 after country code' do
let(:wa_id) { '5491123456789' }
it 'creates appropriate conversations, message and contacts if contact does not exist' do
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
expect(Contact.all.first.name).to eq('Sojan Jose')
expect(whatsapp_channel.inbox.messages.first.content).to eq('Test')
expect(whatsapp_channel.inbox.contact_inboxes.first.source_id).to eq(wa_id)
end
it 'appends to existing contact if contact inbox exists with normalized format' do
# Normalized format removes the 9 after country code
normalized_wa_id = '541123456789'
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: normalized_wa_id)
last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
# no new conversation should be created
expect(whatsapp_channel.inbox.conversations.count).to eq(1)
# message appended to the last conversation
expect(last_conversation.messages.last.content).to eq(params[:messages].first[:text][:body])
# should use the normalized wa_id from existing contact
expect(whatsapp_channel.inbox.contact_inboxes.first.source_id).to eq(normalized_wa_id)
end
end
describe 'When incoming waid is an Argentine number without 9 after country code' do
let(:wa_id) { '541123456789' }
context 'when a contact inbox exists with the same format' do
it 'appends to existing contact' do
contact_inbox = create(:contact_inbox, inbox: whatsapp_channel.inbox, source_id: wa_id)
last_conversation = create(:conversation, inbox: whatsapp_channel.inbox, contact_inbox: contact_inbox)
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
# no new conversation should be created
expect(whatsapp_channel.inbox.conversations.count).to eq(1)
# message appended to the last conversation
expect(last_conversation.messages.last.content).to eq(params[:messages].first[:text][:body])
end
end
context 'when a contact inbox does not exist' do
it 'creates contact inbox with the incoming waid' do
described_class.new(inbox: whatsapp_channel.inbox, params: params).perform
expect(whatsapp_channel.inbox.conversations.count).not_to eq(0)
expect(Contact.all.first.name).to eq('Sojan Jose')
expect(whatsapp_channel.inbox.messages.first.content).to eq('Test')
expect(whatsapp_channel.inbox.contact_inboxes.first.source_id).to eq(wa_id)
end
end
end
describe 'when message processing is in progress' do describe 'when message processing is in progress' do
it 'ignores the current message creation request' do it 'ignores the current message creation request' do
params = { 'contacts' => [{ 'profile' => { 'name' => 'Kedar' }, 'wa_id' => '919746334593' }], params = { 'contacts' => [{ 'profile' => { 'name' => 'Kedar' }, 'wa_id' => '919746334593' }],