zammad/lib/validations/verify_perform_rules_validator.rb

100 lines
3 KiB
Ruby

# Copyright (C) 2012-2026 Zammad Foundation, https://zammad-foundation.org/
class Validations::VerifyPerformRulesValidator < ActiveModel::EachValidator
CHECK_PRESENT = {
'article.note' => %w[body subject internal],
'notification.email' => %w[body recipient subject],
'notification.sms' => %w[body recipient],
'notification.webhook' => %w[webhook_id],
'ai.ai_agent' => %w[ai_agent_id],
'x-zammad-ticket-owner_id' => %w[value], # PostmasterFilter
'x-zammad-ticket-customer_id' => %w[value], # PostmasterFilter
}.freeze
CHECK_SPECIFIC_PRESENT = %w[
ticket.customer_id
ticket.organization_id
ticket.owner_id
].freeze
def validate_each(record, attribute, value)
return if !value.is_a? Hash
check_present(record, attribute, value)
check_specific_present(record, attribute, value)
check_pending_time_present(record, value)
end
private
def check_present(record, attribute, value)
check_present_missing(value)
.each do |key, inner|
add_error(record, attribute, key, inner)
end
end
def check_present_missing(value)
CHECK_PRESENT.each_with_object([]) do |(key, attrs), result|
next if !value[key].is_a? Hash
attrs.each do |attr|
result << [key, attr] if value[key][attr].blank?
end
end
end
def check_specific_present(record, attribute, value)
check_specific_present_missing(value)
.each do |key|
add_error(record, attribute, key, 'value')
end
end
def check_specific_present_missing(value)
CHECK_SPECIFIC_PRESENT.each_with_object([]) do |key, result|
next if !value[key].is_a? Hash
next if value[key]['pre_condition'] != 'specific'
result << key if value[key]['value'].blank?
end
end
def check_pending_time_present(record, value)
return if !value.is_a?(Hash) || value.empty?
return if pending_time_present?(value)
return if !perform_sets_pending_state?(value)
record.errors.add :base, __('The "Pending till" attribute is required for the selected state action.')
end
# Pending reminder and pending action both use ticket.pending_time
# (@see Ticket.process_pending, Ticket::StateType::CATEGORIES[:pending]).
def perform_sets_pending_state?(value)
state_id = perform_ticket_state_id(value)
return false if state_id.blank?
Ticket::State.by_category(:pending).exists?(id: state_id)
end
def perform_ticket_state_id(value)
raw = value.dig('ticket.state_id', 'value')
return raw if raw.present?
name = value.dig('ticket.state', 'value')
return if name.blank?
Ticket::State.lookup(name: name)&.id
end
def pending_time_present?(value)
pending_time = value['ticket.pending_time']
return false if !pending_time.is_a?(Hash)
pending_time['value'].present?
end
def add_error(record, attribute, key, inner)
record.errors.add :base, __("The required '%{attribute}' value for %{key}, %{inner} is missing!"), attribute: attribute, key: key, inner: inner
end
end