# Pull Request Template ## Description Blocked contacts are now excluded from SLA assignment, processing, reports, and conversation SLA UI while they remain blocked. Existing SLA records are preserved, and SLA behavior resumes if the contact is unblocked. Fixes https://linear.app/chatwoot/issue/CW-7435/sla-should-not-trigger-for-blocked-contacts ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? - `bundle exec rspec spec/enterprise/models/conversation_spec.rb spec/enterprise/models/applied_sla_spec.rb spec/enterprise/services/enterprise/action_service_spec.rb spec/enterprise/services/sla/evaluate_applied_sla_service_spec.rb spec/enterprise/jobs/sla/process_account_applied_slas_job_spec.rb spec/enterprise/controllers/api/v1/accounts/applied_slas_controller_spec.rb spec/enterprise/controllers/api/v1/accounts/conversations_controller_spec.rb spec/enterprise/controllers/enterprise/api/v1/accounts/conversations_controller_spec.rb spec/enterprise/presenters/conversations/event_data_presenter_spec.rb` — 78 examples, 0 failures - `bundle exec rubocop enterprise/app/controllers/api/v1/accounts/applied_slas_controller.rb enterprise/app/jobs/sla/process_account_applied_slas_job.rb enterprise/app/models/applied_sla.rb enterprise/app/models/enterprise/concerns/conversation.rb enterprise/app/presenters/enterprise/conversations/event_data_presenter.rb enterprise/app/services/enterprise/action_service.rb enterprise/app/services/sla/evaluate_applied_sla_service.rb lib/tasks/apply_sla.rake spec/enterprise/controllers/api/v1/accounts/applied_slas_controller_spec.rb spec/enterprise/controllers/api/v1/accounts/conversations_controller_spec.rb spec/enterprise/controllers/enterprise/api/v1/accounts/conversations_controller_spec.rb spec/enterprise/jobs/sla/process_account_applied_slas_job_spec.rb spec/enterprise/models/applied_sla_spec.rb spec/enterprise/models/conversation_spec.rb spec/enterprise/presenters/conversations/event_data_presenter_spec.rb spec/enterprise/services/enterprise/action_service_spec.rb spec/enterprise/services/sla/evaluate_applied_sla_service_spec.rb` — no offenses - `pnpm exec vitest --no-watch --no-cache --no-coverage app/javascript/dashboard/components/widgets/conversation/specs/ConversationCard.spec.js` — 2 tests passed - `pnpm exec eslint app/javascript/dashboard/components-next/Conversation/ConversationCard/CardMessagePreviewWithMeta.vue app/javascript/dashboard/components-next/Conversation/ConversationCard/ConversationCardExpanded.vue app/javascript/dashboard/components/widgets/conversation/ConversationCard.vue app/javascript/dashboard/components/widgets/conversation/ConversationHeader.vue app/javascript/dashboard/components/widgets/conversation/specs/ConversationCard.spec.js` — passed with existing raw-text warnings in `ConversationHeader.vue` - `git diff --cached --check` — clean ## Checklist: - [x] My code follows the style guidelines of this project - [x] 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 - [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 - [ ] Any dependent changes have been merged and published in downstream modules --------- Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
103 lines
4.1 KiB
Ruby
103 lines
4.1 KiB
Ruby
# Apply SLA Policy to Conversations
|
|
#
|
|
# This task applies an SLA policy to existing conversations that don't have one assigned.
|
|
# It processes conversations in batches and only affects conversations with sla_policy_id = nil.
|
|
#
|
|
# Usage Examples:
|
|
# # Using arguments (may need escaping in some shells)
|
|
# bundle exec rake "sla:apply_to_conversations[19,1,500]"
|
|
#
|
|
# # Using environment variables (recommended)
|
|
# SLA_POLICY_ID=19 ACCOUNT_ID=1 BATCH_SIZE=500 bundle exec rake sla:apply_to_conversations
|
|
#
|
|
# Parameters:
|
|
# SLA_POLICY_ID: ID of the SLA policy to apply (required)
|
|
# ACCOUNT_ID: ID of the account (required)
|
|
# BATCH_SIZE: Number of conversations to process (default: 1000)
|
|
#
|
|
# Notes:
|
|
# - Only runs in development environment
|
|
# - Processes conversations in order of newest first (id DESC)
|
|
# - Safe to run multiple times - skips conversations that already have SLA policies
|
|
# - Creates AppliedSla records automatically via Rails callbacks
|
|
# - SlaEvent records are created later by background jobs when violations occur
|
|
#
|
|
# rubocop:disable Metrics/BlockLength
|
|
namespace :sla do
|
|
desc 'Apply SLA policy to existing conversations'
|
|
task :apply_to_conversations, [:sla_policy_id, :account_id, :batch_size] => :environment do |_t, args|
|
|
unless Rails.env.development?
|
|
puts 'This task can only be run in the development environment.'
|
|
puts "Current environment: #{Rails.env}"
|
|
exit(1)
|
|
end
|
|
|
|
sla_policy_id = args[:sla_policy_id] || ENV.fetch('SLA_POLICY_ID', nil)
|
|
account_id = args[:account_id] || ENV.fetch('ACCOUNT_ID', nil)
|
|
batch_size = (args[:batch_size] || ENV['BATCH_SIZE'] || 1000).to_i
|
|
|
|
if sla_policy_id.blank?
|
|
puts 'Error: SLA_POLICY_ID is required'
|
|
puts 'Usage: bundle exec rake sla:apply_to_conversations[sla_policy_id,account_id,batch_size]'
|
|
puts 'Or: SLA_POLICY_ID=1 ACCOUNT_ID=1 BATCH_SIZE=500 bundle exec rake sla:apply_to_conversations'
|
|
exit(1)
|
|
end
|
|
|
|
if account_id.blank?
|
|
puts 'Error: ACCOUNT_ID is required'
|
|
puts 'Usage: bundle exec rake sla:apply_to_conversations[sla_policy_id,account_id,batch_size]'
|
|
puts 'Or: SLA_POLICY_ID=1 ACCOUNT_ID=1 BATCH_SIZE=500 bundle exec rake sla:apply_to_conversations'
|
|
exit(1)
|
|
end
|
|
|
|
account = Account.find_by(id: account_id)
|
|
unless account
|
|
puts "Error: Account with ID #{account_id} not found"
|
|
exit(1)
|
|
end
|
|
|
|
sla_policy = account.sla_policies.find_by(id: sla_policy_id)
|
|
unless sla_policy
|
|
puts "Error: SLA Policy with ID #{sla_policy_id} not found for Account #{account_id}"
|
|
exit(1)
|
|
end
|
|
|
|
conversations = account.conversations.where(sla_policy_id: nil)
|
|
conversations = conversations.with_sla_applicable_contact if conversations.respond_to?(:with_sla_applicable_contact)
|
|
conversations = conversations.order(id: :desc).limit(batch_size)
|
|
total_count = conversations.count
|
|
|
|
if total_count.zero?
|
|
puts 'No conversations found without SLA policy'
|
|
exit(0)
|
|
end
|
|
|
|
puts "Applying SLA Policy '#{sla_policy.name}' (ID: #{sla_policy_id}) to #{total_count} conversations in Account #{account_id}"
|
|
puts "Processing in batches of #{batch_size}"
|
|
puts "Started at: #{Time.current}"
|
|
|
|
start_time = Time.current
|
|
processed_count = 0
|
|
error_count = 0
|
|
|
|
conversations.find_in_batches(batch_size: batch_size) do |batch|
|
|
batch.each do |conversation|
|
|
conversation.update!(sla_policy_id: sla_policy_id)
|
|
processed_count += 1
|
|
puts "Processed #{processed_count}/#{total_count} conversations" if (processed_count % 100).zero?
|
|
rescue StandardError => e
|
|
error_count += 1
|
|
puts "Error applying SLA to conversation #{conversation.id}: #{e.message}"
|
|
end
|
|
end
|
|
|
|
elapsed_time = Time.current - start_time
|
|
puts "\nCompleted!"
|
|
puts "Successfully processed: #{processed_count} conversations"
|
|
puts "Errors encountered: #{error_count}" if error_count.positive?
|
|
puts "Total time: #{elapsed_time.round(2)}s"
|
|
puts "Average time per conversation: #{(elapsed_time / processed_count).round(3)}s" if processed_count.positive?
|
|
end
|
|
end
|
|
# rubocop:enable Metrics/BlockLength
|