Files
chatwoot/app/models/concerns/activity_message_handler.rb
T
354c2cab6b fix(captain): handle resolved conversation context (#14433)
# Pull Request Template

## Description

Fixes: https://github.com/chatwoot/chatwoot/issues/13880

Uses approaches discussed from:
https://github.com/chatwoot/chatwoot/pull/13883

Activity messages pertaining to resolve are included along with an
instruction for the LLM to choose whether to consider them or not along

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.

locally and with specs


## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: Sony Mathew <sony@chatwoot.com>
2026-07-15 23:30:17 +05:30

126 lines
3.6 KiB
Ruby

module ActivityMessageHandler
extend ActiveSupport::Concern
include AssigneeActivityMessageHandler
include PriorityActivityMessageHandler
include LabelActivityMessageHandler
include SlaActivityMessageHandler
include TeamActivityMessageHandler
private
def create_activity
user_name = determine_user_name
handle_status_change(user_name)
handle_priority_change(user_name)
handle_label_change(user_name)
handle_sla_policy_change(user_name)
end
def determine_user_name
Current.user&.name
end
def handle_status_change(user_name)
return unless saved_change_to_status?
status_change_activity(user_name)
end
def handle_priority_change(user_name)
return unless saved_change_to_priority?
priority_change_activity(user_name)
end
def handle_label_change(user_name)
return unless saved_change_to_label_list?
create_label_change(activity_message_owner(user_name))
end
def handle_sla_policy_change(user_name)
return unless saved_change_to_sla_policy_id?
sla_change_type = determine_sla_change_type
create_sla_change_activity(sla_change_type, activity_message_owner(user_name))
end
def status_change_activity(user_name)
content = if Current.executed_by.present?
automation_status_change_activity_content
else
user_status_change_activity_content(user_name)
end
return if content.blank?
::Conversations::ActivityMessageJob.perform_later(
self,
activity_message_params(
content,
content_attributes: {
activity: {
type: 'conversation_status_changed',
status: status
}
}
)
)
end
def auto_resolve_message_key(minutes)
if minutes >= 1440 && (minutes % 1440).zero?
{ key: 'auto_resolved_days', count: minutes / 1440 }
elsif minutes >= 60 && (minutes % 60).zero?
{ key: 'auto_resolved_hours', count: minutes / 60 }
else
{ key: 'auto_resolved_minutes', count: minutes }
end
end
def user_status_change_activity_content(user_name)
if user_name
I18n.t("conversations.activity.status.#{status}", user_name: user_name)
elsif Current.contact.present? && resolved?
I18n.t('conversations.activity.status.contact_resolved', contact_name: Current.contact.name.capitalize)
elsif resolved?
message_data = auto_resolve_message_key(auto_resolve_after || 0)
I18n.t("conversations.activity.status.#{message_data[:key]}", count: message_data[:count])
end
end
def automation_status_change_activity_content
if Current.executed_by.instance_of?(AutomationRule)
I18n.t("conversations.activity.status.#{status}", user_name: I18n.t('automation.system_name'))
elsif Current.executed_by.instance_of?(Contact)
Current.executed_by = nil
I18n.t('conversations.activity.status.system_auto_open')
end
end
def activity_message_params(content, content_attributes: nil)
params = { account_id: account_id, inbox_id: inbox_id, message_type: :activity, content: content }
params[:content_attributes] = content_attributes if content_attributes.present?
params
end
def create_muted_message
create_mute_change_activity('muted')
end
def create_unmuted_message
create_mute_change_activity('unmuted')
end
def create_mute_change_activity(change_type)
return unless Current.user
content = I18n.t("conversations.activity.#{change_type}", user_name: Current.user.name)
::Conversations::ActivityMessageJob.perform_later(self, activity_message_params(content)) if content
end
end
ActivityMessageHandler.prepend_mod_with('ActivityMessageHandler')