feat: Conversation workflow backend changes (#13070)

Extracted the backend changes from
https://github.com/chatwoot/chatwoot/pull/13040

- Added the support for saving `conversation_required_attributes` in
account
- Delete `conversation_required_attributes` if custom attribute deleted.

Co-authored-by: Vinay Keerthi <11478411+stonecharioteer@users.noreply.github.com>
This commit is contained in:
Muhsin Keloth
2025-12-16 14:43:15 +05:30
committed by GitHub
parent 02216471c3
commit 0d490640f2
4 changed files with 65 additions and 3 deletions

View File

@@ -92,7 +92,8 @@ class Api::V1::AccountsController < Api::BaseController
end
def settings_params
params.permit(:auto_resolve_after, :auto_resolve_message, :auto_resolve_ignore_waiting, :audio_transcriptions, :auto_resolve_label)
params.permit(:auto_resolve_after, :auto_resolve_message, :auto_resolve_ignore_waiting, :audio_transcriptions, :auto_resolve_label,
conversation_required_attributes: [])
end
def check_signup_enabled

View File

@@ -37,7 +37,11 @@ class Account < ApplicationRecord
'auto_resolve_message': { 'type': %w[string null] },
'auto_resolve_ignore_waiting': { 'type': %w[boolean null] },
'audio_transcriptions': { 'type': %w[boolean null] },
'auto_resolve_label': { 'type': %w[string null] }
'auto_resolve_label': { 'type': %w[string null] },
'conversation_required_attributes': {
'type': %w[array null],
'items': { 'type': 'string' }
}
},
'required': [],
'additionalProperties': true
@@ -55,7 +59,7 @@ class Account < ApplicationRecord
attribute_resolver: ->(record) { record.settings }
store_accessor :settings, :auto_resolve_after, :auto_resolve_message, :auto_resolve_ignore_waiting
store_accessor :settings, :audio_transcriptions, :auto_resolve_label
store_accessor :settings, :audio_transcriptions, :auto_resolve_label, :conversation_required_attributes
has_many :account_users, dependent: :destroy_async
has_many :agent_bot_inboxes, dependent: :destroy_async

View File

@@ -45,6 +45,7 @@ class CustomAttributeDefinition < ApplicationRecord
belongs_to :account
after_update :update_widget_pre_chat_custom_fields
after_destroy :sync_widget_pre_chat_custom_fields
after_destroy :cleanup_conversation_required_attributes
private
@@ -56,6 +57,13 @@ class CustomAttributeDefinition < ApplicationRecord
::Inboxes::UpdateWidgetPreChatCustomFieldsJob.perform_later(account, self)
end
def cleanup_conversation_required_attributes
return unless conversation_attribute? && account.conversation_required_attributes&.include?(attribute_key)
account.conversation_required_attributes = account.conversation_required_attributes - [attribute_key]
account.save!
end
def attribute_must_not_conflict
model_keys = attribute_model.to_sym == :conversation_attribute ? :conversation : :contact
return unless attribute_key.in?(STANDARD_ATTRIBUTES[model_keys])

View File

@@ -0,0 +1,49 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe CustomAttributeDefinition do
describe 'callbacks' do
describe '#cleanup_conversation_required_attributes' do
let(:account) { create(:account) }
let(:attribute_key) { 'test_attribute' }
let!(:custom_attribute) do
create(:custom_attribute_definition,
account: account,
attribute_key: attribute_key,
attribute_model: 'conversation_attribute')
end
context 'when conversation attribute is in required attributes list' do
before do
account.update!(conversation_required_attributes: [attribute_key, 'other_attribute'])
end
it 'removes the attribute from conversation_required_attributes when destroyed' do
expect { custom_attribute.destroy! }
.to change { account.reload.conversation_required_attributes }
.from([attribute_key, 'other_attribute'])
.to(['other_attribute'])
end
end
context 'when attribute is contact_attribute' do
let!(:contact_attribute) do
create(:custom_attribute_definition,
account: account,
attribute_key: attribute_key,
attribute_model: 'contact_attribute')
end
before do
account.update!(conversation_required_attributes: [attribute_key])
end
it 'does not modify conversation_required_attributes when destroyed' do
expect { contact_attribute.destroy! }
.not_to(change { account.reload.conversation_required_attributes })
end
end
end
end
end