Add new rule engine to API commands.

This commit is contained in:
James Cole
2020-08-23 16:26:39 +02:00
parent fecc9f7659
commit ce34e097a2
5 changed files with 41 additions and 68 deletions

View File

@@ -34,6 +34,7 @@ use FireflyIII\Models\RuleGroup;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface; use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
use FireflyIII\TransactionRules\Engine\RuleEngine; use FireflyIII\TransactionRules\Engine\RuleEngine;
use FireflyIII\TransactionRules\Engine\RuleEngineInterface;
use FireflyIII\TransactionRules\TransactionMatcher; use FireflyIII\TransactionRules\TransactionMatcher;
use FireflyIII\Transformers\RuleGroupTransformer; use FireflyIII\Transformers\RuleGroupTransformer;
use FireflyIII\Transformers\RuleTransformer; use FireflyIII\Transformers\RuleTransformer;
@@ -316,32 +317,28 @@ class RuleGroupController extends Controller
/** @var Collection $collection */ /** @var Collection $collection */
$collection = $this->ruleGroupRepository->getActiveRules($group); $collection = $this->ruleGroupRepository->getActiveRules($group);
$rules = [];
/** @var Rule $item */
foreach ($collection as $item) {
$rules[] = $item->id;
}
// start looping. // start looping.
/** @var RuleEngine $ruleEngine */ $ruleEngine = app(RuleEngineInterface::class);
$ruleEngine = app(RuleEngine::class); $ruleEngine->setRules($collection);
$ruleEngine->setUser(auth()->user());
$ruleEngine->setRulesToApply($rules);
$ruleEngine->setTriggerMode(RuleEngine::TRIGGER_STORE);
/** @var GroupCollectorInterface $collector */ // overrule the rule(s) if necessary.
$collector = app(GroupCollectorInterface::class); if (array_key_exists('start', $parameters) && null !== $parameters['start'] ) {
$collector->setAccounts($parameters['accounts']); // add a range:
$collector->setRange($parameters['start_date'], $parameters['end_date']); $ruleEngine->addOperator(['type' => 'date_after', 'value' => $parameters['start']->format('Y-m-d')]);
$journals = $collector->getExtractedJournals();
/** @var array $journal */
foreach ($journals as $journal) {
Log::debug('Start of new journal.');
$ruleEngine->processJournalArray($journal);
Log::debug('Done with all rules for this group + done with journal.');
} }
if (array_key_exists('end', $parameters) && null !== $parameters['end']) {
// add a range:
$ruleEngine->addOperator(['type' => 'date_before', 'value' => $parameters['end']->format('Y-m-d')]);
}
if (array_key_exists('accounts', $parameters) && '' !== $parameters['accounts']) {
$ruleEngine->addOperator(['type' => 'account_id', 'value' => $parameters['accounts']]);
}
// file the rule(s)
$ruleEngine->fire();
return response()->json([], 204); return response()->json([], 204);
} }

View File

@@ -40,6 +40,7 @@ use Log;
class RuleGroupTriggerRequest extends FormRequest class RuleGroupTriggerRequest extends FormRequest
{ {
use ConvertsDataTypes; use ConvertsDataTypes;
/** /**
* Authorize logged in users. * Authorize logged in users.
* *
@@ -57,9 +58,9 @@ class RuleGroupTriggerRequest extends FormRequest
public function getTriggerParameters(): array public function getTriggerParameters(): array
{ {
return [ return [
'start_date' => $this->getDate('start_date'), 'start' => $this->getDate('start'),
'end_date' => $this->getDate('end_date'), 'end' => $this->getDate('end'),
'accounts' => $this->getAccounts(), 'accounts' => $this->getAccounts(),
]; ];
} }
@@ -69,33 +70,17 @@ class RuleGroupTriggerRequest extends FormRequest
public function rules(): array public function rules(): array
{ {
return [ return [
'start_date' => 'required|date', 'start' => 'date',
'end_date' => 'required|date|after:start_date', 'end' => 'date|after:start',
]; ];
} }
/** /**
* @return Collection * @return string
*/ */
private function getAccounts(): Collection private function getAccounts(): string
{ {
$accountList = '' === (string) $this->query('accounts') ? [] : explode(',', $this->query('accounts')); return (string) $this->query('accounts');
$accounts = new Collection;
/** @var AccountRepositoryInterface $accountRepository */
$accountRepository = app(AccountRepositoryInterface::class);
foreach ($accountList as $accountId) {
Log::debug(sprintf('Searching for asset account with id "%s"', $accountId));
$account = $accountRepository->findNull((int) $accountId);
if ($this->validAccount($account)) {
/** @noinspection NullPointerExceptionInspection */
Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name));
$accounts->push($account);
}
}
return $accounts;
} }
/** /**
@@ -106,19 +91,7 @@ class RuleGroupTriggerRequest extends FormRequest
private function getDate(string $field): ?Carbon private function getDate(string $field): ?Carbon
{ {
/** @var Carbon $result */ /** @var Carbon $result */
$result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field)); return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field));
return $result;
}
/**
* @param Account|null $account
*
* @return bool
*/
private function validAccount(?Account $account): bool
{
return null !== $account && AccountType::ASSET === $account->accountType->type;
} }
} }

View File

@@ -87,10 +87,7 @@ class RuleTriggerRequest extends FormRequest
*/ */
private function getDate(string $field): ?Carbon private function getDate(string $field): ?Carbon
{ {
/** @var Carbon $result */ return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field));
$result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field));
return $result;
} }
} }

View File

@@ -58,6 +58,7 @@ class ConvertToDeposit implements ActionInterface
* *
* @param TransactionJournal $journal * @param TransactionJournal $journal
* @deprecated * @deprecated
* @codeCoverageIgnore
* @return bool * @return bool
* @throws FireflyException * @throws FireflyException
*/ */

View File

@@ -94,6 +94,7 @@ class SearchRuleEngine implements RuleEngineInterface
foreach ($this->rules as $rule) { foreach ($this->rules as $rule) {
$this->fireRule($rule); $this->fireRule($rule);
} }
Log::debug('SearchRuleEngine:: done processing all rules!');
} }
/** /**
@@ -102,14 +103,17 @@ class SearchRuleEngine implements RuleEngineInterface
*/ */
private function fireRule(Rule $rule): void private function fireRule(Rule $rule): void
{ {
Log::debug(sprintf('SearchRuleEngine::fireRule(%d)!', $rule->id));
$searchArray = []; $searchArray = [];
/** @var RuleTrigger $ruleTrigger */ /** @var RuleTrigger $ruleTrigger */
foreach ($rule->ruleTriggers as $ruleTrigger) { foreach ($rule->ruleTriggers as $ruleTrigger) {
Log::debug(sprintf('SearchRuleEngine:: add a rule trigger: %s:"%s"', $ruleTrigger->trigger_type, $ruleTrigger->trigger_value));
$searchArray[$ruleTrigger->trigger_type] = sprintf('"%s"', $ruleTrigger->trigger_value); $searchArray[$ruleTrigger->trigger_type] = sprintf('"%s"', $ruleTrigger->trigger_value);
} }
// add local operators: // add local operators:
foreach ($this->operators as $operator) { foreach ($this->operators as $operator) {
Log::debug(sprintf('SearchRuleEngine:: add local added operator: %s:"%s"', $operator['type'], $operator['value']));
$searchArray[$operator['type']] = sprintf('"%s"', $operator['value']); $searchArray[$operator['type']] = sprintf('"%s"', $operator['value']);
} }
$toJoin = []; $toJoin = [];
@@ -118,20 +122,21 @@ class SearchRuleEngine implements RuleEngineInterface
} }
$searchQuery = join(' ', $toJoin); $searchQuery = join(' ', $toJoin);
Log::debug(sprintf('Search query for rule #%d ("%s") = %s', $rule->id, $rule->title, $searchQuery)); Log::debug(sprintf('SearchRuleEngine:: Search query for rule #%d ("%s") = %s', $rule->id, $rule->title, $searchQuery));
// build and run the search engine. // build and run the search engine.
$searchEngine = app(SearchInterface::class); $searchEngine = app(SearchInterface::class);
$searchEngine->setUser($this->user); $searchEngine->setUser($this->user);
$searchEngine->setPage(1); $searchEngine->setPage(1);
$searchEngine->setLimit(1337); $searchEngine->setLimit(31337);
$searchEngine->parseQuery($searchQuery); $searchEngine->parseQuery($searchQuery);
$result = $searchEngine->searchTransactions(); $result = $searchEngine->searchTransactions();
$collection = $result->getCollection(); $collection = $result->getCollection();
Log::debug(sprintf('Found %d transactions using search engine.', $collection->count())); Log::debug(sprintf('SearchRuleEngine:: Found %d transactions using search engine with query "%s".', $collection->count(), $searchQuery));
$this->processResults($rule, $collection); $this->processResults($rule, $collection);
Log::debug(sprintf('SearchRuleEngine:: done processing rule #%d', $rule->id));
} }
/** /**
@@ -141,7 +146,7 @@ class SearchRuleEngine implements RuleEngineInterface
*/ */
private function processResults(Rule $rule, Collection $collection): void private function processResults(Rule $rule, Collection $collection): void
{ {
Log::debug('Going to process results.'); Log::debug(sprintf('SearchRuleEngine:: Going to process %d results.', $collection->count()));
/** @var array $group */ /** @var array $group */
foreach ($collection as $group) { foreach ($collection as $group) {
$this->processTransactionGroup($rule, $group); $this->processTransactionGroup($rule, $group);
@@ -155,7 +160,7 @@ class SearchRuleEngine implements RuleEngineInterface
*/ */
private function processTransactionGroup(Rule $rule, array $group): void private function processTransactionGroup(Rule $rule, array $group): void
{ {
Log::debug(sprintf('Will now execute actions on transaction group #%d', $group['id'])); Log::debug(sprintf('SearchRuleEngine:: Will now execute actions on transaction group #%d', $group['id']));
/** @var array $transaction */ /** @var array $transaction */
foreach ($group['transactions'] as $transaction) { foreach ($group['transactions'] as $transaction) {
$this->processTransactionJournal($rule, $transaction); $this->processTransactionJournal($rule, $transaction);
@@ -169,7 +174,7 @@ class SearchRuleEngine implements RuleEngineInterface
*/ */
private function processTransactionJournal(Rule $rule, array $transaction): void private function processTransactionJournal(Rule $rule, array $transaction): void
{ {
Log::debug(sprintf('Will now execute actions on transaction journal #%d', $transaction['transaction_journal_id'])); Log::debug(sprintf('SearchRuleEngine:: Will now execute actions on transaction journal #%d', $transaction['transaction_journal_id']));
/** @var RuleAction $ruleAction */ /** @var RuleAction $ruleAction */
foreach ($rule->ruleActions as $ruleAction) { foreach ($rule->ruleActions as $ruleAction) {
$break = $this->processRuleAction($ruleAction, $transaction); $break = $this->processRuleAction($ruleAction, $transaction);