mirror of
https://github.com/chatwoot/chatwoot.git
synced 2026-06-13 21:01:16 +08:00
## Summary - Remove label deletion dependency on association cleanup by deleting immediately and enqueueing a background job. - Add `Labels::RemoveAssociationsJob` to strip deleted label references from tagged conversations and contacts. - Keep this version simple by removing the label count/prompt requirement requested. ## Implementation notes - Enqueue job from `Api::V1::Accounts::LabelsController#destroy` with label title + account id. - Background work performed in `Labels::DestroyService`. ## References - Linear issue: https://linear.app/chatwoot/issue/CW-4765/cw-2857-enhancement-removing-labels-is-inconsistent - GitHub issue: https://github.com/chatwoot/chatwoot/issues/1249 ## Testing - `bundle exec rspec spec/controllers/api/v1/accounts/labels_controller_spec.rb spec/services/labels/destroy_service_spec.rb spec/jobs/labels/remove_associations_job_spec.rb spec/services/labels/update_service_spec.rb` - `bundle exec rubocop app/controllers/api/v1/accounts/labels_controller.rb app/jobs/labels/remove_associations_job.rb spec/controllers/api/v1/accounts/labels_controller_spec.rb spec/jobs/labels/remove_associations_job_spec.rb spec/services/labels/destroy_service_spec.rb` --------- Co-authored-by: Sony Mathew <sony@chatwoot.com> Co-authored-by: Sony Mathew <2040199+sony-mathew@users.noreply.github.com>
61 lines
1.8 KiB
Ruby
61 lines
1.8 KiB
Ruby
class Labels::DestroyService
|
|
pattr_initialize [:label_title!, :account_id!, :label_deleted_at!]
|
|
|
|
def perform
|
|
remove_conversation_labels
|
|
remove_contact_labels
|
|
end
|
|
|
|
private
|
|
|
|
def remove_conversation_labels
|
|
tagged_conversations.find_in_batches do |conversation_batch|
|
|
conversation_batch.each do |conversation|
|
|
update_conversation_cached_labels(conversation)
|
|
end
|
|
delete_label_taggings('Conversation', conversation_batch.map(&:id))
|
|
end
|
|
end
|
|
|
|
def remove_contact_labels
|
|
contact_label_taggings.in_batches do |tagging_batch|
|
|
ActsAsTaggableOn::Tagging.where(id: tagging_batch.select(:id)).delete_all
|
|
end
|
|
end
|
|
|
|
def update_conversation_cached_labels(conversation)
|
|
label_list = conversation.label_list.dup
|
|
label_list.remove(label_title)
|
|
|
|
# We only want the acts-as-taggable-on cache effect here, not Conversation callbacks/events.
|
|
# rubocop:disable Rails/SkipsModelValidations
|
|
conversation.update_column(:cached_label_list, label_list.join("#{ActsAsTaggableOn.delimiter} "))
|
|
# rubocop:enable Rails/SkipsModelValidations
|
|
end
|
|
|
|
def tagged_conversations
|
|
account.conversations.where(id: label_taggings_for('Conversation').select(:taggable_id))
|
|
end
|
|
|
|
def contact_label_taggings
|
|
label_taggings_for('Contact').where(taggable_id: account.contacts.select(:id))
|
|
end
|
|
|
|
def delete_label_taggings(taggable_type, taggable_ids)
|
|
ActsAsTaggableOn::Tagging
|
|
.where(id: label_taggings_for(taggable_type).where(taggable_id: taggable_ids).select(:id))
|
|
.delete_all
|
|
end
|
|
|
|
def label_taggings_for(taggable_type)
|
|
ActsAsTaggableOn::Tagging
|
|
.joins(:tag)
|
|
.where(context: 'labels', taggable_type: taggable_type, tags: { name: label_title })
|
|
.where('taggings.created_at <= ?', label_deleted_at)
|
|
end
|
|
|
|
def account
|
|
@account ||= Account.find(account_id)
|
|
end
|
|
end
|