mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-31 02:36:28 +00:00 
			
		
		
		
	Code for #1324
This commit is contained in:
		| @@ -52,7 +52,7 @@ class BillFactory | ||||
|                 'match'                   => 'MIGRATED_TO_RULES', | ||||
|                 'amount_min'              => $data['amount_min'], | ||||
|                 'user_id'                 => $this->user->id, | ||||
|                 'currency_id' => $data['currency_id'], | ||||
|                 'transaction_currency_id' => $data['transaction_currency_id'], | ||||
|                 'amount_max'              => $data['amount_max'], | ||||
|                 'date'                    => $data['date'], | ||||
|                 'repeat_freq'             => $data['repeat_freq'], | ||||
|   | ||||
| @@ -136,7 +136,7 @@ class BillController extends Controller | ||||
|      * | ||||
|      * @return View | ||||
|      */ | ||||
|     public function edit(Request $request, Bill $bill) | ||||
|     public function edit(Request $request, CurrencyRepositoryInterface $repository, Bill $bill) | ||||
|     { | ||||
|         $periods = []; | ||||
|         foreach (config('firefly.bill_periods') as $current) { | ||||
| @@ -152,6 +152,8 @@ class BillController extends Controller | ||||
|         $currency         = app('amount')->getDefaultCurrency(); | ||||
|         $bill->amount_min = round($bill->amount_min, $currency->decimal_places); | ||||
|         $bill->amount_max = round($bill->amount_max, $currency->decimal_places); | ||||
|         $defaultCurrency  = app('amount')->getDefaultCurrency(); | ||||
|         $currencies       = ExpandedForm::makeSelectList($repository->get()); | ||||
|  | ||||
|         $preFilled = [ | ||||
|             'notes' => '', | ||||
| @@ -167,7 +169,7 @@ class BillController extends Controller | ||||
|  | ||||
|         $request->session()->forget('bills.edit.fromUpdate'); | ||||
|  | ||||
|         return view('bills.edit', compact('subTitle', 'periods', 'bill')); | ||||
|         return view('bills.edit', compact('subTitle', 'periods', 'bill', 'defaultCurrency', 'currencies')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -296,6 +298,12 @@ class BillController extends Controller | ||||
|             $request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         // do return to original bill form? | ||||
|         $return = 'false'; | ||||
|         if (1 === (int)$request->get('create_another')) { | ||||
|             $return = 'true'; | ||||
|         } | ||||
|  | ||||
|         // find first rule group, or create one: | ||||
|         $count = $ruleGroupRepository->count(); | ||||
|         if ($count === 0) { | ||||
| @@ -309,9 +317,10 @@ class BillController extends Controller | ||||
|             $group = $ruleGroupRepository->getActiveGroups(auth()->user())->first(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         // redirect to page that will create a new rule. | ||||
|         return redirect(route('rules.create', [$group->id]) . '?fromBill=' . $bill->id); | ||||
|         $params = http_build_query(['fromBill' => $bill->id, 'return' => $return]); | ||||
|  | ||||
|         return redirect(route('rules.create', [$group->id]) . '?' . $params); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -31,6 +31,7 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Bill\BillRepositoryInterface; | ||||
| use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| use FireflyIII\Repositories\Category\CategoryRepositoryInterface; | ||||
| use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; | ||||
| use FireflyIII\Repositories\Journal\JournalRepositoryInterface; | ||||
| use FireflyIII\Repositories\Tag\TagRepositoryInterface; | ||||
| use FireflyIII\Support\CacheProperties; | ||||
| @@ -119,6 +120,19 @@ class AutoCompleteController extends Controller | ||||
|         return response()->json($return); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param CurrencyRepositoryInterface $repository | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function currencyNames(CurrencyRepositoryInterface $repository) | ||||
|     { | ||||
|         $return = $repository->get()->pluck('name')->toArray(); | ||||
|         sort($return); | ||||
|  | ||||
|         return response()->json($return); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a JSON list of all beneficiaries. | ||||
|      * | ||||
|   | ||||
| @@ -29,6 +29,7 @@ use FireflyIII\Http\Requests\SelectTransactionsRequest; | ||||
| use FireflyIII\Http\Requests\TestRuleFormRequest; | ||||
| use FireflyIII\Jobs\ExecuteRuleOnExistingTransactions; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\Rule; | ||||
| use FireflyIII\Models\RuleAction; | ||||
| use FireflyIII\Models\RuleGroup; | ||||
| @@ -39,8 +40,10 @@ use FireflyIII\Repositories\Rule\RuleRepositoryInterface; | ||||
| use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface; | ||||
| use FireflyIII\TransactionRules\TransactionMatcher; | ||||
| use Illuminate\Http\Request; | ||||
| use Log; | ||||
| use Preferences; | ||||
| use Session; | ||||
| use Throwable; | ||||
| use View; | ||||
|  | ||||
| /** | ||||
| @@ -73,81 +76,47 @@ class RuleController extends Controller | ||||
|      * | ||||
|      * @return View | ||||
|      * | ||||
|  | ||||
|  | ||||
|      */ | ||||
|     public function create(Request $request, RuleGroupRepositoryInterface $ruleGroupRepository, BillRepositoryInterface $billRepository, RuleGroup $ruleGroup) | ||||
|     { | ||||
|         $bill         = null; | ||||
|         $billId       = (int)$request->get('fromBill'); | ||||
|         $preFilled    = []; | ||||
|         // count for possible present previous entered triggers/actions. | ||||
|         $triggerCount = 0; | ||||
|         $actionCount  = 0; | ||||
|  | ||||
|         // collection of those triggers/actions. | ||||
|         $groups       = ExpandedForm::makeSelectList($ruleGroupRepository->get()); | ||||
|         $oldTriggers  = []; | ||||
|         $oldActions   = []; | ||||
|         $returnToBill = false; | ||||
|  | ||||
|         if ($request->get('return') === 'true') { | ||||
|             $returnToBill = true; | ||||
|         } | ||||
|  | ||||
|         // has bill? | ||||
|         if ($billId > 0) { | ||||
|             $bill = $billRepository->find($billId); | ||||
|         } | ||||
|  | ||||
|         // has old input? | ||||
|         if ($request->old()) { | ||||
|             // process old triggers. | ||||
|             $oldTriggers = $this->getPreviousTriggers($request); | ||||
|             $triggerCount = \count($oldTriggers); | ||||
|  | ||||
|             // process old actions | ||||
|             $oldActions  = $this->getPreviousActions($request); | ||||
|             $actionCount = \count($oldActions); | ||||
|  | ||||
|         } | ||||
|         if ($billId > 0) { | ||||
|             $bill = $billRepository->find($billId); | ||||
|         // has existing bill refered to in URI? | ||||
|         if (null !== $bill && !$request->old()) { | ||||
|  | ||||
|             // create some sensible defaults: | ||||
|             $preFilled['title']       = trans('firefly.new_rule_for_bill_title', ['name' => $bill->name]); | ||||
|             $preFilled['description'] = trans('firefly.new_rule_for_bill_description', ['name' => $bill->name]); | ||||
|             $request->session()->flash('preFilled', $preFilled); | ||||
|  | ||||
|             // pretend there are old triggers, so the page will fill them in: | ||||
|             $oldTriggers[] = view( | ||||
|                 'rules.partials.trigger', | ||||
|                 [ | ||||
|                     'oldTrigger' => 'amount_more', | ||||
|                     'oldValue'   => round($bill->amount_min,12), | ||||
|                     'oldChecked' => false, | ||||
|                     'count'      => 1, | ||||
|                 ] | ||||
|             )->render(); | ||||
|             $oldTriggers[] = view( | ||||
|                 'rules.partials.trigger', | ||||
|                 [ | ||||
|                     'oldTrigger' => 'amount_less', | ||||
|                     'oldValue'   => round($bill->amount_max,12), | ||||
|                     'oldChecked' => false, | ||||
|                     'count'      => 2, | ||||
|                 ] | ||||
|             )->render(); | ||||
|             $oldTriggers[] = view( | ||||
|                 'rules.partials.trigger', | ||||
|                 [ | ||||
|                     'oldTrigger' => 'description_contains', | ||||
|                     'oldValue'   => $bill->name,12, | ||||
|                     'oldChecked' => false, | ||||
|                     'count'      => 3, | ||||
|                 ] | ||||
|             )->render(); | ||||
|  | ||||
|             $oldActions[] = view( | ||||
|                 'rules.partials.action', | ||||
|                 [ | ||||
|                     'oldAction'  => 'link_to_bill', | ||||
|                     'oldValue'   => $bill->name, | ||||
|                     'oldChecked' => false, | ||||
|                     'count'      => 1, | ||||
|                 ] | ||||
|             )->render(); | ||||
|  | ||||
|             // get triggers and actions for bill: | ||||
|             $oldTriggers = $this->getTriggersForBill($bill); | ||||
|             $oldActions  = $this->getActionsForBill($bill); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $triggerCount = \count($oldTriggers); | ||||
|         $actionCount  = \count($oldActions); | ||||
|         $subTitleIcon = 'fa-clone'; | ||||
|         $subTitle     = trans('firefly.make_new_rule', ['title' => $ruleGroup->title]); | ||||
|  | ||||
| @@ -159,7 +128,10 @@ class RuleController extends Controller | ||||
|  | ||||
|         return view( | ||||
|             'rules.rule.create', | ||||
|             compact('subTitleIcon', 'oldTriggers', 'preFilled', 'bill', 'oldActions', 'triggerCount', 'actionCount', 'ruleGroup', 'subTitle') | ||||
|             compact( | ||||
|                 'subTitleIcon', 'oldTriggers', 'returnToBill', 'groups', 'preFilled', 'bill', 'oldActions', 'triggerCount', 'actionCount', 'ruleGroup', | ||||
|                 'subTitle' | ||||
|             ) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| @@ -380,24 +352,32 @@ class RuleController extends Controller | ||||
|     /** | ||||
|      * @param RuleFormRequest         $request | ||||
|      * @param RuleRepositoryInterface $repository | ||||
|      * @param RuleGroup               $ruleGroup | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector | ||||
|      */ | ||||
|     public function store(RuleFormRequest $request, RuleRepositoryInterface $repository, RuleGroup $ruleGroup) | ||||
|     public function store(RuleFormRequest $request, RuleRepositoryInterface $repository) | ||||
|     { | ||||
|         $data = $request->getRuleData(); | ||||
|         $data['rule_group_id'] = $ruleGroup->id; | ||||
|  | ||||
|         $rule = $repository->store($data); | ||||
|         Session::flash('success', trans('firefly.stored_new_rule', ['title' => $rule->title])); | ||||
|         session()->flash('success', trans('firefly.stored_new_rule', ['title' => $rule->title])); | ||||
|         Preferences::mark(); | ||||
|  | ||||
|         // redirect to show bill. | ||||
|         if ($request->get('return_to_bill') === 'true' && (int)$request->get('bill_id') > 0) { | ||||
|             return redirect(route('bills.show', [(int)$request->get('bill_id')])); | ||||
|         } | ||||
|  | ||||
|         // redirect to new bill creation. | ||||
|         if ((int)$request->get('bill_id') > 0) { | ||||
|             return redirect(route('bills.create')); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         if (1 === (int)$request->get('create_another')) { | ||||
|             // @codeCoverageIgnoreStart | ||||
|             Session::put('rules.create.fromStore', true); | ||||
|  | ||||
|             return redirect(route('rules.create', [$ruleGroup]))->withInput(); | ||||
|             return redirect(route('rules.create', [$data['rule_group_id']]))->withInput(); | ||||
|             // @codeCoverageIgnoreEnd | ||||
|         } | ||||
|  | ||||
| @@ -416,7 +396,6 @@ class RuleController extends Controller | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      * | ||||
|  | ||||
|      */ | ||||
|     public function testTriggers(TestRuleFormRequest $request) | ||||
|     { | ||||
| @@ -586,6 +565,31 @@ class RuleController extends Controller | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getActionsForBill(Bill $bill): array | ||||
|     { | ||||
|         $actions = []; | ||||
|         try { | ||||
|             $actions[] = view( | ||||
|                 'rules.partials.action', | ||||
|                 [ | ||||
|                     'oldAction'  => 'link_to_bill', | ||||
|                     'oldValue'   => $bill->name, | ||||
|                     'oldChecked' => false, | ||||
|                     'count'      => 1, | ||||
|                 ] | ||||
|             )->render(); | ||||
|         } catch (Throwable $e) { | ||||
|             Log::debug(sprintf('Throwable was thrown in getActionsForBill(): %s', $e->getMessage())); | ||||
|         } | ||||
|  | ||||
|         return $actions; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Rule $rule | ||||
|      * | ||||
| @@ -601,6 +605,7 @@ class RuleController extends Controller | ||||
|         /** @var RuleAction $entry */ | ||||
|         foreach ($rule->ruleActions as $entry) { | ||||
|             $count = ($index + 1); | ||||
|             try { | ||||
|                 $actions[] = view( | ||||
|                     'rules.partials.action', | ||||
|                     [ | ||||
| @@ -610,6 +615,9 @@ class RuleController extends Controller | ||||
|                         'count'      => $count, | ||||
|                     ] | ||||
|                 )->render(); | ||||
|             } catch (Throwable $e) { | ||||
|                 Log::debug(sprintf('Throwable was thrown in getCurrentActions(): %s', $e->getMessage())); | ||||
|             } | ||||
|             ++$index; | ||||
|         } | ||||
|  | ||||
| @@ -632,6 +640,7 @@ class RuleController extends Controller | ||||
|         foreach ($rule->ruleTriggers as $entry) { | ||||
|             if ('user_action' !== $entry->trigger_type) { | ||||
|                 $count = ($index + 1); | ||||
|                 try { | ||||
|                     $triggers[] = view( | ||||
|                         'rules.partials.trigger', | ||||
|                         [ | ||||
| @@ -641,6 +650,9 @@ class RuleController extends Controller | ||||
|                             'count'      => $count, | ||||
|                         ] | ||||
|                     )->render(); | ||||
|                 } catch (Throwable $e) { | ||||
|                     Log::debug(sprintf('Throwable was thrown in getCurrentTriggers(): %s', $e->getMessage())); | ||||
|                 } | ||||
|                 ++$index; | ||||
|             } | ||||
|         } | ||||
| @@ -664,6 +676,7 @@ class RuleController extends Controller | ||||
|         foreach ($oldActions as $index => $entry) { | ||||
|             $count   = ($newIndex + 1); | ||||
|             $checked = isset($request->old('rule-action-stop')[$index]) ? true : false; | ||||
|             try { | ||||
|                 $actions[] = view( | ||||
|                     'rules.partials.action', | ||||
|                     [ | ||||
| @@ -673,6 +686,9 @@ class RuleController extends Controller | ||||
|                         'count'      => $count, | ||||
|                     ] | ||||
|                 )->render(); | ||||
|             } catch (Throwable $e) { | ||||
|                 Log::debug(sprintf('Throwable was thrown in getPreviousActions(): %s', $e->getMessage())); | ||||
|             } | ||||
|             ++$newIndex; | ||||
|         } | ||||
|  | ||||
| @@ -695,6 +711,7 @@ class RuleController extends Controller | ||||
|         foreach ($oldTriggers as $index => $entry) { | ||||
|             $count      = ($newIndex + 1); | ||||
|             $oldChecked = isset($request->old('rule-trigger-stop')[$index]) ? true : false; | ||||
|             try { | ||||
|                 $triggers[] = view( | ||||
|                     'rules.partials.trigger', | ||||
|                     [ | ||||
| @@ -704,12 +721,72 @@ class RuleController extends Controller | ||||
|                         'count'      => $count, | ||||
|                     ] | ||||
|                 )->render(); | ||||
|             } catch (Throwable $e) { | ||||
|                 Log::debug(sprintf('Throwable was thrown in getPreviousTriggers(): %s', $e->getMessage())); | ||||
|             } | ||||
|             ++$newIndex; | ||||
|         } | ||||
|  | ||||
|         return $triggers; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Create fake triggers to match the bill's properties | ||||
|      * | ||||
|      * @param Bill $bill | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getTriggersForBill(Bill $bill): array | ||||
|     { | ||||
|         $triggers = []; | ||||
|         try { | ||||
|             $triggers[] = view( | ||||
|                 'rules.partials.trigger', | ||||
|                 [ | ||||
|                     'oldTrigger' => 'currency_is', | ||||
|                     'oldValue'   => $bill->transactionCurrency()->first()->name, | ||||
|                     'oldChecked' => false, | ||||
|                     'count'      => 1, | ||||
|                 ] | ||||
|             )->render(); | ||||
|  | ||||
|             $triggers[] = view( | ||||
|                 'rules.partials.trigger', | ||||
|                 [ | ||||
|                     'oldTrigger' => 'amount_more', | ||||
|                     'oldValue'   => round($bill->amount_min, 12), | ||||
|                     'oldChecked' => false, | ||||
|                     'count'      => 2, | ||||
|                 ] | ||||
|             )->render(); | ||||
|  | ||||
|             $triggers[] = view( | ||||
|                 'rules.partials.trigger', | ||||
|                 [ | ||||
|                     'oldTrigger' => 'amount_less', | ||||
|                     'oldValue'   => round($bill->amount_max, 12), | ||||
|                     'oldChecked' => false, | ||||
|                     'count'      => 3, | ||||
|                 ] | ||||
|             )->render(); | ||||
|             $triggers[] = view( | ||||
|                 'rules.partials.trigger', | ||||
|                 [ | ||||
|                     'oldTrigger' => 'description_contains', | ||||
|                     'oldValue'   => $bill->name, 12, | ||||
|                     'oldChecked' => false, | ||||
|                     'count'      => 4, | ||||
|                 ] | ||||
|             )->render(); | ||||
|         } catch (Throwable $e) { | ||||
|             Log::debug(sprintf('Throwable was thrown in getTriggersForBill(): %s', $e->getMessage())); | ||||
|             Log::debug($e->getTraceAsString()); | ||||
|         } | ||||
|  | ||||
|         return $triggers; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TestRuleFormRequest $request | ||||
|      * | ||||
| @@ -723,7 +800,7 @@ class RuleController extends Controller | ||||
|             'rule-trigger-values' => $request->get('rule-trigger-value'), | ||||
|             'rule-trigger-stop'   => $request->get('rule-trigger-stop'), | ||||
|         ]; | ||||
|         if (is_array($data['rule-triggers'])) { | ||||
|         if (\is_array($data['rule-triggers'])) { | ||||
|             foreach ($data['rule-triggers'] as $index => $triggerType) { | ||||
|                 $data['rule-trigger-stop'][$index] = (int)($data['rule-trigger-stop'][$index] ?? 0.0); | ||||
|                 $triggers[]                        = [ | ||||
|   | ||||
| @@ -44,7 +44,7 @@ class BillFormRequest extends Request | ||||
|         return [ | ||||
|             'name'                    => $this->string('name'), | ||||
|             'amount_min'              => $this->string('amount_min'), | ||||
|             'currency_id' => $this->integer('currency_id'), | ||||
|             'transaction_currency_id' => $this->integer('transaction_currency_id'), | ||||
|             'amount_max'              => $this->string('amount_max'), | ||||
|             'date'                    => $this->date('date'), | ||||
|             'repeat_freq'             => $this->string('repeat_freq'), | ||||
| @@ -69,7 +69,7 @@ class BillFormRequest extends Request | ||||
|             'name'                    => $nameRule, | ||||
|             'amount_min'              => 'required|numeric|more:0', | ||||
|             'amount_max'              => 'required|numeric|more:0', | ||||
|             'currency_id' => 'required|exists:transaction_currencies,id', | ||||
|             'transaction_currency_id' => 'required|exists:transaction_currencies,id', | ||||
|             'date'                    => 'required|date', | ||||
|             'repeat_freq'             => 'required|in:weekly,monthly,quarterly,half-year,yearly', | ||||
|             'skip'                    => 'required|between:0,31', | ||||
|   | ||||
| @@ -23,6 +23,7 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Models; | ||||
|  | ||||
| use Crypt; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\Relations\BelongsTo; | ||||
| use Illuminate\Database\Eloquent\Relations\HasMany; | ||||
| @@ -57,7 +58,7 @@ class Bill extends Model | ||||
|      */ | ||||
|     protected $fillable | ||||
|         = ['name', 'match', 'amount_min', 'match_encrypted', 'name_encrypted', 'user_id', 'amount_max', 'date', 'repeat_freq', 'skip', | ||||
|            'automatch', 'active','currency_id']; | ||||
|            'automatch', 'active', 'transaction_currency_id']; | ||||
|     /** | ||||
|      * @var array | ||||
|      */ | ||||
| @@ -179,13 +180,22 @@ class Bill extends Model | ||||
|         $this->attributes['name_encrypted'] = $encrypt; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * @return BelongsTo | ||||
|      */ | ||||
|     public function transactionCurrency(): BelongsTo | ||||
|     { | ||||
|         return $this->belongsTo(TransactionCurrency::class); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * @return HasMany | ||||
|      */ | ||||
|     public function transactionJournals(): HasMany | ||||
|     { | ||||
|         return $this->hasMany('FireflyIII\Models\TransactionJournal'); | ||||
|         return $this->hasMany(TransactionJournal::class); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -194,6 +204,6 @@ class Bill extends Model | ||||
|      */ | ||||
|     public function user(): BelongsTo | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\User'); | ||||
|         return $this->belongsTo(User::class); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -42,19 +42,14 @@ class BillUpdateService | ||||
|      */ | ||||
|     public function update(Bill $bill, array $data): Bill | ||||
|     { | ||||
|  | ||||
|         $matchArray = explode(',', $data['match']); | ||||
|         $matchArray = array_unique($matchArray); | ||||
|         $match      = implode(',', $matchArray); | ||||
|  | ||||
|         $bill->name                    = $data['name']; | ||||
|         $bill->match       = $match; | ||||
|         $bill->amount_min              = $data['amount_min']; | ||||
|         $bill->amount_max              = $data['amount_max']; | ||||
|         $bill->date                    = $data['date']; | ||||
|         $bill->transaction_currency_id = $data['transaction_currency_id']; | ||||
|         $bill->repeat_freq             = $data['repeat_freq']; | ||||
|         $bill->skip                    = $data['skip']; | ||||
|         $bill->automatch   = $data['automatch']; | ||||
|         $bill->automatch               = true; | ||||
|         $bill->active                  = $data['active']; | ||||
|         $bill->save(); | ||||
|  | ||||
|   | ||||
							
								
								
									
										92
									
								
								app/TransactionRules/Triggers/CurrencyIs.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								app/TransactionRules/Triggers/CurrencyIs.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| <?php | ||||
| /** | ||||
|  * CurrencyIs.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\TransactionRules\Triggers; | ||||
|  | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class CurrencyIs. | ||||
|  */ | ||||
| final class CurrencyIs 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 null $value | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public static function willMatchEverything($value = null) | ||||
|     { | ||||
|         if (null !== $value) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         Log::error(sprintf('Cannot use %s with a null value.', self::class)); | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns true when description is X | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function triggered(TransactionJournal $journal): bool | ||||
|     { | ||||
|         /** @var CurrencyRepositoryInterface $repository */ | ||||
|         $repository = app(CurrencyRepositoryInterface::class); | ||||
|         $currency   = $repository->findByNameNull($this->triggerValue); | ||||
|         $hit        = true; | ||||
|         if (null !== $currency) { | ||||
|             /** @var Transaction $transaction */ | ||||
|             foreach ($journal->transactions as $transaction) { | ||||
|                 if ((int)$transaction->transaction_currency_id !== (int)$currency->id) { | ||||
|                     Log::debug( | ||||
|                         sprintf( | ||||
|                             'Trigger CurrencyIs: Transaction #%d in journal #%d uses currency %d instead of sought for #%d. No hit!', | ||||
|                             $transaction->id, $journal->id, $transaction->transaction_currency_id, $currency->id | ||||
|                         ) | ||||
|                     ); | ||||
|                     $hit = false; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $hit; | ||||
|     } | ||||
| } | ||||
| @@ -25,6 +25,7 @@ use FireflyIII\TransactionRules\Triggers\AmountLess; | ||||
| use FireflyIII\TransactionRules\Triggers\AmountMore; | ||||
| use FireflyIII\TransactionRules\Triggers\BudgetIs; | ||||
| use FireflyIII\TransactionRules\Triggers\CategoryIs; | ||||
| use FireflyIII\TransactionRules\Triggers\CurrencyIs; | ||||
| use FireflyIII\TransactionRules\Triggers\DescriptionContains; | ||||
| use FireflyIII\TransactionRules\Triggers\DescriptionEnds; | ||||
| use FireflyIII\TransactionRules\Triggers\DescriptionIs; | ||||
| @@ -89,7 +90,7 @@ return [ | ||||
|     'encryption'     => null === env('USE_ENCRYPTION') || env('USE_ENCRYPTION') === true, | ||||
|     'version'        => '4.7.2.2', | ||||
|     'api_version'    => '0.1', | ||||
|     'db_version'     => 2, | ||||
|     'db_version'     => 3, | ||||
|     'maxUploadSize'  => 15242880, | ||||
|     'allowedMimes'   => [ | ||||
|         /* plain files */ | ||||
| @@ -324,6 +325,7 @@ return [ | ||||
|         'category_is'           => CategoryIs::class, | ||||
|         'budget_is'             => BudgetIs::class, | ||||
|         'tag_is'                => TagIs::class, | ||||
|         'currency_is'           => CurrencyIs::class, | ||||
|         'has_attachments'       => HasAttachment::class, | ||||
|         'has_no_category'       => HasNoCategory::class, | ||||
|         'has_any_category'      => HasAnyCategory::class, | ||||
| @@ -362,6 +364,7 @@ return [ | ||||
|         'set_budget', | ||||
|         'add_tag', | ||||
|         'remove_tag', | ||||
|         'link_to_bill', | ||||
|         'set_description', | ||||
|         'append_description', | ||||
|         'prepend_description', | ||||
|   | ||||
| @@ -28,6 +28,7 @@ return [ | ||||
|                 '4.3'   => 'Make sure you run the migrations and clear your cache. If you need more help, please check Github or the Firefly III website.', | ||||
|                 '4.6.3' => 'This will be the last version to require PHP7.0. Future versions will require PHP7.1 minimum.', | ||||
|                 '4.6.4' => 'This version of Firefly III requires PHP7.1.', | ||||
|                 '4.7.3' => 'This version of Firefly III handles bills differently. See https://goo.gl/zkVdrF for more information.', | ||||
|             ], | ||||
|         'install' => | ||||
|             [ | ||||
|   | ||||
| @@ -28,8 +28,8 @@ class ChangesForV473 extends Migration | ||||
|         Schema::table( | ||||
|             'bills', | ||||
|             function (Blueprint $table) { | ||||
|                 $table->integer('currency_id', false, true)->nullable()->after('user_id'); | ||||
|                 $table->foreign('currency_id')->references('id')->on('transaction_currencies')->onDelete('set null'); | ||||
|                 $table->integer('transaction_currency_id', false, true)->nullable()->after('user_id'); | ||||
|                 $table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('set null'); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|   | ||||
							
								
								
									
										3
									
								
								public/js/ff/rules/create-edit.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								public/js/ff/rules/create-edit.js
									
									
									
									
										vendored
									
									
								
							| @@ -285,6 +285,9 @@ function updateTriggerInput(selectList) { | ||||
|             input.prop('disabled', true); | ||||
|             input.typeahead('destroy'); | ||||
|             break; | ||||
|         case 'currency_is': | ||||
|             createAutoComplete(input, 'json/currency-names'); | ||||
|             break; | ||||
|         default: | ||||
|             input.typeahead('destroy'); | ||||
|             break; | ||||
|   | ||||
| @@ -345,6 +345,8 @@ return [ | ||||
|     'rule_trigger_budget_is'                     => 'Budget is ":trigger_value"', | ||||
|     'rule_trigger_tag_is_choice'                 => '(A) tag is..', | ||||
|     'rule_trigger_tag_is'                        => 'A tag is ":trigger_value"', | ||||
|     'rule_trigger_currency_is_choice'            => 'Transaction currency is..', | ||||
|     'rule_trigger_currency_is'                   => 'Transaction currency is ":trigger_value"', | ||||
|     'rule_trigger_has_attachments_choice'        => 'Has at least this many attachments', | ||||
|     'rule_trigger_has_attachments'               => 'Has at least :trigger_value attachment(s)', | ||||
|     'rule_trigger_store_journal'                 => 'When a transaction is created', | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
|  | ||||
| /** | ||||
|  * form.php | ||||
|  * Copyright (c) 2017 thegrumpydictator@gmail.com | ||||
| @@ -36,6 +37,7 @@ return [ | ||||
|     'repeat_freq'                    => 'Repeats', | ||||
|     'journal_currency_id'            => 'Currency', | ||||
|     'currency_id'                    => 'Currency', | ||||
|     'transaction_currency_id'        => 'Currency', | ||||
|     'attachments'                    => 'Attachments', | ||||
|     'journal_amount'                 => 'Amount', | ||||
|     'journal_source_account_name'    => 'Revenue account (source)', | ||||
|   | ||||
| @@ -17,7 +17,7 @@ | ||||
|                     </div> | ||||
|                     <div class="box-body"> | ||||
|                         {{ ExpandedForm.text('name') }} | ||||
|                         {{ ExpandedForm.select('currency_id',currencies, defaultCurrency.id) }} | ||||
|                         {{ ExpandedForm.select('transaction_currency_id',currencies, defaultCurrency.id) }} | ||||
|                         {{ ExpandedForm.amountNoCurrency('amount_min') }} | ||||
|                         {{ ExpandedForm.amountNoCurrency('amount_max') }} | ||||
|                         {{ ExpandedForm.date('date',phpdate('Y-m-d')) }} | ||||
|   | ||||
| @@ -18,9 +18,9 @@ | ||||
|                 </div> | ||||
|                 <div class="box-body"> | ||||
|                     {{ ExpandedForm.text('name') }} | ||||
|                     {{ ExpandedForm.tags('match') }} | ||||
|                     {{ ExpandedForm.amount('amount_min') }} | ||||
|                     {{ ExpandedForm.amount('amount_max') }} | ||||
|                     {{ ExpandedForm.select('transaction_currency_id',currencies) }} | ||||
|                     {{ ExpandedForm.amountNoCurrency('amount_min') }} | ||||
|                     {{ ExpandedForm.amountNoCurrency('amount_max') }} | ||||
|                     {{ ExpandedForm.date('date',bill.date.format('Y-m-d')) }} | ||||
|                     {{ ExpandedForm.select('repeat_freq',periods) }} | ||||
|                 </div> | ||||
| @@ -37,7 +37,6 @@ | ||||
|                     {{ ExpandedForm.textarea('notes',null,{helpText: trans('firefly.field_supports_markdown')}) }} | ||||
|                     {{ ExpandedForm.file('attachments[]', {'multiple': 'multiple','helpText': trans('firefly.upload_max_file_size', {'size': uploadSize|filesize}) }) }} | ||||
|                     {{ ExpandedForm.integer('skip') }} | ||||
|                     {{ ExpandedForm.checkbox('automatch',1) }} | ||||
|                     {{ ExpandedForm.checkbox('active',1) }} | ||||
|  | ||||
|                 </div> | ||||
|   | ||||
| @@ -6,9 +6,12 @@ | ||||
|  | ||||
| {% block content %} | ||||
|  | ||||
|     <form method="POST" action="{{ route('rules.store', ruleGroup.id) }}" accept-charset="UTF-8" class="form-horizontal" id="store"> | ||||
|     <form method="POST" action="{{ route('rules.store') }}" accept-charset="UTF-8" class="form-horizontal" id="store"> | ||||
|         <input name="_token" type="hidden" value="{{ csrf_token() }}"> | ||||
|         <input type="hidden" name="rule_group_id" value="{{ ruleGroup.id }}"/> | ||||
|         <input type="hidden" name="return_to_bill" value="{% if returnToBill %}true{% else %}false{% endif %}"/> | ||||
|         <input type="hidden" name="bill_id" value="{% if bill %}{{ bill.id }}{% else %}0{% endif %}"/> | ||||
|  | ||||
|         <input type="hidden" name="active" value="1"/> | ||||
|         {% if bill %} | ||||
|             <div class="row"> | ||||
| @@ -35,6 +38,7 @@ | ||||
|                     <div class="box-body"> | ||||
|                         {{ ExpandedForm.text('title') }} | ||||
|                         {{ ExpandedForm.select('trigger',allJournalTriggers()) }} | ||||
|                         {{ ExpandedForm.select('rule_group_id',groups, ruleGroup.id) }} | ||||
|                         {{ ExpandedForm.checkbox('stop_processing',1,null, {helpText: trans('firefly.rule_help_stop_processing')}) }} | ||||
|                     </div> | ||||
|                 </div> | ||||
|   | ||||
| @@ -501,6 +501,7 @@ Route::group( | ||||
|     Route::get('budgets', ['uses' => 'Json\AutoCompleteController@budgets', 'as' => 'budgets']); | ||||
|     Route::get('tags', ['uses' => 'Json\AutoCompleteController@tags', 'as' => 'tags']); | ||||
|     Route::get('bills', ['uses' => 'Json\AutoCompleteController@bills', 'as' => 'bills']); | ||||
|     Route::get('currency-names', ['uses' => 'Json\AutoCompleteController@currencyNames', 'as' => 'currency-names']); | ||||
|     Route::get('transaction-journals/all', ['uses' => 'Json\AutoCompleteController@allTransactionJournals', 'as' => 'all-transaction-journals']); | ||||
|     Route::get('transaction-journals/with-id/{tj}', ['uses' => 'Json\AutoCompleteController@journalsWithId', 'as' => 'journals-with-id']); | ||||
|     Route::get('transaction-journals/{what}', ['uses' => 'Json\AutoCompleteController@transactionJournals', 'as' => 'transaction-journals']); | ||||
| @@ -723,7 +724,7 @@ Route::group( | ||||
|  | ||||
|     Route::post('trigger/order/{rule}', ['uses' => 'RuleController@reorderRuleTriggers', 'as' => 'reorder-triggers']); | ||||
|     Route::post('action/order/{rule}', ['uses' => 'RuleController@reorderRuleActions', 'as' => 'reorder-actions']); | ||||
|     Route::post('store/{ruleGroup}', ['uses' => 'RuleController@store', 'as' => 'store']); | ||||
|     Route::post('store', ['uses' => 'RuleController@store', 'as' => 'store']); | ||||
|     Route::post('update/{rule}', ['uses' => 'RuleController@update', 'as' => 'update']); | ||||
|     Route::post('destroy/{rule}', ['uses' => 'RuleController@destroy', 'as' => 'destroy']); | ||||
|     Route::post('execute/{rule}', ['uses' => 'RuleController@execute', 'as' => 'execute']); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user