| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  | <?php | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * JournalUpdateService.php | 
					
						
							| 
									
										
										
										
											2020-02-16 13:56:35 +01:00
										 |  |  |  * Copyright (c) 2019 james@firefly-iii.org | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-10-02 06:37:26 +02:00
										 |  |  |  * This file is part of Firefly III (https://github.com/firefly-iii). | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-10-02 06:37:26 +02:00
										 |  |  |  * 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. | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-10-02 06:37:26 +02:00
										 |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							| 
									
										
										
										
											2019-10-02 06:37:26 +02:00
										 |  |  |  * GNU Affero General Public License for more details. | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-10-02 06:37:26 +02:00
										 |  |  |  * 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/>. | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | declare(strict_types=1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 18:42:15 +01:00
										 |  |  | namespace FireflyIII\Services\Internal\Update; | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  | use Carbon\Carbon; | 
					
						
							|  |  |  | use Exception; | 
					
						
							|  |  |  | use FireflyIII\Exceptions\FireflyException; | 
					
						
							|  |  |  | use FireflyIII\Factory\TagFactory; | 
					
						
							|  |  |  | use FireflyIII\Factory\TransactionJournalMetaFactory; | 
					
						
							|  |  |  | use FireflyIII\Factory\TransactionTypeFactory; | 
					
						
							|  |  |  | use FireflyIII\Models\Account; | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  | use FireflyIII\Models\Transaction; | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  | use FireflyIII\Models\TransactionGroup; | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  | use FireflyIII\Models\TransactionJournal; | 
					
						
							| 
									
										
										
										
											2018-08-09 20:46:47 +02:00
										 |  |  | use FireflyIII\Models\TransactionType; | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  | 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; | 
					
						
							| 
									
										
										
										
											2018-02-23 15:12:47 +01:00
										 |  |  | use FireflyIII\Services\Internal\Support\JournalServiceTrait; | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  | use FireflyIII\Support\NullArrayObject; | 
					
						
							|  |  |  | use FireflyIII\Validation\AccountValidator; | 
					
						
							| 
									
										
										
										
											2018-03-02 16:31:02 +01:00
										 |  |  | use Log; | 
					
						
							| 
									
										
										
										
											2019-02-12 21:49:28 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Class to centralise code that updates a journal given the input by system. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Class JournalUpdateService | 
					
						
							| 
									
										
										
										
											2019-07-31 16:53:09 +02:00
										 |  |  |  * TODO test me | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | class JournalUpdateService | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-23 15:12:47 +01:00
										 |  |  |     use JournalServiceTrait; | 
					
						
							| 
									
										
										
										
											2019-02-12 21:49:28 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-10 06:34:03 +01:00
										 |  |  |     private BillRepositoryInterface     $billRepository; | 
					
						
							|  |  |  |     private CurrencyRepositoryInterface $currencyRepository; | 
					
						
							|  |  |  |     private array                       $data; | 
					
						
							|  |  |  |     private ?Account                    $destinationAccount; | 
					
						
							|  |  |  |     private ?Transaction                $destinationTransaction; | 
					
						
							|  |  |  |     private array                       $metaDate; | 
					
						
							|  |  |  |     private array                       $metaString; | 
					
						
							|  |  |  |     private ?Account                    $sourceAccount; | 
					
						
							|  |  |  |     private ?Transaction                $sourceTransaction; | 
					
						
							| 
									
										
										
										
											2021-03-23 18:38:24 +01:00
										 |  |  |     private ?TransactionGroup           $transactionGroup; | 
					
						
							|  |  |  |     private ?TransactionJournal         $transactionJournal; | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-06 12:29:32 +02:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |      * JournalUpdateService constructor. | 
					
						
							| 
									
										
										
										
											2018-09-06 12:29:32 +02:00
										 |  |  |      */ | 
					
						
							|  |  |  |     public function __construct() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-03-23 18:38:24 +01:00
										 |  |  |         $this->destinationAccount     = null; | 
					
						
							|  |  |  |         $this->destinationTransaction = null; | 
					
						
							|  |  |  |         $this->sourceAccount          = null; | 
					
						
							|  |  |  |         $this->sourceTransaction      = null; | 
					
						
							|  |  |  |         $this->transactionGroup       = null; | 
					
						
							|  |  |  |         $this->transactionJournal     = null; | 
					
						
							|  |  |  |         $this->billRepository         = app(BillRepositoryInterface::class); | 
					
						
							|  |  |  |         $this->categoryRepository     = app(CategoryRepositoryInterface::class); | 
					
						
							|  |  |  |         $this->budgetRepository       = app(BudgetRepositoryInterface::class); | 
					
						
							|  |  |  |         $this->tagFactory             = app(TagFactory::class); | 
					
						
							|  |  |  |         $this->accountRepository      = app(AccountRepositoryInterface::class); | 
					
						
							|  |  |  |         $this->currencyRepository     = app(CurrencyRepositoryInterface::class); | 
					
						
							|  |  |  |         $this->metaString             = ['sepa_cc', 'sepa_ct_op', 'sepa_ct_id', 'sepa_db', 'sepa_country', 'sepa_ep', 'sepa_ci', 'sepa_batch_id', | 
					
						
							|  |  |  |                                          'recurrence_id', | 
					
						
							|  |  |  |                                          'internal_reference', 'bunq_payment_id', 'external_id', 'external_uri']; | 
					
						
							|  |  |  |         $this->metaDate               = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date',]; | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * @param array $data | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function setData(array $data): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->data = $data; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * @param TransactionGroup $transactionGroup | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function setTransactionGroup(TransactionGroup $transactionGroup): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->transactionGroup = $transactionGroup; | 
					
						
							|  |  |  |         $this->billRepository->setUser($transactionGroup->user); | 
					
						
							|  |  |  |         $this->categoryRepository->setUser($transactionGroup->user); | 
					
						
							|  |  |  |         $this->budgetRepository->setUser($transactionGroup->user); | 
					
						
							|  |  |  |         $this->tagFactory->setUser($transactionGroup->user); | 
					
						
							|  |  |  |         $this->accountRepository->setUser($transactionGroup->user); | 
					
						
							| 
									
										
										
										
											2021-03-10 06:34:03 +01:00
										 |  |  |         $this->destinationAccount     = null; | 
					
						
							|  |  |  |         $this->destinationTransaction = null; | 
					
						
							|  |  |  |         $this->sourceAccount          = null; | 
					
						
							|  |  |  |         $this->sourceTransaction      = null; | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * @param TransactionJournal $transactionJournal | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function setTransactionJournal(TransactionJournal $transactionJournal): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->transactionJournal = $transactionJournal; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function update(): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Log::debug(sprintf('Now in JournalUpdateService for journal #%d.', $this->transactionJournal->id)); | 
					
						
							|  |  |  |         // can we update account data using the new type?
 | 
					
						
							|  |  |  |         if ($this->hasValidAccounts()) { | 
					
						
							| 
									
										
										
										
											2021-03-10 06:34:03 +01:00
										 |  |  |             Log::info('Account info is valid, now update.'); | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |             // update accounts:
 | 
					
						
							|  |  |  |             $this->updateAccounts(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // then also update transaction journal type ID:
 | 
					
						
							|  |  |  |             $this->updateType(); | 
					
						
							|  |  |  |             $this->transactionJournal->refresh(); | 
					
						
							| 
									
										
										
										
											2018-09-06 12:29:32 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |         // find and update bill, if possible.
 | 
					
						
							|  |  |  |         $this->updateBill(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // update journal fields.
 | 
					
						
							|  |  |  |         $this->updateField('description'); | 
					
						
							|  |  |  |         $this->updateField('date'); | 
					
						
							|  |  |  |         $this->updateField('order'); | 
					
						
							|  |  |  |         $this->transactionJournal->save(); | 
					
						
							|  |  |  |         $this->transactionJournal->refresh(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 20:55:31 +01:00
										 |  |  |         $this->updateCategory(); | 
					
						
							|  |  |  |         $this->updateBudget(); | 
					
						
							|  |  |  |         $this->updateTags(); | 
					
						
							| 
									
										
										
										
											2021-03-11 06:29:07 +01:00
										 |  |  |         $this->updateReconciled(); | 
					
						
							| 
									
										
										
										
											2020-03-18 20:55:31 +01:00
										 |  |  |         $this->updateNotes(); | 
					
						
							|  |  |  |         $this->updateMeta(); | 
					
						
							|  |  |  |         $this->updateCurrency(); | 
					
						
							|  |  |  |         $this->updateAmount(); | 
					
						
							|  |  |  |         $this->updateForeignAmount(); | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // TODO update hash
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         app('preferences')->mark(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->transactionJournal->refresh(); | 
					
						
							| 
									
										
										
										
											2018-09-06 12:29:32 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |      * @return bool | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |     private function hasValidAccounts(): bool | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         return $this->hasValidSourceAccount() && $this->hasValidDestinationAccount(); | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |      * @return bool | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |     private function hasValidSourceAccount(): bool | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         Log::debug('Now in hasValidSourceAccount().'); | 
					
						
							|  |  |  |         $sourceId   = $this->data['source_id'] ?? null; | 
					
						
							|  |  |  |         $sourceName = $this->data['source_name'] ?? null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!$this->hasFields(['source_id', 'source_name'])) { | 
					
						
							|  |  |  |             $origSourceAccount = $this->getOriginalSourceAccount(); | 
					
						
							|  |  |  |             $sourceId          = $origSourceAccount->id; | 
					
						
							|  |  |  |             $sourceName        = $origSourceAccount->name; | 
					
						
							| 
									
										
										
										
											2018-02-21 08:58:06 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         // make new account validator.
 | 
					
						
							|  |  |  |         $expectedType = $this->getExpectedType(); | 
					
						
							|  |  |  |         Log::debug(sprintf('Expected type (new or unchanged) is %s', $expectedType)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // make a new validator.
 | 
					
						
							|  |  |  |         /** @var AccountValidator $validator */ | 
					
						
							|  |  |  |         $validator = app(AccountValidator::class); | 
					
						
							|  |  |  |         $validator->setTransactionType($expectedType); | 
					
						
							|  |  |  |         $validator->setUser($this->transactionJournal->user); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $result = $validator->validateSource($sourceId, $sourceName, null); | 
					
						
							|  |  |  |         Log::debug(sprintf('hasValidSourceAccount(%d, "%s") will return %s', $sourceId, $sourceName, var_export($result, true))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // TODO typeOverrule: the account validator may have another opinion on the transaction type.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // validate submitted info:
 | 
					
						
							|  |  |  |         return $result; | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |      * @param array $fields | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return bool | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |     private function hasFields(array $fields): bool | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         foreach ($fields as $field) { | 
					
						
							|  |  |  |             if (array_key_exists($field, $this->data)) { | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * @return Account | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     private function getOriginalSourceAccount(): Account | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (null === $this->sourceAccount) { | 
					
						
							|  |  |  |             $source              = $this->getSourceTransaction(); | 
					
						
							|  |  |  |             $this->sourceAccount = $source->account; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $this->sourceAccount; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * @return Transaction | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     private function getSourceTransaction(): Transaction | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (null === $this->sourceTransaction) { | 
					
						
							|  |  |  |             $this->sourceTransaction = $this->transactionJournal->transactions()->with(['account'])->where('amount', '<', 0)->first(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-07-20 16:02:50 +02:00
										 |  |  |         Log::debug(sprintf('getSourceTransaction: %s', $this->sourceTransaction->amount)); | 
					
						
							| 
									
										
										
										
											2018-02-21 08:51:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |         return $this->sourceTransaction; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-05-29 07:25:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |      * This method returns the current or expected type of the journal (in case of a change) based on the data in the array. | 
					
						
							| 
									
										
										
										
											2018-02-23 16:21:28 +01:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |      * If the array contains key 'type' and the value is correct, this is returned. Otherwise, the original type is returned. | 
					
						
							| 
									
										
										
										
											2018-02-23 16:21:28 +01:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |      * @return string | 
					
						
							| 
									
										
										
										
											2018-02-23 16:21:28 +01:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |     private function getExpectedType(): string | 
					
						
							| 
									
										
										
										
											2018-02-23 16:21:28 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         Log::debug('Now in getExpectedType()'); | 
					
						
							|  |  |  |         if ($this->hasFields(['type'])) { | 
					
						
							|  |  |  |             return ucfirst('opening-balance' === $this->data['type'] ? 'opening balance' : $this->data['type']); | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         return $this->transactionJournal->transactionType->type; | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * @return bool | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     private function hasValidDestinationAccount(): bool | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Log::debug('Now in hasValidDestinationAccount().'); | 
					
						
							|  |  |  |         $destId   = $this->data['destination_id'] ?? null; | 
					
						
							|  |  |  |         $destName = $this->data['destination_name'] ?? null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!$this->hasFields(['destination_id', 'destination_name'])) { | 
					
						
							| 
									
										
										
										
											2021-03-10 06:34:03 +01:00
										 |  |  |             Log::debug('No destination info submitted, grab the original data.'); | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |             $destination = $this->getOriginalDestinationAccount(); | 
					
						
							|  |  |  |             $destId      = $destination->id; | 
					
						
							|  |  |  |             $destName    = $destination->name; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // make new account validator.
 | 
					
						
							|  |  |  |         $expectedType = $this->getExpectedType(); | 
					
						
							|  |  |  |         Log::debug(sprintf('Expected type (new or unchanged) is %s', $expectedType)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // make a new validator.
 | 
					
						
							|  |  |  |         /** @var AccountValidator $validator */ | 
					
						
							|  |  |  |         $validator = app(AccountValidator::class); | 
					
						
							|  |  |  |         $validator->setTransactionType($expectedType); | 
					
						
							|  |  |  |         $validator->setUser($this->transactionJournal->user); | 
					
						
							|  |  |  |         $validator->source = $this->getValidSourceAccount(); | 
					
						
							| 
									
										
										
										
											2021-04-15 06:15:17 +02:00
										 |  |  |         $result            = $validator->validateDestination($destId, $destName, null); | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |         Log::debug(sprintf('hasValidDestinationAccount(%d, "%s") will return %s', $destId, $destName, var_export($result, true))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-31 07:41:48 +02:00
										 |  |  |         // TODO typeOverrule: the account validator may have another opinion on the transaction type.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |         // validate submitted info:
 | 
					
						
							|  |  |  |         return $result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |      * @return Account | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |     private function getOriginalDestinationAccount(): Account | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         if (null === $this->destinationAccount) { | 
					
						
							|  |  |  |             $destination              = $this->getDestinationTransaction(); | 
					
						
							|  |  |  |             $this->destinationAccount = $destination->account; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $this->destinationAccount; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get destination transaction. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return Transaction | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     private function getDestinationTransaction(): Transaction | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (null === $this->destinationTransaction) { | 
					
						
							|  |  |  |             $this->destinationTransaction = $this->transactionJournal->transactions()->where('amount', '>', 0)->first(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $this->destinationTransaction; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Does a validation and returns the source account. This method will break if the source isn't really valid. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return Account | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     private function getValidSourceAccount(): Account | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Log::debug('Now in getValidSourceAccount().'); | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (!$this->hasFields(['source_id', 'source_name'])) { | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |             return $this->getOriginalSourceAccount(); | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         $sourceInfo = [ | 
					
						
							|  |  |  |             'id'     => (int)($this->data['source_id'] ?? null), | 
					
						
							|  |  |  |             'name'   => $this->data['source_name'] ?? null, | 
					
						
							|  |  |  |             'iban'   => $this->data['source_iban'] ?? null, | 
					
						
							|  |  |  |             'number' => $this->data['source_number'] ?? null, | 
					
						
							|  |  |  |             'bic'    => $this->data['source_bic'] ?? null, | 
					
						
							|  |  |  |         ]; | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         $expectedType = $this->getExpectedType(); | 
					
						
							|  |  |  |         try { | 
					
						
							|  |  |  |             $result = $this->getAccount($expectedType, 'source', $sourceInfo); | 
					
						
							|  |  |  |         } catch (FireflyException $e) { | 
					
						
							|  |  |  |             Log::error(sprintf('Cant get the valid source account: %s', $e->getMessage())); | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |             $result = $this->getOriginalSourceAccount(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         Log::debug(sprintf('getValidSourceAccount() will return #%d ("%s")', $result->id, $result->name)); | 
					
						
							| 
									
										
										
										
											2020-03-31 07:41:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |         return $result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Will update the source and destination accounts of this journal. Assumes they are valid. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     private function updateAccounts(): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $source      = $this->getValidSourceAccount(); | 
					
						
							|  |  |  |         $destination = $this->getValidDestinationAccount(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // cowardly refuse to update if both accounts are the same.
 | 
					
						
							|  |  |  |         if ($source->id === $destination->id) { | 
					
						
							|  |  |  |             Log::error(sprintf('Source + dest accounts are equal (%d, "%s")', $source->id, $source->name)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return; | 
					
						
							| 
									
										
										
										
											2018-02-23 16:21:28 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-24 18:40:17 +02:00
										 |  |  |         $origSourceTransaction = $this->getSourceTransaction(); | 
					
						
							|  |  |  |         $origSourceTransaction->account()->associate($source); | 
					
						
							|  |  |  |         $origSourceTransaction->save(); | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-20 16:02:50 +02:00
										 |  |  |         $destTransaction = $this->getDestinationTransaction(); | 
					
						
							|  |  |  |         $destTransaction->account()->associate($destination); | 
					
						
							|  |  |  |         $destTransaction->save(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // refresh transactions.
 | 
					
						
							|  |  |  |         $this->sourceTransaction->refresh(); | 
					
						
							|  |  |  |         $this->destinationTransaction->refresh(); | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |         Log::debug(sprintf('Will set source to #%d ("%s")', $source->id, $source->name)); | 
					
						
							|  |  |  |         Log::debug(sprintf('Will set dest to #%d ("%s")', $destination->id, $destination->name)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |      * Does a validation and returns the destination account. This method will break if the dest isn't really valid. | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |      * @return Account | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |     private function getValidDestinationAccount(): Account | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         Log::debug('Now in getValidDestinationAccount().'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!$this->hasFields(['destination_id', 'destination_name'])) { | 
					
						
							|  |  |  |             return $this->getOriginalDestinationAccount(); | 
					
						
							| 
									
										
										
										
											2020-03-18 20:55:31 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         $destInfo = [ | 
					
						
							|  |  |  |             'id'     => (int)($this->data['destination_id'] ?? null), | 
					
						
							|  |  |  |             'name'   => $this->data['destination_name'] ?? null, | 
					
						
							|  |  |  |             'iban'   => $this->data['destination_iban'] ?? null, | 
					
						
							|  |  |  |             'number' => $this->data['destination_number'] ?? null, | 
					
						
							|  |  |  |             'bic'    => $this->data['destination_bic'] ?? null, | 
					
						
							|  |  |  |         ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // make new account validator.
 | 
					
						
							|  |  |  |         $expectedType = $this->getExpectedType(); | 
					
						
							|  |  |  |         Log::debug(sprintf('Expected type (new or unchanged) is %s', $expectedType)); | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |         try { | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |             $result = $this->getAccount($expectedType, 'destination', $destInfo); | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |         } catch (FireflyException $e) { | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |             Log::error(sprintf('getValidDestinationAccount() threw unexpected error: %s', $e->getMessage())); | 
					
						
							|  |  |  |             $result = $this->getOriginalDestinationAccount(); | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         return $result; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-07-20 16:02:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Updates journal transaction type. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     private function updateType(): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Log::debug('Now in updateType()'); | 
					
						
							|  |  |  |         if ($this->hasFields(['type'])) { | 
					
						
							|  |  |  |             $type = 'opening-balance' === $this->data['type'] ? 'opening balance' : $this->data['type']; | 
					
						
							|  |  |  |             Log::debug( | 
					
						
							|  |  |  |                 sprintf( | 
					
						
							|  |  |  |                     'Trying to change journal #%d from a %s to a %s.', | 
					
						
							|  |  |  |                     $this->transactionJournal->id, $this->transactionJournal->transactionType->type, $type | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |             ); | 
					
						
							| 
									
										
										
										
											2019-07-20 16:02:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |             /** @var TransactionTypeFactory $typeFactory */ | 
					
						
							|  |  |  |             $typeFactory = app(TransactionTypeFactory::class); | 
					
						
							|  |  |  |             $result      = $typeFactory->find($this->data['type']); | 
					
						
							|  |  |  |             if (null !== $result) { | 
					
						
							|  |  |  |                 Log::debug('Changed transaction type!'); | 
					
						
							|  |  |  |                 $this->transactionJournal->transaction_type_id = $result->id; | 
					
						
							|  |  |  |                 $this->transactionJournal->save(); | 
					
						
							| 
									
										
										
										
											2019-07-20 16:02:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Log::debug('No type field present.'); | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Update journal bill information. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     private function updateBill(): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $type = $this->transactionJournal->transactionType->type; | 
					
						
							|  |  |  |         if (( | 
					
						
							|  |  |  |                 array_key_exists('bill_id', $this->data) | 
					
						
							|  |  |  |                 || array_key_exists('bill_name', $this->data) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             && TransactionType::WITHDRAWAL === $type | 
					
						
							|  |  |  |         ) { | 
					
						
							| 
									
										
										
										
											2020-10-24 17:27:36 +02:00
										 |  |  |             $billId                            = (int)($this->data['bill_id'] ?? 0); | 
					
						
							|  |  |  |             $billName                          = (string)($this->data['bill_name'] ?? ''); | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |             $bill                              = $this->billRepository->findBill($billId, $billName); | 
					
						
							|  |  |  |             $this->transactionJournal->bill_id = null === $bill ? null : $bill->id; | 
					
						
							|  |  |  |             Log::debug('Updated bill ID'); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 20:55:31 +01:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |      * Update journal generic field. Cannot be set to NULL. | 
					
						
							| 
									
										
										
										
											2020-03-18 20:55:31 +01:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |      * @param string $fieldName | 
					
						
							| 
									
										
										
										
											2020-03-18 20:55:31 +01:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |     private function updateField(string $fieldName): void | 
					
						
							| 
									
										
										
										
											2020-03-18 20:55:31 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         if (array_key_exists($fieldName, $this->data) && '' !== (string)$this->data[$fieldName]) { | 
					
						
							|  |  |  |             $value = $this->data[$fieldName]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if ('date' === $fieldName) { | 
					
						
							|  |  |  |                 if ($value instanceof Carbon) { | 
					
						
							|  |  |  |                     // update timezone.
 | 
					
						
							|  |  |  |                     $value->setTimezone(config('app.timezone')); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if (!($value instanceof Carbon)) { | 
					
						
							|  |  |  |                     $value = new Carbon($value); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 // do some parsing.
 | 
					
						
							|  |  |  |                 Log::debug(sprintf('Create date value from string "%s".', $value)); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             $this->transactionJournal->$fieldName = $value; | 
					
						
							|  |  |  |             Log::debug(sprintf('Updated %s', $fieldName)); | 
					
						
							| 
									
										
										
										
											2020-03-18 20:55:31 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     private function updateCategory(): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // update category
 | 
					
						
							|  |  |  |         if ($this->hasFields(['category_id', 'category_name'])) { | 
					
						
							|  |  |  |             Log::debug('Will update category.'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $this->storeCategory($this->transactionJournal, new NullArrayObject($this->data)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |     private function updateBudget(): void | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         // update budget
 | 
					
						
							|  |  |  |         if ($this->hasFields(['budget_id', 'budget_name'])) { | 
					
						
							|  |  |  |             Log::debug('Will update budget.'); | 
					
						
							|  |  |  |             $this->storeBudget($this->transactionJournal, new NullArrayObject($this->data)); | 
					
						
							| 
									
										
										
										
											2018-08-09 20:49:30 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-04-15 06:15:17 +02:00
										 |  |  |         // is transfer? remove budget
 | 
					
						
							|  |  |  |         if (TransactionType::TRANSFER === $this->transactionJournal->transactionType->type) { | 
					
						
							|  |  |  |             $this->transactionJournal->budgets()->sync([]); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-23 16:21:28 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |     private function updateTags(): void | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         if ($this->hasFields(['tags'])) { | 
					
						
							|  |  |  |             Log::debug('Will update tags.'); | 
					
						
							|  |  |  |             $tags = $this->data['tags'] ?? null; | 
					
						
							|  |  |  |             $this->storeTags($this->transactionJournal, $tags); | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-02-23 16:21:28 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |     private function updateReconciled(): void | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         if (array_key_exists('reconciled', $this->data) && is_bool($this->data['reconciled'])) { | 
					
						
							|  |  |  |             $this->transactionJournal->transactions()->update(['reconciled' => $this->data['reconciled']]); | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     private function updateNotes(): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // update notes.
 | 
					
						
							|  |  |  |         if ($this->hasFields(['notes'])) { | 
					
						
							|  |  |  |             $notes = '' === (string)$this->data['notes'] ? null : $this->data['notes']; | 
					
						
							|  |  |  |             $this->storeNotes($this->transactionJournal, $notes); | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 20:55:31 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     private function updateMeta(): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // update meta fields.
 | 
					
						
							|  |  |  |         // first string
 | 
					
						
							|  |  |  |         if ($this->hasFields($this->metaString)) { | 
					
						
							|  |  |  |             Log::debug('Meta string fields are present.'); | 
					
						
							|  |  |  |             $this->updateMetaFields(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // then date fields.
 | 
					
						
							|  |  |  |         if ($this->hasFields($this->metaDate)) { | 
					
						
							|  |  |  |             Log::debug('Meta date fields are present.'); | 
					
						
							|  |  |  |             $this->updateMetaDateFields(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2018-02-23 16:21:28 +01:00
										 |  |  |      * | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |     private function updateMetaFields(): void | 
					
						
							| 
									
										
										
										
											2018-02-23 16:21:28 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |         /** @var TransactionJournalMetaFactory $factory */ | 
					
						
							|  |  |  |         $factory = app(TransactionJournalMetaFactory::class); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         foreach ($this->metaString as $field) { | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |             if ($this->hasFields([$field])) { | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |                 $value = '' === $this->data[$field] ? null : $this->data[$field]; | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |                 Log::debug(sprintf('Field "%s" is present ("%s"), try to update it.', $field, $value)); | 
					
						
							|  |  |  |                 $set = [ | 
					
						
							|  |  |  |                     'journal' => $this->transactionJournal, | 
					
						
							|  |  |  |                     'name'    => $field, | 
					
						
							|  |  |  |                     'data'    => $value, | 
					
						
							|  |  |  |                 ]; | 
					
						
							|  |  |  |                 $factory->updateOrCreate($set); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-02-23 16:21:28 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-23 16:21:28 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |     private function updateMetaDateFields(): void | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         /** @var TransactionJournalMetaFactory $factory */ | 
					
						
							|  |  |  |         $factory = app(TransactionJournalMetaFactory::class); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         foreach ($this->metaDate as $field) { | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |             if ($this->hasFields([$field])) { | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |                 try { | 
					
						
							|  |  |  |                     $value = '' === (string)$this->data[$field] ? null : new Carbon($this->data[$field]); | 
					
						
							| 
									
										
										
										
											2021-04-06 17:00:16 +02:00
										 |  |  |                 } catch (Exception $e) { // @phpstan-ignore-line
 | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |                     Log::debug(sprintf('%s is not a valid date value: %s', $this->data[$field], $e->getMessage())); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     return; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |                 Log::debug(sprintf('Field "%s" is present ("%s"), try to update it.', $field, $value)); | 
					
						
							|  |  |  |                 $set = [ | 
					
						
							|  |  |  |                     'journal' => $this->transactionJournal, | 
					
						
							|  |  |  |                     'name'    => $field, | 
					
						
							|  |  |  |                     'data'    => $value, | 
					
						
							|  |  |  |                 ]; | 
					
						
							|  |  |  |                 $factory->updateOrCreate($set); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-02-23 16:21:28 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 20:55:31 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |     private function updateCurrency(): void | 
					
						
							| 
									
										
										
										
											2020-03-18 20:55:31 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         // update transactions.
 | 
					
						
							|  |  |  |         if (!$this->hasFields(['currency_id', 'currency_code'])) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $currencyId   = $this->data['currency_id'] ?? null; | 
					
						
							|  |  |  |         $currencyCode = $this->data['currency_code'] ?? null; | 
					
						
							|  |  |  |         $currency     = $this->currencyRepository->findCurrency($currencyId, $currencyCode); | 
					
						
							|  |  |  |         if (null !== $currency) { | 
					
						
							|  |  |  |             // update currency everywhere.
 | 
					
						
							|  |  |  |             $this->transactionJournal->transaction_currency_id = $currency->id; | 
					
						
							|  |  |  |             $this->transactionJournal->save(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $source                          = $this->getSourceTransaction(); | 
					
						
							|  |  |  |             $source->transaction_currency_id = $currency->id; | 
					
						
							|  |  |  |             $source->save(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $dest                          = $this->getDestinationTransaction(); | 
					
						
							|  |  |  |             $dest->transaction_currency_id = $currency->id; | 
					
						
							|  |  |  |             $dest->save(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // refresh transactions.
 | 
					
						
							|  |  |  |             $this->sourceTransaction->refresh(); | 
					
						
							|  |  |  |             $this->destinationTransaction->refresh(); | 
					
						
							|  |  |  |             Log::debug(sprintf('Updated currency to #%d (%s)', $currency->id, $currency->code)); | 
					
						
							| 
									
										
										
										
											2020-03-18 20:55:31 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |     private function updateAmount(): void | 
					
						
							| 
									
										
										
										
											2020-03-18 20:55:31 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         if (!$this->hasFields(['amount'])) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $value = $this->data['amount'] ?? ''; | 
					
						
							|  |  |  |         try { | 
					
						
							|  |  |  |             $amount = $this->getAmount($value); | 
					
						
							|  |  |  |         } catch (FireflyException $e) { | 
					
						
							|  |  |  |             Log::debug(sprintf('getAmount("%s") returns error: %s', $value, $e->getMessage())); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return; | 
					
						
							| 
									
										
										
										
											2020-03-18 20:55:31 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         $origSourceTransaction         = $this->getSourceTransaction(); | 
					
						
							|  |  |  |         $origSourceTransaction->amount = app('steam')->negative($amount); | 
					
						
							|  |  |  |         $origSourceTransaction->save(); | 
					
						
							|  |  |  |         $destTransaction         = $this->getDestinationTransaction(); | 
					
						
							|  |  |  |         $destTransaction->amount = app('steam')->positive($amount); | 
					
						
							|  |  |  |         $destTransaction->save(); | 
					
						
							|  |  |  |         // refresh transactions.
 | 
					
						
							|  |  |  |         $this->sourceTransaction->refresh(); | 
					
						
							|  |  |  |         $this->destinationTransaction->refresh(); | 
					
						
							|  |  |  |         Log::debug(sprintf('Updated amount to "%s"', $amount)); | 
					
						
							| 
									
										
										
										
											2020-03-18 20:55:31 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |     private function updateForeignAmount(): void | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         // amount, foreign currency.
 | 
					
						
							|  |  |  |         if (!$this->hasFields(['foreign_currency_id', 'foreign_currency_code', 'foreign_amount'])) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         $amount          = $this->data['foreign_amount'] ?? null; | 
					
						
							|  |  |  |         $foreignAmount   = $this->getForeignAmount($amount); | 
					
						
							|  |  |  |         $source          = $this->getSourceTransaction(); | 
					
						
							|  |  |  |         $dest            = $this->getDestinationTransaction(); | 
					
						
							|  |  |  |         $foreignCurrency = $source->foreignCurrency; | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         // find currency in data array
 | 
					
						
							|  |  |  |         $newForeignId    = $this->data['foreign_currency_id'] ?? null; | 
					
						
							|  |  |  |         $newForeignCode  = $this->data['foreign_currency_code'] ?? null; | 
					
						
							|  |  |  |         $foreignCurrency = $this->currencyRepository->findCurrencyNull($newForeignId, $newForeignCode) ?? $foreignCurrency; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // not the same as normal currency
 | 
					
						
							|  |  |  |         if (null !== $foreignCurrency && $foreignCurrency->id === $this->transactionJournal->transaction_currency_id) { | 
					
						
							|  |  |  |             Log::error(sprintf('Foreign currency is equal to normal currency (%s)', $foreignCurrency->code)); | 
					
						
							| 
									
										
										
										
											2019-04-06 08:10:50 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-03-11 06:29:07 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         // add foreign currency info to source and destination if possible.
 | 
					
						
							|  |  |  |         if (null !== $foreignCurrency && null !== $foreignAmount) { | 
					
						
							|  |  |  |             $source->foreign_currency_id = $foreignCurrency->id; | 
					
						
							|  |  |  |             $source->foreign_amount      = app('steam')->negative($foreignAmount); | 
					
						
							|  |  |  |             $source->save(); | 
					
						
							|  |  |  |             $dest->foreign_currency_id = $foreignCurrency->id; | 
					
						
							|  |  |  |             $dest->foreign_amount      = app('steam')->positive($foreignAmount); | 
					
						
							|  |  |  |             $dest->save(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             Log::debug(sprintf('Update foreign info to %s (#%d) %s', $foreignCurrency->code, $foreignCurrency->id, $foreignAmount)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // refresh transactions.
 | 
					
						
							|  |  |  |             $this->sourceTransaction->refresh(); | 
					
						
							|  |  |  |             $this->destinationTransaction->refresh(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if ('0' === $amount) { | 
					
						
							|  |  |  |             $source->foreign_currency_id = null; | 
					
						
							|  |  |  |             $source->foreign_amount      = null; | 
					
						
							|  |  |  |             $source->save(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $dest->foreign_currency_id = null; | 
					
						
							|  |  |  |             $dest->foreign_amount      = null; | 
					
						
							|  |  |  |             $dest->save(); | 
					
						
							|  |  |  |             Log::debug(sprintf('Foreign amount is "%s" so remove foreign amount info.', $amount)); | 
					
						
							| 
									
										
										
										
											2021-03-11 06:29:07 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-03-12 18:31:19 +01:00
										 |  |  |         Log::info('Not enough info to update foreign currency info.'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // refresh transactions.
 | 
					
						
							|  |  |  |         $this->sourceTransaction->refresh(); | 
					
						
							|  |  |  |         $this->destinationTransaction->refresh(); | 
					
						
							| 
									
										
										
										
											2021-03-11 06:29:07 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-05 19:35:58 +01:00
										 |  |  | } |