+
-
-
-
-
diff --git a/app/models/contact.rb b/app/models/contact.rb
index 1f3d2fb90..a60e9f4d2 100644
--- a/app/models/contact.rb
+++ b/app/models/contact.rb
@@ -61,7 +61,7 @@ class Contact < ApplicationRecord
after_create_commit :dispatch_create_event, :ip_lookup
after_update_commit :dispatch_update_event
after_destroy_commit :dispatch_destroy_event
- before_save :update_contact_location_and_country_code
+ before_save :sync_contact_attributes
enum contact_type: { visitor: 0, lead: 1, customer: 2 }
@@ -207,11 +207,8 @@ class Contact < ApplicationRecord
self.custom_attributes = {} if custom_attributes.blank?
end
- def update_contact_location_and_country_code
- # TODO: Ensure that location and country_code are updated from additional_attributes.
- # We will remove this once all contacts are updated and both the location and country_code fields are standardized throughout the app.
- self.location = additional_attributes['city']
- self.country_code = additional_attributes['country']
+ def sync_contact_attributes
+ ::Contacts::SyncAttributes.new(self).perform
end
def dispatch_create_event
diff --git a/app/services/contacts/sync_attributes.rb b/app/services/contacts/sync_attributes.rb
new file mode 100644
index 000000000..bc10def66
--- /dev/null
+++ b/app/services/contacts/sync_attributes.rb
@@ -0,0 +1,37 @@
+class Contacts::SyncAttributes
+ attr_reader :contact
+
+ def initialize(contact)
+ @contact = contact
+ end
+
+ def perform
+ update_contact_location_and_country_code
+ set_contact_type
+ end
+
+ private
+
+ def update_contact_location_and_country_code
+ # Ensure that location and country_code are updated from additional_attributes.
+ # TODO: Remove this once all contacts are updated and both the location and country_code fields are standardized throughout the app.
+ @contact.location = @contact.additional_attributes['city']
+ @contact.country_code = @contact.additional_attributes['country']
+ end
+
+ def set_contact_type
+ # If the contact is already a lead or customer then do not change the contact type
+ return unless @contact.contact_type == 'visitor'
+ # If the contact has an email or phone number or social details( facebook_user_id, instagram_user_id, etc) then it is a lead
+ # If contact is from external channel like facebook, instagram, whatsapp, etc then it is a lead
+ return unless @contact.email.present? || @contact.phone_number.present? || social_details_present?
+
+ @contact.contact_type = 'lead'
+ end
+
+ def social_details_present?
+ @contact.additional_attributes.keys.any? do |key|
+ key.start_with?('social_') && @contact.additional_attributes[key].present?
+ end
+ end
+end
diff --git a/app/services/telegram/incoming_message_service.rb b/app/services/telegram/incoming_message_service.rb
index d18994a00..a36231634 100644
--- a/app/services/telegram/incoming_message_service.rb
+++ b/app/services/telegram/incoming_message_service.rb
@@ -130,6 +130,7 @@ class Telegram::IncomingMessageService
@message.attachments.new(
account_id: @message.account_id,
file_type: :location,
+ fallback_title: location_fallback_title,
coordinates_lat: location['latitude'],
coordinates_long: location['longitude']
)
@@ -139,6 +140,16 @@ class Telegram::IncomingMessageService
@file ||= visual_media_params || params[:message][:voice].presence || params[:message][:audio].presence || params[:message][:document].presence
end
+ def location_fallback_title
+ return '' if venue.blank?
+
+ venue[:title] || ''
+ end
+
+ def venue
+ @venue ||= params.dig(:message, :venue).presence
+ end
+
def location
@location ||= params.dig(:message, :location).presence
end
diff --git a/spec/models/contact_spec.rb b/spec/models/contact_spec.rb
index ff186466a..2ca65fa4e 100644
--- a/spec/models/contact_spec.rb
+++ b/spec/models/contact_spec.rb
@@ -22,11 +22,13 @@ RSpec.describe Contact do
it 'sets email to lowercase' do
contact = create(:contact, email: 'Test@test.com')
expect(contact.email).to eq('test@test.com')
+ expect(contact.contact_type).to eq('lead')
end
it 'sets email to nil when empty string' do
contact = create(:contact, email: '')
expect(contact.email).to be_nil
+ expect(contact.contact_type).to eq('visitor')
end
it 'sets custom_attributes to {} when nil' do
@@ -83,4 +85,21 @@ RSpec.describe Contact do
expect(contact.country_code).to eq 'US'
end
end
+
+ context 'when a contact is created' do
+ it 'has contact type "visitor" by default' do
+ contact = create(:contact)
+ expect(contact.contact_type).to eq 'visitor'
+ end
+
+ it 'has contact type "lead" when email is present' do
+ contact = create(:contact, email: 'test@test.com')
+ expect(contact.contact_type).to eq 'lead'
+ end
+
+ it 'has contact type "lead" when contacted through a social channel' do
+ contact = create(:contact, additional_attributes: { social_facebook_user_id: '123' })
+ expect(contact.contact_type).to eq 'lead'
+ end
+ end
end
diff --git a/spec/services/contacts/sync_attributes_spec.rb b/spec/services/contacts/sync_attributes_spec.rb
new file mode 100644
index 000000000..447bcd740
--- /dev/null
+++ b/spec/services/contacts/sync_attributes_spec.rb
@@ -0,0 +1,46 @@
+# spec/services/contacts/sync_attributes_spec.rb
+
+require 'rails_helper'
+
+RSpec.describe Contacts::SyncAttributes do
+ describe '#perform' do
+ let(:contact) { create(:contact, additional_attributes: { 'city' => 'New York', 'country' => 'US' }) }
+
+ context 'when contact has neither email/phone number nor social details' do
+ it 'does not change contact type' do
+ described_class.new(contact).perform
+ expect(contact.reload.contact_type).to eq('visitor')
+ end
+ end
+
+ context 'when contact has email or phone number' do
+ it 'sets contact type to lead' do
+ contact.email = 'test@test.com'
+ contact.save
+ described_class.new(contact).perform
+
+ expect(contact.reload.contact_type).to eq('lead')
+ end
+ end
+
+ context 'when contact has social details' do
+ it 'sets contact type to lead' do
+ contact.additional_attributes['social_facebook_user_id'] = '123456789'
+ contact.save
+ described_class.new(contact).perform
+
+ expect(contact.reload.contact_type).to eq('lead')
+ end
+ end
+
+ context 'when location and country code are updated from additional attributes' do
+ it 'updates location and country code' do
+ described_class.new(contact).perform
+
+ # Expect location and country code to be updated
+ expect(contact.reload.location).to eq('New York')
+ expect(contact.reload.country_code).to eq('US')
+ end
+ end
+ end
+end
diff --git a/spec/services/telegram/incoming_message_service_spec.rb b/spec/services/telegram/incoming_message_service_spec.rb
index 795202894..3cade6343 100644
--- a/spec/services/telegram/incoming_message_service_spec.rb
+++ b/spec/services/telegram/incoming_message_service_spec.rb
@@ -255,6 +255,30 @@ describe Telegram::IncomingMessageService do
expect(Contact.all.first.name).to eq('Sojan Jose')
expect(telegram_channel.inbox.messages.first.attachments.first.file_type).to eq('location')
end
+
+ it 'creates appropriate conversations, message and contacts if venue is present' do
+ params = {
+ 'update_id' => 2_342_342_343_242,
+ 'message' => {
+ 'location': {
+ 'latitude': 37.7893768,
+ 'longitude': -122.3895553
+ },
+ venue: {
+ title: 'San Francisco'
+ }
+ }.merge(message_params)
+ }.with_indifferent_access
+ described_class.new(inbox: telegram_channel.inbox, params: params).perform
+ expect(telegram_channel.inbox.conversations.count).not_to eq(0)
+ expect(Contact.all.first.name).to eq('Sojan Jose')
+
+ attachment = telegram_channel.inbox.messages.first.attachments.first
+ expect(attachment.file_type).to eq('location')
+ expect(attachment.coordinates_lat).to eq(37.7893768)
+ expect(attachment.coordinates_long).to eq(-122.3895553)
+ expect(attachment.fallback_title).to eq('San Francisco')
+ end
end
context 'when valid callback_query params' do