mirror of
https://github.com/lingble/chatwoot.git
synced 2025-11-02 20:18:08 +00:00
feat: Phone number based automation conditions (#6783)
This commit is contained in:
@@ -22,7 +22,8 @@
|
||||
"is_not_present": "Is not present",
|
||||
"is_greater_than": "Is greater than",
|
||||
"is_less_than": "Is lesser than",
|
||||
"days_before": "Is x days before"
|
||||
"days_before": "Is x days before",
|
||||
"starts_with": "Starts with"
|
||||
},
|
||||
"ATTRIBUTE_LABELS": {
|
||||
"TRUE": "True",
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
OPERATOR_TYPES_1,
|
||||
OPERATOR_TYPES_2,
|
||||
OPERATOR_TYPES_3,
|
||||
OPERATOR_TYPES_6,
|
||||
} from './operators';
|
||||
|
||||
export const AUTOMATIONS = {
|
||||
@@ -35,6 +36,13 @@ export const AUTOMATIONS = {
|
||||
inputType: 'multi_select',
|
||||
filterOperators: OPERATOR_TYPES_1,
|
||||
},
|
||||
{
|
||||
key: 'phone_number',
|
||||
name: 'Phone Number',
|
||||
attributeI18nKey: 'PHONE_NUMBER',
|
||||
inputType: 'plain_text',
|
||||
filterOperators: OPERATOR_TYPES_6,
|
||||
},
|
||||
],
|
||||
actions: [
|
||||
{
|
||||
@@ -125,6 +133,13 @@ export const AUTOMATIONS = {
|
||||
inputType: 'search_select',
|
||||
filterOperators: OPERATOR_TYPES_1,
|
||||
},
|
||||
{
|
||||
key: 'phone_number',
|
||||
name: 'Phone Number',
|
||||
attributeI18nKey: 'PHONE_NUMBER',
|
||||
inputType: 'plain_text',
|
||||
filterOperators: OPERATOR_TYPES_6,
|
||||
},
|
||||
{
|
||||
key: 'referer',
|
||||
name: 'Referrer Link',
|
||||
@@ -242,6 +257,13 @@ export const AUTOMATIONS = {
|
||||
inputType: 'plain_text',
|
||||
filterOperators: OPERATOR_TYPES_2,
|
||||
},
|
||||
{
|
||||
key: 'phone_number',
|
||||
name: 'Phone Number',
|
||||
attributeI18nKey: 'PHONE_NUMBER',
|
||||
inputType: 'plain_text',
|
||||
filterOperators: OPERATOR_TYPES_6,
|
||||
},
|
||||
{
|
||||
key: 'assignee_id',
|
||||
name: 'Assignee',
|
||||
@@ -373,6 +395,13 @@ export const AUTOMATIONS = {
|
||||
inputType: 'search_select',
|
||||
filterOperators: OPERATOR_TYPES_3,
|
||||
},
|
||||
{
|
||||
key: 'phone_number',
|
||||
name: 'Phone Number',
|
||||
attributeI18nKey: 'PHONE_NUMBER',
|
||||
inputType: 'plain_text',
|
||||
filterOperators: OPERATOR_TYPES_6,
|
||||
},
|
||||
{
|
||||
key: 'team_id',
|
||||
name: 'Team',
|
||||
|
||||
@@ -88,3 +88,26 @@ export const OPERATOR_TYPES_5 = [
|
||||
label: 'Is x days before',
|
||||
},
|
||||
];
|
||||
|
||||
export const OPERATOR_TYPES_6 = [
|
||||
{
|
||||
value: 'equal_to',
|
||||
label: 'Equal to',
|
||||
},
|
||||
{
|
||||
value: 'not_equal_to',
|
||||
label: 'Not equal to',
|
||||
},
|
||||
{
|
||||
value: 'contains',
|
||||
label: 'Contains',
|
||||
},
|
||||
{
|
||||
value: 'does_not_contain',
|
||||
label: 'Does not contain',
|
||||
},
|
||||
{
|
||||
value: 'starts_with',
|
||||
label: 'Starts With',
|
||||
},
|
||||
];
|
||||
|
||||
@@ -31,7 +31,7 @@ class AutomationRule < ApplicationRecord
|
||||
scope :active, -> { where(active: true) }
|
||||
|
||||
CONDITIONS_ATTRS = %w[content email country_code status message_type browser_language assignee_id team_id referer city company inbox_id
|
||||
mail_subject].freeze
|
||||
mail_subject phone_number].freeze
|
||||
ACTIONS_ATTRS = %w[send_message add_label send_email_to_team assign_team assign_agent send_webhook_event mute_conversation send_attachment
|
||||
change_status resolve_conversation snooze_conversation send_email_transcript].freeze
|
||||
|
||||
|
||||
@@ -32,6 +32,15 @@ class AutomationRules::ConditionsFilterService < FilterService
|
||||
records.any?
|
||||
end
|
||||
|
||||
def filter_operation(query_hash, current_index)
|
||||
if query_hash[:filter_operator] == 'starts_with'
|
||||
@filter_values["value_#{current_index}"] = "#{string_filter_values(query_hash)}%"
|
||||
like_filter_string(query_hash[:filter_operator], current_index)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def apply_filter(query_hash, current_index)
|
||||
conversation_filter = @conversation_filters[query_hash['attribute_key']]
|
||||
contact_filter = @contact_filters[query_hash['attribute_key']]
|
||||
|
||||
@@ -150,7 +150,7 @@ class FilterService
|
||||
end
|
||||
|
||||
def like_filter_string(filter_operator, current_index)
|
||||
return "LIKE :value_#{current_index}" if filter_operator == 'contains'
|
||||
return "LIKE :value_#{current_index}" if %w[contains starts_with].include?(filter_operator)
|
||||
|
||||
"NOT LIKE :value_#{current_index}"
|
||||
end
|
||||
|
||||
@@ -100,6 +100,13 @@
|
||||
"filter_operators": [ "equal_to", "not_equal_to", "contains", "does_not_contain", "is_present", "is_not_present" ],
|
||||
"attribute_type": "standard"
|
||||
},
|
||||
"phone_number": {
|
||||
"attribute_name": "Phone Number",
|
||||
"input_type": "textbox",
|
||||
"data_type": "text",
|
||||
"filter_operators": [ "equal_to", "not_equal_to", "contains", "does_not_contain", "starts_with" ],
|
||||
"attribute_type": "standard"
|
||||
},
|
||||
"contact_id": {
|
||||
"attribute_name": "Contact Name",
|
||||
"input_type": "plain_text",
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
},
|
||||
"phone_number": {
|
||||
"attribute_name": "Phone Number",
|
||||
"input_type": "search_box with name tags/plain text",
|
||||
"input_type": "text",
|
||||
"data_type": "text",
|
||||
"filter_operators": [ "equal_to", "not_equal_to", "contains", "does_not_contain" ],
|
||||
"attribute_type": "standard"
|
||||
|
||||
@@ -5,25 +5,57 @@ RSpec.describe AutomationRules::ConditionsFilterService do
|
||||
let(:conversation) { create(:conversation, account: account) }
|
||||
let(:rule) { create(:automation_rule, account: account) }
|
||||
|
||||
describe '#perform' do
|
||||
before do
|
||||
rule.conditions = [{ 'values': ['open'], 'attribute_key': 'status', 'query_operator': nil, 'filter_operator': 'equal_to' }]
|
||||
rule.save
|
||||
end
|
||||
before do
|
||||
conversation = create(:conversation, account: account)
|
||||
conversation.contact.update(phone_number: '+918484828282', email: 'test@test.com')
|
||||
create(:conversation, account: account)
|
||||
create(:conversation, account: account)
|
||||
end
|
||||
|
||||
context 'when conditions in rule matches with object' do
|
||||
it 'will return true' do
|
||||
expect(described_class.new(rule, conversation, { changed_attributes: { status: [nil, 'open'] } }).perform).to be(true)
|
||||
describe '#perform' do
|
||||
context 'when conditions based on filter_operator equal_to' do
|
||||
before do
|
||||
rule.conditions = [{ 'values': ['open'], 'attribute_key': 'status', 'query_operator': nil, 'filter_operator': 'equal_to' }]
|
||||
rule.save
|
||||
end
|
||||
|
||||
context 'when conditions in rule matches with object' do
|
||||
it 'will return true' do
|
||||
expect(described_class.new(rule, conversation, { changed_attributes: { status: [nil, 'open'] } }).perform).to be(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when conditions in rule does not match with object' do
|
||||
it 'will return false' do
|
||||
conversation.update(status: 'resolved')
|
||||
expect(described_class.new(rule, conversation, { changed_attributes: { status: %w[open resolved] } }).perform).to be(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when conditions in rule does not match with object' do
|
||||
it 'will return false' do
|
||||
conversation.update(status: 'resolved')
|
||||
expect(described_class.new(rule, conversation, { changed_attributes: { status: %w[open resolved] } }).perform).to be(false)
|
||||
context 'when conditions based on filter_operator start_with' do
|
||||
before do
|
||||
contact = conversation.contact
|
||||
contact.update(phone_number: '+918484848484')
|
||||
rule.conditions = [
|
||||
{ 'values': ['+918484'], 'attribute_key': 'phone_number', 'query_operator': 'OR', 'filter_operator': 'starts_with' },
|
||||
{ 'values': ['test'], 'attribute_key': 'email', 'query_operator': nil, 'filter_operator': 'contains' }
|
||||
]
|
||||
rule.save
|
||||
end
|
||||
|
||||
context 'when conditions in rule matches with object' do
|
||||
it 'will return true' do
|
||||
expect(described_class.new(rule, conversation, { changed_attributes: {} }).perform).to be(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when conditions in rule does not match with object' do
|
||||
it 'will return false' do
|
||||
conversation.contact.update(phone_number: '+918585858585')
|
||||
expect(described_class.new(rule, conversation, { changed_attributes: {} }).perform).to be(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
## TODO: add tests for the other conditions
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user