This PR add the backend changes for the feature [sending CSAT surveys via WhatsApp message templates ](https://github.com/chatwoot/chatwoot/pull/12787) --------- Co-authored-by: Vinay Keerthi <11478411+stonecharioteer@users.noreply.github.com>
161 lines
5.4 KiB
Ruby
161 lines
5.4 KiB
Ruby
class Api::V1::Accounts::InboxCsatTemplatesController < Api::V1::Accounts::BaseController
|
|
DEFAULT_BUTTON_TEXT = 'Please rate us'.freeze
|
|
DEFAULT_LANGUAGE = 'en'.freeze
|
|
|
|
before_action :fetch_inbox
|
|
before_action :validate_whatsapp_channel
|
|
|
|
def show
|
|
template = @inbox.csat_config&.dig('template')
|
|
return render json: { template_exists: false } unless template
|
|
|
|
template_name = template['name'] || Whatsapp::CsatTemplateNameService.csat_template_name(@inbox.id)
|
|
status_result = @inbox.channel.provider_service.get_template_status(template_name)
|
|
|
|
render_template_status_response(status_result, template_name)
|
|
rescue StandardError => e
|
|
Rails.logger.error "Error fetching CSAT template status: #{e.message}"
|
|
render json: { error: e.message }, status: :internal_server_error
|
|
end
|
|
|
|
def create
|
|
template_params = extract_template_params
|
|
return render_missing_message_error if template_params[:message].blank?
|
|
|
|
# Delete existing template even though we are using a new one.
|
|
# We don't want too many templates in the business portfolio, but the create operation shouldn't fail if deletion fails.
|
|
delete_existing_template_if_needed
|
|
|
|
result = create_template_via_provider(template_params)
|
|
render_template_creation_result(result)
|
|
rescue ActionController::ParameterMissing
|
|
render json: { error: 'Template parameters are required' }, status: :unprocessable_entity
|
|
rescue StandardError => e
|
|
Rails.logger.error "Error creating CSAT template: #{e.message}"
|
|
render json: { error: 'Template creation failed' }, status: :internal_server_error
|
|
end
|
|
|
|
private
|
|
|
|
def fetch_inbox
|
|
@inbox = Current.account.inboxes.find(params[:inbox_id])
|
|
authorize @inbox, :show?
|
|
end
|
|
|
|
def validate_whatsapp_channel
|
|
return if @inbox.whatsapp?
|
|
|
|
render json: { error: 'CSAT template operations only available for WhatsApp channels' },
|
|
status: :bad_request
|
|
end
|
|
|
|
def extract_template_params
|
|
params.require(:template).permit(:message, :button_text, :language)
|
|
end
|
|
|
|
def render_missing_message_error
|
|
render json: { error: 'Message is required' }, status: :unprocessable_entity
|
|
end
|
|
|
|
def create_template_via_provider(template_params)
|
|
template_config = {
|
|
message: template_params[:message],
|
|
button_text: template_params[:button_text] || DEFAULT_BUTTON_TEXT,
|
|
base_url: ENV.fetch('FRONTEND_URL', 'http://localhost:3000'),
|
|
language: template_params[:language] || DEFAULT_LANGUAGE,
|
|
template_name: Whatsapp::CsatTemplateNameService.csat_template_name(@inbox.id)
|
|
}
|
|
|
|
@inbox.channel.provider_service.create_csat_template(template_config)
|
|
end
|
|
|
|
def render_template_creation_result(result)
|
|
if result[:success]
|
|
render_successful_template_creation(result)
|
|
else
|
|
render_failed_template_creation(result)
|
|
end
|
|
end
|
|
|
|
def render_successful_template_creation(result)
|
|
render json: {
|
|
template: {
|
|
name: result[:template_name],
|
|
template_id: result[:template_id],
|
|
status: 'PENDING',
|
|
language: result[:language] || DEFAULT_LANGUAGE
|
|
}
|
|
}, status: :created
|
|
end
|
|
|
|
def render_failed_template_creation(result)
|
|
whatsapp_error = parse_whatsapp_error(result[:response_body])
|
|
error_message = whatsapp_error[:user_message] || result[:error]
|
|
|
|
render json: {
|
|
error: error_message,
|
|
details: whatsapp_error[:technical_details]
|
|
}, status: :unprocessable_entity
|
|
end
|
|
|
|
def delete_existing_template_if_needed
|
|
template = @inbox.csat_config&.dig('template')
|
|
return true if template.blank?
|
|
|
|
template_name = template['name']
|
|
return true if template_name.blank?
|
|
|
|
template_status = @inbox.channel.provider_service.get_template_status(template_name)
|
|
return true unless template_status[:success]
|
|
|
|
deletion_result = @inbox.channel.provider_service.delete_csat_template(template_name)
|
|
if deletion_result[:success]
|
|
Rails.logger.info "Deleted existing CSAT template '#{template_name}' for inbox #{@inbox.id}"
|
|
true
|
|
else
|
|
Rails.logger.warn "Failed to delete existing CSAT template '#{template_name}' for inbox #{@inbox.id}: #{deletion_result[:response_body]}"
|
|
false
|
|
end
|
|
rescue StandardError => e
|
|
Rails.logger.error "Error during template deletion for inbox #{@inbox.id}: #{e.message}"
|
|
false
|
|
end
|
|
|
|
def render_template_status_response(status_result, template_name)
|
|
if status_result[:success]
|
|
render json: {
|
|
template_exists: true,
|
|
template_name: template_name,
|
|
status: status_result[:template][:status],
|
|
template_id: status_result[:template][:id]
|
|
}
|
|
else
|
|
render json: {
|
|
template_exists: false,
|
|
error: 'Template not found'
|
|
}
|
|
end
|
|
end
|
|
|
|
def parse_whatsapp_error(response_body)
|
|
return { user_message: nil, technical_details: nil } if response_body.blank?
|
|
|
|
begin
|
|
error_data = JSON.parse(response_body)
|
|
whatsapp_error = error_data['error'] || {}
|
|
|
|
user_message = whatsapp_error['error_user_msg'] || whatsapp_error['message']
|
|
technical_details = {
|
|
code: whatsapp_error['code'],
|
|
subcode: whatsapp_error['error_subcode'],
|
|
type: whatsapp_error['type'],
|
|
title: whatsapp_error['error_user_title']
|
|
}.compact
|
|
|
|
{ user_message: user_message, technical_details: technical_details }
|
|
rescue JSON::ParserError
|
|
{ user_message: nil, technical_details: response_body }
|
|
end
|
|
end
|
|
end
|