diff --git a/app/Http/Controllers/Rule/CreateController.php b/app/Http/Controllers/Rule/CreateController.php
index a655c17508..5ca08cfcd9 100644
--- a/app/Http/Controllers/Rule/CreateController.php
+++ b/app/Http/Controllers/Rule/CreateController.php
@@ -28,6 +28,7 @@ use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\RuleFormRequest;
use FireflyIII\Models\Bill;
use FireflyIII\Models\RuleGroup;
+use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use FireflyIII\Support\Http\Controllers\ModelInformation;
use FireflyIII\Support\Http\Controllers\RuleManagement;
@@ -45,6 +46,7 @@ class CreateController extends Controller
/**
* RuleController constructor.
+ *
* @codeCoverageIgnore
*/
public function __construct()
@@ -158,6 +160,48 @@ class CreateController extends Controller
);
}
+ /**
+ * @param Request $request
+ * @param TransactionJournal $journal
+ */
+ public function createFromJournal(Request $request, TransactionJournal $journal)
+ {
+ $request->session()->flash('info', (string)trans('firefly.instructions_rule_from_journal', ['name' => e($journal->name)]));
+
+ $subTitleIcon = 'fa-clone';
+ $subTitle = (string)trans('firefly.make_new_rule_no_group');
+
+ // get triggers and actions for journal.
+ $oldTriggers = $this->getTriggersForJournal($journal);
+ $oldActions = [];
+ $triggerCount = count($oldTriggers);
+ $actionCount = count($oldActions);
+
+ $this->createDefaultRuleGroup();
+ $this->createDefaultRule();
+
+ // collect pre-filled information:
+ $preFilled = [
+ 'strict' => true,
+ 'title' => (string)trans('firefly.new_rule_for_journal_title', ['description' => $journal->description]),
+ 'description' => (string)trans('firefly.new_rule_for_journal_description', ['description' => $journal->description]),
+ ];
+
+ // flash old data
+ $request->session()->flash('preFilled', $preFilled);
+
+ // put previous url in session if not redirect from store (not "create another").
+ if (true !== session('rules.create.fromStore')) {
+ $this->rememberPreviousUri('rules.create.uri');
+ }
+ session()->forget('rules.create.fromStore');
+
+ return view(
+ 'rules.rule.create', compact('subTitleIcon', 'oldTriggers', 'preFilled', 'oldActions', 'triggerCount', 'actionCount', 'subTitle')
+ );
+
+ }
+
/**
* Store the new rule.
*
diff --git a/app/Support/Http/Controllers/ModelInformation.php b/app/Support/Http/Controllers/ModelInformation.php
index 597cbaff16..82b4a09031 100644
--- a/app/Support/Http/Controllers/ModelInformation.php
+++ b/app/Support/Http/Controllers/ModelInformation.php
@@ -23,14 +23,12 @@ declare(strict_types=1);
namespace FireflyIII\Support\Http\Controllers;
-use FireflyIII\Exceptions\FireflyException;
-use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Bill;
+use FireflyIII\Models\Tag;
+use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
-use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
-use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use Log;
use Throwable;
@@ -71,6 +69,43 @@ trait ModelInformation
return [$result];
}
+ /**
+ * @codeCoverageIgnore
+ * @return array
+ */
+ protected function getLiabilityTypes(): array
+ {
+ /** @var AccountRepositoryInterface $repository */
+ $repository = app(AccountRepositoryInterface::class);
+ // types of liability:
+ $debt = $repository->getAccountTypeByType(AccountType::DEBT);
+ $loan = $repository->getAccountTypeByType(AccountType::LOAN);
+ $mortgage = $repository->getAccountTypeByType(AccountType::MORTGAGE);
+ /** @noinspection NullPointerExceptionInspection */
+ $liabilityTypes = [
+ $debt->id => (string)trans(sprintf('firefly.account_type_%s', AccountType::DEBT)),
+ $loan->id => (string)trans(sprintf('firefly.account_type_%s', AccountType::LOAN)),
+ $mortgage->id => (string)trans(sprintf('firefly.account_type_%s', AccountType::MORTGAGE)),
+ ];
+ asort($liabilityTypes);
+
+ return $liabilityTypes;
+ }
+
+ /**
+ * @codeCoverageIgnore
+ * @return array
+ */
+ protected function getRoles(): array
+ {
+ $roles = [];
+ foreach (config('firefly.accountRoles') as $role) {
+ $roles[$role] = (string)trans(sprintf('firefly.account_role_%s', $role));
+ }
+
+ return $roles;
+ }
+
/**
* Create fake triggers to match the bill's properties
*
@@ -116,39 +151,109 @@ trait ModelInformation
}
/**
- * @codeCoverageIgnore
+ * @param TransactionJournal $journal
+ *
* @return array
*/
- protected function getRoles(): array
+ private function getTriggersForJournal(TransactionJournal $journal): array
{
- $roles = [];
- foreach (config('firefly.accountRoles') as $role) {
- $roles[$role] = (string)trans(sprintf('firefly.account_role_%s', $role));
+ $result = [];
+ $triggers = [];
+ $values = [];
+ $index = 0;
+ // amount, description, category, budget, tags, source, destination, notes, currency type
+ //,type
+ /** @var Transaction $source */
+ $source = $journal->transactions()->where('amount', '<', 0)->first();
+ /** @var Transaction $destination */
+ $destination = $journal->transactions()->where('amount', '>', 0)->first();
+ if (null === $destination || null === $source) {
+ return $result;
+ }
+ // type
+ $triggers[$index] = 'transaction_type';
+ $values[$index] = $journal->transactionType->type;
+ $index++;
+
+ // currency
+ $triggers[$index] = 'currency_is';
+ $values[$index] = sprintf('%s (%s)', $journal->transactionCurrency->name, $journal->transactionCurrency->code);
+ $index++;
+
+ // amount_exactly:
+ $triggers[$index] = 'amount_exactly';
+ $values[$index] = $destination->amount;
+ $index++;
+
+ // description_is:
+ $triggers[$index] = 'description_is';
+ $values[$index] = $journal->description;
+ $index++;
+
+ // from_account_is
+ $triggers[$index] = 'from_account_is';
+ $values[$index] = $source->account->name;
+ $index++;
+
+ // to_account_is
+ $triggers[$index] = 'to_account_is';
+ $values[$index] = $destination->account->name;
+ $index++;
+
+ // category (if)
+ $category = $journal->categories()->first();
+ if (null !== $category) {
+ $triggers[$index] = 'category_is';
+ $values[$index] = $category->name;
+ $index++;
+ }
+ // budget (if)
+ $budget = $journal->budgets()->first();
+ if (null !== $budget) {
+ $triggers[$index] = 'budget_is';
+ $values[$index] = $budget->name;
+ $index++;
+ }
+ // tags (if)
+ $tags = $journal->tags()->get();
+ /** @var Tag $tag */
+ foreach ($tags as $tag) {
+ $triggers[$index] = 'tag_is';
+ $values[$index] = $tag->tag;
+ $index++;
+ }
+ // notes (if)
+ $notes = $journal->notes()->first();
+ if (null !== $notes) {
+ $triggers[$index] = 'notes_are';
+ $values[$index] = $notes->text;
+ $index++;
}
- return $roles;
- }
+ foreach ($triggers as $index => $trigger) {
+ try {
+ $string = view(
+ 'rules.partials.trigger',
+ [
+ 'oldTrigger' => $trigger,
+ 'oldValue' => $values[$index],
+ 'oldChecked' => false,
+ 'count' => $index + 1,
+ ]
+ )->render();
+ // @codeCoverageIgnoreStart
+ } catch (Throwable $e) {
- /**
- * @codeCoverageIgnore
- * @return array
- */
- protected function getLiabilityTypes(): array
- {
- /** @var AccountRepositoryInterface $repository */
- $repository = app(AccountRepositoryInterface::class);
- // types of liability:
- $debt = $repository->getAccountTypeByType(AccountType::DEBT);
- $loan = $repository->getAccountTypeByType(AccountType::LOAN);
- $mortgage = $repository->getAccountTypeByType(AccountType::MORTGAGE);
- /** @noinspection NullPointerExceptionInspection */
- $liabilityTypes = [
- $debt->id => (string)trans(sprintf('firefly.account_type_%s', AccountType::DEBT)),
- $loan->id => (string)trans(sprintf('firefly.account_type_%s', AccountType::LOAN)),
- $mortgage->id => (string)trans(sprintf('firefly.account_type_%s', AccountType::MORTGAGE)),
- ];
- asort($liabilityTypes);
+ Log::debug(sprintf('Throwable was thrown in getTriggersForJournal(): %s', $e->getMessage()));
+ Log::debug($e->getTraceAsString());
+ $string = '';
+ // @codeCoverageIgnoreEnd
+ }
+ if ('' !== $string) {
+ $result[] = $string;
+ }
+ }
- return $liabilityTypes;
+ return $result;
}
}
diff --git a/app/Support/Http/Controllers/RuleManagement.php b/app/Support/Http/Controllers/RuleManagement.php
index 8964248f7b..b31ee93aa6 100644
--- a/app/Support/Http/Controllers/RuleManagement.php
+++ b/app/Support/Http/Controllers/RuleManagement.php
@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Support\Http\Controllers;
+use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
use Illuminate\Http\Request;
diff --git a/resources/lang/en_US/firefly.php b/resources/lang/en_US/firefly.php
index 7acb166d26..919904f8b9 100644
--- a/resources/lang/en_US/firefly.php
+++ b/resources/lang/en_US/firefly.php
@@ -512,6 +512,7 @@ return [
'delete_all_selected_tags' => 'Delete all selected tags',
'select_tags_to_delete' => 'Don\'t forget to select some tags.',
'deleted_x_tags' => 'Deleted :count tag(s).',
+ 'create_rule_from_transaction' => 'Create rule based on transaction',
// preferences
'pref_home_screen_accounts' => 'Home screen accounts',
diff --git a/resources/views/v1/transactions/show.twig b/resources/views/v1/transactions/show.twig
index bbfb9d6637..b9ebd56c09 100644
--- a/resources/views/v1/transactions/show.twig
+++ b/resources/views/v1/transactions/show.twig
@@ -276,6 +276,10 @@
{{ 'link_transaction'|_ }}
+
+
+ {{ 'create_rule_from_transaction'|_ }}
+
diff --git a/routes/breadcrumbs.php b/routes/breadcrumbs.php
index c9ecac8eb5..5dcd657148 100644
--- a/routes/breadcrumbs.php
+++ b/routes/breadcrumbs.php
@@ -887,6 +887,15 @@ try {
$breadcrumbs->push(trans('firefly.make_new_rule_no_group'), route('rules.create'));
}
);
+
+ Breadcrumbs::register(
+ 'rules.create-from-journal',
+ function (BreadcrumbsGenerator $breadcrumbs) {
+ $breadcrumbs->parent('rules.index');
+ $breadcrumbs->push(trans('firefly.make_new_rule_no_group'), route('rules.create'));
+ }
+ );
+
Breadcrumbs::register(
'rules.edit',
function (BreadcrumbsGenerator $breadcrumbs, Rule $rule) {
diff --git a/routes/web.php b/routes/web.php
index 68e875f38f..babf1c9752 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -863,6 +863,7 @@ Route::group(
// create controller
Route::get('create/{ruleGroup?}', ['uses' => 'Rule\CreateController@create', 'as' => 'create']);
Route::get('create-from-bill/{bill}', ['uses' => 'Rule\CreateController@createFromBill', 'as' => 'create-from-bill']);
+ Route::get('create-from-journal/{tj}', ['uses' => 'Rule\CreateController@createFromJournal', 'as' => 'create-from-journal']);
Route::post('store', ['uses' => 'Rule\CreateController@store', 'as' => 'store']);
// delete controller