From c6e5657ee52192112c9913d1de797bcd86b5be8a Mon Sep 17 00:00:00 2001 From: Tanmay Deep Sharma <32020192+tds-1@users.noreply.github.com> Date: Thu, 11 Jun 2026 11:16:41 +0530 Subject: [PATCH] fix(call): emit assignee activity message when agent answers a call (#14700) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Linear Ticket - https://linear.app/chatwoot/issue/CW-7249/debug-assignment-log ## Description When an agent answers an inbound WhatsApp call on an unassigned conversation, the conversation is claimed for that agent — but no "assigned" activity message or assignee-changed event was emitted, so the assignment was invisible in the timeline (and notifications/live assignee panel didn't update). The claim ran before `update_conversation_call_status`, so that later `update!` on the same conversation clobbered `saved_change_to_assignee_id?` before `after_commit` fired. Moving the claim to be the conversation's final write in the transaction restores the activity message, the `ASSIGNEE_CHANGED` event, and the live assignee update. ## Type of change - [ ] Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? 1. Open an unassigned WhatsApp-call conversation. 2. As an agent, answer an inbound call. 3. Before: the conversation is assigned to you, but no "self-assigned" activity message appears. After: the activity message is created and the assignee updates live. ## Checklist: - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my code - [ ] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules --- enterprise/app/services/whatsapp/call_service.rb | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/enterprise/app/services/whatsapp/call_service.rb b/enterprise/app/services/whatsapp/call_service.rb index 93eba957c..743409839 100644 --- a/enterprise/app/services/whatsapp/call_service.rb +++ b/enterprise/app/services/whatsapp/call_service.rb @@ -9,7 +9,7 @@ class Whatsapp::CallService call.with_lock do transition_to_in_progress! update_message_status('in_progress') - update_conversation_call_status(call.display_status) + claim_conversation_and_set_call_status broadcast(:accepted, accepted_by_agent_id: agent.id) end call @@ -56,7 +56,6 @@ class Whatsapp::CallService forward_answer_to_meta! call.update!(status: 'in_progress', accepted_by_agent_id: agent.id, started_at: Time.current, meta: (call.meta || {}).merge('sdp_answer' => sdp_answer)) - claim_conversation_for_agent end def forward_answer_to_meta! @@ -64,9 +63,13 @@ class Whatsapp::CallService invoke_provider!(:accept_call, sdp_answer) end - # Take ownership of the conversation if no one holds it; leave assignee alone otherwise (transfer via UI). - def claim_conversation_for_agent - call.conversation.update!(assignee: agent) if call.conversation.assignee_id.blank? + # Claim an unheld conversation and set call_status in one save so previous_changes carries both the + # assignee change (activity message + ASSIGNEE_CHANGED) and the call_status change (conversation.updated webhook). + def claim_conversation_and_set_call_status + conversation = call.conversation + attrs = { additional_attributes: (conversation.additional_attributes || {}).merge('call_status' => call.display_status) } + attrs[:assignee] = agent if conversation.assignee_id.blank? + conversation.update!(attrs) end # Raise on Meta failure (bool false or transport error) so callers bail before