mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-11-21 09:00:07 +00:00
Merge branch 'develop' of https://github.com/JC5/firefly-iii into develop
# By Robert Horlings # Via Robert Horlings (2) and James Cole (1) * 'develop' of https://github.com/JC5/firefly-iii: Added button to specify parameters and execute the job Added missing imports for job Implemented job to execute rulegroup on existing transactions Moved JournalCollector to other package to encourage reuse
This commit is contained in:
@@ -88,7 +88,7 @@ class Processor
|
||||
public function collectJournals()
|
||||
{
|
||||
$args = [$this->accounts, Auth::user(), $this->settings['startDate'], $this->settings['endDate']];
|
||||
$journalCollector = app('FireflyIII\Export\JournalCollector', $args);
|
||||
$journalCollector = app('FireflyIII\Repositories\Journal\JournalCollector', $args);
|
||||
$this->journals = $journalCollector->collect();
|
||||
Log::debug(
|
||||
'Collected ' .
|
||||
|
||||
@@ -4,10 +4,14 @@ declare(strict_types = 1);
|
||||
namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use ExpandedForm;
|
||||
use FireflyIII\Http\Requests\RuleGroupFormRequest;
|
||||
use FireflyIII\Http\Requests\SelectTransactionsRequest;
|
||||
use FireflyIII\Jobs\ExecuteRuleGroupOnExistingTransactions;
|
||||
use FireflyIII\Models\RuleGroup;
|
||||
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use Input;
|
||||
use Preferences;
|
||||
use Session;
|
||||
@@ -205,4 +209,47 @@ class RuleGroupController extends Controller
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a form for the user to select a range of transactions to execute this rulegroup for
|
||||
* @param RuleGroup $ruleGroup
|
||||
*/
|
||||
public function selectTransactions(AccountRepositoryInterface $repository, RuleGroup $ruleGroup)
|
||||
{
|
||||
// does the user have shared accounts?
|
||||
$accounts = $repository->getAccounts(['Default account', 'Asset account']);
|
||||
$accountList = ExpandedForm::makeSelectList($accounts);
|
||||
$checkedAccounts = array_keys($accountList);
|
||||
$first = session('first')->format('Y-m-d');
|
||||
$today = Carbon::create()->format('Y-m-d');
|
||||
|
||||
return view('rules.rule-group.select-transactions', compact('checkedAccounts', 'accountList', 'first', 'today', 'ruleGroup'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the given rulegroup on a set of existing transactions
|
||||
* @param RuleGroup $ruleGroup
|
||||
*/
|
||||
public function execute(SelectTransactionsRequest $request, AccountRepositoryInterface $repository, RuleGroup $ruleGroup)
|
||||
{
|
||||
// Get parameters specified by the user
|
||||
$accounts = $repository->get($request->get('accounts'));
|
||||
$startDate = new Carbon($request->get('start_date'));
|
||||
$endDate = new Carbon($request->get('end_date'));
|
||||
|
||||
// Create a job to do the work asynchronously
|
||||
$job = new ExecuteRuleGroupOnExistingTransactions($ruleGroup);
|
||||
|
||||
// Apply parameters to the job
|
||||
$job->setUser(Auth::user());
|
||||
$job->setAccounts($accounts);
|
||||
$job->setStartDate($startDate);
|
||||
$job->setEndDate($endDate);
|
||||
|
||||
// Dispatch a new job to execute it in a queue
|
||||
$this->dispatch($job);
|
||||
|
||||
// Tell the user that the job is queued
|
||||
Session::flash('success', trans('firefly.executed_group_on_existing_transactions', ['title' => $ruleGroup->title]));
|
||||
return redirect()->route('rules.index');
|
||||
}
|
||||
}
|
||||
|
||||
50
app/Http/Requests/SelectTransactionsRequest.php
Normal file
50
app/Http/Requests/SelectTransactionsRequest.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
declare(strict_types = 1);
|
||||
/**
|
||||
* SelectTransactionsRequest.php
|
||||
* Copyright (C) 2016 Robert Horlings
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Http\Requests;
|
||||
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
|
||||
/**
|
||||
* Class ExportFormRequest
|
||||
*
|
||||
*
|
||||
* @package FireflyIII\Http\Requests
|
||||
*/
|
||||
class SelectTransactionsRequest extends Request
|
||||
{
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
// Only allow logged in users
|
||||
return Auth::check();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
$sessionFirst = clone session('first');
|
||||
|
||||
$first = $sessionFirst->subDay()->format('Y-m-d');
|
||||
$today = Carbon::create()->addDay()->format('Y-m-d');
|
||||
|
||||
return [
|
||||
'start_date' => 'required|date|after:' . $first,
|
||||
'end_date' => 'required|date|before:' . $today,
|
||||
'accounts' => 'required',
|
||||
'accounts.*' => 'required|exists:accounts,id|belongsToUser:accounts',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -289,12 +289,14 @@ Route::group(
|
||||
Route::get('/rules/groups/delete/{ruleGroup}', ['uses' => 'RuleGroupController@delete', 'as' => 'rules.rule-group.delete']);
|
||||
Route::get('/rules/groups/up/{ruleGroup}', ['uses' => 'RuleGroupController@up', 'as' => 'rules.rule-group.up']);
|
||||
Route::get('/rules/groups/down/{ruleGroup}', ['uses' => 'RuleGroupController@down', 'as' => 'rules.rule-group.down']);
|
||||
|
||||
Route::get('/rules/groups/select_transactions/{ruleGroup}', ['uses' => 'RuleGroupController@selectTransactions', 'as' => 'rules.rule-group.select_transactions']);
|
||||
|
||||
// rule groups POST
|
||||
Route::post('/rules/groups/store', ['uses' => 'RuleGroupController@store', 'as' => 'rules.rule-group.store']);
|
||||
Route::post('/rules/groups/update/{ruleGroup}', ['uses' => 'RuleGroupController@update', 'as' => 'rules.rule-group.update']);
|
||||
Route::post('/rules/groups/destroy/{ruleGroup}', ['uses' => 'RuleGroupController@destroy', 'as' => 'rules.rule-group.destroy']);
|
||||
|
||||
Route::post('/rules/groups/execute/{ruleGroup}', ['uses' => 'RuleGroupController@execute', 'as' => 'rules.rule-group.execute']);
|
||||
|
||||
/**
|
||||
* Search Controller
|
||||
*/
|
||||
|
||||
158
app/Jobs/ExecuteRuleGroupOnExistingTransactions.php
Normal file
158
app/Jobs/ExecuteRuleGroupOnExistingTransactions.php
Normal file
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Jobs;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Jobs\Job;
|
||||
use FireflyIII\User;
|
||||
use FireflyIII\Models\RuleGroup;
|
||||
use FireflyIII\Rules\Processor;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Log;
|
||||
|
||||
class ExecuteRuleGroupOnExistingTransactions extends Job implements ShouldQueue
|
||||
{
|
||||
use InteractsWithQueue, SerializesModels;
|
||||
|
||||
/** @var RuleGroup */
|
||||
private $ruleGroup;
|
||||
/** @var Collection */
|
||||
private $accounts;
|
||||
/** @var Carbon */
|
||||
private $endDate;
|
||||
/** @var Carbon */
|
||||
private $startDate;
|
||||
/** @var User */
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(RuleGroup $ruleGroup)
|
||||
{
|
||||
$this->ruleGroup = $ruleGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
// Lookup all journals that match the parameters specified
|
||||
$journals = $this->collectJournals();
|
||||
|
||||
// Find processors for each rule within the current rule group
|
||||
$processors = $this->collectProcessors();
|
||||
|
||||
// Execute the rules for each transaction
|
||||
foreach($journals as $journal) {
|
||||
/** @var Processor $processor */
|
||||
foreach ($processors as $processor) {
|
||||
$processor->handleTransactionJournal($journal);
|
||||
|
||||
// Stop processing this group if the rule specifies 'stop_processing'
|
||||
if ($processor->getRule()->stop_processing) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect all journals that should be processed
|
||||
* @return Collection
|
||||
*/
|
||||
protected function collectJournals()
|
||||
{
|
||||
$args = [$this->accounts, $this->user, $this->startDate, $this->endDate];
|
||||
$journalCollector = app('FireflyIII\Repositories\Journal\JournalCollector', $args);
|
||||
return $journalCollector->collect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects a list of rule processors, one for each rule within the rule group
|
||||
* @return array
|
||||
*/
|
||||
protected function collectProcessors() {
|
||||
// Find all rules belonging to this rulegroup
|
||||
$rules = $this->ruleGroup->rules()
|
||||
->leftJoin('rule_triggers', 'rules.id', '=', 'rule_triggers.rule_id')
|
||||
->where('rule_triggers.trigger_type', 'user_action')
|
||||
->where('rule_triggers.trigger_value', 'store-journal')
|
||||
->where('rules.active', 1)
|
||||
->get(['rules.*']);
|
||||
|
||||
// Create a list of processors for these rules
|
||||
return array_map( function( $rule ) {
|
||||
return Processor::make($rule);
|
||||
}, $rules->all());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return User
|
||||
*/
|
||||
public function getUser() {
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param User $user
|
||||
*/
|
||||
public function setUser(User $user) {
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getAccounts() {
|
||||
return $this->accounts;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Carbon $user
|
||||
*/
|
||||
public function setAccounts(Collection $accounts) {
|
||||
$this->accounts = $accounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Carbon\Carbon
|
||||
*/
|
||||
public function getStartDate() {
|
||||
return $this->startDate;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Carbon $date
|
||||
*/
|
||||
public function setStartDate(Carbon $date) {
|
||||
$this->startDate = $date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Carbon\Carbon
|
||||
*/
|
||||
public function getEndDate() {
|
||||
return $this->endDate;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Carbon $date
|
||||
*/
|
||||
public function setEndDate(Carbon $date) {
|
||||
$this->endDate = $date;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,7 +8,7 @@ declare(strict_types = 1);
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Export;
|
||||
namespace FireflyIII\Repositories\Journal;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\User;
|
||||
@@ -140,6 +140,14 @@ final class Processor
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return \FireflyIII\Models\Rule
|
||||
*/
|
||||
public function getRule() {
|
||||
return $this->rule;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
|
||||
@@ -133,6 +133,13 @@ return [
|
||||
'warning_no_matching_transactions' => 'No matching transactions found. Please note that for performance reasons, only the last :num_transactions transactions have been checked.',
|
||||
'warning_no_valid_triggers' => 'No valid triggers provided.',
|
||||
|
||||
'execute_on_existing_transactions' => 'Execute for existing transactions',
|
||||
'execute_on_existing_transactions_intro' => 'When a rule or group has been changed or added, you can execute it for existing transactions',
|
||||
'execute_on_existing_transactions_short' => 'Existing transactions',
|
||||
'executed_group_on_existing_transactions' => 'Executed group ":title" for existing transactions',
|
||||
'include_transactions_from_accounts' => 'Include transactions from these accounts',
|
||||
'execute' => 'Execute',
|
||||
|
||||
// actions and triggers
|
||||
'rule_trigger_user_action' => 'User action is ":trigger_value"',
|
||||
'rule_trigger_from_account_starts' => 'Source account starts with ":trigger_value"',
|
||||
|
||||
@@ -131,6 +131,13 @@ return [
|
||||
'warning_transaction_subset' => 'Je ziet hier maximaal :max_num_transactions transacties omdat je anders veel te lang moet wachten',
|
||||
'warning_no_matching_transactions' => 'Niks gevonden in je laatste :num_transactions transacties.',
|
||||
'warning_no_valid_triggers' => 'Geen geldige triggers gevonden.',
|
||||
|
||||
'execute_on_existing_transactions' => 'Uitvoeren op bestaande transacties',
|
||||
'execute_on_existing_transactions_intro' => 'Wanneer een regel of groep is veranderd of toegevoegd, kun je hem hier uitvoeren voor bestaande transacties.',
|
||||
'execute_on_existing_transactions_short' => 'Bestaande transacties',
|
||||
'executed_group_on_existing_transactions' => 'Groep :title is uitgevoerd op bestaande transacties',
|
||||
'include_transactions_from_accounts' => 'Gebruik transacties van deze rekeningen',
|
||||
'execute' => 'Uitvoeren',
|
||||
|
||||
// actions and triggers
|
||||
'rule_trigger_user_action' => 'Gebruikersactie is ":trigger_value"',
|
||||
|
||||
@@ -47,6 +47,8 @@
|
||||
class="fa fa-fw fa-pencil"></i> {{ 'edit'|_ }}</a></li>
|
||||
<li><a href="{{ route('rules.rule-group.delete',ruleGroup.id) }}"><i
|
||||
class="fa fa-fw fa-trash"></i> {{ 'delete'|_ }}</a></li>
|
||||
<li><a href="{{ route('rules.rule-group.select_transactions',ruleGroup.id) }}"><i
|
||||
class="fa fa-fw fa-anchor"></i> {{ 'execute_on_existing_transactions_short'|_ }}</a></li>
|
||||
{% if ruleGroup.order > 1 %}
|
||||
<li><a href="{{ route('rules.rule-group.up',ruleGroup.id) }}"><i
|
||||
class="fa fa-fw fa-arrow-up"></i> {{ 'move_rule_group_up'|_ }}</a></li>
|
||||
|
||||
42
resources/views/rules/rule-group/select-transactions.twig
Normal file
42
resources/views/rules/rule-group/select-transactions.twig
Normal file
@@ -0,0 +1,42 @@
|
||||
{% extends "./layout/default.twig" %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form method="POST" action="{{ route('rules.rule-group.execute', ruleGroup.id) }}" accept-charset="UTF-8" class="form-horizontal" id="execute-rule-group">
|
||||
<input name="_token" type="hidden" value="{{ csrf_token() }}">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-sm-12 col-xs-12">
|
||||
|
||||
<div class="box box-primary">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'execute_on_existing_transactions'|_ }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div id="form-body">
|
||||
<p>
|
||||
{{ 'execute_on_existing_transactions_intro'|_ }}
|
||||
</p>
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-md-8 col-sm-12 col-xs-12">
|
||||
{{ ExpandedForm.date('start_date', first) }}
|
||||
{{ ExpandedForm.date('end_date', today) }}
|
||||
|
||||
<!-- ACCOUNTS -->
|
||||
{{ ExpandedForm.multiCheckbox('accounts',accountList, checkedAccounts, {' class': 'account-checkbox', 'label': trans('firefly.include_transactions_from_accounts') }) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<input type="submit" name="submit" value="{{ 'execute'|_ }}" id="do-execute-button" class="btn btn-success pull-right"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user