From 2f36c3be9c020ece7bcc99deab581d0ee34d9898 Mon Sep 17 00:00:00 2001 From: Tanmay Deep Sharma Date: Wed, 20 May 2026 16:39:49 +0530 Subject: [PATCH] fix(voice): require embedded-signup cloud inbox to toggle WhatsApp calling --- app/models/channel/whatsapp.rb | 14 ++++++++++---- .../api/v1/accounts/inboxes_controller.rb | 18 ++++++++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/app/models/channel/whatsapp.rb b/app/models/channel/whatsapp.rb index d157baab0..d64873208 100644 --- a/app/models/channel/whatsapp.rb +++ b/app/models/channel/whatsapp.rb @@ -44,12 +44,18 @@ class Channel::Whatsapp < ApplicationRecord # Meta's Calling API is only available via the embedded-signup whatsapp_cloud flow — # 360dialog (default provider) and manual whatsapp_cloud setups can't reach the call APIs. def voice_enabled? - provider == 'whatsapp_cloud' && - provider_config['source'] == 'embedded_signup' && + voice_calling_supported? && provider_config['calling_enabled'].present? && account.feature_enabled?('channel_voice') end + # Whether this inbox can do WhatsApp calling at all. Meta's Calling API is only + # reachable via the embedded-signup whatsapp_cloud flow, so manual whatsapp_cloud + # and 360dialog inboxes can't be toggled on even though calling_enabled would persist. + def voice_calling_supported? + provider == 'whatsapp_cloud' && provider_config['source'] == 'embedded_signup' + end + def provider_service if provider == 'whatsapp_cloud' Whatsapp::Providers::WhatsappCloudService.new(whatsapp_channel: self) @@ -63,7 +69,7 @@ class Channel::Whatsapp < ApplicationRecord # Saved with validate: false to skip validate_provider_config's remote credential # re-check, which could spuriously fail and desync the flag from Meta. def enable_voice_calling! - raise 'Voice calling is only supported on whatsapp_cloud channels' unless provider == 'whatsapp_cloud' + raise 'WhatsApp calling requires an embedded-signup whatsapp_cloud inbox' unless voice_calling_supported? provider_service.update_calling_status('ENABLED') webhook_setup_service.register_callback @@ -75,7 +81,7 @@ class Channel::Whatsapp < ApplicationRecord # `calls` from the webhook subscription (best-effort, so a Meta outage can't # trap admins). Leaves Meta's WABA calling.status untouched. def disable_voice_calling! - raise 'Voice calling is only supported on whatsapp_cloud channels' unless provider == 'whatsapp_cloud' + raise 'WhatsApp calling requires an embedded-signup whatsapp_cloud inbox' unless voice_calling_supported? self.provider_config = provider_config.merge('calling_enabled' => false) save!(validate: false) diff --git a/enterprise/app/controllers/enterprise/api/v1/accounts/inboxes_controller.rb b/enterprise/app/controllers/enterprise/api/v1/accounts/inboxes_controller.rb index 30806e326..76f578bf1 100644 --- a/enterprise/app/controllers/enterprise/api/v1/accounts/inboxes_controller.rb +++ b/enterprise/app/controllers/enterprise/api/v1/accounts/inboxes_controller.rb @@ -4,20 +4,18 @@ module Enterprise::Api::V1::Accounts::InboxesController end def enable_whatsapp_calling - channel = @inbox.channel - return render_could_not_create_error('Not a WhatsApp Cloud inbox') unless channel.is_a?(Channel::Whatsapp) && channel.provider == 'whatsapp_cloud' + return unless ensure_whatsapp_calling_supported - channel.enable_voice_calling! + @inbox.channel.enable_voice_calling! head :ok rescue StandardError => e render_could_not_create_error(e.message) end def disable_whatsapp_calling - channel = @inbox.channel - return render_could_not_create_error('Not a WhatsApp Cloud inbox') unless channel.is_a?(Channel::Whatsapp) && channel.provider == 'whatsapp_cloud' + return unless ensure_whatsapp_calling_supported - channel.disable_voice_calling! + @inbox.channel.disable_voice_calling! head :ok rescue StandardError => e render_could_not_create_error(e.message) @@ -29,6 +27,14 @@ module Enterprise::Api::V1::Accounts::InboxesController private + def ensure_whatsapp_calling_supported + channel = @inbox.channel + return true if channel.is_a?(Channel::Whatsapp) && channel.voice_calling_supported? + + render_could_not_create_error('Inbox does not support WhatsApp calling') + false + end + def allowed_channel_types super + ['voice'] end