| 
									
										
										
										
											2018-02-21 20:34:24 +01:00
										 |  |  | <?php | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * AccountServiceTrait.php | 
					
						
							| 
									
										
										
										
											2020-02-16 13:56:35 +01:00
										 |  |  |  * Copyright (c) 2019 james@firefly-iii.org | 
					
						
							| 
									
										
										
										
											2018-02-21 20:34:24 +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 20:34:24 +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 20:34:24 +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 20:34:24 +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 20:34:24 +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 20:34:24 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | declare(strict_types=1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace FireflyIII\Services\Internal\Support; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  | use Carbon\Carbon; | 
					
						
							|  |  |  | use FireflyIII\Exceptions\DuplicateTransactionException; | 
					
						
							| 
									
										
										
										
											2019-06-16 13:16:04 +02:00
										 |  |  | use FireflyIII\Exceptions\FireflyException; | 
					
						
							| 
									
										
										
										
											2018-02-21 21:06:59 +01:00
										 |  |  | use FireflyIII\Factory\AccountMetaFactory; | 
					
						
							| 
									
										
										
										
											2019-06-22 10:25:34 +02:00
										 |  |  | use FireflyIII\Factory\TransactionCurrencyFactory; | 
					
						
							| 
									
										
										
										
											2019-06-16 13:16:04 +02:00
										 |  |  | use FireflyIII\Factory\TransactionGroupFactory; | 
					
						
							| 
									
										
										
										
											2018-02-21 20:34:24 +01:00
										 |  |  | use FireflyIII\Models\Account; | 
					
						
							|  |  |  | use FireflyIII\Models\AccountType; | 
					
						
							|  |  |  | use FireflyIII\Models\Note; | 
					
						
							| 
									
										
										
										
											2019-06-22 10:25:34 +02:00
										 |  |  | use FireflyIII\Models\Transaction; | 
					
						
							|  |  |  | use FireflyIII\Models\TransactionCurrency; | 
					
						
							| 
									
										
										
										
											2019-06-16 13:16:04 +02:00
										 |  |  | use FireflyIII\Models\TransactionGroup; | 
					
						
							| 
									
										
										
										
											2019-06-22 10:25:34 +02:00
										 |  |  | use FireflyIII\Models\TransactionJournal; | 
					
						
							| 
									
										
										
										
											2021-03-08 17:56:21 +01:00
										 |  |  | use FireflyIII\Repositories\Account\AccountRepositoryInterface; | 
					
						
							| 
									
										
										
										
											2019-06-16 13:16:04 +02:00
										 |  |  | use FireflyIII\Services\Internal\Destroy\TransactionGroupDestroyService; | 
					
						
							| 
									
										
										
										
											2023-04-01 07:04:42 +02:00
										 |  |  | use Illuminate\Support\Facades\Log; | 
					
						
							| 
									
										
										
										
											2023-05-29 13:56:55 +02:00
										 |  |  | use JsonException; | 
					
						
							| 
									
										
										
										
											2018-02-21 20:34:24 +01:00
										 |  |  | use Validator; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Trait AccountServiceTrait | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | trait AccountServiceTrait | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-03-08 17:56:21 +01:00
										 |  |  |     protected AccountRepositoryInterface $accountRepository; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 20:34:24 +01:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |      * @param null|string $iban | 
					
						
							| 
									
										
										
										
											2018-02-21 20:34:24 +01:00
										 |  |  |      * | 
					
						
							|  |  |  |      * @return null|string | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2018-07-26 06:27:52 +02:00
										 |  |  |     public function filterIban(?string $iban): ?string | 
					
						
							| 
									
										
										
										
											2018-02-21 20:34:24 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         if (null === $iban) { | 
					
						
							|  |  |  |             return null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $data      = ['iban' => $iban]; | 
					
						
							|  |  |  |         $rules     = ['iban' => 'required|iban']; | 
					
						
							|  |  |  |         $validator = Validator::make($data, $rules); | 
					
						
							|  |  |  |         if ($validator->fails()) { | 
					
						
							| 
									
										
										
										
											2018-04-24 19:26:31 +02:00
										 |  |  |             Log::info(sprintf('Detected invalid IBAN ("%s"). Return NULL instead.', $iban)); | 
					
						
							| 
									
										
										
										
											2018-02-21 20:34:24 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             return null; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-04-06 18:36:37 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 06:34:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return app('steam')->filterSpaces($iban); | 
					
						
							| 
									
										
										
										
											2018-02-21 20:34:24 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-15 10:31:11 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Returns true if the data in the array is submitted but empty. | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |      * @param array $data | 
					
						
							| 
									
										
										
										
											2021-03-15 10:31:11 +01:00
										 |  |  |      * | 
					
						
							|  |  |  |      * @return bool | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function isEmptyOBData(array $data): bool | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!array_key_exists('opening_balance', $data) | 
					
						
							|  |  |  |             && !array_key_exists('opening_balance_date', $data) | 
					
						
							|  |  |  |         ) { | 
					
						
							|  |  |  |             // not set, so false.
 | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-04-07 07:28:43 +02:00
										 |  |  |         // if is set, but is empty:
 | 
					
						
							| 
									
										
										
										
											2021-03-15 10:31:11 +01:00
										 |  |  |         if ( | 
					
						
							|  |  |  |             (array_key_exists('opening_balance', $data) && '' === $data['opening_balance']) | 
					
						
							|  |  |  |             || (array_key_exists('opening_balance_date', $data) && '' === $data['opening_balance_date']) | 
					
						
							|  |  |  |         ) { | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-22 10:25:34 +02:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2022-10-30 11:43:17 +01:00
										 |  |  |      * Update metadata for account. Depends on type which fields are valid. | 
					
						
							| 
									
										
										
										
											2019-06-22 10:25:34 +02:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2022-10-30 11:43:17 +01:00
										 |  |  |      * TODO this method treats expense accounts and liabilities the same way (tries to save interest) | 
					
						
							| 
									
										
										
										
											2019-06-22 10:25:34 +02:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |      * @param Account $account | 
					
						
							|  |  |  |      * @param array   $data | 
					
						
							| 
									
										
										
										
											2019-08-17 10:47:29 +02:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2019-06-22 10:25:34 +02:00
										 |  |  |      */ | 
					
						
							|  |  |  |     public function updateMetaData(Account $account, array $data): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $fields = $this->validFields; | 
					
						
							|  |  |  |         if ($account->accountType->type === AccountType::ASSET) { | 
					
						
							|  |  |  |             $fields = $this->validAssetFields; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-03-08 17:56:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-23 14:46:26 +02:00
										 |  |  |         // remove currency_id if necessary.
 | 
					
						
							|  |  |  |         $type = $account->accountType->type; | 
					
						
							|  |  |  |         $list = config('firefly.valid_currency_account_types'); | 
					
						
							| 
									
										
										
										
											2022-10-30 14:24:37 +01:00
										 |  |  |         if (!in_array($type, $list, true)) { | 
					
						
							|  |  |  |             $pos = array_search('currency_id', $fields, true); | 
					
						
							| 
									
										
										
										
											2022-10-23 14:46:26 +02:00
										 |  |  |             if ($pos !== false) { | 
					
						
							|  |  |  |                 unset($fields[$pos]); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-18 06:37:05 +01:00
										 |  |  |         // the account role may not be set in the data, but we may have it already:
 | 
					
						
							| 
									
										
										
										
											2021-03-08 17:56:21 +01:00
										 |  |  |         if (!array_key_exists('account_role', $data)) { | 
					
						
							|  |  |  |             $data['account_role'] = null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (null === $data['account_role']) { | 
					
						
							|  |  |  |             $data['account_role'] = $this->accountRepository->getMetaValue($account, 'account_role'); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-03-20 07:02:06 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // only asset account may have a role:
 | 
					
						
							|  |  |  |         if ($account->accountType->type !== AccountType::ASSET) { | 
					
						
							|  |  |  |             $data['account_role'] = ''; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($account->accountType->type === AccountType::ASSET && array_key_exists('account_role', $data) && 'ccAsset' === $data['account_role']) { | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |             $fields = $this->validCCFields; | 
					
						
							| 
									
										
										
										
											2019-06-22 10:25:34 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         /** @var AccountMetaFactory $factory */ | 
					
						
							|  |  |  |         $factory = app(AccountMetaFactory::class); | 
					
						
							|  |  |  |         foreach ($fields as $field) { | 
					
						
							| 
									
										
										
										
											2019-08-24 08:22:46 +02:00
										 |  |  |             // if the field is set but NULL, skip it.
 | 
					
						
							|  |  |  |             // if the field is set but "", update it.
 | 
					
						
							| 
									
										
										
										
											2021-04-06 18:36:37 +02:00
										 |  |  |             if (array_key_exists($field, $data) && null !== $data[$field]) { | 
					
						
							| 
									
										
										
										
											2019-10-06 07:03:34 +02:00
										 |  |  |                 // convert boolean value:
 | 
					
						
							|  |  |  |                 if (is_bool($data[$field]) && false === $data[$field]) { | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |                     $data[$field] = 0; | 
					
						
							| 
									
										
										
										
											2019-10-06 07:03:34 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2023-06-04 06:30:22 +02:00
										 |  |  |                 if (true === $data[$field]) { | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |                     $data[$field] = 1; | 
					
						
							| 
									
										
										
										
											2019-10-06 07:03:34 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2023-05-29 13:56:55 +02:00
										 |  |  |                 if ($data[$field] instanceof Carbon) { | 
					
						
							| 
									
										
										
										
											2023-05-17 07:02:08 +02:00
										 |  |  |                     $data[$field] = $data[$field]->toAtomString(); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2019-10-06 07:03:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-27 07:01:13 +01:00
										 |  |  |                 $factory->crud($account, $field, (string)$data[$field]); | 
					
						
							| 
									
										
										
										
											2019-08-24 08:22:46 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-06-22 10:25:34 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-21 21:06:59 +01:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |      * @param Account $account | 
					
						
							|  |  |  |      * @param string  $note | 
					
						
							| 
									
										
										
										
											2019-06-22 10:25:34 +02:00
										 |  |  |      * | 
					
						
							|  |  |  |      * @return bool | 
					
						
							| 
									
										
										
										
											2018-02-21 21:06:59 +01:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2019-06-22 10:25:34 +02:00
										 |  |  |     public function updateNote(Account $account, string $note): bool | 
					
						
							| 
									
										
										
										
											2018-02-21 21:06:59 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-06-04 06:30:22 +02:00
										 |  |  |         $dbNote = $account->notes()->first(); | 
					
						
							| 
									
										
										
										
											2019-06-22 10:25:34 +02:00
										 |  |  |         if ('' === $note) { | 
					
						
							|  |  |  |             if (null !== $dbNote) { | 
					
						
							| 
									
										
										
										
											2022-12-30 20:25:04 +01:00
										 |  |  |                 $dbNote->delete(); | 
					
						
							| 
									
										
										
										
											2019-06-22 10:25:34 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-02-21 21:06:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-22 10:25:34 +02:00
										 |  |  |             return true; | 
					
						
							| 
									
										
										
										
											2018-02-21 21:06:59 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-06-22 10:25:34 +02:00
										 |  |  |         if (null === $dbNote) { | 
					
						
							| 
									
										
										
										
											2022-10-30 14:24:37 +01:00
										 |  |  |             $dbNote = new Note(); | 
					
						
							| 
									
										
										
										
											2019-06-22 10:25:34 +02:00
										 |  |  |             $dbNote->noteable()->associate($account); | 
					
						
							| 
									
										
										
										
											2018-02-21 21:06:59 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-06-22 10:25:34 +02:00
										 |  |  |         $dbNote->text = trim($note); | 
					
						
							|  |  |  |         $dbNote->save(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2018-02-21 21:06:59 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Verify if array contains valid data to possibly store or update the opening balance. | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |      * @param array $data | 
					
						
							| 
									
										
										
										
											2018-02-21 21:06:59 +01:00
										 |  |  |      * | 
					
						
							|  |  |  |      * @return bool | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2019-06-16 13:16:04 +02:00
										 |  |  |     public function validOBData(array $data): bool | 
					
						
							| 
									
										
										
										
											2018-02-21 21:06:59 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-12-27 07:01:13 +01:00
										 |  |  |         $data['opening_balance'] = (string)($data['opening_balance'] ?? ''); | 
					
						
							| 
									
										
										
										
											2019-09-06 15:55:17 +02:00
										 |  |  |         if ('' !== $data['opening_balance'] && 0 === bccomp($data['opening_balance'], '0')) { | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |             $data['opening_balance'] = ''; | 
					
						
							| 
									
										
										
										
											2019-09-06 15:55:17 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |         if ('' !== $data['opening_balance'] && array_key_exists('opening_balance_date', $data) && '' !== $data['opening_balance_date'] | 
					
						
							|  |  |  |             && $data['opening_balance_date'] instanceof Carbon) { | 
					
						
							| 
									
										
										
										
											2018-02-21 21:06:59 +01:00
										 |  |  |             Log::debug('Array has valid opening balance data.'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Log::debug('Array does not have valid opening balance data.'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-06-16 13:16:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-29 13:56:55 +02:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |      * @param Account $account | 
					
						
							|  |  |  |      * @param array   $data | 
					
						
							| 
									
										
										
										
											2021-09-18 10:26:12 +02:00
										 |  |  |      * | 
					
						
							|  |  |  |      * @return TransactionGroup | 
					
						
							|  |  |  |      * @throws FireflyException | 
					
						
							| 
									
										
										
										
											2023-02-22 18:03:31 +01:00
										 |  |  |      * @throws JsonException | 
					
						
							| 
									
										
										
										
											2021-09-18 10:26:12 +02:00
										 |  |  |      * @deprecated | 
					
						
							| 
									
										
										
										
											2019-08-24 08:22:46 +02:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-09-18 10:26:12 +02:00
										 |  |  |     protected function createOBGroup(Account $account, array $data): TransactionGroup | 
					
						
							| 
									
										
										
										
											2019-08-24 08:22:46 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-09-18 10:26:12 +02:00
										 |  |  |         Log::debug('Now going to create an OB group.'); | 
					
						
							|  |  |  |         $language   = app('preferences')->getForUser($account->user, 'language', 'en_US')->data; | 
					
						
							|  |  |  |         $sourceId   = null; | 
					
						
							|  |  |  |         $sourceName = null; | 
					
						
							|  |  |  |         $destId     = null; | 
					
						
							|  |  |  |         $destName   = null; | 
					
						
							|  |  |  |         $amount     = array_key_exists('opening_balance', $data) ? $data['opening_balance'] : '0'; | 
					
						
							| 
									
										
										
										
											2019-08-24 08:22:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-18 10:26:12 +02:00
										 |  |  |         // amount is positive.
 | 
					
						
							|  |  |  |         if (1 === bccomp($amount, '0')) { | 
					
						
							|  |  |  |             Log::debug(sprintf('Amount is %s, which is positive. Source is a new IB account, destination is #%d', $amount, $account->id)); | 
					
						
							|  |  |  |             $sourceName = trans('firefly.initial_balance_description', ['account' => $account->name], $language); | 
					
						
							|  |  |  |             $destId     = $account->id; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // amount is not positive
 | 
					
						
							|  |  |  |         if (-1 === bccomp($amount, '0')) { | 
					
						
							|  |  |  |             Log::debug(sprintf('Amount is %s, which is negative. Destination is a new IB account, source is #%d', $amount, $account->id)); | 
					
						
							|  |  |  |             $destName = trans('firefly.initial_balance_account', ['account' => $account->name], $language); | 
					
						
							|  |  |  |             $sourceId = $account->id; | 
					
						
							| 
									
										
										
										
											2019-08-24 08:22:46 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-09-18 10:26:12 +02:00
										 |  |  |         // amount is 0
 | 
					
						
							|  |  |  |         if (0 === bccomp($amount, '0')) { | 
					
						
							|  |  |  |             Log::debug('Amount is zero, so will not make an OB group.'); | 
					
						
							|  |  |  |             throw new FireflyException('Amount for new opening balance was unexpectedly 0.'); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // make amount positive, regardless:
 | 
					
						
							|  |  |  |         $amount = app('steam')->positive($amount); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // get or grab currency:
 | 
					
						
							|  |  |  |         $currency = $this->accountRepository->getAccountCurrency($account); | 
					
						
							|  |  |  |         if (null === $currency) { | 
					
						
							|  |  |  |             $currency = app('default')->getDefaultCurrencyByUser($account->user); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // submit to factory:
 | 
					
						
							|  |  |  |         $submission = [ | 
					
						
							|  |  |  |             'group_title'  => null, | 
					
						
							|  |  |  |             'user'         => $account->user_id, | 
					
						
							|  |  |  |             'transactions' => [ | 
					
						
							|  |  |  |                 [ | 
					
						
							|  |  |  |                     'type'             => 'Opening balance', | 
					
						
							|  |  |  |                     'date'             => $data['opening_balance_date'], | 
					
						
							|  |  |  |                     'source_id'        => $sourceId, | 
					
						
							|  |  |  |                     'source_name'      => $sourceName, | 
					
						
							|  |  |  |                     'destination_id'   => $destId, | 
					
						
							|  |  |  |                     'destination_name' => $destName, | 
					
						
							|  |  |  |                     'user'             => $account->user_id, | 
					
						
							|  |  |  |                     'currency_id'      => $currency->id, | 
					
						
							|  |  |  |                     'order'            => 0, | 
					
						
							|  |  |  |                     'amount'           => $amount, | 
					
						
							|  |  |  |                     'foreign_amount'   => null, | 
					
						
							|  |  |  |                     'description'      => trans('firefly.initial_balance_description', ['account' => $account->name]), | 
					
						
							|  |  |  |                     'budget_id'        => null, | 
					
						
							|  |  |  |                     'budget_name'      => null, | 
					
						
							|  |  |  |                     'category_id'      => null, | 
					
						
							|  |  |  |                     'category_name'    => null, | 
					
						
							|  |  |  |                     'piggy_bank_id'    => null, | 
					
						
							|  |  |  |                     'piggy_bank_name'  => null, | 
					
						
							|  |  |  |                     'reconciled'       => false, | 
					
						
							|  |  |  |                     'notes'            => null, | 
					
						
							|  |  |  |                     'tags'             => [], | 
					
						
							|  |  |  |                 ], | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |         ]; | 
					
						
							|  |  |  |         Log::debug('Going for submission in createOBGroup', $submission); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /** @var TransactionGroupFactory $factory */ | 
					
						
							|  |  |  |         $factory = app(TransactionGroupFactory::class); | 
					
						
							|  |  |  |         $factory->setUser($account->user); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         try { | 
					
						
							|  |  |  |             $group = $factory->create($submission); | 
					
						
							|  |  |  |         } catch (DuplicateTransactionException $e) { | 
					
						
							|  |  |  |             Log::error($e->getMessage()); | 
					
						
							|  |  |  |             Log::error($e->getTraceAsString()); | 
					
						
							|  |  |  |             throw new FireflyException($e->getMessage(), 0, $e); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $group; | 
					
						
							| 
									
										
										
										
											2019-08-24 08:22:46 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-10 17:56:09 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Delete TransactionGroup with liability credit in it. | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |      * @param Account $account | 
					
						
							| 
									
										
										
										
											2021-04-10 17:56:09 +02:00
										 |  |  |      */ | 
					
						
							|  |  |  |     protected function deleteCreditTransaction(Account $account): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Log::debug(sprintf('deleteCreditTransaction() for account #%d', $account->id)); | 
					
						
							|  |  |  |         $creditGroup = $this->getCreditTransaction($account); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (null !== $creditGroup) { | 
					
						
							|  |  |  |             Log::debug('Credit journal found, delete journal.'); | 
					
						
							|  |  |  |             /** @var TransactionGroupDestroyService $service */ | 
					
						
							|  |  |  |             $service = app(TransactionGroupDestroyService::class); | 
					
						
							|  |  |  |             $service->destroy($creditGroup); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Returns the credit transaction group, or NULL if it does not exist. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Account $account | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return TransactionGroup|null | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function getCreditTransaction(Account $account): ?TransactionGroup | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Log::debug(sprintf('Now at %s', __METHOD__)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $this->accountRepository->getCreditTransactionGroup($account); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2021-09-18 10:26:12 +02:00
										 |  |  |      * Delete TransactionGroup with opening balance in it. | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |      * @param Account $account | 
					
						
							| 
									
										
										
										
											2021-09-18 10:26:12 +02:00
										 |  |  |      */ | 
					
						
							|  |  |  |     protected function deleteOBGroup(Account $account): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Log::debug(sprintf('deleteOB() for account #%d', $account->id)); | 
					
						
							|  |  |  |         $openingBalanceGroup = $this->getOBGroup($account); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // opening balance data? update it!
 | 
					
						
							|  |  |  |         if (null !== $openingBalanceGroup) { | 
					
						
							|  |  |  |             Log::debug('Opening balance journal found, delete journal.'); | 
					
						
							|  |  |  |             /** @var TransactionGroupDestroyService $service */ | 
					
						
							|  |  |  |             $service = app(TransactionGroupDestroyService::class); | 
					
						
							|  |  |  |             $service->destroy($openingBalanceGroup); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |      * Returns the opening balance group, or NULL if it does not exist. | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |      * @param Account $account | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |      * | 
					
						
							|  |  |  |      * @return TransactionGroup|null | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |     protected function getOBGroup(Account $account): ?TransactionGroup | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |         return $this->accountRepository->getOpeningBalanceGroup($account); | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-24 08:22:46 +02:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |      * @param int    $currencyId | 
					
						
							|  |  |  |      * @param string $currencyCode | 
					
						
							| 
									
										
										
										
											2019-08-24 08:22:46 +02:00
										 |  |  |      * | 
					
						
							|  |  |  |      * @return TransactionCurrency | 
					
						
							| 
									
										
										
										
											2022-03-29 15:10:05 +02:00
										 |  |  |      * @throws FireflyException | 
					
						
							| 
									
										
										
										
											2022-12-29 19:42:26 +01:00
										 |  |  |      * @throws JsonException | 
					
						
							| 
									
										
										
										
											2019-08-24 08:22:46 +02:00
										 |  |  |      */ | 
					
						
							|  |  |  |     protected function getCurrency(int $currencyId, string $currencyCode): TransactionCurrency | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // find currency, or use default currency instead.
 | 
					
						
							|  |  |  |         /** @var TransactionCurrencyFactory $factory */ | 
					
						
							|  |  |  |         $factory = app(TransactionCurrencyFactory::class); | 
					
						
							| 
									
										
										
										
											2021-04-06 18:36:37 +02:00
										 |  |  |         /** @var TransactionCurrency|null $currency */ | 
					
						
							| 
									
										
										
										
											2019-08-24 08:22:46 +02:00
										 |  |  |         $currency = $factory->find($currencyId, $currencyCode); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (null === $currency) { | 
					
						
							|  |  |  |             // use default currency:
 | 
					
						
							|  |  |  |             $currency = app('amount')->getDefaultCurrencyByUser($this->user); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $currency->enabled = true; | 
					
						
							|  |  |  |         $currency->save(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $currency; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Create the opposing "credit liability" transaction for credit liabilities. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2023-07-04 13:29:19 +02:00
										 |  |  |      * @param Account $account | 
					
						
							| 
									
										
										
										
											2023-07-15 16:02:42 +02:00
										 |  |  |      * @param string  $direction | 
					
						
							|  |  |  |      * @param string  $openingBalance | 
					
						
							|  |  |  |      * @param Carbon  $openingBalanceDate | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2023-07-04 13:29:19 +02:00
										 |  |  |      * @return TransactionGroup | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |      * @throws FireflyException | 
					
						
							| 
									
										
										
										
											2023-07-04 13:29:19 +02:00
										 |  |  |      * @throws JsonException | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-12-27 07:01:13 +01:00
										 |  |  |     protected function updateCreditTransaction(Account $account, string $direction, string $openingBalance, Carbon $openingBalanceDate): TransactionGroup | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         Log::debug(sprintf('Now in %s', __METHOD__)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (0 === bccomp($openingBalance, '0')) { | 
					
						
							| 
									
										
										
										
											2022-12-27 07:01:13 +01:00
										 |  |  |             Log::debug('Amount is zero, so will not update liability credit/debit group.'); | 
					
						
							|  |  |  |             throw new FireflyException('Amount for update liability credit/debit was unexpectedly 0.'); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // if direction is "debit" (i owe this debt), amount is negative.
 | 
					
						
							|  |  |  |         // which means the liability will have a negative balance which the user must fill.
 | 
					
						
							|  |  |  |         $openingBalance = app('steam')->negative($openingBalance); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // if direction is "credit" (I am owed this debt), amount is positive.
 | 
					
						
							|  |  |  |         // which means the liability will have a positive balance which is drained when its paid back into any asset.
 | 
					
						
							|  |  |  |         if ('credit' === $direction) { | 
					
						
							|  |  |  |             $openingBalance = app('steam')->positive($openingBalance); | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // create if not exists:
 | 
					
						
							|  |  |  |         $clGroup = $this->getCreditTransaction($account); | 
					
						
							|  |  |  |         if (null === $clGroup) { | 
					
						
							|  |  |  |             return $this->createCreditTransaction($account, $openingBalance, $openingBalanceDate); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // if exists, update:
 | 
					
						
							|  |  |  |         $currency = $this->accountRepository->getAccountCurrency($account); | 
					
						
							|  |  |  |         if (null === $currency) { | 
					
						
							|  |  |  |             $currency = app('default')->getDefaultCurrencyByUser($account->user); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // simply grab the first journal and change it:
 | 
					
						
							|  |  |  |         $journal            = $this->getObJournal($clGroup); | 
					
						
							|  |  |  |         $clTransaction      = $this->getOBTransaction($journal, $account); | 
					
						
							|  |  |  |         $accountTransaction = $this->getNotOBTransaction($journal, $account); | 
					
						
							|  |  |  |         $journal->date      = $openingBalanceDate; | 
					
						
							|  |  |  |         $journal->transactionCurrency()->associate($currency); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // account always gains money:
 | 
					
						
							|  |  |  |         $accountTransaction->amount                  = app('steam')->positive($openingBalance); | 
					
						
							|  |  |  |         $accountTransaction->transaction_currency_id = $currency->id; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // CL account always loses money:
 | 
					
						
							|  |  |  |         $clTransaction->amount                  = app('steam')->negative($openingBalance); | 
					
						
							|  |  |  |         $clTransaction->transaction_currency_id = $currency->id; | 
					
						
							|  |  |  |         // save both
 | 
					
						
							|  |  |  |         $accountTransaction->save(); | 
					
						
							|  |  |  |         $clTransaction->save(); | 
					
						
							|  |  |  |         $journal->save(); | 
					
						
							|  |  |  |         $clGroup->refresh(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $clGroup; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * @param Account $account | 
					
						
							|  |  |  |      * @param string  $openingBalance | 
					
						
							|  |  |  |      * @param Carbon  $openingBalanceDate | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return TransactionGroup | 
					
						
							|  |  |  |      * @throws FireflyException | 
					
						
							|  |  |  |      * @throws JsonException | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     protected function createCreditTransaction(Account $account, string $openingBalance, Carbon $openingBalanceDate): TransactionGroup | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Log::debug('Now going to create an createCreditTransaction.'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (0 === bccomp($openingBalance, '0')) { | 
					
						
							|  |  |  |             Log::debug('Amount is zero, so will not make an liability credit group.'); | 
					
						
							|  |  |  |             throw new FireflyException('Amount for new liability credit was unexpectedly 0.'); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $language = app('preferences')->getForUser($account->user, 'language', 'en_US')->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // set source and/or destination based on whether the amount is positive or negative.
 | 
					
						
							|  |  |  |         // first, assume the amount is positive and go from there:
 | 
					
						
							|  |  |  |         // if amount is positive ("I am owed this debt"), source is special account, destination is the liability.
 | 
					
						
							|  |  |  |         $sourceId   = null; | 
					
						
							|  |  |  |         $sourceName = trans('firefly.liability_credit_description', ['account' => $account->name], $language); | 
					
						
							|  |  |  |         $destId     = $account->id; | 
					
						
							|  |  |  |         $destName   = null; | 
					
						
							|  |  |  |         if (-1 === bccomp($openingBalance, '0')) { | 
					
						
							|  |  |  |             // amount is negative, reverse it
 | 
					
						
							|  |  |  |             $sourceId   = $account->id; | 
					
						
							|  |  |  |             $sourceName = null; | 
					
						
							|  |  |  |             $destId     = null; | 
					
						
							|  |  |  |             $destName   = trans('firefly.liability_credit_description', ['account' => $account->name], $language); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // amount must be positive for the transaction to work.
 | 
					
						
							|  |  |  |         $amount = app('steam')->positive($openingBalance); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // get or grab currency:
 | 
					
						
							|  |  |  |         $currency = $this->accountRepository->getAccountCurrency($account); | 
					
						
							|  |  |  |         if (null === $currency) { | 
					
						
							|  |  |  |             $currency = app('default')->getDefaultCurrencyByUser($account->user); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // submit to factory:
 | 
					
						
							|  |  |  |         $submission = [ | 
					
						
							|  |  |  |             'group_title'  => null, | 
					
						
							|  |  |  |             'user'         => $account->user_id, | 
					
						
							|  |  |  |             'transactions' => [ | 
					
						
							|  |  |  |                 [ | 
					
						
							|  |  |  |                     'type'             => 'Liability credit', | 
					
						
							|  |  |  |                     'date'             => $openingBalanceDate, | 
					
						
							|  |  |  |                     'source_id'        => $sourceId, | 
					
						
							|  |  |  |                     'source_name'      => $sourceName, | 
					
						
							|  |  |  |                     'destination_id'   => $destId, | 
					
						
							|  |  |  |                     'destination_name' => $destName, | 
					
						
							|  |  |  |                     'user'             => $account->user_id, | 
					
						
							|  |  |  |                     'currency_id'      => $currency->id, | 
					
						
							|  |  |  |                     'order'            => 0, | 
					
						
							|  |  |  |                     'amount'           => $amount, | 
					
						
							|  |  |  |                     'foreign_amount'   => null, | 
					
						
							|  |  |  |                     'description'      => trans('firefly.liability_credit_description', ['account' => $account->name]), | 
					
						
							|  |  |  |                     'budget_id'        => null, | 
					
						
							|  |  |  |                     'budget_name'      => null, | 
					
						
							|  |  |  |                     'category_id'      => null, | 
					
						
							|  |  |  |                     'category_name'    => null, | 
					
						
							|  |  |  |                     'piggy_bank_id'    => null, | 
					
						
							|  |  |  |                     'piggy_bank_name'  => null, | 
					
						
							|  |  |  |                     'reconciled'       => false, | 
					
						
							|  |  |  |                     'notes'            => null, | 
					
						
							|  |  |  |                     'tags'             => [], | 
					
						
							|  |  |  |                 ], | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |         ]; | 
					
						
							|  |  |  |         Log::debug('Going for submission in createCreditTransaction', $submission); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /** @var TransactionGroupFactory $factory */ | 
					
						
							|  |  |  |         $factory = app(TransactionGroupFactory::class); | 
					
						
							|  |  |  |         $factory->setUser($account->user); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         try { | 
					
						
							|  |  |  |             $group = $factory->create($submission); | 
					
						
							|  |  |  |         } catch (DuplicateTransactionException $e) { | 
					
						
							|  |  |  |             Log::error($e->getMessage()); | 
					
						
							|  |  |  |             Log::error($e->getTraceAsString()); | 
					
						
							|  |  |  |             throw new FireflyException($e->getMessage(), 0, $e); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $group; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * TODO refactor to "getfirstjournal" | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param TransactionGroup $group | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return TransactionJournal | 
					
						
							|  |  |  |      * @throws FireflyException | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     private function getObJournal(TransactionGroup $group): TransactionJournal | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         /** @var TransactionJournal $journal */ | 
					
						
							|  |  |  |         $journal = $group->transactionJournals()->first(); | 
					
						
							|  |  |  |         if (null === $journal) { | 
					
						
							|  |  |  |             throw new FireflyException(sprintf('Group #%d has no OB journal', $group->id)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $journal; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * TODO Rename to getOpposingTransaction | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param TransactionJournal $journal | 
					
						
							|  |  |  |      * @param Account            $account | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return Transaction | 
					
						
							|  |  |  |      * @throws FireflyException | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     private function getOBTransaction(TransactionJournal $journal, Account $account): Transaction | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         /** @var Transaction $transaction */ | 
					
						
							|  |  |  |         $transaction = $journal->transactions()->where('account_id', '!=', $account->id)->first(); | 
					
						
							|  |  |  |         if (null === $transaction) { | 
					
						
							|  |  |  |             throw new FireflyException(sprintf('Could not get OB transaction for journal #%d', $journal->id)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $transaction; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * @param TransactionJournal $journal | 
					
						
							|  |  |  |      * @param Account            $account | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return Transaction | 
					
						
							|  |  |  |      * @throws FireflyException | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     private function getNotOBTransaction(TransactionJournal $journal, Account $account): Transaction | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         /** @var Transaction $transaction */ | 
					
						
							|  |  |  |         $transaction = $journal->transactions()->where('account_id', $account->id)->first(); | 
					
						
							|  |  |  |         if (null === $transaction) { | 
					
						
							|  |  |  |             throw new FireflyException(sprintf('Could not get non-OB transaction for journal #%d', $journal->id)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $transaction; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2021-09-18 10:26:12 +02:00
										 |  |  |      * Update or create the opening balance group. | 
					
						
							|  |  |  |      * Since opening balance and date can still be empty strings, it may fail. | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |      * @param Account $account | 
					
						
							| 
									
										
										
										
											2023-07-15 16:02:42 +02:00
										 |  |  |      * @param string  $openingBalance | 
					
						
							|  |  |  |      * @param Carbon  $openingBalanceDate | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |      * | 
					
						
							|  |  |  |      * @return TransactionGroup | 
					
						
							|  |  |  |      * @throws FireflyException | 
					
						
							| 
									
										
										
										
											2023-07-04 13:29:19 +02:00
										 |  |  |      * @throws JsonException | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-09-18 10:26:12 +02:00
										 |  |  |     protected function updateOBGroupV2(Account $account, string $openingBalance, Carbon $openingBalanceDate): TransactionGroup | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-09-18 10:26:12 +02:00
										 |  |  |         Log::debug(sprintf('Now in %s', __METHOD__)); | 
					
						
							|  |  |  |         // create if not exists:
 | 
					
						
							|  |  |  |         $obGroup = $this->getOBGroup($account); | 
					
						
							|  |  |  |         if (null === $obGroup) { | 
					
						
							|  |  |  |             return $this->createOBGroupV2($account, $openingBalance, $openingBalanceDate); | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-11-26 06:16:21 +01:00
										 |  |  |         Log::debug('Update OB group'); | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-18 10:26:12 +02:00
										 |  |  |         // if exists, update:
 | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |         $currency = $this->accountRepository->getAccountCurrency($account); | 
					
						
							|  |  |  |         if (null === $currency) { | 
					
						
							|  |  |  |             $currency = app('default')->getDefaultCurrencyByUser($account->user); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-18 10:26:12 +02:00
										 |  |  |         // simply grab the first journal and change it:
 | 
					
						
							|  |  |  |         $journal            = $this->getObJournal($obGroup); | 
					
						
							|  |  |  |         $obTransaction      = $this->getOBTransaction($journal, $account); | 
					
						
							|  |  |  |         $accountTransaction = $this->getNotOBTransaction($journal, $account); | 
					
						
							|  |  |  |         $journal->date      = $openingBalanceDate; | 
					
						
							|  |  |  |         $journal->transactionCurrency()->associate($currency); | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-18 10:26:12 +02:00
										 |  |  |         // if amount is negative:
 | 
					
						
							|  |  |  |         if (1 === bccomp('0', $openingBalance)) { | 
					
						
							| 
									
										
										
										
											2021-11-26 06:16:21 +01:00
										 |  |  |             Log::debug('Amount is negative.'); | 
					
						
							| 
									
										
										
										
											2021-09-18 10:26:12 +02:00
										 |  |  |             // account transaction loses money:
 | 
					
						
							|  |  |  |             $accountTransaction->amount                  = app('steam')->negative($openingBalance); | 
					
						
							|  |  |  |             $accountTransaction->transaction_currency_id = $currency->id; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // OB account transaction gains money
 | 
					
						
							|  |  |  |             $obTransaction->amount                  = app('steam')->positive($openingBalance); | 
					
						
							|  |  |  |             $obTransaction->transaction_currency_id = $currency->id; | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-09-18 10:26:12 +02:00
										 |  |  |         if (-1 === bccomp('0', $openingBalance)) { | 
					
						
							| 
									
										
										
										
											2021-11-26 06:16:21 +01:00
										 |  |  |             Log::debug('Amount is positive.'); | 
					
						
							| 
									
										
										
										
											2021-09-18 10:26:12 +02:00
										 |  |  |             // account gains money:
 | 
					
						
							|  |  |  |             $accountTransaction->amount                  = app('steam')->positive($openingBalance); | 
					
						
							|  |  |  |             $accountTransaction->transaction_currency_id = $currency->id; | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-18 10:26:12 +02:00
										 |  |  |             // OB account loses money:
 | 
					
						
							|  |  |  |             $obTransaction->amount                  = app('steam')->negative($openingBalance); | 
					
						
							|  |  |  |             $obTransaction->transaction_currency_id = $currency->id; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // save both
 | 
					
						
							|  |  |  |         $accountTransaction->save(); | 
					
						
							|  |  |  |         $obTransaction->save(); | 
					
						
							|  |  |  |         $journal->save(); | 
					
						
							|  |  |  |         $obGroup->refresh(); | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-18 10:26:12 +02:00
										 |  |  |         return $obGroup; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-15 10:31:11 +01:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |      * @param Account $account | 
					
						
							|  |  |  |      * @param string  $openingBalance | 
					
						
							|  |  |  |      * @param Carbon  $openingBalanceDate | 
					
						
							| 
									
										
										
										
											2021-03-15 10:31:11 +01:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |      * @return TransactionGroup | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  |      * @throws FireflyException | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |      * @throws JsonException | 
					
						
							| 
									
										
										
										
											2021-03-15 10:31:11 +01:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |     protected function createOBGroupV2(Account $account, string $openingBalance, Carbon $openingBalanceDate): TransactionGroup | 
					
						
							| 
									
										
										
										
											2021-03-15 10:31:11 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |         Log::debug('Now going to create an OB group.'); | 
					
						
							|  |  |  |         $language   = app('preferences')->getForUser($account->user, 'language', 'en_US')->data; | 
					
						
							|  |  |  |         $sourceId   = null; | 
					
						
							|  |  |  |         $sourceName = null; | 
					
						
							|  |  |  |         $destId     = null; | 
					
						
							|  |  |  |         $destName   = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // amount is positive.
 | 
					
						
							|  |  |  |         if (1 === bccomp($openingBalance, '0')) { | 
					
						
							|  |  |  |             Log::debug(sprintf('Amount is %s, which is positive. Source is a new IB account, destination is #%d', $openingBalance, $account->id)); | 
					
						
							|  |  |  |             $sourceName = trans('firefly.initial_balance_description', ['account' => $account->name], $language); | 
					
						
							|  |  |  |             $destId     = $account->id; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // amount is not positive
 | 
					
						
							|  |  |  |         if (-1 === bccomp($openingBalance, '0')) { | 
					
						
							|  |  |  |             Log::debug(sprintf('Amount is %s, which is negative. Destination is a new IB account, source is #%d', $openingBalance, $account->id)); | 
					
						
							|  |  |  |             $destName = trans('firefly.initial_balance_account', ['account' => $account->name], $language); | 
					
						
							|  |  |  |             $sourceId = $account->id; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // amount is 0
 | 
					
						
							|  |  |  |         if (0 === bccomp($openingBalance, '0')) { | 
					
						
							|  |  |  |             Log::debug('Amount is zero, so will not make an OB group.'); | 
					
						
							|  |  |  |             throw new FireflyException('Amount for new opening balance was unexpectedly 0.'); | 
					
						
							| 
									
										
										
										
											2021-03-15 10:31:11 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |         // make amount positive, regardless:
 | 
					
						
							|  |  |  |         $amount = app('steam')->positive($openingBalance); | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |         // get or grab currency:
 | 
					
						
							|  |  |  |         $currency = $this->accountRepository->getAccountCurrency($account); | 
					
						
							|  |  |  |         if (null === $currency) { | 
					
						
							|  |  |  |             $currency = app('default')->getDefaultCurrencyByUser($account->user); | 
					
						
							| 
									
										
										
										
											2021-03-15 10:31:11 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |         // submit to factory:
 | 
					
						
							|  |  |  |         $submission = [ | 
					
						
							|  |  |  |             'group_title'  => null, | 
					
						
							|  |  |  |             'user'         => $account->user_id, | 
					
						
							|  |  |  |             'transactions' => [ | 
					
						
							|  |  |  |                 [ | 
					
						
							|  |  |  |                     'type'             => 'Opening balance', | 
					
						
							|  |  |  |                     'date'             => $openingBalanceDate, | 
					
						
							|  |  |  |                     'source_id'        => $sourceId, | 
					
						
							|  |  |  |                     'source_name'      => $sourceName, | 
					
						
							|  |  |  |                     'destination_id'   => $destId, | 
					
						
							|  |  |  |                     'destination_name' => $destName, | 
					
						
							|  |  |  |                     'user'             => $account->user_id, | 
					
						
							|  |  |  |                     'currency_id'      => $currency->id, | 
					
						
							|  |  |  |                     'order'            => 0, | 
					
						
							|  |  |  |                     'amount'           => $amount, | 
					
						
							|  |  |  |                     'foreign_amount'   => null, | 
					
						
							|  |  |  |                     'description'      => trans('firefly.initial_balance_description', ['account' => $account->name]), | 
					
						
							|  |  |  |                     'budget_id'        => null, | 
					
						
							|  |  |  |                     'budget_name'      => null, | 
					
						
							|  |  |  |                     'category_id'      => null, | 
					
						
							|  |  |  |                     'category_name'    => null, | 
					
						
							|  |  |  |                     'piggy_bank_id'    => null, | 
					
						
							|  |  |  |                     'piggy_bank_name'  => null, | 
					
						
							|  |  |  |                     'reconciled'       => false, | 
					
						
							|  |  |  |                     'notes'            => null, | 
					
						
							|  |  |  |                     'tags'             => [], | 
					
						
							|  |  |  |                 ], | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |         ]; | 
					
						
							|  |  |  |         Log::debug('Going for submission in createOBGroupV2', $submission); | 
					
						
							| 
									
										
										
										
											2021-03-15 10:31:11 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |         /** @var TransactionGroupFactory $factory */ | 
					
						
							|  |  |  |         $factory = app(TransactionGroupFactory::class); | 
					
						
							|  |  |  |         $factory->setUser($account->user); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         try { | 
					
						
							|  |  |  |             $group = $factory->create($submission); | 
					
						
							|  |  |  |         } catch (DuplicateTransactionException $e) { | 
					
						
							|  |  |  |             Log::error($e->getMessage()); | 
					
						
							|  |  |  |             Log::error($e->getTraceAsString()); | 
					
						
							|  |  |  |             throw new FireflyException($e->getMessage(), 0, $e); | 
					
						
							| 
									
										
										
										
											2021-03-15 10:31:11 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-04-10 17:26:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |         return $group; | 
					
						
							| 
									
										
										
										
											2021-03-15 10:31:11 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-05 19:35:58 +01:00
										 |  |  | } |