$conditions */ public function evaluate(array $conditions, DecisionEventContext $context): bool { foreach ($conditions as $condition) { if (! $this->evaluateOne($condition, $context)) { return false; } } return true; } protected function evaluateOne(array $condition, DecisionEventContext $context): bool { $field = $condition['field'] ?? ''; $operator = $condition['operator'] ?? '='; $expected = $condition['value'] ?? null; $actual = $this->resolveField($field, $context); return $this->compare($actual, $operator, $expected); } protected function resolveField(string $field, DecisionEventContext $context): mixed { return match ($field) { 'activity.amount' => $context->activity?->amount, 'activity.note' => $context->activity?->note, 'contract.active' => $context->contract !== null ? (bool) $context->contract->active : null, 'contract.account.balance_amount' => $this->resolveAccountBalance($context), default => null, }; } private function resolveAccountBalance(DecisionEventContext $context): mixed { if (! $context->contract) { return null; } $context->contract->loadMissing('account'); return $context->contract->account?->balance_amount; } protected function compare(mixed $actual, string $operator, mixed $expected): bool { if ($actual === null) { return false; } if (in_array($operator, ['>', '>=', '<', '<='], true)) { $actual = (float) $actual; $expected = (float) $expected; } return match ($operator) { '=' => $actual == $expected, '!=' => $actual != $expected, '>' => $actual > $expected, '>=' => $actual >= $expected, '<' => $actual < $expected, '<=' => $actual <= $expected, 'contains' => str_contains((string) $actual, (string) $expected), default => false, }; } /** * Returns available condition field definitions for the frontend. * * @return array */ public static function availableFields(): array { return [ ['key' => 'activity.amount', 'label' => 'Aktivnost – znesek', 'type' => 'numeric'], ['key' => 'activity.note', 'label' => 'Aktivnost – opomba', 'type' => 'string'], ['key' => 'contract.active', 'label' => 'Pogodba – aktivna', 'type' => 'boolean'], ['key' => 'contract.account.balance_amount', 'label' => 'Račun – stanje', 'type' => 'numeric'], ]; } /** * Returns available operators grouped by field type. * * @return array> */ public static function availableOperators(): array { return [ 'numeric' => [ ['key' => '=', 'label' => 'je enako'], ['key' => '!=', 'label' => 'ni enako'], ['key' => '>', 'label' => 'je večje od'], ['key' => '>=', 'label' => 'je večje ali enako'], ['key' => '<', 'label' => 'je manjše od'], ['key' => '<=', 'label' => 'je manjše ali enako'], ], 'string' => [ ['key' => '=', 'label' => 'je enako'], ['key' => '!=', 'label' => 'ni enako'], ['key' => 'contains', 'label' => 'vsebuje'], ], 'boolean' => [ ['key' => '=', 'label' => 'je'], ['key' => '!=', 'label' => 'ni'], ], ]; } }