From 4f4576e4586039868e76d028cd932c9a56aae39f Mon Sep 17 00:00:00 2001
From: James Cole
Date: Fri, 10 Oct 2025 16:41:46 +0200
Subject: [PATCH] Add option to select date, fix #11042
---
.../Controllers/Rule/SelectController.php | 68 +++++++++++--------
.../RuleGroup/ExecutionController.php | 11 +++
.../rules/rule-group/select-transactions.twig | 2 +
.../views/rules/rule/select-transactions.twig | 2 +
4 files changed, 54 insertions(+), 29 deletions(-)
diff --git a/app/Http/Controllers/Rule/SelectController.php b/app/Http/Controllers/Rule/SelectController.php
index 1084a9f2c8..c16572851b 100644
--- a/app/Http/Controllers/Rule/SelectController.php
+++ b/app/Http/Controllers/Rule/SelectController.php
@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Rule;
+use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\SelectTransactionsRequest;
@@ -56,7 +57,7 @@ class SelectController extends Controller
$this->middleware(
static function ($request, $next) {
- app('view')->share('title', (string) trans('firefly.rules'));
+ app('view')->share('title', (string)trans('firefly.rules'));
app('view')->share('mainTitleIcon', 'fa-random');
return $next($request);
@@ -71,20 +72,29 @@ class SelectController extends Controller
{
// Get parameters specified by the user
/** @var User $user */
- $user = auth()->user();
- $accounts = implode(',', $request->get('accounts'));
-
+ $user = auth()->user();
+ $accounts = implode(',', $request->get('accounts'));
// create new rule engine:
$newRuleEngine = app(RuleEngineInterface::class);
$newRuleEngine->setUser($user);
+ // add date operators.
+ if (null !== $request->get('start')) {
+ $startDate = new Carbon($request->get('start'));
+ $newRuleEngine->addOperator(['type' => 'date_after', 'value' => $startDate->format('Y-m-d')]);
+ }
+ if (null !== $request->get('end')) {
+ $endDate = new Carbon($request->get('end'));
+ $newRuleEngine->addOperator(['type' => 'date_before', 'value' => $endDate->format('Y-m-d')]);
+ }
+
// add extra operators:
$newRuleEngine->addOperator(['type' => 'account_id', 'value' => $accounts]);
// set rules:
$newRuleEngine->setRules(new Collection()->push($rule));
$newRuleEngine->fire();
- $resultCount = $newRuleEngine->getResults();
+ $resultCount = $newRuleEngine->getResults();
session()->flash('success', trans_choice('firefly.applied_rule_selection', $resultCount, ['title' => $rule->title]));
@@ -94,7 +104,7 @@ class SelectController extends Controller
/**
* View to select transactions by a rule.
*/
- public function selectTransactions(Rule $rule): Factory|RedirectResponse|View
+ public function selectTransactions(Rule $rule): Factory | RedirectResponse | View
{
if (false === $rule->active) {
session()->flash('warning', trans('firefly.cannot_fire_inactive_rules'));
@@ -102,7 +112,7 @@ class SelectController extends Controller
return redirect(route('rules.index'));
}
// does the user have shared accounts?
- $subTitle = (string) trans('firefly.apply_rule_selection', ['title' => $rule->title]);
+ $subTitle = (string)trans('firefly.apply_rule_selection', ['title' => $rule->title]);
return view('rules.rule.select-transactions', compact('rule', 'subTitle'));
}
@@ -116,25 +126,25 @@ class SelectController extends Controller
public function testTriggers(TestRuleFormRequest $request): JsonResponse
{
// build fake rule
- $rule = new Rule();
+ $rule = new Rule();
/** @var \Illuminate\Database\Eloquent\Collection $triggers */
- $triggers = new Collection();
- $rule->strict = '1' === $request->get('strict');
+ $triggers = new Collection();
+ $rule->strict = '1' === $request->get('strict');
// build trigger array from response
- $textTriggers = $this->getValidTriggerList($request);
+ $textTriggers = $this->getValidTriggerList($request);
// warn if nothing.
if (0 === count($textTriggers)) {
- return response()->json(['html' => '', 'warning' => (string) trans('firefly.warning_no_valid_triggers')]);
+ return response()->json(['html' => '', 'warning' => (string)trans('firefly.warning_no_valid_triggers')]);
}
foreach ($textTriggers as $textTrigger) {
- $needsContext = config(sprintf('search.operators.%s.needs_context', $textTrigger['type'])) ?? true;
- $trigger = new RuleTrigger();
- $trigger->trigger_type = $textTrigger['type'];
- $trigger->trigger_value = $textTrigger['value'];
+ $needsContext = config(sprintf('search.operators.%s.needs_context', $textTrigger['type'])) ?? true;
+ $trigger = new RuleTrigger();
+ $trigger->trigger_type = $textTrigger['type'];
+ $trigger->trigger_value = $textTrigger['value'];
if (false === $needsContext) {
$trigger->trigger_value = 'true';
}
@@ -149,22 +159,22 @@ class SelectController extends Controller
// create new rule engine:
/** @var RuleEngineInterface $newRuleEngine */
- $newRuleEngine = app(RuleEngineInterface::class);
+ $newRuleEngine = app(RuleEngineInterface::class);
// set rules:
$newRuleEngine->setRules(new Collection()->push($rule));
$newRuleEngine->setRefreshTriggers(false);
- $collection = $newRuleEngine->find();
- $collection = $collection->slice(0, 20);
+ $collection = $newRuleEngine->find();
+ $collection = $collection->slice(0, 20);
// Warn the user if only a subset of transactions is returned
- $warning = '';
+ $warning = '';
if (0 === count($collection)) {
- $warning = (string) trans('firefly.warning_no_matching_transactions');
+ $warning = (string)trans('firefly.warning_no_matching_transactions');
}
// Return json response
- $view = 'ERROR, see logs.';
+ $view = 'ERROR, see logs.';
try {
$view = view('list.journals-array-tiny', ['groups' => $collection])->render();
@@ -187,26 +197,26 @@ class SelectController extends Controller
*/
public function testTriggersByRule(Rule $rule): JsonResponse
{
- $triggers = $rule->ruleTriggers;
+ $triggers = $rule->ruleTriggers;
if (0 === count($triggers)) {
- return response()->json(['html' => '', 'warning' => (string) trans('firefly.warning_no_valid_triggers')]);
+ return response()->json(['html' => '', 'warning' => (string)trans('firefly.warning_no_valid_triggers')]);
}
// create new rule engine:
$newRuleEngine = app(RuleEngineInterface::class);
// set rules:
$newRuleEngine->setRules(new Collection()->push($rule));
- $collection = $newRuleEngine->find();
- $collection = $collection->slice(0, 20);
+ $collection = $newRuleEngine->find();
+ $collection = $collection->slice(0, 20);
- $warning = '';
+ $warning = '';
if (0 === count($collection)) {
- $warning = (string) trans('firefly.warning_no_matching_transactions');
+ $warning = (string)trans('firefly.warning_no_matching_transactions');
}
// Return json response
- $view = 'ERROR, see logs.';
+ $view = 'ERROR, see logs.';
try {
$view = view('list.journals-array-tiny', ['groups' => $collection])->render();
diff --git a/app/Http/Controllers/RuleGroup/ExecutionController.php b/app/Http/Controllers/RuleGroup/ExecutionController.php
index a0191cba3f..14ee17209a 100644
--- a/app/Http/Controllers/RuleGroup/ExecutionController.php
+++ b/app/Http/Controllers/RuleGroup/ExecutionController.php
@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\RuleGroup;
+use Carbon\Carbon;
use Exception;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\SelectTransactionsRequest;
@@ -73,6 +74,16 @@ class ExecutionController extends Controller
$newRuleEngine = app(RuleEngineInterface::class);
$newRuleEngine->setUser($user);
+ // add date operators.
+ if (null !== $request->get('start')) {
+ $startDate = new Carbon($request->get('start'));
+ $newRuleEngine->addOperator(['type' => 'date_after', 'value' => $startDate->format('Y-m-d')]);
+ }
+ if (null !== $request->get('end')) {
+ $endDate = new Carbon($request->get('end'));
+ $newRuleEngine->addOperator(['type' => 'date_before', 'value' => $endDate->format('Y-m-d')]);
+ }
+
// add extra operators:
$newRuleEngine->addOperator(['type' => 'account_id', 'value' => $accounts]);
diff --git a/resources/views/rules/rule-group/select-transactions.twig b/resources/views/rules/rule-group/select-transactions.twig
index 81abe48208..4988fc45ed 100644
--- a/resources/views/rules/rule-group/select-transactions.twig
+++ b/resources/views/rules/rule-group/select-transactions.twig
@@ -24,6 +24,8 @@
+ {{ ExpandedForm.date('start') }}
+ {{ ExpandedForm.date('end') }}
{{ AccountForm.assetAccountCheckList('accounts', {'select_all': true,'class': 'account-checkbox', 'label': trans('firefly.include_transactions_from_accounts') }) }}
diff --git a/resources/views/rules/rule/select-transactions.twig b/resources/views/rules/rule/select-transactions.twig
index a6575e53f9..1338ce3c39 100644
--- a/resources/views/rules/rule/select-transactions.twig
+++ b/resources/views/rules/rule/select-transactions.twig
@@ -23,6 +23,8 @@
+ {{ ExpandedForm.date('start') }}
+ {{ ExpandedForm.date('end') }}
{{ AccountForm.assetAccountCheckList('accounts', {'select_all': true, 'class': 'account-checkbox', 'label': trans('firefly.include_transactions_from_accounts') }) }}