| 
									
										
										
										
											2020-05-09 14:47:47 +02:00
										 |  |  | <?php | 
					
						
							| 
									
										
										
										
											2020-06-30 19:05:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * UpdatePiggybank.php | 
					
						
							|  |  |  |  * Copyright (c) 2020 james@firefly-iii.org | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This file is part of Firefly III (https://github.com/firefly-iii). | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  |  * it under the terms of the GNU Affero General Public License as | 
					
						
							|  |  |  |  * published by the Free Software Foundation, either version 3 of the | 
					
						
							|  |  |  |  * License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program 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 Affero General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Affero General Public License | 
					
						
							|  |  |  |  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-09 14:47:47 +02:00
										 |  |  | declare(strict_types=1); | 
					
						
							| 
									
										
										
										
											2021-04-05 22:12:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-09 14:47:47 +02:00
										 |  |  | namespace FireflyIII\TransactionRules\Actions; | 
					
						
							| 
									
										
										
										
											2021-04-05 22:12:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-13 15:01:12 +02:00
										 |  |  | use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; | 
					
						
							| 
									
										
										
										
											2022-10-02 06:23:31 +02:00
										 |  |  | use FireflyIII\Events\TriggeredAuditLog; | 
					
						
							| 
									
										
										
										
											2020-05-09 14:47:47 +02:00
										 |  |  | use FireflyIII\Models\PiggyBank; | 
					
						
							|  |  |  | use FireflyIII\Models\RuleAction; | 
					
						
							|  |  |  | use FireflyIII\Models\Transaction; | 
					
						
							| 
									
										
										
										
											2022-10-02 14:37:50 +02:00
										 |  |  | use FireflyIII\Models\TransactionJournal; | 
					
						
							| 
									
										
										
										
											2020-05-09 14:47:47 +02:00
										 |  |  | use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; | 
					
						
							|  |  |  | use FireflyIII\User; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Class UpdatePiggybank | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | class UpdatePiggybank implements ActionInterface | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-03-07 17:18:46 -05:00
										 |  |  |     private RuleAction $action; | 
					
						
							| 
									
										
										
										
											2020-05-09 14:47:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * TriggerInterface constructor. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2024-03-07 17:18:46 -05:00
										 |  |  |     public function __construct(RuleAction $action) | 
					
						
							| 
									
										
										
										
											2020-05-09 14:47:47 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         $this->action = $action; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-23 06:42:26 +01:00
										 |  |  |     public function actOnArray(array $journal): bool | 
					
						
							| 
									
										
										
										
											2020-05-09 14:47:47 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-03-07 17:18:46 -05:00
										 |  |  |         $actionValue = $this->action->getValue($journal); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |         app('log')->debug(sprintf('Triggered rule action UpdatePiggybank on journal #%d', $journal['transaction_journal_id'])); | 
					
						
							| 
									
										
										
										
											2021-09-11 06:52:49 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // refresh the transaction type.
 | 
					
						
							| 
									
										
										
										
											2023-11-28 17:18:31 +01:00
										 |  |  |         /** @var User $user */ | 
					
						
							| 
									
										
										
										
											2024-01-01 14:43:56 +01:00
										 |  |  |         $user        = User::find($journal['user_id']); | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-02 14:37:50 +02:00
										 |  |  |         /** @var TransactionJournal $journalObj */ | 
					
						
							| 
									
										
										
										
											2024-01-01 14:43:56 +01:00
										 |  |  |         $journalObj  = $user->transactionJournals()->find($journal['transaction_journal_id']); | 
					
						
							| 
									
										
										
										
											2021-09-11 06:52:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-07 17:18:46 -05:00
										 |  |  |         $piggyBank   = $this->findPiggyBank($user, $actionValue); | 
					
						
							| 
									
										
										
										
											2021-03-23 06:42:26 +01:00
										 |  |  |         if (null === $piggyBank) { | 
					
						
							| 
									
										
										
										
											2023-10-29 06:31:27 +01:00
										 |  |  |             app('log')->info( | 
					
						
							| 
									
										
										
										
											2024-03-07 17:18:46 -05:00
										 |  |  |                 sprintf('No piggy bank named "%s", cant execute action #%d of rule #%d', $actionValue, $this->action->id, $this->action->rule_id) | 
					
						
							| 
									
										
										
										
											2021-03-23 06:42:26 +01:00
										 |  |  |             ); | 
					
						
							| 
									
										
										
										
											2024-03-07 17:18:46 -05:00
										 |  |  |             event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_piggy', ['name' => $actionValue]))); | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-23 06:42:26 +01:00
										 |  |  |             return false; | 
					
						
							| 
									
										
										
										
											2020-05-09 14:47:47 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |         app('log')->debug(sprintf('Found piggy bank #%d ("%s")', $piggyBank->id, $piggyBank->name)); | 
					
						
							| 
									
										
										
										
											2020-05-09 14:47:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-23 06:42:26 +01:00
										 |  |  |         /** @var Transaction $source */ | 
					
						
							| 
									
										
										
										
											2024-01-01 14:43:56 +01:00
										 |  |  |         $source      = $journalObj->transactions()->where('amount', '<', 0)->first(); | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-31 13:32:42 +01:00
										 |  |  |         /** @var Transaction $destination */ | 
					
						
							| 
									
										
										
										
											2022-12-11 07:29:06 +01:00
										 |  |  |         $destination = $journalObj->transactions()->where('amount', '>', 0)->first(); | 
					
						
							| 
									
										
										
										
											2021-03-23 06:42:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-05 19:41:37 +01:00
										 |  |  |         if ($source->account_id === $piggyBank->account_id) { | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |             app('log')->debug('Piggy bank account is linked to source, so remove amount from piggy bank.'); | 
					
						
							| 
									
										
										
										
											2024-11-02 05:17:46 +01:00
										 |  |  |             $this->removeAmount($piggyBank, $journal, $journalObj, $destination->amount); | 
					
						
							| 
									
										
										
										
											2021-03-23 06:42:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-29 19:42:26 +01:00
										 |  |  |             event( | 
					
						
							|  |  |  |                 new TriggeredAuditLog( | 
					
						
							|  |  |  |                     $this->action->rule, | 
					
						
							|  |  |  |                     $journalObj, | 
					
						
							|  |  |  |                     'remove_from_piggy', | 
					
						
							|  |  |  |                     null, | 
					
						
							|  |  |  |                     [ | 
					
						
							|  |  |  |                         'currency_symbol' => $journalObj->transactionCurrency->symbol, | 
					
						
							|  |  |  |                         'decimal_places'  => $journalObj->transactionCurrency->decimal_places, | 
					
						
							|  |  |  |                         'amount'          => $destination->amount, | 
					
						
							|  |  |  |                         'piggy'           => $piggyBank->name, | 
					
						
							|  |  |  |                     ] | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |             ); | 
					
						
							| 
									
										
										
										
											2022-10-02 06:23:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-23 06:42:26 +01:00
										 |  |  |             return true; | 
					
						
							| 
									
										
										
										
											2020-05-09 14:47:47 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-11-05 19:41:37 +01:00
										 |  |  |         if ($destination->account_id === $piggyBank->account_id) { | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |             app('log')->debug('Piggy bank account is linked to source, so add amount to piggy bank.'); | 
					
						
							| 
									
										
										
										
											2024-11-03 09:01:53 +01:00
										 |  |  |             $this->addAmount($piggyBank, $journal, $journalObj, $destination->amount); | 
					
						
							| 
									
										
										
										
											2020-05-09 14:47:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-29 19:42:26 +01:00
										 |  |  |             event( | 
					
						
							|  |  |  |                 new TriggeredAuditLog( | 
					
						
							|  |  |  |                     $this->action->rule, | 
					
						
							|  |  |  |                     $journalObj, | 
					
						
							|  |  |  |                     'add_to_piggy', | 
					
						
							|  |  |  |                     null, | 
					
						
							|  |  |  |                     [ | 
					
						
							| 
									
										
										
										
											2024-11-03 09:01:53 +01:00
										 |  |  |                         'currency_symbol'    => $journalObj->transactionCurrency->symbol, | 
					
						
							|  |  |  |                         'decimal_places'     => $journalObj->transactionCurrency->decimal_places, | 
					
						
							|  |  |  |                         'amount'             => $destination->amount, | 
					
						
							|  |  |  |                         'piggy'              => $piggyBank->name, | 
					
						
							| 
									
										
										
										
											2024-11-02 05:17:46 +01:00
										 |  |  |                         'piggy_id'           => $piggyBank->id, | 
					
						
							| 
									
										
										
										
											2022-12-29 19:42:26 +01:00
										 |  |  |                     ] | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |             ); | 
					
						
							| 
									
										
										
										
											2022-10-02 06:23:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-23 06:42:26 +01:00
										 |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-10-29 06:31:27 +01:00
										 |  |  |         app('log')->info( | 
					
						
							| 
									
										
										
										
											2021-09-18 10:26:12 +02:00
										 |  |  |             sprintf( | 
					
						
							| 
									
										
										
										
											2022-10-30 14:24:37 +01:00
										 |  |  |                 'Piggy bank is not linked to source ("#%d") or destination ("#%d"), so no action will be taken.', | 
					
						
							|  |  |  |                 $source->account_id, | 
					
						
							|  |  |  |                 $destination->account_id | 
					
						
							| 
									
										
										
										
											2021-09-18 10:26:12 +02:00
										 |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							| 
									
										
										
										
											2024-03-07 17:18:46 -05:00
										 |  |  |         event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_link_piggy', ['name' => $actionValue]))); | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-05 19:12:22 +02:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2020-05-09 14:47:47 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-06 20:54:50 -05:00
										 |  |  |     private function findPiggyBank(User $user, string $name): ?PiggyBank | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-03-06 20:54:50 -05:00
										 |  |  |         return $user->piggyBanks()->where('piggy_banks.name', $name)->first(); | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-02 05:17:46 +01:00
										 |  |  |     private function removeAmount(PiggyBank $piggyBank, array $array, TransactionJournal $journal, string $amount): void | 
					
						
							| 
									
										
										
										
											2020-05-09 14:47:47 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         $repository = app(PiggyBankRepositoryInterface::class); | 
					
						
							|  |  |  |         $repository->setUser($journal->user); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |         // how much can we remove from this piggy bank?
 | 
					
						
							| 
									
										
										
										
											2024-01-01 14:43:56 +01:00
										 |  |  |         $toRemove   = $repository->getCurrentAmount($piggyBank); | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |         app('log')->debug(sprintf('Amount is %s, max to remove is %s', $amount, $toRemove)); | 
					
						
							| 
									
										
										
										
											2022-12-11 07:29:06 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |         // if $amount is bigger than $toRemove, shrink it.
 | 
					
						
							| 
									
										
										
										
											2024-01-01 14:43:56 +01:00
										 |  |  |         $amount     = -1 === bccomp($amount, $toRemove) ? $amount : $toRemove; | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |         app('log')->debug(sprintf('Amount is now %s', $amount)); | 
					
						
							| 
									
										
										
										
											2020-05-09 14:47:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // if amount is zero, stop.
 | 
					
						
							|  |  |  |         if (0 === bccomp('0', $amount)) { | 
					
						
							| 
									
										
										
										
											2022-10-30 14:44:49 +01:00
										 |  |  |             app('log')->warning('Amount left is zero, stop.'); | 
					
						
							| 
									
										
										
										
											2024-11-02 05:17:46 +01:00
										 |  |  |             event(new RuleActionFailedOnArray($this->action, $array, trans('rules.cannot_remove_zero_piggy', ['name' => $piggyBank->name]))); | 
					
						
							| 
									
										
										
										
											2020-05-09 14:47:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |         // make sure we can remove amount:
 | 
					
						
							|  |  |  |         if (false === $repository->canRemoveAmount($piggyBank, $amount)) { | 
					
						
							|  |  |  |             app('log')->warning(sprintf('Cannot remove %s from piggy bank.', $amount)); | 
					
						
							| 
									
										
										
										
											2024-11-03 09:01:53 +01:00
										 |  |  |             event(new RuleActionFailedOnArray($this->action, $array, trans('rules.cannot_remove_from_piggy', ['amount' => $amount, 'name' => $piggyBank->name]))); | 
					
						
							| 
									
										
										
										
											2020-05-09 14:47:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |         app('log')->debug(sprintf('Will now remove %s from piggy bank.', $amount)); | 
					
						
							| 
									
										
										
										
											2023-05-29 13:56:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |         $repository->removeAmount($piggyBank, $amount, $journal); | 
					
						
							| 
									
										
										
										
											2020-05-09 14:47:47 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-08-23 07:42:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-02 05:17:46 +01:00
										 |  |  |     private function addAmount(PiggyBank $piggyBank, array $array, TransactionJournal $journal, string $amount): void | 
					
						
							| 
									
										
										
										
											2020-08-23 07:42:14 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-03-23 06:42:26 +01:00
										 |  |  |         $repository = app(PiggyBankRepositoryInterface::class); | 
					
						
							|  |  |  |         $repository->setUser($journal->user); | 
					
						
							| 
									
										
										
										
											2020-08-28 11:24:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |         // how much can we add to the piggy bank?
 | 
					
						
							| 
									
										
										
										
											2024-11-30 16:02:30 +01:00
										 |  |  |         if (0 !== bccomp($piggyBank->target_amount, '0')) { | 
					
						
							|  |  |  |             $toAdd  = bcsub($piggyBank->target_amount, $repository->getCurrentAmount($piggyBank)); | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |             app('log')->debug(sprintf('Max amount to add to piggy bank is %s, amount is %s', $toAdd, $amount)); | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // update amount to fit:
 | 
					
						
							|  |  |  |             $amount = -1 === bccomp($amount, $toAdd) ? $amount : $toAdd; | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |             app('log')->debug(sprintf('Amount is now %s', $amount)); | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-11-30 16:02:30 +01:00
										 |  |  |         if (0 === bccomp($piggyBank->target_amount, '0')) { | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |             app('log')->debug('Target amount is zero, can add anything.'); | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-08-28 11:24:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-23 06:42:26 +01:00
										 |  |  |         // if amount is zero, stop.
 | 
					
						
							|  |  |  |         if (0 === bccomp('0', $amount)) { | 
					
						
							| 
									
										
										
										
											2022-10-30 14:44:49 +01:00
										 |  |  |             app('log')->warning('Amount left is zero, stop.'); | 
					
						
							| 
									
										
										
										
											2024-11-02 05:17:46 +01:00
										 |  |  |             event(new RuleActionFailedOnArray($this->action, $array, trans('rules.cannot_add_zero_piggy', ['name' => $piggyBank->name]))); | 
					
						
							| 
									
										
										
										
											2024-11-03 09:01:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-23 06:42:26 +01:00
										 |  |  |             return; | 
					
						
							| 
									
										
										
										
											2020-08-28 11:24:55 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |         // make sure we can add amount:
 | 
					
						
							|  |  |  |         if (false === $repository->canAddAmount($piggyBank, $amount)) { | 
					
						
							|  |  |  |             app('log')->warning(sprintf('Cannot add %s to piggy bank.', $amount)); | 
					
						
							| 
									
										
										
										
											2024-11-03 09:01:53 +01:00
										 |  |  |             event(new RuleActionFailedOnArray($this->action, $array, trans('rules.cannot_add_to_piggy', ['amount' => $amount, 'name' => $piggyBank->name]))); | 
					
						
							| 
									
										
										
										
											2021-03-23 06:42:26 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             return; | 
					
						
							| 
									
										
										
										
											2020-08-28 11:24:55 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |         app('log')->debug(sprintf('Will now add %s to piggy bank.', $amount)); | 
					
						
							| 
									
										
										
										
											2020-08-28 11:24:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |         $repository->addAmount($piggyBank, $amount, $journal); | 
					
						
							| 
									
										
										
										
											2020-08-23 07:42:14 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-05-09 14:47:47 +02:00
										 |  |  | } |