diff --git a/app/listeners/automation_rule_listener.rb b/app/listeners/automation_rule_listener.rb index bb23b7983..e4d2da0b3 100644 --- a/app/listeners/automation_rule_listener.rb +++ b/app/listeners/automation_rule_listener.rb @@ -46,9 +46,8 @@ class AutomationRuleListener < BaseListener account = conversation.account changed_attributes = event.data[:changed_attributes] - return unless rule_present?(event_name, account) - - rules = current_account_rules(event_name, account) + rules = conversation_rules(event_name, account) + return if rules.blank? rules.each do |rule| conditions_match = ::AutomationRules::ConditionsFilterService.new(rule, conversation, { changed_attributes: changed_attributes }).perform @@ -56,6 +55,17 @@ class AutomationRuleListener < BaseListener end end + # A delayed conversation rule reads as "the conversation has been in this status for N minutes", + # so a conversation created in that status must arm it too. Creation never dispatches + # CONVERSATION_UPDATED, and both paths key the episode on the same status_changed_at, so a later + # update arming the same episode is deduped by the unique index. + def conversation_rules(event_name, account) + rules = current_account_rules(event_name, account) + return rules unless event_name == 'conversation_created' + + rules + current_account_rules('conversation_updated', account).where.not(execution_delay: nil) + end + # Delayed rules record a pending execution instead of acting; the sweep re-checks and # runs them at due time. Flag off means no arming and no immediate fallback — a delayed # message silently becoming instant is worse than skipping.