Merge branch 'feat/whatsapp-call-meta-bridge' into feat/whatsapp-call-ui

# Conflicts:
#	app/services/base/send_on_channel_service.rb
#	enterprise/app/controllers/api/v1/accounts/whatsapp_calls_controller.rb
#	enterprise/app/models/enterprise/concerns/attachment.rb
This commit is contained in:
Tanmay Deep Sharma 2026-05-04 20:51:43 +07:00
commit 41a7c88aef
3 changed files with 9 additions and 8 deletions

View File

@ -112,9 +112,8 @@ class Api::V1::Accounts::WhatsappCallsController < Api::V1::Accounts::BaseContro
)
end
# 138006 = no call permission yet; send opt-in template (throttled) and surface state to FE.
# Lock the conversation so concurrent initiate requests can't both pass the throttle gate
# and double-send the opt-in template.
# Meta error 138006 means the contact hasn't opted in yet; send the opt-in
# template (throttled, behind a conversation lock to prevent double-send).
def render_permission_request
status = nil
@conversation.with_lock do
@ -142,8 +141,7 @@ class Api::V1::Accounts::WhatsappCallsController < Api::V1::Accounts::BaseContro
last_requested.present? && Time.zone.parse(last_requested) > PERMISSION_REQUEST_THROTTLE.ago
end
# Treat transport errors the same as a falsy provider return so the action renders 422
# rather than letting Faraday/HTTParty exceptions bubble up as 500s.
# Treat transport errors as a falsy return so we render 422 rather than 500.
def send_permission_request_safely
provider_service.send_call_permission_request(@conversation.contact.phone_number.delete('+'))
rescue StandardError => e
@ -151,7 +149,7 @@ class Api::V1::Accounts::WhatsappCallsController < Api::V1::Accounts::BaseContro
nil
end
# Record the wamid so the reply webhook can match context.id back to this conversation.
# Stash the outbound wamid so the reply webhook can match context.id back here.
def record_permission_request_wamid(sent)
attrs = (@conversation.additional_attributes || {}).merge(
'call_permission_requested_at' => Time.current.iso8601,

View File

@ -29,9 +29,7 @@
# index_calls_on_provider_and_provider_call_id (provider,provider_call_id) UNIQUE
#
class Call < ApplicationRecord
# All valid call statuses
STATUSES = %w[ringing in_progress completed no_answer failed].freeze
# Statuses where the call is finished and won't change again
TERMINAL_STATUSES = %w[completed no_answer failed].freeze
store_accessor :meta, :conference_sid, :twilio_conference_sid, :recording_sid, :parent_call_sid, :initiated_at, :ended_at

View File

@ -14,6 +14,7 @@ module Enterprise::Concerns::Attachment
def enqueue_audio_transcription
return unless file_type.to_sym == :audio
return unless file.attached?
Messages::AudioTranscriptionJob.perform_later(id)
end
@ -21,6 +22,10 @@ module Enterprise::Concerns::Attachment
def broadcast_message_update_for_audio
return unless file_type.to_sym == :audio
return unless message
# Without an attached file, the message serializer's audio_metadata path
# dereferences `file.metadata[:width]` on nil and raises. The pre-attach
# broadcast wouldn't carry useful audio info anyway — skip until upload completes.
return unless file.attached?
message.reload.send_update_event
end