diff --git a/enterprise/app/controllers/api/v1/accounts/whatsapp_calls_controller.rb b/enterprise/app/controllers/api/v1/accounts/whatsapp_calls_controller.rb index b83723f84..8a7912425 100644 --- a/enterprise/app/controllers/api/v1/accounts/whatsapp_calls_controller.rb +++ b/enterprise/app/controllers/api/v1/accounts/whatsapp_calls_controller.rb @@ -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, diff --git a/enterprise/app/models/call.rb b/enterprise/app/models/call.rb index b0d8bc3d1..f8c0580f8 100644 --- a/enterprise/app/models/call.rb +++ b/enterprise/app/models/call.rb @@ -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 diff --git a/enterprise/app/models/enterprise/concerns/attachment.rb b/enterprise/app/models/enterprise/concerns/attachment.rb index 24cc338cd..06b8b641a 100644 --- a/enterprise/app/models/enterprise/concerns/attachment.rb +++ b/enterprise/app/models/enterprise/concerns/attachment.rb @@ -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