2020-06-07 08:28:05 +00:00
|
|
|
class Api::V1::Accounts::ContactsController < Api::V1::Accounts::BaseController
|
2021-05-13 08:02:19 +00:00
|
|
|
include Sift
|
|
|
|
sort_on :email, type: :string
|
2021-11-10 08:41:00 +00:00
|
|
|
sort_on :name, internal_name: :order_on_name, type: :scope, scope_params: [:direction]
|
2021-05-13 08:02:19 +00:00
|
|
|
sort_on :phone_number, type: :string
|
2021-11-10 08:41:00 +00:00
|
|
|
sort_on :last_activity_at, internal_name: :order_on_last_activity_at, type: :scope, scope_params: [:direction]
|
|
|
|
sort_on :company, internal_name: :order_on_company_name, type: :scope, scope_params: [:direction]
|
|
|
|
sort_on :city, internal_name: :order_on_city, type: :scope, scope_params: [:direction]
|
|
|
|
sort_on :country, internal_name: :order_on_country_name, type: :scope, scope_params: [:direction]
|
2021-05-13 08:02:19 +00:00
|
|
|
|
2020-11-10 09:55:26 +00:00
|
|
|
RESULTS_PER_PAGE = 15
|
2019-08-14 09:48:44 +00:00
|
|
|
|
|
|
|
before_action :check_authorization
|
2021-11-25 06:31:31 +00:00
|
|
|
before_action :set_current_page, only: [:index, :active, :search, :filter]
|
2022-07-12 08:03:16 +00:00
|
|
|
before_action :fetch_contact, only: [:show, :update, :destroy, :avatar, :contactable_inboxes, :destroy_custom_attributes]
|
2021-11-25 06:31:31 +00:00
|
|
|
before_action :set_include_contact_inboxes, only: [:index, :search, :filter]
|
2019-08-14 09:48:44 +00:00
|
|
|
|
|
|
|
def index
|
2020-11-11 10:32:14 +00:00
|
|
|
@contacts_count = resolved_contacts.count
|
2021-06-18 14:38:58 +00:00
|
|
|
@contacts = fetch_contacts_with_conversation_count(resolved_contacts)
|
2020-11-10 09:55:26 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def search
|
|
|
|
render json: { error: 'Specify search string with parameter q' }, status: :unprocessable_entity if params[:q].blank? && return
|
|
|
|
|
2020-12-11 17:55:00 +00:00
|
|
|
contacts = resolved_contacts.where(
|
2021-08-13 07:32:46 +00:00
|
|
|
'name ILIKE :search OR email ILIKE :search OR phone_number ILIKE :search OR contacts.identifier LIKE :search',
|
2020-12-11 17:55:00 +00:00
|
|
|
search: "%#{params[:q]}%"
|
|
|
|
)
|
2020-11-10 09:55:26 +00:00
|
|
|
@contacts_count = contacts.count
|
2021-06-18 14:38:58 +00:00
|
|
|
@contacts = fetch_contacts_with_conversation_count(contacts)
|
2019-08-14 09:48:44 +00:00
|
|
|
end
|
|
|
|
|
2021-02-03 13:54:51 +00:00
|
|
|
def import
|
2021-09-21 04:50:12 +00:00
|
|
|
render json: { error: I18n.t('errors.contacts.import.failed') }, status: :unprocessable_entity and return if params[:import_file].blank?
|
|
|
|
|
2021-02-03 13:54:51 +00:00
|
|
|
ActiveRecord::Base.transaction do
|
|
|
|
import = Current.account.data_imports.create!(data_type: 'contacts')
|
|
|
|
import.import_file.attach(params[:import_file])
|
|
|
|
end
|
2021-09-21 04:50:12 +00:00
|
|
|
|
2021-02-03 13:54:51 +00:00
|
|
|
head :ok
|
|
|
|
end
|
|
|
|
|
2020-10-05 18:00:27 +00:00
|
|
|
# returns online contacts
|
|
|
|
def active
|
2020-11-10 09:55:26 +00:00
|
|
|
contacts = Current.account.contacts.where(id: ::OnlineStatusTracker
|
2020-10-05 18:00:27 +00:00
|
|
|
.get_available_contact_ids(Current.account.id))
|
2020-11-10 09:55:26 +00:00
|
|
|
@contacts_count = contacts.count
|
|
|
|
@contacts = contacts.page(@current_page)
|
2020-10-05 18:00:27 +00:00
|
|
|
end
|
|
|
|
|
2019-10-20 08:47:26 +00:00
|
|
|
def show; end
|
2019-08-14 09:48:44 +00:00
|
|
|
|
2021-10-20 12:44:56 +00:00
|
|
|
def filter
|
2021-11-01 08:27:04 +00:00
|
|
|
result = ::Contacts::FilterService.new(params.permit!, current_user).perform
|
|
|
|
contacts = result[:contacts]
|
|
|
|
@contacts_count = result[:count]
|
|
|
|
@contacts = fetch_contacts_with_conversation_count(contacts)
|
2021-10-20 12:44:56 +00:00
|
|
|
end
|
|
|
|
|
2021-04-15 09:43:01 +00:00
|
|
|
def contactable_inboxes
|
2021-06-11 06:14:31 +00:00
|
|
|
@all_contactable_inboxes = Contacts::ContactableInboxesService.new(contact: @contact).get
|
|
|
|
@contactable_inboxes = @all_contactable_inboxes.select { |contactable_inbox| policy(contactable_inbox[:inbox]).show? }
|
2021-04-15 09:43:01 +00:00
|
|
|
end
|
|
|
|
|
2021-11-11 09:53:33 +00:00
|
|
|
# TODO : refactor this method into dedicated contacts/custom_attributes controller class and routes
|
|
|
|
def destroy_custom_attributes
|
|
|
|
@contact.custom_attributes = @contact.custom_attributes.excluding(params[:custom_attributes])
|
|
|
|
@contact.save!
|
|
|
|
end
|
|
|
|
|
2019-08-14 09:48:44 +00:00
|
|
|
def create
|
2020-07-21 06:45:24 +00:00
|
|
|
ActiveRecord::Base.transaction do
|
2022-07-12 08:03:16 +00:00
|
|
|
@contact = Current.account.contacts.new(permitted_params.except(:avatar_url))
|
2020-07-21 06:45:24 +00:00
|
|
|
@contact.save!
|
|
|
|
@contact_inbox = build_contact_inbox
|
2022-07-12 08:03:16 +00:00
|
|
|
process_avatar
|
2020-07-21 06:45:24 +00:00
|
|
|
end
|
2019-08-14 09:48:44 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def update
|
2020-10-27 20:44:36 +00:00
|
|
|
@contact.assign_attributes(contact_update_params)
|
|
|
|
@contact.save!
|
2022-07-12 08:03:16 +00:00
|
|
|
process_avatar if permitted_params[:avatar].present? || permitted_params[:avatar_url].present?
|
2019-08-14 09:48:44 +00:00
|
|
|
end
|
|
|
|
|
2021-09-23 07:22:49 +00:00
|
|
|
def destroy
|
|
|
|
if ::OnlineStatusTracker.get_presence(
|
|
|
|
@contact.account.id, 'Contact', @contact.id
|
|
|
|
)
|
|
|
|
return render_error({ message: I18n.t('contacts.online.delete', contact_name: @contact.name.capitalize) },
|
|
|
|
:unprocessable_entity)
|
|
|
|
end
|
|
|
|
|
|
|
|
@contact.destroy!
|
|
|
|
head :ok
|
|
|
|
end
|
|
|
|
|
2022-07-12 08:03:16 +00:00
|
|
|
def avatar
|
|
|
|
@contact.avatar.purge if @contact.avatar.attached?
|
|
|
|
@contact
|
|
|
|
end
|
|
|
|
|
2020-11-10 09:55:26 +00:00
|
|
|
private
|
2020-08-10 06:45:29 +00:00
|
|
|
|
2021-06-18 14:38:58 +00:00
|
|
|
# TODO: Move this to a finder class
|
2020-11-11 10:32:14 +00:00
|
|
|
def resolved_contacts
|
2021-06-18 14:38:58 +00:00
|
|
|
return @resolved_contacts if @resolved_contacts
|
|
|
|
|
2021-11-10 08:41:00 +00:00
|
|
|
@resolved_contacts = Current.account.contacts.resolved_contacts
|
|
|
|
|
2021-06-18 14:38:58 +00:00
|
|
|
@resolved_contacts = @resolved_contacts.tagged_with(params[:labels], any: true) if params[:labels].present?
|
|
|
|
@resolved_contacts
|
2020-11-11 10:32:14 +00:00
|
|
|
end
|
|
|
|
|
2020-11-10 09:55:26 +00:00
|
|
|
def set_current_page
|
|
|
|
@current_page = params[:page] || 1
|
2020-08-10 06:45:29 +00:00
|
|
|
end
|
|
|
|
|
2021-06-18 14:38:58 +00:00
|
|
|
def fetch_contacts_with_conversation_count(contacts)
|
2021-07-23 13:09:24 +00:00
|
|
|
contacts_with_conversation_count = filtrate(contacts).left_outer_joins(:conversations)
|
|
|
|
.select('contacts.*, COUNT(conversations.id) as conversations_count')
|
|
|
|
.group('contacts.id')
|
|
|
|
.includes([{ avatar_attachment: [:blob] }])
|
|
|
|
.page(@current_page).per(RESULTS_PER_PAGE)
|
|
|
|
|
|
|
|
return contacts_with_conversation_count.includes([{ contact_inboxes: [:inbox] }]) if @include_contact_inboxes
|
|
|
|
|
|
|
|
contacts_with_conversation_count
|
2020-11-10 09:55:26 +00:00
|
|
|
end
|
2019-08-14 09:48:44 +00:00
|
|
|
|
2020-07-21 06:45:24 +00:00
|
|
|
def build_contact_inbox
|
|
|
|
return if params[:inbox_id].blank?
|
|
|
|
|
2020-08-10 06:45:29 +00:00
|
|
|
inbox = Current.account.inboxes.find(params[:inbox_id])
|
2020-07-21 06:45:24 +00:00
|
|
|
source_id = params[:source_id] || SecureRandom.uuid
|
|
|
|
ContactInbox.create(contact: @contact, inbox: inbox, source_id: source_id)
|
|
|
|
end
|
|
|
|
|
2022-07-12 08:03:16 +00:00
|
|
|
def permitted_params
|
|
|
|
params.permit(:name, :identifier, :email, :phone_number, :avatar, :avatar_url, additional_attributes: {}, custom_attributes: {})
|
2019-08-14 09:48:44 +00:00
|
|
|
end
|
|
|
|
|
2020-08-21 14:00:27 +00:00
|
|
|
def contact_custom_attributes
|
2022-07-12 08:03:16 +00:00
|
|
|
return @contact.custom_attributes.merge(permitted_params[:custom_attributes]) if permitted_params[:custom_attributes]
|
2020-08-21 14:00:27 +00:00
|
|
|
|
|
|
|
@contact.custom_attributes
|
2019-08-14 09:48:44 +00:00
|
|
|
end
|
|
|
|
|
2020-08-21 14:00:27 +00:00
|
|
|
def contact_update_params
|
|
|
|
# we want the merged custom attributes not the original one
|
2022-07-12 08:03:16 +00:00
|
|
|
permitted_params.except(:custom_attributes, :avatar_url).merge({ custom_attributes: contact_custom_attributes })
|
2020-08-21 14:00:27 +00:00
|
|
|
end
|
|
|
|
|
2021-07-23 13:09:24 +00:00
|
|
|
def set_include_contact_inboxes
|
|
|
|
@include_contact_inboxes = if params[:include_contact_inboxes].present?
|
|
|
|
params[:include_contact_inboxes] == 'true'
|
|
|
|
else
|
|
|
|
true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-08-21 14:00:27 +00:00
|
|
|
def fetch_contact
|
2020-09-19 07:16:34 +00:00
|
|
|
@contact = Current.account.contacts.includes(contact_inboxes: [:inbox]).find(params[:id])
|
2019-08-14 09:48:44 +00:00
|
|
|
end
|
2021-09-23 07:22:49 +00:00
|
|
|
|
2022-07-12 08:03:16 +00:00
|
|
|
def process_avatar
|
|
|
|
if permitted_params[:avatar].blank? && permitted_params[:avatar_url].present?
|
|
|
|
::ContactAvatarJob.perform_later(@contact, params[:avatar_url])
|
|
|
|
elsif permitted_params[:avatar].blank? && permitted_params[:email].present?
|
|
|
|
hash = Digest::MD5.hexdigest(params[:email])
|
|
|
|
gravatar_url = "https://www.gravatar.com/avatar/#{hash}?d=404"
|
|
|
|
::ContactAvatarJob.perform_later(@contact, gravatar_url)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-09-23 07:22:49 +00:00
|
|
|
def render_error(error, error_status)
|
|
|
|
render json: error, status: error_status
|
|
|
|
end
|
2019-10-20 08:47:26 +00:00
|
|
|
end
|