From a4f66b3d867d2ed4863f2e1162ee165bebaf3acc Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 16 May 2020 12:55:54 +0200 Subject: [PATCH] Date before and after triggers --- app/TransactionRules/Triggers/DateAfter.php | 107 +++++++++++++++++++ app/TransactionRules/Triggers/DateBefore.php | 107 +++++++++++++++++++ config/firefly.php | 6 ++ public/v1/js/ff/rules/create-edit.js | 2 +- resources/lang/en_US/firefly.php | 6 +- 5 files changed, 226 insertions(+), 2 deletions(-) create mode 100644 app/TransactionRules/Triggers/DateAfter.php create mode 100644 app/TransactionRules/Triggers/DateBefore.php diff --git a/app/TransactionRules/Triggers/DateAfter.php b/app/TransactionRules/Triggers/DateAfter.php new file mode 100644 index 0000000000..71ac2cdbcf --- /dev/null +++ b/app/TransactionRules/Triggers/DateAfter.php @@ -0,0 +1,107 @@ +. + */ +declare(strict_types=1); + +namespace FireflyIII\TransactionRules\Triggers; + +use Carbon\Carbon; +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Support\ParseDateString; +use Log; + +/** + * Class DateAfter. + */ +final class DateAfter extends AbstractTrigger implements TriggerInterface +{ + /** + * A trigger is said to "match anything", or match any given transaction, + * when the trigger value is very vague or has no restrictions. Easy examples + * are the "AmountMore"-trigger combined with an amount of 0: any given transaction + * has an amount of more than zero! Other examples are all the "Description"-triggers + * which have hard time handling empty trigger values such as "" or "*" (wild cards). + * + * If the user tries to create such a trigger, this method MUST return true so Firefly III + * can stop the storing / updating the trigger. If the trigger is in any way restrictive + * (even if it will still include 99.9% of the users transactions), this method MUST return + * false. + * + * @param mixed $value + * + * @return bool + */ + public static function willMatchEverything($value = null): bool + { + if (null !== $value) { + return false; + } + Log::error(sprintf('Cannot use %s with a null value.', self::class)); + + return true; + } + + /** + * Returns true when category is X. + * + * @param TransactionJournal $journal + * + * @return bool + */ + public function triggered(TransactionJournal $journal): bool + { + /** @var Carbon $date */ + $date = $journal->date; + Log::debug(sprintf('Found date on journal: %s', $date->format('Y-m-d'))); + $dateParser = new ParseDateString(); + + + try { + $ruleDate = $dateParser->parseDate($this->triggerValue); + } catch (FireflyException $e) { + Log::error('Cannot execute rule trigger.'); + Log::error($e->getMessage()); + + return false; + } + if ($date->isAfter($ruleDate)) { + Log::debug( + sprintf( + '%s is after %s, so return true.', + $date->format('Y-m-d H:i:s'), + $ruleDate->format('Y-m-d H:i:s'), + ) + ); + + return true; + } + + Log::debug( + sprintf( + '%s is NOT after %s, so return true.', + $date->format('Y-m-d H:i:s'), + $ruleDate->format('Y-m-d H:i:s'), + ) + ); + + return false; + } +} diff --git a/app/TransactionRules/Triggers/DateBefore.php b/app/TransactionRules/Triggers/DateBefore.php new file mode 100644 index 0000000000..0b6a6e7c40 --- /dev/null +++ b/app/TransactionRules/Triggers/DateBefore.php @@ -0,0 +1,107 @@ +. + */ +declare(strict_types=1); + +namespace FireflyIII\TransactionRules\Triggers; + +use Carbon\Carbon; +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Support\ParseDateString; +use Log; + +/** + * Class DateBefore. + */ +final class DateBefore extends AbstractTrigger implements TriggerInterface +{ + /** + * A trigger is said to "match anything", or match any given transaction, + * when the trigger value is very vague or has no restrictions. Easy examples + * are the "AmountMore"-trigger combined with an amount of 0: any given transaction + * has an amount of more than zero! Other examples are all the "Description"-triggers + * which have hard time handling empty trigger values such as "" or "*" (wild cards). + * + * If the user tries to create such a trigger, this method MUST return true so Firefly III + * can stop the storing / updating the trigger. If the trigger is in any way restrictive + * (even if it will still include 99.9% of the users transactions), this method MUST return + * false. + * + * @param mixed $value + * + * @return bool + */ + public static function willMatchEverything($value = null): bool + { + if (null !== $value) { + return false; + } + Log::error(sprintf('Cannot use %s with a null value.', self::class)); + + return true; + } + + /** + * Returns true when category is X. + * + * @param TransactionJournal $journal + * + * @return bool + */ + public function triggered(TransactionJournal $journal): bool + { + /** @var Carbon $date */ + $date = $journal->date; + Log::debug(sprintf('Found date on journal: %s', $date->format('Y-m-d'))); + $dateParser = new ParseDateString(); + + + try { + $ruleDate = $dateParser->parseDate($this->triggerValue); + } catch (FireflyException $e) { + Log::error('Cannot execute rule trigger.'); + Log::error($e->getMessage()); + + return false; + } + if ($date->isBefore($ruleDate)) { + Log::debug( + sprintf( + '%s is before %s, so return true.', + $date->format('Y-m-d H:i:s'), + $ruleDate->format('Y-m-d H:i:s'), + ) + ); + + return true; + } + + Log::debug( + sprintf( + '%s is NOT before %s, so return true.', + $date->format('Y-m-d H:i:s'), + $ruleDate->format('Y-m-d H:i:s'), + ) + ); + + return false; + } +} diff --git a/config/firefly.php b/config/firefly.php index 7273dd0333..9d7f3ab02a 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -86,6 +86,8 @@ use FireflyIII\TransactionRules\Triggers\BudgetIs; use FireflyIII\TransactionRules\Triggers\CategoryIs; use FireflyIII\TransactionRules\Triggers\CurrencyIs; use FireflyIII\TransactionRules\Triggers\DateIs; +use FireflyIII\TransactionRules\Triggers\DateBefore; +use FireflyIII\TransactionRules\Triggers\DateAfter; use FireflyIII\TransactionRules\Triggers\DescriptionContains; use FireflyIII\TransactionRules\Triggers\DescriptionEnds; use FireflyIII\TransactionRules\Triggers\DescriptionIs; @@ -470,6 +472,8 @@ return [ 'description_contains' => DescriptionContains::class, 'description_is' => DescriptionIs::class, 'date_is' => DateIs::class, + 'date_before' => DateBefore::class, + 'date_after' => DateAfter::class, 'transaction_type' => TransactionType::class, 'category_is' => CategoryIs::class, 'budget_is' => BudgetIs::class, @@ -557,6 +561,8 @@ return [ 'notes_end', 'notes_are', 'date_is', + 'date_before', + 'date_after', ], 'test-triggers' => [ diff --git a/public/v1/js/ff/rules/create-edit.js b/public/v1/js/ff/rules/create-edit.js index 5aa87e573d..69d0b95a97 100644 --- a/public/v1/js/ff/rules/create-edit.js +++ b/public/v1/js/ff/rules/create-edit.js @@ -233,6 +233,7 @@ function updateActionInput(selectList) { case 'clear_category': case 'clear_budget': case 'clear_notes': + case 'delete_transaction': case 'remove_all_tags': console.log('Select list value is ' + selectList.val() + ', so input needs to be disabled.'); inputResult.attr('disabled', 'disabled'); @@ -278,7 +279,6 @@ function updateActionInput(selectList) { console.log('Select list value is ' + selectList.val() + ', so input needs auto complete.'); createAutoComplete(inputResult, 'json/piggy-banks'); break; - break; default: console.log('Select list value is ' + selectList.val() + ', destroy auto complete, do nothing else.'); inputResult.typeahead('destroy'); diff --git a/resources/lang/en_US/firefly.php b/resources/lang/en_US/firefly.php index 030edc77aa..8ce6d58ee1 100644 --- a/resources/lang/en_US/firefly.php +++ b/resources/lang/en_US/firefly.php @@ -423,7 +423,11 @@ return [ 'rule_trigger_description_is' => 'Description is ":trigger_value"', 'rule_trigger_date_is_choice' => 'Transaction date is..', - 'rule_trigger_date_is' => 'Transaction date is ":trigger_value"', + 'rule_trigger_date_is' => 'Transaction date is ":trigger_value"', + 'rule_trigger_date_before_choice' => 'Transaction date is before..', + 'rule_trigger_date_before' => 'Transaction date is before ":trigger_value"', + 'rule_trigger_date_after_choice' => 'Transaction date is after..', + 'rule_trigger_date_after' => 'Transaction date is after ":trigger_value"', 'rule_trigger_budget_is_choice' => 'Budget is..', 'rule_trigger_budget_is' => 'Budget is ":trigger_value"',