mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-29 18:20:01 +00:00
Replace transaction collector.
This commit is contained in:
381
app/Console/Commands/Tools/ApplyRules.php
Normal file
381
app/Console/Commands/Tools/ApplyRules.php
Normal file
@@ -0,0 +1,381 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace FireflyIII\Console\Commands\Tools;
|
||||||
|
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Console\Commands\VerifiesAccessToken;
|
||||||
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
|
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||||
|
use FireflyIII\Models\AccountType;
|
||||||
|
use FireflyIII\Models\Rule;
|
||||||
|
use FireflyIII\Models\RuleGroup;
|
||||||
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||||
|
use FireflyIII\TransactionRules\Processor;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ApplyRules
|
||||||
|
*/
|
||||||
|
class ApplyRules extends Command
|
||||||
|
{
|
||||||
|
use VerifiesAccessToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'This command will apply your rules and rule groups on a selection of your transactions.';
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature
|
||||||
|
= 'firefly-iii:apply-rules
|
||||||
|
{--user=1 : The user ID that the import should import for.}
|
||||||
|
{--token= : The user\'s access token.}
|
||||||
|
{--accounts= : A comma-separated list of asset accounts or liabilities to apply your rules to.}
|
||||||
|
{--rule_groups= : A comma-separated list of rule groups to apply. Take the ID\'s of these rule groups from the Firefly III interface.}
|
||||||
|
{--rules= : A comma-separated list of rules to apply. Take the ID\'s of these rules from the Firefly III interface. Using this option overrules the option that selects rule groups.}
|
||||||
|
{--all_rules : If set, will overrule both settings and simply apply ALL of your rules.}
|
||||||
|
{--start_date= : The date of the earliest transaction to be included (inclusive). If omitted, will be your very first transaction ever. Format: YYYY-MM-DD}
|
||||||
|
{--end_date= : The date of the latest transaction to be included (inclusive). If omitted, will be your latest transaction ever. Format: YYYY-MM-DD}';
|
||||||
|
|
||||||
|
/** @var Collection */
|
||||||
|
private $accounts;
|
||||||
|
/** @var array */
|
||||||
|
private $acceptedAccounts;
|
||||||
|
/** @var Carbon */
|
||||||
|
private $endDate;
|
||||||
|
/** @var Collection */
|
||||||
|
private $results;
|
||||||
|
/** @var array */
|
||||||
|
private $ruleGroupSelection;
|
||||||
|
/** @var array */
|
||||||
|
private $ruleSelection;
|
||||||
|
/** @var Carbon */
|
||||||
|
private $startDate;
|
||||||
|
/** @var Collection */
|
||||||
|
private $groups;
|
||||||
|
/** @var bool */
|
||||||
|
private $allRules;
|
||||||
|
|
||||||
|
/** @var RuleRepositoryInterface */
|
||||||
|
private $ruleRepository;
|
||||||
|
|
||||||
|
/** @var RuleGroupRepositoryInterface */
|
||||||
|
private $ruleGroupRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new command instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
$this->allRules = false;
|
||||||
|
$this->accounts = new Collection;
|
||||||
|
$this->ruleSelection = [];
|
||||||
|
$this->ruleGroupSelection = [];
|
||||||
|
$this->results = new Collection;
|
||||||
|
$this->ruleRepository = app(RuleRepositoryInterface::class);
|
||||||
|
$this->ruleGroupRepository = app(RuleGroupRepositoryInterface::class);
|
||||||
|
$this->acceptedAccounts = [AccountType::DEFAULT, AccountType::DEBT, AccountType::ASSET, AccountType::LOAN, AccountType::MORTGAGE];
|
||||||
|
$this->groups = new Collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
public function handle(): int
|
||||||
|
{
|
||||||
|
if (!$this->verifyAccessToken()) {
|
||||||
|
$this->error('Invalid access token.');
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// set user:
|
||||||
|
$this->ruleRepository->setUser($this->getUser());
|
||||||
|
$this->ruleGroupRepository->setUser($this->getUser());
|
||||||
|
|
||||||
|
$result = $this->verifyInput();
|
||||||
|
if (false === $result) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->allRules = $this->option('all_rules');
|
||||||
|
|
||||||
|
$this->grabAllRules();
|
||||||
|
|
||||||
|
// loop all groups and rules and indicate if they're included:
|
||||||
|
$count = 0;
|
||||||
|
/** @var RuleGroup $group */
|
||||||
|
foreach ($this->groups as $group) {
|
||||||
|
/** @var Rule $rule */
|
||||||
|
foreach ($group->rules as $rule) {
|
||||||
|
// if in rule selection, or group in selection or all rules, it's included.
|
||||||
|
if ($this->includeRule($rule, $group)) {
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (0 === $count) {
|
||||||
|
$this->error('No rules or rule groups have been included.');
|
||||||
|
$this->warn('Make a selection using:');
|
||||||
|
$this->warn(' --rules=1,2,...');
|
||||||
|
$this->warn(' --rule_groups=1,2,...');
|
||||||
|
$this->warn(' --all_rules');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// get transactions from asset accounts.
|
||||||
|
/** @var GroupCollectorInterface $collector */
|
||||||
|
$collector = app(GroupCollectorInterface::class);
|
||||||
|
$collector->setUser($this->getUser());
|
||||||
|
$collector->setAccounts($this->accounts);
|
||||||
|
$collector->setRange($this->startDate, $this->endDate);
|
||||||
|
$journals = $collector->getExtractedJournals();
|
||||||
|
|
||||||
|
// start running rules.
|
||||||
|
$this->line(sprintf('Will apply %d rules to %d transactions.', $count, count($journals)));
|
||||||
|
|
||||||
|
// start looping.
|
||||||
|
$bar = $this->output->createProgressBar(count($journals) * $count);
|
||||||
|
Log::debug(sprintf('Now looping %d transactions.', count($journals)));
|
||||||
|
/** @var array $journal */
|
||||||
|
foreach ($journals as $journal) {
|
||||||
|
Log::debug('Start of new journal.');
|
||||||
|
foreach ($this->groups as $group) {
|
||||||
|
$groupTriggered = false;
|
||||||
|
/** @var Rule $rule */
|
||||||
|
foreach ($group->rules as $rule) {
|
||||||
|
$ruleTriggered = false;
|
||||||
|
// if in rule selection, or group in selection or all rules, it's included.
|
||||||
|
if ($this->includeRule($rule, $group)) {
|
||||||
|
/** @var Processor $processor */
|
||||||
|
$processor = app(Processor::class);
|
||||||
|
$processor->make($rule, true);
|
||||||
|
$ruleTriggered = $processor->handleJournalArray($journal);
|
||||||
|
$bar->advance();
|
||||||
|
if ($ruleTriggered) {
|
||||||
|
$groupTriggered = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the rule is triggered and stop processing is true, cancel the entire group.
|
||||||
|
if ($ruleTriggered && $rule->stop_processing) {
|
||||||
|
Log::info('Break out group because rule was triggered.');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if group is triggered and stop processing is true, cancel the whole thing.
|
||||||
|
if ($groupTriggered && $group->stop_processing) {
|
||||||
|
Log::info('Break out ALL because group was triggered.');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log::debug('Done with all rules for this group + done with journal.');
|
||||||
|
}
|
||||||
|
$this->line('');
|
||||||
|
$this->line('Done!');
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
private function verifyInput(): bool
|
||||||
|
{
|
||||||
|
// verify account.
|
||||||
|
$result = $this->verifyInputAccounts();
|
||||||
|
if (false === $result) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify rule groups.
|
||||||
|
$result = $this->verifyInputRuleGroups();
|
||||||
|
if (false === $result) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify rules.
|
||||||
|
$result = $this->verifyInputRules();
|
||||||
|
if (false === $result) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->verifyInputDates();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
private function verifyInputAccounts(): bool
|
||||||
|
{
|
||||||
|
$accountString = $this->option('accounts');
|
||||||
|
if (null === $accountString || '' === $accountString) {
|
||||||
|
$this->error('Please use the --accounts option to indicate the accounts to apply rules to.');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$finalList = new Collection;
|
||||||
|
$accountList = explode(',', $accountString);
|
||||||
|
|
||||||
|
if (0 === count($accountList)) {
|
||||||
|
$this->error('Please use the --accounts option to indicate the accounts to apply rules to.');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var AccountRepositoryInterface $accountRepository */
|
||||||
|
$accountRepository = app(AccountRepositoryInterface::class);
|
||||||
|
$accountRepository->setUser($this->getUser());
|
||||||
|
|
||||||
|
|
||||||
|
foreach ($accountList as $accountId) {
|
||||||
|
$accountId = (int)$accountId;
|
||||||
|
$account = $accountRepository->findNull($accountId);
|
||||||
|
if (null !== $account && in_array($account->accountType->type, $this->acceptedAccounts, true)) {
|
||||||
|
$finalList->push($account);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 === $finalList->count()) {
|
||||||
|
$this->error('Please make sure all accounts in --accounts are asset accounts or liabilities.');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$this->accounts = $finalList;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function verifyInputRuleGroups(): bool
|
||||||
|
{
|
||||||
|
$ruleGroupString = $this->option('rule_groups');
|
||||||
|
if (null === $ruleGroupString || '' === $ruleGroupString) {
|
||||||
|
// can be empty.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$ruleGroupList = explode(',', $ruleGroupString);
|
||||||
|
|
||||||
|
if (0 === count($ruleGroupList)) {
|
||||||
|
// can be empty.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
foreach ($ruleGroupList as $ruleGroupId) {
|
||||||
|
$ruleGroup = $this->ruleGroupRepository->find((int)$ruleGroupId);
|
||||||
|
if ($ruleGroup->active) {
|
||||||
|
$this->ruleGroupSelection[] = $ruleGroup->id;
|
||||||
|
}
|
||||||
|
if (false === $ruleGroup->active) {
|
||||||
|
$this->warn(sprintf('Will ignore inactive rule group #%d ("%s")', $ruleGroup->id, $ruleGroup->title));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function verifyInputRules(): bool
|
||||||
|
{
|
||||||
|
$ruleString = $this->option('rules');
|
||||||
|
if (null === $ruleString || '' === $ruleString) {
|
||||||
|
// can be empty.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$ruleList = explode(',', $ruleString);
|
||||||
|
|
||||||
|
if (0 === count($ruleList)) {
|
||||||
|
// can be empty.
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
foreach ($ruleList as $ruleId) {
|
||||||
|
$rule = $this->ruleRepository->find((int)$ruleId);
|
||||||
|
if (null !== $rule && $rule->active) {
|
||||||
|
$this->ruleSelection[] = $rule->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
private function verifyInputDates(): void
|
||||||
|
{
|
||||||
|
// parse start date.
|
||||||
|
$startDate = Carbon::now()->startOfMonth();
|
||||||
|
$startString = $this->option('start_date');
|
||||||
|
if (null === $startString) {
|
||||||
|
/** @var JournalRepositoryInterface $repository */
|
||||||
|
$repository = app(JournalRepositoryInterface::class);
|
||||||
|
$repository->setUser($this->getUser());
|
||||||
|
$first = $repository->firstNull();
|
||||||
|
if (null !== $first) {
|
||||||
|
$startDate = $first->date;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (null !== $startString && '' !== $startString) {
|
||||||
|
$startDate = Carbon::createFromFormat('Y-m-d', $startString);
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse end date
|
||||||
|
$endDate = Carbon::now();
|
||||||
|
$endString = $this->option('end_date');
|
||||||
|
if (null !== $endString && '' !== $endString) {
|
||||||
|
$endDate = Carbon::createFromFormat('Y-m-d', $endString);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($startDate > $endDate) {
|
||||||
|
[$endDate, $startDate] = [$startDate, $endDate];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->startDate = $startDate;
|
||||||
|
$this->endDate = $endDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
private function grabAllRules(): void
|
||||||
|
{
|
||||||
|
$this->groups = $this->ruleGroupRepository->getActiveGroups();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Rule $rule
|
||||||
|
* @param RuleGroup $group
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function includeRule(Rule $rule, RuleGroup $group): bool
|
||||||
|
{
|
||||||
|
return in_array($group->id, $this->ruleGroupSelection, true) ||
|
||||||
|
in_array($rule->id, $this->ruleSelection, true) ||
|
||||||
|
$this->allRules;
|
||||||
|
}
|
||||||
|
}
|
@@ -51,7 +51,7 @@ class StoredGroupEventHandler
|
|||||||
|
|
||||||
foreach ($journals as $journal) {
|
foreach ($journals as $journal) {
|
||||||
$ruleGroupRepos->setUser($journal->user);
|
$ruleGroupRepos->setUser($journal->user);
|
||||||
$groups = $ruleGroupRepos->getActiveGroups($journal->user);
|
$groups = $ruleGroupRepos->getActiveGroups();
|
||||||
|
|
||||||
/** @var RuleGroup $group */
|
/** @var RuleGroup $group */
|
||||||
foreach ($groups as $group) {
|
foreach ($groups as $group) {
|
||||||
|
@@ -52,7 +52,7 @@ class UpdatedGroupEventHandler
|
|||||||
foreach ($journals as $journal) {
|
foreach ($journals as $journal) {
|
||||||
$ruleGroupRepos->setUser($journal->user);
|
$ruleGroupRepos->setUser($journal->user);
|
||||||
|
|
||||||
$groups = $ruleGroupRepos->getActiveGroups($journal->user);
|
$groups = $ruleGroupRepos->getActiveGroups();
|
||||||
|
|
||||||
/** @var RuleGroup $group */
|
/** @var RuleGroup $group */
|
||||||
foreach ($groups as $group) {
|
foreach ($groups as $group) {
|
||||||
|
@@ -25,6 +25,7 @@ namespace FireflyIII\Http\Controllers\Account;
|
|||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
|
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||||
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
|
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
|
||||||
use FireflyIII\Http\Controllers\Controller;
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
@@ -76,8 +77,8 @@ class ShowController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Show an account.
|
* Show an account.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param Account $account
|
* @param Account $account
|
||||||
* @param Carbon|null $start
|
* @param Carbon|null $start
|
||||||
* @param Carbon|null $end
|
* @param Carbon|null $end
|
||||||
*
|
*
|
||||||
@@ -119,19 +120,22 @@ class ShowController extends Controller
|
|||||||
$subTitle = (string)trans('firefly.journals_in_period_for_account', ['name' => $account->name, 'start' => $fStart, 'end' => $fEnd]);
|
$subTitle = (string)trans('firefly.journals_in_period_for_account', ['name' => $account->name, 'start' => $fStart, 'end' => $fEnd]);
|
||||||
$chartUri = route('chart.account.period', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')]);
|
$chartUri = route('chart.account.period', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')]);
|
||||||
$periods = $this->getAccountPeriodOverview($account, $end);
|
$periods = $this->getAccountPeriodOverview($account, $end);
|
||||||
/** @var TransactionCollectorInterface $collector */
|
|
||||||
$collector = app(TransactionCollectorInterface::class);
|
|
||||||
$collector->setAccounts(new Collection([$account]))->setLimit($pageSize)->setPage($page);
|
|
||||||
$collector->setRange($start, $end);
|
|
||||||
$transactions = $collector->getPaginatedTransactions();
|
|
||||||
$transactions->setPath(route('accounts.show', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')]));
|
|
||||||
$showAll = false;
|
|
||||||
|
|
||||||
|
/** @var GroupCollectorInterface $collector */
|
||||||
|
$collector = app(GroupCollectorInterface::class);
|
||||||
|
$collector
|
||||||
|
->setAccounts(new Collection([$account]))
|
||||||
|
->setLimit($pageSize)
|
||||||
|
->setPage($page)
|
||||||
|
->setRange($start, $end);
|
||||||
|
$groups = $collector->getPaginatedGroups();
|
||||||
|
$groups->setPath(route('accounts.show', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')]));
|
||||||
|
$showAll = false;
|
||||||
|
|
||||||
return view(
|
return view(
|
||||||
'accounts.show',
|
'accounts.show',
|
||||||
compact(
|
compact(
|
||||||
'account', 'showAll', 'what', 'currency', 'today', 'periods', 'subTitleIcon', 'transactions', 'subTitle', 'start', 'end',
|
'account', 'showAll', 'what', 'currency', 'today', 'periods', 'subTitleIcon', 'groups', 'subTitle', 'start', 'end',
|
||||||
'chartUri'
|
'chartUri'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@@ -34,19 +34,18 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|||||||
/**
|
/**
|
||||||
* Class RuleGroup.
|
* Class RuleGroup.
|
||||||
*
|
*
|
||||||
* @property bool $active
|
* @property bool $active
|
||||||
* @property User $user
|
* @property User $user
|
||||||
* @property Carbon $created_at
|
* @property Carbon $created_at
|
||||||
* @property Carbon $updated_at
|
* @property Carbon $updated_at
|
||||||
* @property string $title
|
* @property string $title
|
||||||
* @property string $text
|
* @property string $text
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property int $order
|
* @property int $order
|
||||||
* @property Collection $rules
|
* @property Collection $rules
|
||||||
* @property string description
|
* @property string description
|
||||||
* @property \Illuminate\Support\Carbon|null $deleted_at
|
* @property \Illuminate\Support\Carbon|null $deleted_at
|
||||||
* @property int $user_id
|
* @property int $user_id
|
||||||
* @property string|null $description
|
|
||||||
* @method static bool|null forceDelete()
|
* @method static bool|null forceDelete()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\FireflyIII\Models\RuleGroup newModelQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|\FireflyIII\Models\RuleGroup newModelQuery()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|\FireflyIII\Models\RuleGroup newQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|\FireflyIII\Models\RuleGroup newQuery()
|
||||||
@@ -64,6 +63,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|||||||
* @method static \Illuminate\Database\Eloquent\Builder|\FireflyIII\Models\RuleGroup whereUserId($value)
|
* @method static \Illuminate\Database\Eloquent\Builder|\FireflyIII\Models\RuleGroup whereUserId($value)
|
||||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\RuleGroup withTrashed()
|
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\RuleGroup withTrashed()
|
||||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\RuleGroup withoutTrashed()
|
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\RuleGroup withoutTrashed()
|
||||||
|
* @property bool $stop_processing
|
||||||
* @mixin \Eloquent
|
* @mixin \Eloquent
|
||||||
*/
|
*/
|
||||||
class RuleGroup extends Model
|
class RuleGroup extends Model
|
||||||
@@ -76,15 +76,16 @@ class RuleGroup extends Model
|
|||||||
*/
|
*/
|
||||||
protected $casts
|
protected $casts
|
||||||
= [
|
= [
|
||||||
'created_at' => 'datetime',
|
'created_at' => 'datetime',
|
||||||
'updated_at' => 'datetime',
|
'updated_at' => 'datetime',
|
||||||
'deleted_at' => 'datetime',
|
'deleted_at' => 'datetime',
|
||||||
'active' => 'boolean',
|
'active' => 'boolean',
|
||||||
'order' => 'int',
|
'stop_processing' => 'boolean',
|
||||||
|
'order' => 'int',
|
||||||
];
|
];
|
||||||
|
|
||||||
/** @var array Fields that can be filled */
|
/** @var array Fields that can be filled */
|
||||||
protected $fillable = ['user_id', 'order', 'title', 'description', 'active'];
|
protected $fillable = ['user_id', 'stop_processing', 'order', 'title', 'description', 'active'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Route binder. Converts the key in the URL to the specified object (or throw 404).
|
* Route binder. Converts the key in the URL to the specified object (or throw 404).
|
||||||
|
@@ -56,7 +56,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param RuleGroup $ruleGroup
|
* @param RuleGroup $ruleGroup
|
||||||
* @param RuleGroup|null $moveTo
|
* @param RuleGroup|null $moveTo
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
@@ -85,6 +85,49 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function resetRuleGroupOrder(): bool
|
||||||
|
{
|
||||||
|
$this->user->ruleGroups()->whereNotNull('deleted_at')->update(['order' => 0]);
|
||||||
|
|
||||||
|
$set = $this->user->ruleGroups()->where('active', 1)->orderBy('order', 'ASC')->get();
|
||||||
|
$count = 1;
|
||||||
|
/** @var RuleGroup $entry */
|
||||||
|
foreach ($set as $entry) {
|
||||||
|
$entry->order = $count;
|
||||||
|
$entry->save();
|
||||||
|
++$count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param RuleGroup $ruleGroup
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function resetRulesInGroupOrder(RuleGroup $ruleGroup): bool
|
||||||
|
{
|
||||||
|
$ruleGroup->rules()->whereNotNull('deleted_at')->update(['order' => 0]);
|
||||||
|
|
||||||
|
$set = $ruleGroup->rules()
|
||||||
|
->orderBy('order', 'ASC')
|
||||||
|
->orderBy('updated_at', 'DESC')
|
||||||
|
->get();
|
||||||
|
$count = 1;
|
||||||
|
/** @var Rule $entry */
|
||||||
|
foreach ($set as $entry) {
|
||||||
|
$entry->order = $count;
|
||||||
|
$entry->save();
|
||||||
|
++$count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $ruleGroupId
|
* @param int $ruleGroupId
|
||||||
*
|
*
|
||||||
@@ -109,13 +152,11 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param User $user
|
|
||||||
*
|
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
public function getActiveGroups(User $user): Collection
|
public function getActiveGroups(): Collection
|
||||||
{
|
{
|
||||||
return $user->ruleGroups()->where('rule_groups.active', 1)->orderBy('order', 'ASC')->get(['rule_groups.*']);
|
return $this->user->ruleGroups()->where('rule_groups.active', 1)->orderBy('order', 'ASC')->get(['rule_groups.*']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -160,16 +201,6 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface
|
|||||||
->get(['rules.*']);
|
->get(['rules.*']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function getHighestOrderRuleGroup(): int
|
|
||||||
{
|
|
||||||
$entry = $this->user->ruleGroups()->max('order');
|
|
||||||
|
|
||||||
return (int)$entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param User $user
|
* @param User $user
|
||||||
*
|
*
|
||||||
@@ -253,49 +284,6 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function resetRuleGroupOrder(): bool
|
|
||||||
{
|
|
||||||
$this->user->ruleGroups()->whereNotNull('deleted_at')->update(['order' => 0]);
|
|
||||||
|
|
||||||
$set = $this->user->ruleGroups()->where('active', 1)->orderBy('order', 'ASC')->get();
|
|
||||||
$count = 1;
|
|
||||||
/** @var RuleGroup $entry */
|
|
||||||
foreach ($set as $entry) {
|
|
||||||
$entry->order = $count;
|
|
||||||
$entry->save();
|
|
||||||
++$count;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param RuleGroup $ruleGroup
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function resetRulesInGroupOrder(RuleGroup $ruleGroup): bool
|
|
||||||
{
|
|
||||||
$ruleGroup->rules()->whereNotNull('deleted_at')->update(['order' => 0]);
|
|
||||||
|
|
||||||
$set = $ruleGroup->rules()
|
|
||||||
->orderBy('order', 'ASC')
|
|
||||||
->orderBy('updated_at', 'DESC')
|
|
||||||
->get();
|
|
||||||
$count = 1;
|
|
||||||
/** @var Rule $entry */
|
|
||||||
foreach ($set as $entry) {
|
|
||||||
$entry->order = $count;
|
|
||||||
$entry->save();
|
|
||||||
++$count;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param User $user
|
* @param User $user
|
||||||
*/
|
*/
|
||||||
@@ -328,9 +316,19 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface
|
|||||||
return $newRuleGroup;
|
return $newRuleGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getHighestOrderRuleGroup(): int
|
||||||
|
{
|
||||||
|
$entry = $this->user->ruleGroups()->max('order');
|
||||||
|
|
||||||
|
return (int)$entry;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param RuleGroup $ruleGroup
|
* @param RuleGroup $ruleGroup
|
||||||
* @param array $data
|
* @param array $data
|
||||||
*
|
*
|
||||||
* @return RuleGroup
|
* @return RuleGroup
|
||||||
*/
|
*/
|
||||||
|
@@ -59,11 +59,9 @@ interface RuleGroupRepositoryInterface
|
|||||||
public function get(): Collection;
|
public function get(): Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param User $user
|
|
||||||
*
|
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
public function getActiveGroups(User $user): Collection;
|
public function getActiveGroups(): Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param RuleGroup $group
|
* @param RuleGroup $group
|
||||||
|
@@ -25,6 +25,7 @@ namespace FireflyIII\Support\Http\Controllers;
|
|||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
|
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||||
use FireflyIII\Helpers\Collector\GroupSumCollectorInterface;
|
use FireflyIII\Helpers\Collector\GroupSumCollectorInterface;
|
||||||
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
|
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
|
||||||
use FireflyIII\Helpers\Filter\InternalTransferFilter;
|
use FireflyIII\Helpers\Filter\InternalTransferFilter;
|
||||||
@@ -69,13 +70,12 @@ trait PeriodOverview
|
|||||||
* The method has been refactored recently for better performance.
|
* The method has been refactored recently for better performance.
|
||||||
*
|
*
|
||||||
* @param Account $account The account involved
|
* @param Account $account The account involved
|
||||||
* @param Carbon $date The start date.
|
* @param Carbon $date The start date.
|
||||||
*
|
*
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
protected function getAccountPeriodOverview(Account $account, Carbon $date): Collection
|
protected function getAccountPeriodOverview(Account $account, Carbon $date): Collection
|
||||||
{
|
{
|
||||||
throw new FireflyException('Is using collector.');
|
|
||||||
/** @var AccountRepositoryInterface $repository */
|
/** @var AccountRepositoryInterface $repository */
|
||||||
$repository = app(AccountRepositoryInterface::class);
|
$repository = app(AccountRepositoryInterface::class);
|
||||||
$range = app('preferences')->get('viewRange', '1M')->data;
|
$range = app('preferences')->get('viewRange', '1M')->data;
|
||||||
@@ -100,25 +100,30 @@ trait PeriodOverview
|
|||||||
$entries = new Collection;
|
$entries = new Collection;
|
||||||
// loop dates
|
// loop dates
|
||||||
foreach ($dates as $currentDate) {
|
foreach ($dates as $currentDate) {
|
||||||
/** @var TransactionCollectorInterface $collector */
|
|
||||||
$collector = app(TransactionCollectorInterface::class);
|
|
||||||
$collector->setAccounts(new Collection([$account]))->setRange($currentDate['start'], $currentDate['end'])->setTypes([TransactionType::DEPOSIT])
|
|
||||||
->withOpposingAccount();
|
|
||||||
$earnedSet = $collector->getTransactions();
|
|
||||||
$earned = $this->groupByCurrency($earnedSet);
|
|
||||||
|
|
||||||
/** @var TransactionCollectorInterface $collector */
|
// collect from start to end:
|
||||||
$collector = app(TransactionCollectorInterface::class);
|
/** @var GroupCollectorInterface $collector */
|
||||||
$collector->setAccounts(new Collection([$account]))->setRange($currentDate['start'], $currentDate['end'])->setTypes([TransactionType::WITHDRAWAL])
|
$collector = app(GroupCollectorInterface::class);
|
||||||
->withOpposingAccount();
|
$collector->setAccounts(new Collection([$account]));
|
||||||
$spentSet = $collector->getTransactions();
|
$collector->setRange($currentDate['start'], $currentDate['end']);
|
||||||
|
$collector->setTypes([TransactionType::DEPOSIT]);
|
||||||
|
$earnedSet = $collector->getExtractedJournals();
|
||||||
|
|
||||||
|
$earned = $this->groupByCurrency($earnedSet);
|
||||||
|
|
||||||
|
/** @var GroupCollectorInterface $collector */
|
||||||
|
$collector = app(GroupCollectorInterface::class);
|
||||||
|
$collector->setAccounts(new Collection([$account]));
|
||||||
|
$collector->setRange($currentDate['start'], $currentDate['end']);
|
||||||
|
$collector->setTypes([TransactionType::WITHDRAWAL]);
|
||||||
|
$spentSet = $collector->getExtractedJournals();
|
||||||
$spent = $this->groupByCurrency($spentSet);
|
$spent = $this->groupByCurrency($spentSet);
|
||||||
|
|
||||||
$title = app('navigation')->periodShow($currentDate['start'], $currentDate['period']);
|
$title = app('navigation')->periodShow($currentDate['start'], $currentDate['period']);
|
||||||
/** @noinspection PhpUndefinedMethodInspection */
|
/** @noinspection PhpUndefinedMethodInspection */
|
||||||
$entries->push(
|
$entries->push(
|
||||||
[
|
[
|
||||||
'transactions' => 0,
|
'transactions' => count($spentSet) + count($earnedSet),
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'spent' => $spent,
|
'spent' => $spent,
|
||||||
'earned' => $earned,
|
'earned' => $earned,
|
||||||
@@ -127,17 +132,44 @@ trait PeriodOverview
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
//$cache->store($entries);
|
||||||
$cache->store($entries);
|
|
||||||
|
|
||||||
return $entries;
|
return $entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $journals
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function groupByCurrency(array $journals): array
|
||||||
|
{
|
||||||
|
$return = [];
|
||||||
|
/** @var array $journal */
|
||||||
|
foreach ($journals as $journal) {
|
||||||
|
$currencyId = (int)$journal['currency_id'];
|
||||||
|
if (!isset($return[$currencyId])) {
|
||||||
|
$currency = new TransactionCurrency;
|
||||||
|
$currency->symbol = $journal['currency_symbol'];
|
||||||
|
$currency->decimal_places = $journal['currency_decimal_places'];
|
||||||
|
$currency->name = $journal['currency_name'];
|
||||||
|
$return[$currencyId] = [
|
||||||
|
'amount' => '0',
|
||||||
|
'currency' => $currency,
|
||||||
|
//'currency' => 'x',//$currency,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$return[$currencyId]['amount'] = bcadd($return[$currencyId]['amount'], $journal['amount']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overview for single category. Has been refactored recently.
|
* Overview for single category. Has been refactored recently.
|
||||||
*
|
*
|
||||||
* @param Category $category
|
* @param Category $category
|
||||||
* @param Carbon $date
|
* @param Carbon $date
|
||||||
*
|
*
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
@@ -357,7 +389,7 @@ trait PeriodOverview
|
|||||||
/**
|
/**
|
||||||
* This shows a period overview for a tag. It goes back in time and lists all relevant transactions and sums.
|
* This shows a period overview for a tag. It goes back in time and lists all relevant transactions and sums.
|
||||||
*
|
*
|
||||||
* @param Tag $tag
|
* @param Tag $tag
|
||||||
*
|
*
|
||||||
* @param Carbon $date
|
* @param Carbon $date
|
||||||
*
|
*
|
||||||
@@ -524,31 +556,4 @@ trait PeriodOverview
|
|||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $journals
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private function groupByCurrency(array $journals): array
|
|
||||||
{
|
|
||||||
$return = [];
|
|
||||||
/** @var array $journal */
|
|
||||||
foreach ($journals as $journal) {
|
|
||||||
$currencyId = (int)$journal['currency_id'];
|
|
||||||
if (!isset($return[$currencyId])) {
|
|
||||||
$currency = new TransactionCurrency;
|
|
||||||
$currency->symbol = $journal['currency_symbol'];
|
|
||||||
$currency->decimal_places = $journal['currency_decimal_places'];
|
|
||||||
$currency->name = $journal['currency_name'];
|
|
||||||
$return[$currencyId] = [
|
|
||||||
'amount' => '0',
|
|
||||||
'currency' => $currency,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
$return[$currencyId]['amount'] = bcadd($return[$currencyId]['amount'], $journal['amount']);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -62,26 +62,6 @@ class Processor
|
|||||||
$this->actions = new Collection;
|
$this->actions = new Collection;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return found triggers
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function getFoundTriggers(): int
|
|
||||||
{
|
|
||||||
return $this->foundTriggers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set found triggers
|
|
||||||
*
|
|
||||||
* @param int $foundTriggers
|
|
||||||
*/
|
|
||||||
public function setFoundTriggers(int $foundTriggers): void
|
|
||||||
{
|
|
||||||
$this->foundTriggers = $foundTriggers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the rule
|
* Returns the rule
|
||||||
*
|
*
|
||||||
@@ -127,6 +107,126 @@ class Processor
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to check whether the current transaction would be triggered
|
||||||
|
* by the given list of triggers.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function triggered(): bool
|
||||||
|
{
|
||||||
|
Log::debug('start of Processor::triggered()');
|
||||||
|
$foundTriggers = $this->getFoundTriggers();
|
||||||
|
$hitTriggers = 0;
|
||||||
|
Log::debug(sprintf('Found triggers starts at %d', $foundTriggers));
|
||||||
|
/** @var AbstractTrigger $trigger */
|
||||||
|
foreach ($this->triggers as $trigger) {
|
||||||
|
++$foundTriggers;
|
||||||
|
Log::debug(sprintf('Now checking trigger %s with value %s', \get_class($trigger), $trigger->getTriggerValue()));
|
||||||
|
/** @var AbstractTrigger $trigger */
|
||||||
|
if ($trigger->triggered($this->journal)) {
|
||||||
|
Log::debug('Is a match!');
|
||||||
|
++$hitTriggers;
|
||||||
|
// is non-strict? then return true!
|
||||||
|
if (!$this->strict && UserAction::class !== \get_class($trigger)) {
|
||||||
|
Log::debug('Rule is set as non-strict, return true!');
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!$this->strict && UserAction::class === \get_class($trigger)) {
|
||||||
|
Log::debug('Rule is set as non-strict, but action was "user-action". Will not return true.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($trigger->stopProcessing) {
|
||||||
|
Log::debug('Stop processing this trigger and break.');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$result = ($hitTriggers === $foundTriggers && $foundTriggers > 0);
|
||||||
|
Log::debug('Result of triggered()', ['hitTriggers' => $hitTriggers, 'foundTriggers' => $foundTriggers, 'result' => $result]);
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return found triggers
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getFoundTriggers(): int
|
||||||
|
{
|
||||||
|
return $this->foundTriggers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set found triggers
|
||||||
|
*
|
||||||
|
* @param int $foundTriggers
|
||||||
|
*/
|
||||||
|
public function setFoundTriggers(int $foundTriggers): void
|
||||||
|
{
|
||||||
|
$this->foundTriggers = $foundTriggers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the actions
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @throws \FireflyIII\Exceptions\FireflyException
|
||||||
|
*/
|
||||||
|
private function actions(): void
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
* @var RuleAction $action
|
||||||
|
*/
|
||||||
|
foreach ($this->actions as $action) {
|
||||||
|
/** @var ActionInterface $actionClass */
|
||||||
|
$actionClass = ActionFactory::getAction($action);
|
||||||
|
Log::debug(sprintf('Fire action %s on journal #%d', \get_class($actionClass), $this->journal->id));
|
||||||
|
$actionClass->act($this->journal);
|
||||||
|
if ($action->stop_processing) {
|
||||||
|
Log::debug('Stop processing now and break.');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will scan the given transaction journal and check if it matches the triggers found in the Processor
|
||||||
|
* If so, it will also attempt to run the given actions on the journal. It returns a bool indicating if the transaction journal
|
||||||
|
* matches all of the triggers (regardless of whether the Processor could act on it).
|
||||||
|
*
|
||||||
|
* @param array $journal
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @throws \FireflyIII\Exceptions\FireflyException
|
||||||
|
*/
|
||||||
|
public function handleJournalArray(array $journal): bool
|
||||||
|
{
|
||||||
|
|
||||||
|
Log::debug(sprintf('handleJournalArray for journal #%d (group #%d)', $journal['transaction_journal_id'], $journal['transaction_group_id']));
|
||||||
|
|
||||||
|
// grab the actual journal.
|
||||||
|
$this->journal = TransactionJournal::find($journal['transaction_journal_id']);
|
||||||
|
// get all triggers:
|
||||||
|
$triggered = $this->triggered();
|
||||||
|
if ($triggered) {
|
||||||
|
Log::debug('Rule is triggered, go to actions.');
|
||||||
|
if ($this->actions->count() > 0) {
|
||||||
|
Log::debug('Has more than zero actions.');
|
||||||
|
$this->actions();
|
||||||
|
}
|
||||||
|
if (0 === $this->actions->count()) {
|
||||||
|
Log::info('Rule has no actions!');
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will scan the given transaction journal and check if it matches the triggers found in the Processor
|
* This method will scan the given transaction journal and check if it matches the triggers found in the Processor
|
||||||
* If so, it will also attempt to run the given actions on the journal. It returns a bool indicating if the transaction journal
|
* If so, it will also attempt to run the given actions on the journal. It returns a bool indicating if the transaction journal
|
||||||
@@ -236,69 +336,4 @@ class Processor
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Run the actions
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
* @throws \FireflyIII\Exceptions\FireflyException
|
|
||||||
*/
|
|
||||||
private function actions(): void
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var int
|
|
||||||
* @var RuleAction $action
|
|
||||||
*/
|
|
||||||
foreach ($this->actions as $action) {
|
|
||||||
/** @var ActionInterface $actionClass */
|
|
||||||
$actionClass = ActionFactory::getAction($action);
|
|
||||||
Log::debug(sprintf('Fire action %s on journal #%d', \get_class($actionClass), $this->journal->id));
|
|
||||||
$actionClass->act($this->journal);
|
|
||||||
if ($action->stop_processing) {
|
|
||||||
Log::debug('Stop processing now and break.');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to check whether the current transaction would be triggered
|
|
||||||
* by the given list of triggers.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private function triggered(): bool
|
|
||||||
{
|
|
||||||
Log::debug('start of Processor::triggered()');
|
|
||||||
$foundTriggers = $this->getFoundTriggers();
|
|
||||||
$hitTriggers = 0;
|
|
||||||
Log::debug(sprintf('Found triggers starts at %d', $foundTriggers));
|
|
||||||
/** @var AbstractTrigger $trigger */
|
|
||||||
foreach ($this->triggers as $trigger) {
|
|
||||||
++$foundTriggers;
|
|
||||||
Log::debug(sprintf('Now checking trigger %s with value %s', \get_class($trigger), $trigger->getTriggerValue()));
|
|
||||||
/** @var AbstractTrigger $trigger */
|
|
||||||
if ($trigger->triggered($this->journal)) {
|
|
||||||
Log::debug('Is a match!');
|
|
||||||
++$hitTriggers;
|
|
||||||
// is non-strict? then return true!
|
|
||||||
if (!$this->strict && UserAction::class !== \get_class($trigger)) {
|
|
||||||
Log::debug('Rule is set as non-strict, return true!');
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!$this->strict && UserAction::class === \get_class($trigger)) {
|
|
||||||
Log::debug('Rule is set as non-strict, but action was "user-action". Will not return true.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($trigger->stopProcessing) {
|
|
||||||
Log::debug('Stop processing this trigger and break.');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$result = ($hitTriggers === $foundTriggers && $foundTriggers > 0);
|
|
||||||
Log::debug('Result of triggered()', ['hitTriggers' => $hitTriggers, 'foundTriggers' => $foundTriggers, 'result' => $result]);
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -26,6 +26,9 @@ class ChangesForV480 extends Migration
|
|||||||
$table->dropColumn('transaction_group_id');
|
$table->dropColumn('transaction_group_id');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
Schema::table('rule_groups', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('stop_processing');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,5 +53,8 @@ class ChangesForV480 extends Migration
|
|||||||
$table->foreign('transaction_group_id')->references('id')->on('transaction_groups')->onDelete('cascade');
|
$table->foreign('transaction_group_id')->references('id')->on('transaction_groups')->onDelete('cascade');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
Schema::table('rule_groups', function (Blueprint $table) {
|
||||||
|
$table->boolean('stop_processing')->default(false);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user