| 
									
										
										
										
											2018-02-16 16:43:25 +01:00
										 |  |  | <?php | 
					
						
							| 
									
										
										
										
											2018-05-11 10:08:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 16:43:25 +01:00
										 |  |  | /** | 
					
						
							|  |  |  |  * TransactionFactory.php | 
					
						
							| 
									
										
										
										
											2020-02-16 14:00:57 +01:00
										 |  |  |  * Copyright (c) 2019 james@firefly-iii.org | 
					
						
							| 
									
										
										
										
											2018-02-16 16:43:25 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-10-02 06:37:26 +02:00
										 |  |  |  * This file is part of Firefly III (https://github.com/firefly-iii). | 
					
						
							| 
									
										
										
										
											2018-02-16 16:43:25 +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-16 16:43:25 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-10-02 06:37:26 +02:00
										 |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2018-02-16 16:43:25 +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-16 16:43:25 +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-16 16:43:25 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-11 10:08:34 +02:00
										 |  |  | declare(strict_types=1); | 
					
						
							| 
									
										
										
										
											2018-02-16 16:43:25 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace FireflyIII\Factory; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-12 05:06:42 +01:00
										 |  |  | use FireflyIII\Exceptions\FireflyException; | 
					
						
							| 
									
										
										
										
											2019-03-08 05:47:51 +01:00
										 |  |  | use FireflyIII\Models\Account; | 
					
						
							| 
									
										
										
										
											2018-02-16 16:43:25 +01:00
										 |  |  | use FireflyIII\Models\Transaction; | 
					
						
							| 
									
										
										
										
											2019-03-08 05:47:51 +01:00
										 |  |  | use FireflyIII\Models\TransactionCurrency; | 
					
						
							| 
									
										
										
										
											2018-02-16 16:43:25 +01:00
										 |  |  | use FireflyIII\Models\TransactionJournal; | 
					
						
							| 
									
										
										
										
											2023-02-18 06:37:05 +01:00
										 |  |  | use FireflyIII\Rules\UniqueIban; | 
					
						
							|  |  |  | use FireflyIII\Services\Internal\Update\AccountUpdateService; | 
					
						
							| 
									
										
										
										
											2019-03-18 16:52:49 +01:00
										 |  |  | use Illuminate\Database\QueryException; | 
					
						
							| 
									
										
										
										
											2025-05-24 17:15:46 +02:00
										 |  |  | use Illuminate\Support\Facades\Validator; | 
					
						
							| 
									
										
										
										
											2018-02-16 16:43:25 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Class TransactionFactory | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | class TransactionFactory | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |     private Account              $account; | 
					
						
							| 
									
										
										
										
											2023-02-22 18:14:14 +01:00
										 |  |  |     private array                $accountInformation; | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |     private TransactionCurrency  $currency; | 
					
						
							| 
									
										
										
										
											2025-05-04 12:57:14 +02:00
										 |  |  |     private ?TransactionCurrency $foreignCurrency = null; | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |     private TransactionJournal   $journal; | 
					
						
							|  |  |  |     private bool                 $reconciled; | 
					
						
							| 
									
										
										
										
											2021-03-28 11:46:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-06 12:29:32 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Constructor. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function __construct() | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-02-18 06:37:05 +01:00
										 |  |  |         $this->reconciled         = false; | 
					
						
							|  |  |  |         $this->accountInformation = []; | 
					
						
							| 
									
										
										
										
											2019-06-04 20:42:11 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Create transaction with negative amount (for source accounts). | 
					
						
							| 
									
										
										
										
											2018-02-16 16:43:25 +01:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |      * @throws FireflyException | 
					
						
							| 
									
										
										
										
											2018-02-16 16:43:25 +01:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2020-03-12 05:06:42 +01:00
										 |  |  |     public function createNegative(string $amount, ?string $foreignAmount): Transaction | 
					
						
							| 
									
										
										
										
											2018-02-16 16:43:25 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-03-11 06:41:02 +01:00
										 |  |  |         if ('' === $foreignAmount) { | 
					
						
							|  |  |  |             $foreignAmount = null; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-06-04 20:42:11 +02:00
										 |  |  |         if (null !== $foreignAmount) { | 
					
						
							|  |  |  |             $foreignAmount = app('steam')->negative($foreignAmount); | 
					
						
							| 
									
										
										
										
											2019-03-08 05:47:51 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-04 20:42:11 +02:00
										 |  |  |         return $this->create(app('steam')->negative($amount), $foreignAmount); | 
					
						
							| 
									
										
										
										
											2018-02-16 16:43:25 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |      * @throws FireflyException | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     private function create(string $amount, ?string $foreignAmount): Transaction | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if ('' === $foreignAmount) { | 
					
						
							|  |  |  |             $foreignAmount = null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $data = [ | 
					
						
							|  |  |  |             'reconciled'              => $this->reconciled, | 
					
						
							|  |  |  |             'account_id'              => $this->account->id, | 
					
						
							|  |  |  |             'transaction_journal_id'  => $this->journal->id, | 
					
						
							|  |  |  |             'description'             => null, | 
					
						
							|  |  |  |             'transaction_currency_id' => $this->currency->id, | 
					
						
							|  |  |  |             'amount'                  => $amount, | 
					
						
							|  |  |  |             'foreign_amount'          => null, | 
					
						
							|  |  |  |             'foreign_currency_id'     => null, | 
					
						
							|  |  |  |             'identifier'              => 0, | 
					
						
							|  |  |  |         ]; | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |         try { | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  |             /** @var null|Transaction $result */ | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |             $result = Transaction::create($data); | 
					
						
							|  |  |  |         } catch (QueryException $e) { | 
					
						
							| 
									
										
										
										
											2023-10-29 06:32:00 +01:00
										 |  |  |             app('log')->error(sprintf('Could not create transaction: %s', $e->getMessage()), $data); | 
					
						
							|  |  |  |             app('log')->error($e->getMessage()); | 
					
						
							|  |  |  |             app('log')->error($e->getTraceAsString()); | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-30 06:40:12 +02:00
										 |  |  |             throw new FireflyException(sprintf('Query exception when creating transaction: %s', $e->getMessage()), 0, $e); | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |         if (null === $result) { | 
					
						
							|  |  |  |             throw new FireflyException('Transaction is NULL.'); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-04-07 07:28:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |         app('log')->debug( | 
					
						
							| 
									
										
										
										
											2023-01-03 06:48:53 +01:00
										 |  |  |             sprintf( | 
					
						
							|  |  |  |                 'Created transaction #%d (%s %s, account %s), part of journal #%d', | 
					
						
							|  |  |  |                 $result->id, | 
					
						
							|  |  |  |                 $this->currency->code, | 
					
						
							|  |  |  |                 $amount, | 
					
						
							|  |  |  |                 $this->account->name, | 
					
						
							|  |  |  |                 $this->journal->id | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // do foreign currency thing: add foreign currency info to $one and $two if necessary.
 | 
					
						
							| 
									
										
										
										
											2025-05-27 17:02:18 +02:00
										 |  |  |         if ($this->foreignCurrency instanceof TransactionCurrency | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  |             && null !== $foreignAmount | 
					
						
							|  |  |  |             && $this->foreignCurrency->id !== $this->currency->id) { | 
					
						
							| 
									
										
										
										
											2023-01-03 06:48:53 +01:00
										 |  |  |             $result->foreign_currency_id = $this->foreignCurrency->id; | 
					
						
							|  |  |  |             $result->foreign_amount      = $foreignAmount; | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-01-03 06:48:53 +01:00
										 |  |  |         $result->save(); | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-18 06:37:05 +01:00
										 |  |  |         // if present, update account with relevant account information from the array
 | 
					
						
							|  |  |  |         $this->updateAccountInformation(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |         return $result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-22 18:14:14 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * @throws FireflyException | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     private function updateAccountInformation(): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!array_key_exists('iban', $this->accountInformation)) { | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |             app('log')->debug('No IBAN information in array, will not update.'); | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-22 18:14:14 +01:00
										 |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-12-22 08:43:12 +01:00
										 |  |  |         if ('' !== (string) $this->account->iban) { | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |             app('log')->debug('Account already has IBAN information, will not update.'); | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-22 18:14:14 +01:00
										 |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if ($this->account->iban === $this->accountInformation['iban']) { | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |             app('log')->debug('Account already has this IBAN, will not update.'); | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-22 18:14:14 +01:00
										 |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // validate info:
 | 
					
						
							| 
									
										
										
										
											2025-05-24 17:15:46 +02:00
										 |  |  |         $validator = Validator::make(['iban' => $this->accountInformation['iban']], [ | 
					
						
							| 
									
										
										
										
											2023-02-22 18:14:14 +01:00
										 |  |  |             'iban' => ['required', new UniqueIban($this->account, $this->account->accountType->type)], | 
					
						
							|  |  |  |         ]); | 
					
						
							|  |  |  |         if ($validator->fails()) { | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |             app('log')->debug('Invalid or non-unique IBAN, will not update.'); | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-22 18:14:14 +01:00
										 |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-29 06:33:43 +01:00
										 |  |  |         app('log')->debug('Will update account with IBAN information.'); | 
					
						
							| 
									
										
										
										
											2025-02-10 04:10:23 +01:00
										 |  |  |         $service   = app(AccountUpdateService::class); | 
					
						
							| 
									
										
										
										
											2023-02-22 18:14:14 +01:00
										 |  |  |         $service->update($this->account, ['iban' => $this->accountInformation['iban']]); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-02-22 20:11:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Create transaction with positive amount (for destination accounts). | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @throws FireflyException | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function createPositive(string $amount, ?string $foreignAmount): Transaction | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if ('' === $foreignAmount) { | 
					
						
							|  |  |  |             $foreignAmount = null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (null !== $foreignAmount) { | 
					
						
							|  |  |  |             $foreignAmount = app('steam')->positive($foreignAmount); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $this->create(app('steam')->positive($amount), $foreignAmount); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function setAccount(Account $account): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->account = $account; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function setAccountInformation(array $accountInformation): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->accountInformation = $accountInformation; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function setCurrency(TransactionCurrency $currency): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->currency = $currency; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * @param null|TransactionCurrency $foreignCurrency |null | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function setForeignCurrency(?TransactionCurrency $foreignCurrency): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->foreignCurrency = $foreignCurrency; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function setJournal(TransactionJournal $journal): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->journal = $journal; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function setReconciled(bool $reconciled): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->reconciled = $reconciled; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-05 19:35:58 +01:00
										 |  |  | } |