From 2c9208c6a2736393fbf24cc622ebb0246629d4e9 Mon Sep 17 00:00:00 2001 From: Muhsin Date: Tue, 28 Oct 2025 15:50:23 +0530 Subject: [PATCH] feat: add create_csat_template api --- .../api/v1/accounts/inboxes_controller.rb | 122 +++++++++++------- .../settingsPage/components/CSATTemplate.vue | 28 ++++ app/policies/inbox_policy.rb | 8 ++ .../providers/whatsapp_cloud_service.rb | 6 +- config/routes.rb | 1 + 5 files changed, 113 insertions(+), 52 deletions(-) create mode 100644 app/javascript/dashboard/routes/dashboard/settings/inbox/settingsPage/components/CSATTemplate.vue diff --git a/app/controllers/api/v1/accounts/inboxes_controller.rb b/app/controllers/api/v1/accounts/inboxes_controller.rb index afc961d58..11e661784 100644 --- a/app/controllers/api/v1/accounts/inboxes_controller.rb +++ b/app/controllers/api/v1/accounts/inboxes_controller.rb @@ -44,11 +44,7 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController def update inbox_params = permitted_params.except(:channel, :csat_config) - - if permitted_params[:csat_config].present? - inbox_params[:csat_config] = format_csat_config(permitted_params[:csat_config]) - handle_whatsapp_csat_template_update(inbox_params[:csat_config]) if @inbox.whatsapp? - end + inbox_params[:csat_config] = format_csat_config(permitted_params[:csat_config]) if permitted_params[:csat_config].present? @inbox.update!(inbox_params) update_inbox_working_hours @@ -116,8 +112,71 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController render json: { error: e.message }, status: :internal_server_error end + def create_csat_template + unless @inbox.whatsapp? + return render json: { error: 'CSAT template creation only available for WhatsApp channels' }, + status: :unprocessable_content + end + + template_params = params.require(:template).permit(:message, :button_text) + return render json: { error: 'Message is required' }, status: :unprocessable_content if template_params[:message].blank? + + template_config = { + message: template_params[:message], + button_text: template_params[:button_text] || 'Please rate us', + base_url: ENV.fetch('FRONTEND_URL', 'http://localhost:3000'), + language: 'en' + } + + result = @inbox.channel.provider_service.create_csat_template(template_config) + + if result[:success] + render json: { + template: { + name: 'customer_satisfaction_survey', + template_id: result[:template_id], + status: 'PENDING', + language: 'en' + } + }, status: :created + else + # Parse WhatsApp error details for user-friendly message + whatsapp_error = parse_whatsapp_error(result[:response_body]) + render json: { + error: whatsapp_error[:user_message] || result[:error], + details: whatsapp_error[:technical_details] + }, status: :unprocessable_content + end + rescue ActionController::ParameterMissing + render json: { error: 'Template parameters are required' }, status: :unprocessable_content + 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 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 + def fetch_inbox @inbox = Current.account.inboxes.find(params[:id]) authorize @inbox, :show? @@ -180,56 +239,19 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController @inbox.channel.save! end - def handle_whatsapp_csat_template_update(csat_config) - return unless @inbox.channel.is_a?(Channel::Whatsapp) - return if csat_config[:message].blank? - - # Check if message has changed or template doesn't exist - existing_message = @inbox.csat_config&.dig('message') - template_exists = @inbox.csat_config&.dig('template').present? - - create_whatsapp_csat_template(csat_config) if !template_exists || existing_message != csat_config[:message] - rescue StandardError => e - Rails.logger.error "Error handling WhatsApp CSAT template update: #{e.message}" - # Don't fail the entire update if template creation fails - end - - def create_whatsapp_csat_template(csat_config) - template_config = { - message: csat_config[:message], - button_text: 'Please rate us', - base_url: ENV.fetch('FRONTEND_URL', 'http://localhost:3000'), - language: 'en' - } - - result = @inbox.channel.provider_service.create_csat_template(template_config) - - if result[:success] - # Add template info to csat_config - csat_config[:template] = { - name: 'customer_satisfaction_survey', - template_id: result[:template_id], - created_at: Time.current.iso8601, - language: 'en' - } - Rails.logger.info "WhatsApp CSAT template created successfully for inbox #{@inbox.id}" - else - Rails.logger.error "Failed to create WhatsApp CSAT template: #{result[:error]}" - end - end - def format_csat_config(config) formatted = { - display_type: config['display_type'] || 'emoji', - message: config['message'] || '', - survey_rules: { - operator: config.dig('survey_rules', 'operator') || 'contains', - values: config.dig('survey_rules', 'values') || [] + 'display_type' => config['display_type'] || 'emoji', + 'message' => config['message'] || '', + 'button_text' => config['button_text'] || 'Please rate us', + 'survey_rules' => { + 'operator' => config.dig('survey_rules', 'operator') || 'contains', + 'values' => config.dig('survey_rules', 'values') || [] } } # Preserve existing template config if present - formatted[:template] = config['template'] if config['template'].present? + formatted['template'] = config['template'] if config['template'].present? formatted end @@ -238,7 +260,7 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController [:name, :avatar, :greeting_enabled, :greeting_message, :enable_email_collect, :csat_survey_enabled, :enable_auto_assignment, :working_hours_enabled, :out_of_office_message, :timezone, :allow_messages_after_resolved, :lock_to_single_conversation, :portal_id, :sender_name_type, :business_name, - { csat_config: [:display_type, :message, + { csat_config: [:display_type, :message, :button_text, { survey_rules: [:operator, { values: [] }], template: [:name, :template_id, :created_at, :language] }] }] end diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/settingsPage/components/CSATTemplate.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/settingsPage/components/CSATTemplate.vue new file mode 100644 index 000000000..d1c9ebb37 --- /dev/null +++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/settingsPage/components/CSATTemplate.vue @@ -0,0 +1,28 @@ + + + diff --git a/app/policies/inbox_policy.rb b/app/policies/inbox_policy.rb index cace85e5e..56765cd0b 100644 --- a/app/policies/inbox_policy.rb +++ b/app/policies/inbox_policy.rb @@ -65,4 +65,12 @@ class InboxPolicy < ApplicationPolicy def health? @account_user.administrator? end + + def csat_template_status? + @account_user.administrator? + end + + def create_csat_template? + @account_user.administrator? + end end diff --git a/app/services/whatsapp/providers/whatsapp_cloud_service.rb b/app/services/whatsapp/providers/whatsapp_cloud_service.rb index d81239080..edb5455c2 100644 --- a/app/services/whatsapp/providers/whatsapp_cloud_service.rb +++ b/app/services/whatsapp/providers/whatsapp_cloud_service.rb @@ -75,7 +75,7 @@ class Whatsapp::Providers::WhatsappCloudService < Whatsapp::Providers::BaseServi type: 'URL', text: template_config[:button_text] || 'Please rate us', url: "#{template_config[:base_url]}/survey/responses/{{1}}", - example: ['12345'] + example: ["#{template_config[:base_url]}/survey/responses/12345"] } ] } @@ -96,9 +96,11 @@ class Whatsapp::Providers::WhatsappCloudService < Whatsapp::Providers::BaseServi status: 'PENDING' } else + Rails.logger.error "WhatsApp template creation failed: #{response.code} - #{response.body}" { success: false, - error: error_message(response) || 'Failed to create template' + error: error_message(response) || "Failed to create template: #{response.code}", + response_body: response.body } end end diff --git a/config/routes.rb b/config/routes.rb index d044dde1f..4fae5fa6d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -197,6 +197,7 @@ Rails.application.routes.draw do post :sync_templates, on: :member get :health, on: :member get :csat_template_status, on: :member + post :create_csat_template, on: :member end resources :inbox_members, only: [:create, :show], param: :inbox_id do collection do