From a73c1d5a63884bfc737a626c003567a3049384b7 Mon Sep 17 00:00:00 2001 From: Sobuno Date: Fri, 10 Jan 2025 20:55:45 +0100 Subject: [PATCH] Add ability to set a rule that will trigger both when rules are created or updated --- .../V1/Requests/Models/Rule/StoreRequest.php | 2 +- .../V1/Requests/Models/Rule/UpdateRequest.php | 2 +- .../Events/StoredGroupEventHandler.php | 2 +- .../Events/UpdatedGroupEventHandler.php | 2 +- app/Http/Requests/RuleFormRequest.php | 2 +- app/Repositories/Rule/RuleRepository.php | 7 +++++-- .../RuleGroup/RuleGroupRepository.php | 19 ++++++++++--------- .../RuleGroupRepositoryInterface.php | 2 +- app/Support/Twig/Rule.php | 7 ++++--- resources/lang/en_US/firefly.php | 1 + 10 files changed, 26 insertions(+), 20 deletions(-) diff --git a/app/Api/V1/Requests/Models/Rule/StoreRequest.php b/app/Api/V1/Requests/Models/Rule/StoreRequest.php index fb5b511f4b..14fde90d4e 100644 --- a/app/Api/V1/Requests/Models/Rule/StoreRequest.php +++ b/app/Api/V1/Requests/Models/Rule/StoreRequest.php @@ -119,7 +119,7 @@ class StoreRequest extends FormRequest 'description' => 'min:1|max:32768|nullable', 'rule_group_id' => 'belongsToUser:rule_groups|required_without:rule_group_title', 'rule_group_title' => 'nullable|min:1|max:255|required_without:rule_group_id|belongsToUser:rule_groups,title', - 'trigger' => 'required|in:store-journal,update-journal,manual-activation', + 'trigger' => 'required|in:store-journal,update-journal,manual-activation,store-or-update-journal', 'triggers.*.type' => 'required|in:'.implode(',', $validTriggers), 'triggers.*.value' => 'required_if:actions.*.type,'.$contextTriggers.'|min:1|ruleTriggerValue|max:1024', 'triggers.*.stop_processing' => [new IsBoolean()], diff --git a/app/Api/V1/Requests/Models/Rule/UpdateRequest.php b/app/Api/V1/Requests/Models/Rule/UpdateRequest.php index d9fecdc314..4b45e5fd33 100644 --- a/app/Api/V1/Requests/Models/Rule/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/Rule/UpdateRequest.php @@ -138,7 +138,7 @@ class UpdateRequest extends FormRequest 'description' => 'min:1|max:32768|nullable', 'rule_group_id' => 'belongsToUser:rule_groups', 'rule_group_title' => 'nullable|min:1|max:255|belongsToUser:rule_groups,title', - 'trigger' => 'in:store-journal,update-journal.manual-activation', + 'trigger' => 'in:store-journal,update-journal.manual-activation,store-or-update-journal', 'triggers.*.type' => 'required|in:'.implode(',', $validTriggers), 'triggers.*.value' => 'required_if:actions.*.type,'.$contextTriggers.'|min:1|ruleTriggerValue|max:1024', 'triggers.*.stop_processing' => [new IsBoolean()], diff --git a/app/Handlers/Events/StoredGroupEventHandler.php b/app/Handlers/Events/StoredGroupEventHandler.php index 53faaffe21..8c4bbd41d5 100644 --- a/app/Handlers/Events/StoredGroupEventHandler.php +++ b/app/Handlers/Events/StoredGroupEventHandler.php @@ -66,7 +66,7 @@ class StoredGroupEventHandler // add the groups to the rule engine. // it should run the rules in the group and cancel the group if necessary. - $groups = $ruleGroupRepository->getRuleGroupsWithRules('store-journal'); + $groups = $ruleGroupRepository->getRuleGroupsWithRules(['store-journal', 'store-or-update-journal']); // create and fire rule engine. $newRuleEngine = app(RuleEngineInterface::class); diff --git a/app/Handlers/Events/UpdatedGroupEventHandler.php b/app/Handlers/Events/UpdatedGroupEventHandler.php index ef1ed4e430..05c387eec2 100644 --- a/app/Handlers/Events/UpdatedGroupEventHandler.php +++ b/app/Handlers/Events/UpdatedGroupEventHandler.php @@ -66,7 +66,7 @@ class UpdatedGroupEventHandler $ruleGroupRepository = app(RuleGroupRepositoryInterface::class); $ruleGroupRepository->setUser($updatedGroupEvent->transactionGroup->user); - $groups = $ruleGroupRepository->getRuleGroupsWithRules('update-journal'); + $groups = $ruleGroupRepository->getRuleGroupsWithRules(['update-journal', 'store-or-update-journal']); // file rule engine. $newRuleEngine = app(RuleEngineInterface::class); diff --git a/app/Http/Requests/RuleFormRequest.php b/app/Http/Requests/RuleFormRequest.php index aadf8c7fee..042a3e73e3 100644 --- a/app/Http/Requests/RuleFormRequest.php +++ b/app/Http/Requests/RuleFormRequest.php @@ -144,7 +144,7 @@ class RuleFormRequest extends FormRequest 'description' => 'min:1|max:32768|nullable', 'stop_processing' => 'boolean', 'rule_group_id' => 'required|belongsToUser:rule_groups', - 'trigger' => 'required|in:store-journal,update-journal,manual-activation', + 'trigger' => 'required|in:store-journal,update-journal,manual-activation,store-or-update-journal', 'triggers.*.type' => 'required|in:'.implode(',', $validTriggers), 'triggers.*.value' => sprintf('required_if:triggers.*.type,%s|max:1024|min:1|ruleTriggerValue', $contextTriggers), 'actions.*.type' => 'required|in:'.implode(',', $validActions), diff --git a/app/Repositories/Rule/RuleRepository.php b/app/Repositories/Rule/RuleRepository.php index 0c43cdc0db..f6613b8e25 100644 --- a/app/Repositories/Rule/RuleRepository.php +++ b/app/Repositories/Rule/RuleRepository.php @@ -175,7 +175,7 @@ class RuleRepository implements RuleRepositoryInterface foreach ($collection as $rule) { /** @var RuleTrigger $ruleTrigger */ foreach ($rule->ruleTriggers as $ruleTrigger) { - if ('user_action' === $ruleTrigger->trigger_type && 'store-journal' === $ruleTrigger->trigger_value) { + if ('user_action' === $ruleTrigger->trigger_type && in_array($ruleTrigger->trigger_value, ['store-journal','store-or-update-journal'], true)) { $filtered->push($rule); } } @@ -201,7 +201,7 @@ class RuleRepository implements RuleRepositoryInterface foreach ($collection as $rule) { /** @var RuleTrigger $ruleTrigger */ foreach ($rule->ruleTriggers as $ruleTrigger) { - if ('user_action' === $ruleTrigger->trigger_type && 'update-journal' === $ruleTrigger->trigger_value) { + if ('user_action' === $ruleTrigger->trigger_type && in_array($ruleTrigger->trigger_value, ['update-journal','store-or-update-journal'], true)) { $filtered->push($rule); } } @@ -494,6 +494,9 @@ class RuleRepository implements RuleRepositoryInterface if (array_key_exists('trigger', $data) && 'store-journal' === $data['trigger']) { $this->setRuleTrigger('store-journal', $rule); } + if (array_key_exists('trigger', $data) && 'store-or-update-journal' === $data['trigger']) { + $this->setRuleTrigger('store-or-update-journal', $rule); + } if (array_key_exists('triggers', $data)) { // delete triggers: $rule->ruleTriggers()->where('trigger_type', '!=', 'user_action')->delete(); diff --git a/app/Repositories/RuleGroup/RuleGroupRepository.php b/app/Repositories/RuleGroup/RuleGroupRepository.php index 447151dbad..e6edb5ce30 100644 --- a/app/Repositories/RuleGroup/RuleGroupRepository.php +++ b/app/Repositories/RuleGroup/RuleGroupRepository.php @@ -236,7 +236,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface return $group->rules() ->leftJoin('rule_triggers', 'rules.id', '=', 'rule_triggers.rule_id') ->where('rule_triggers.trigger_type', 'user_action') - ->where('rule_triggers.trigger_value', 'store-journal') + ->whereIn('rule_triggers.trigger_value', ['store-journal', 'store-or-update-journal']) ->where('rules.active', true) ->get(['rules.*']) ; @@ -247,7 +247,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface return $group->rules() ->leftJoin('rule_triggers', 'rules.id', '=', 'rule_triggers.rule_id') ->where('rule_triggers.trigger_type', 'user_action') - ->where('rule_triggers.trigger_value', 'update-journal') + ->whereIn('rule_triggers.trigger_value', ['update-journal', 'store-or-update-journal']) ->where('rules.active', true) ->get(['rules.*']) ; @@ -308,7 +308,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface return (int) $entry; } - public function getRuleGroupsWithRules(?string $filter): Collection + public function getRuleGroupsWithRules(?array $filter): Collection { $groups = $this->user->ruleGroups() ->orderBy('order', 'ASC') @@ -330,23 +330,24 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface if (null === $filter) { return $groups; } - app('log')->debug(sprintf('Will filter getRuleGroupsWithRules on "%s".', $filter)); + $implodedFilter = implode(',', $filter); + app('log')->debug(sprintf('Will filter getRuleGroupsWithRules on any of %s.', $implodedFilter)); return $groups->map( - static function (RuleGroup $group) use ($filter) { // @phpstan-ignore-line + static function (RuleGroup $group) use ($filter, $implodedFilter) { // @phpstan-ignore-line app('log')->debug(sprintf('Now filtering group #%d', $group->id)); // filter the rules in the rule group: $group->rules = $group->rules->filter( - static function (Rule $rule) use ($filter) { + static function (Rule $rule) use ($filter, $implodedFilter) { app('log')->debug(sprintf('Now filtering rule #%d', $rule->id)); foreach ($rule->ruleTriggers as $trigger) { - if ('user_action' === $trigger->trigger_type && $filter === $trigger->trigger_value) { - app('log')->debug(sprintf('Rule #%d triggers on %s, include it.', $rule->id, $filter)); + if ('user_action' === $trigger->trigger_type && in_array($trigger->trigger_value, $filter, true)) { + app('log')->debug(sprintf('Rule #%d triggers on %s, include it.', $rule->id, $trigger->trigger_value)); return true; } } - app('log')->debug(sprintf('Rule #%d does not trigger on %s, do not include it.', $rule->id, $filter)); + app('log')->debug(sprintf('Rule #%d does not trigger on any of %s, do not include it.', $rule->id, $implodedFilter)); return false; } diff --git a/app/Repositories/RuleGroup/RuleGroupRepositoryInterface.php b/app/Repositories/RuleGroup/RuleGroupRepositoryInterface.php index d334fbb473..fc2a0feda9 100644 --- a/app/Repositories/RuleGroup/RuleGroupRepositoryInterface.php +++ b/app/Repositories/RuleGroup/RuleGroupRepositoryInterface.php @@ -71,7 +71,7 @@ interface RuleGroupRepositoryInterface public function getHighestOrderRuleGroup(): int; - public function getRuleGroupsWithRules(?string $filter): Collection; + public function getRuleGroupsWithRules(?array $filter): Collection; public function getRules(RuleGroup $group): Collection; diff --git a/app/Support/Twig/Rule.php b/app/Support/Twig/Rule.php index 42ef0f6ff9..94fc710971 100644 --- a/app/Support/Twig/Rule.php +++ b/app/Support/Twig/Rule.php @@ -46,9 +46,10 @@ class Rule extends AbstractExtension 'allJournalTriggers', static function () { return [ - 'store-journal' => (string) trans('firefly.rule_trigger_store_journal'), - 'update-journal' => (string) trans('firefly.rule_trigger_update_journal'), - 'manual-activation' => (string) trans('firefly.rule_trigger_manual'), + 'store-journal' => (string) trans('firefly.rule_trigger_store_journal'), + 'update-journal' => (string) trans('firefly.rule_trigger_update_journal'), + 'store-or-update-journal' => (string) trans('firefly.rule_trigger_store_or_update_journal'), + 'manual-activation' => (string) trans('firefly.rule_trigger_manual'), ]; } ); diff --git a/resources/lang/en_US/firefly.php b/resources/lang/en_US/firefly.php index f2c3a02362..6cbc2f51b9 100644 --- a/resources/lang/en_US/firefly.php +++ b/resources/lang/en_US/firefly.php @@ -821,6 +821,7 @@ return [ // actions and triggers 'rule_trigger_store_journal' => 'When a transaction is created', 'rule_trigger_update_journal' => 'When a transaction is updated', + 'rule_trigger_store_or_update_journal' => 'When a transaction is created or updated', 'rule_trigger_manual' => 'Only when user-activated', 'rule_trigger_user_action' => 'User action is ":trigger_value"',