From 1ecc454f70cad8f9f32ea7c6222b6c9c559c4e9c Mon Sep 17 00:00:00 2001 From: James Cole Date: Fri, 12 Feb 2021 20:15:23 +0100 Subject: [PATCH] Fix issue in rule engine. --- .../Events/StoredGroupEventHandler.php | 4 +- .../Events/UpdatedGroupEventHandler.php | 10 +-- app/Http/Controllers/Rule/IndexController.php | 2 +- app/Models/RuleGroup.php | 2 +- .../RuleGroup/RuleGroupRepository.php | 67 +++++++++++++------ .../RuleGroupRepositoryInterface.php | 4 +- app/Support/Steam.php | 15 +---- 7 files changed, 63 insertions(+), 41 deletions(-) diff --git a/app/Handlers/Events/StoredGroupEventHandler.php b/app/Handlers/Events/StoredGroupEventHandler.php index 1cb6dc1ef1..751a0422bb 100644 --- a/app/Handlers/Events/StoredGroupEventHandler.php +++ b/app/Handlers/Events/StoredGroupEventHandler.php @@ -62,14 +62,12 @@ class StoredGroupEventHandler Log::debug(sprintf('Add local operator for journal(s): %s', $journalIds)); // collect rules: - $ruleRepository = app(RuleRepositoryInterface::class); $ruleGroupRepository = app(RuleGroupRepositoryInterface::class); - $ruleRepository->setUser($storedGroupEvent->transactionGroup->user); $ruleGroupRepository->setUser($storedGroupEvent->transactionGroup->user); // add the groups to the rule engine. // it should run the rules in the group and cancel the group if necessary. - $groups = $ruleGroupRepository->getRuleGroupsWithRules(); + $groups = $ruleGroupRepository->getRuleGroupsWithRules('store-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 f5b027c2e5..fc281330d9 100644 --- a/app/Handlers/Events/UpdatedGroupEventHandler.php +++ b/app/Handlers/Events/UpdatedGroupEventHandler.php @@ -31,6 +31,7 @@ use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; use FireflyIII\Models\Webhook; use FireflyIII\Repositories\Rule\RuleRepositoryInterface; +use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface; use FireflyIII\TransactionRules\Engine\RuleEngineInterface; use Illuminate\Support\Collection; use Log; @@ -103,15 +104,16 @@ class UpdatedGroupEventHandler Log::debug(sprintf('Add local operator for journal(s): %s', $journalIds)); // collect rules: - $ruleRepository = app(RuleRepositoryInterface::class); - $ruleRepository->setUser($updatedGroupEvent->transactionGroup->user); - $rules = $ruleRepository->getUpdateRules(); + $ruleGroupRepository = app(RuleGroupRepositoryInterface::class); + $ruleGroupRepository->setUser($updatedGroupEvent->transactionGroup->user); + + $groups = $ruleGroupRepository->getRuleGroupsWithRules('update-journal'); // file rule engine. $newRuleEngine = app(RuleEngineInterface::class); $newRuleEngine->setUser($updatedGroupEvent->transactionGroup->user); $newRuleEngine->addOperator(['type' => 'journal_id', 'value' => $journalIds]); - $newRuleEngine->setRules($rules); + $newRuleEngine->setRuleGroups($groups); $newRuleEngine->fire(); } diff --git a/app/Http/Controllers/Rule/IndexController.php b/app/Http/Controllers/Rule/IndexController.php index 6e8ba9ad5c..793451ee07 100644 --- a/app/Http/Controllers/Rule/IndexController.php +++ b/app/Http/Controllers/Rule/IndexController.php @@ -77,7 +77,7 @@ class IndexController extends Controller $this->createDefaultRuleGroup(); $this->createDefaultRule(); $this->ruleGroupRepos->resetRuleGroupOrder(); - $ruleGroups = $this->ruleGroupRepos->getRuleGroupsWithRules($user); + $ruleGroups = $this->ruleGroupRepos->getRuleGroupsWithRules(null); return prefixView('rules.index', compact('ruleGroups')); } diff --git a/app/Models/RuleGroup.php b/app/Models/RuleGroup.php index 06bde1ba19..6bc281100d 100644 --- a/app/Models/RuleGroup.php +++ b/app/Models/RuleGroup.php @@ -47,7 +47,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * @property int $order * @property bool $active * @property bool $stop_processing - * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Rule[] $rules + * @property \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Rule[] $rules * @property-read int|null $rules_count * @property-read User $user * @method static \Illuminate\Database\Eloquent\Builder|RuleGroup newModelQuery() diff --git a/app/Repositories/RuleGroup/RuleGroupRepository.php b/app/Repositories/RuleGroup/RuleGroupRepository.php index 298cc573c3..421e01a531 100644 --- a/app/Repositories/RuleGroup/RuleGroupRepository.php +++ b/app/Repositories/RuleGroup/RuleGroupRepository.php @@ -34,8 +34,7 @@ use Log; */ class RuleGroupRepository implements RuleGroupRepositoryInterface { - /** @var User */ - private $user; + private User $user; /** * @return int @@ -198,26 +197,56 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface } /** + * @param string|null $filter + * * @return Collection */ - public function getRuleGroupsWithRules(): Collection + public function getRuleGroupsWithRules(?string $filter): Collection { - return $this->user->ruleGroups() - ->orderBy('order', 'ASC') - ->where('active', true) - ->with( - [ - 'rules' => static function (HasMany $query) { - $query->orderBy('order', 'ASC'); - }, - 'rules.ruleTriggers' => static function (HasMany $query) { - $query->orderBy('order', 'ASC'); - }, - 'rules.ruleActions' => static function (HasMany $query) { - $query->orderBy('order', 'ASC'); - }, - ] - )->get(); + $groups = $this->user->ruleGroups() + ->orderBy('order', 'ASC') + ->where('active', true) + ->with( + [ + 'rules' => static function (HasMany $query) { + $query->orderBy('order', 'ASC'); + }, + 'rules.ruleTriggers' => static function (HasMany $query) { + $query->orderBy('order', 'ASC'); + }, + 'rules.ruleActions' => static function (HasMany $query) { + $query->orderBy('order', 'ASC'); + }, + ] + )->get(); + if (null === $filter) { + return $groups; + } + Log::debug(sprintf('Will filter getRuleGroupsWithRules on "%s".', $filter)); + + return $groups->map( + function (RuleGroup $group) use ($filter) { + Log::debug(sprintf('Now filtering group #%d', $group->id)); + // filter the rules in the rule group: + $group->rules = $group->rules->filter( + function (Rule $rule) use ($filter) { + Log::debug(sprintf('Now filtering rule #%d', $rule->id)); + foreach ($rule->ruleTriggers as $trigger) { + if ('user_action' === $trigger->trigger_type && $filter === $trigger->trigger_value) { + Log::debug(sprintf('Rule #%d triggers on %s, include it.', $rule->id, $filter)); + + return true; + } + } + Log::debug(sprintf('Rule #%d does not trigger on %s, do not include it.', $rule->id, $filter)); + + return false; + } + ); + + return $group; + } + ); } /** diff --git a/app/Repositories/RuleGroup/RuleGroupRepositoryInterface.php b/app/Repositories/RuleGroup/RuleGroupRepositoryInterface.php index 577133407f..216fefdf57 100644 --- a/app/Repositories/RuleGroup/RuleGroupRepositoryInterface.php +++ b/app/Repositories/RuleGroup/RuleGroupRepositoryInterface.php @@ -102,9 +102,11 @@ interface RuleGroupRepositoryInterface public function getHighestOrderRuleGroup(): int; /** + * @param string|null $filter + * * @return Collection */ - public function getRuleGroupsWithRules(): Collection; + public function getRuleGroupsWithRules(?string $filter): Collection; /** * @param RuleGroup $group diff --git a/app/Support/Steam.php b/app/Support/Steam.php index ad416736e6..20b18ef04c 100644 --- a/app/Support/Steam.php +++ b/app/Support/Steam.php @@ -29,7 +29,6 @@ use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use Illuminate\Support\Collection; -use Log; use stdClass; /** @@ -79,17 +78,9 @@ class Steam ->where('transactions.transaction_currency_id', '!=', $currency->id) ->get(['transactions.foreign_amount'])->toArray(); $foreignBalance = $this->sumTransactions($transactions, 'foreign_amount'); - - // check: - Log::debug(sprintf('Steam::balance. Native balance is "%s"', $nativeBalance)); - Log::debug(sprintf('Steam::balance. Foreign balance is "%s"', $foreignBalance)); - - $balance = bcadd($nativeBalance, $foreignBalance); - $virtual = null === $account->virtual_balance ? '0' : (string)$account->virtual_balance; - - Log::debug(sprintf('Steam::balance. Virtual balance is "%s"', $virtual)); - - $balance = bcadd($balance, $virtual); + $balance = bcadd($nativeBalance, $foreignBalance); + $virtual = null === $account->virtual_balance ? '0' : (string)$account->virtual_balance; + $balance = bcadd($balance, $virtual); $cache->store($balance);