| 
									
										
										
										
											2015-02-07 06:49:24 +01:00
										 |  |  | <?php | 
					
						
							| 
									
										
										
										
											2022-12-24 05:06:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-20 12:41:23 +02:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Amount.php | 
					
						
							| 
									
										
										
										
											2020-02-16 13:56:52 +01:00
										 |  |  |  * Copyright (c) 2019 james@firefly-iii.org | 
					
						
							| 
									
										
										
										
											2016-05-20 12:41:23 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-10-02 06:37:26 +02:00
										 |  |  |  * This file is part of Firefly III (https://github.com/firefly-iii). | 
					
						
							| 
									
										
										
										
											2016-10-05 06:52:15 +02: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. | 
					
						
							| 
									
										
										
										
											2017-10-21 08:40:00 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-10-02 06:37:26 +02:00
										 |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2017-10-21 08:40:00 +02: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. | 
					
						
							| 
									
										
										
										
											2017-10-21 08:40:00 +02: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/>. | 
					
						
							| 
									
										
										
										
											2016-05-20 12:41:23 +02:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2017-04-09 07:44:22 +02:00
										 |  |  | declare(strict_types=1); | 
					
						
							| 
									
										
										
										
											2015-02-07 06:49:24 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace FireflyIII\Support; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-18 10:26:12 +02:00
										 |  |  | use FireflyIII\Exceptions\FireflyException; | 
					
						
							| 
									
										
										
										
											2024-12-24 06:34:12 +01:00
										 |  |  | use FireflyIII\Models\Transaction; | 
					
						
							| 
									
										
										
										
											2015-02-07 08:23:44 +01:00
										 |  |  | use FireflyIII\Models\TransactionCurrency; | 
					
						
							| 
									
										
										
										
											2024-12-24 06:34:12 +01:00
										 |  |  | use FireflyIII\Models\TransactionJournal; | 
					
						
							| 
									
										
										
										
											2023-10-28 06:58:33 +02:00
										 |  |  | use FireflyIII\Models\UserGroup; | 
					
						
							| 
									
										
										
										
											2024-12-28 13:36:25 +01:00
										 |  |  | use FireflyIII\Support\Facades\Preferences; | 
					
						
							| 
									
										
										
										
											2025-09-07 14:49:49 +02:00
										 |  |  | use FireflyIII\Support\Facades\Steam; | 
					
						
							| 
									
										
										
										
											2025-08-08 15:44:15 +02:00
										 |  |  | use FireflyIII\Support\Singleton\PreferencesSingleton; | 
					
						
							| 
									
										
										
										
											2017-06-20 21:04:25 +02:00
										 |  |  | use FireflyIII\User; | 
					
						
							| 
									
										
										
										
											2015-04-03 07:33:18 +02:00
										 |  |  | use Illuminate\Support\Collection; | 
					
						
							| 
									
										
										
										
											2025-09-07 14:54:44 +02:00
										 |  |  | use Illuminate\Support\Facades\Log; | 
					
						
							| 
									
										
										
										
											2025-05-27 16:57:36 +02:00
										 |  |  | use NumberFormatter; | 
					
						
							| 
									
										
										
										
											2015-02-07 23:19:28 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-07 06:49:24 +01:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2017-11-15 12:25:49 +01:00
										 |  |  |  * Class Amount. | 
					
						
							| 
									
										
										
										
											2015-02-07 06:49:24 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | class Amount | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-02-07 23:19:28 +01:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2016-01-09 18:02:36 +01:00
										 |  |  |      * This method will properly format the given number, in color or "black and white", | 
					
						
							|  |  |  |      * as a currency, given two things: the currency required and the current locale. | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2023-02-22 18:03:31 +01:00
										 |  |  |      * @throws FireflyException | 
					
						
							| 
									
										
										
										
											2015-02-07 23:19:28 +01:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2024-03-18 20:25:30 +01:00
										 |  |  |     public function formatAnything(TransactionCurrency $format, string $amount, ?bool $coloured = null): string | 
					
						
							| 
									
										
										
										
											2015-02-07 23:19:28 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-11-26 12:24:37 +01:00
										 |  |  |         return $this->formatFlat($format->symbol, $format->decimal_places, $amount, $coloured); | 
					
						
							| 
									
										
										
										
											2016-01-09 18:02:36 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-24 09:23:36 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * This method will properly format the given number, in color or "black and white", | 
					
						
							|  |  |  |      * as a currency, given two things: the currency required and the current locale. | 
					
						
							| 
									
										
										
										
											2025-01-04 07:39:16 +01:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2022-03-29 15:10:05 +02:00
										 |  |  |      * @throws FireflyException | 
					
						
							| 
									
										
										
										
											2019-03-24 09:23:36 +01:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2024-03-18 20:25:30 +01:00
										 |  |  |     public function formatFlat(string $symbol, int $decimalPlaces, string $amount, ?bool $coloured = null): string | 
					
						
							| 
									
										
										
										
											2019-03-24 09:23:36 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2025-09-15 19:25:59 +02:00
										 |  |  |         $locale  = Steam::getLocale(); | 
					
						
							|  |  |  |         $rounded = Steam::bcround($amount, $decimalPlaces); | 
					
						
							| 
									
										
										
										
											2023-12-10 06:45:59 +01:00
										 |  |  |         $coloured ??= true; | 
					
						
							| 
									
										
										
										
											2020-07-19 00:00:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-15 19:25:59 +02:00
										 |  |  |         $fmt     = new NumberFormatter($locale, NumberFormatter::CURRENCY); | 
					
						
							| 
									
										
										
										
											2025-05-27 16:57:36 +02:00
										 |  |  |         $fmt->setSymbol(NumberFormatter::CURRENCY_SYMBOL, $symbol); | 
					
						
							|  |  |  |         $fmt->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, $decimalPlaces); | 
					
						
							|  |  |  |         $fmt->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, $decimalPlaces); | 
					
						
							| 
									
										
										
										
											2025-09-15 19:25:59 +02:00
										 |  |  |         $result  = (string)$fmt->format((float)$rounded); // intentional float
 | 
					
						
							| 
									
										
										
										
											2019-03-24 09:23:36 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (true === $coloured) { | 
					
						
							| 
									
										
										
										
											2025-09-07 07:31:00 +02:00
										 |  |  |             if (1 === bccomp($rounded, '0')) { | 
					
						
							| 
									
										
										
										
											2023-03-25 11:33:42 +01:00
										 |  |  |                 return sprintf('<span class="text-success money-positive">%s</span>', $result); | 
					
						
							| 
									
										
										
										
											2019-03-24 09:23:36 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2025-09-07 07:31:00 +02:00
										 |  |  |             if (-1 === bccomp($rounded, '0')) { | 
					
						
							| 
									
										
										
										
											2023-03-25 11:33:42 +01:00
										 |  |  |                 return sprintf('<span class="text-danger money-negative">%s</span>', $result); | 
					
						
							| 
									
										
										
										
											2019-03-24 09:23:36 +01:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-25 11:33:42 +01:00
										 |  |  |             return sprintf('<span class="money-neutral">%s</span>', $result); | 
					
						
							| 
									
										
										
										
											2019-03-24 09:23:36 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-22 08:43:12 +01:00
										 |  |  |     public function formatByCurrencyId(int $currencyId, string $amount, ?bool $coloured = null): string | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2025-09-07 14:49:49 +02:00
										 |  |  |         $format = $this->getTransactionCurrencyById($currencyId); | 
					
						
							| 
									
										
										
										
											2024-12-22 08:43:12 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return $this->formatFlat($format->symbol, $format->decimal_places, $amount, $coloured); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-05 22:00:03 +02:00
										 |  |  |     public function getAllCurrencies(): Collection | 
					
						
							| 
									
										
										
										
											2015-04-03 07:33:18 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         return TransactionCurrency::orderBy('code', 'ASC')->get(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-04 17:41:26 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Experimental function to see if we can quickly and quietly get the amount from a journal. | 
					
						
							|  |  |  |      * This depends on the user's default currency and the wish to have it converted. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function getAmountFromJournal(array $journal): string | 
					
						
							| 
									
										
										
										
											2018-11-10 10:04:46 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2025-07-31 20:24:19 +02:00
										 |  |  |         $convertToPrimary = $this->convertToPrimary(); | 
					
						
							| 
									
										
										
										
											2025-08-01 13:10:11 +02:00
										 |  |  |         $currency         = $this->getPrimaryCurrency(); | 
					
						
							|  |  |  |         $field            = $convertToPrimary && $currency->id !== $journal['currency_id'] ? 'pc_amount' : 'amount'; | 
					
						
							|  |  |  |         $amount           = $journal[$field] ?? '0'; | 
					
						
							| 
									
										
										
										
											2025-05-04 17:41:26 +02:00
										 |  |  |         // Log::debug(sprintf('Field is %s, amount is %s', $field, $amount));
 | 
					
						
							|  |  |  |         // fallback, the transaction has a foreign amount in $currency.
 | 
					
						
							| 
									
										
										
										
											2025-07-31 20:24:19 +02:00
										 |  |  |         if ($convertToPrimary && null !== $journal['foreign_amount'] && $currency->id === (int)$journal['foreign_currency_id']) { | 
					
						
							| 
									
										
										
										
											2025-05-04 17:41:26 +02:00
										 |  |  |             $amount = $journal['foreign_amount']; | 
					
						
							|  |  |  |             // Log::debug(sprintf('Overruled, amount is now %s', $amount));
 | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-26 19:17:26 +02:00
										 |  |  |         return (string)$amount; | 
					
						
							| 
									
										
										
										
											2018-11-10 10:04:46 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-07 14:49:49 +02:00
										 |  |  |     public function getTransactionCurrencyById(int $currencyId): TransactionCurrency | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $instance = PreferencesSingleton::getInstance(); | 
					
						
							|  |  |  |         $key      = sprintf('transaction_currency_%d', $currencyId); | 
					
						
							| 
									
										
										
										
											2025-09-07 14:58:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         /** @var null|TransactionCurrency $pref */ | 
					
						
							| 
									
										
										
										
											2025-09-15 19:25:59 +02:00
										 |  |  |         $pref     = $instance->getPreference($key); | 
					
						
							| 
									
										
										
										
											2025-09-07 14:49:49 +02:00
										 |  |  |         if (null !== $pref) { | 
					
						
							|  |  |  |             return $pref; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $currency = TransactionCurrency::find($currencyId); | 
					
						
							|  |  |  |         if (null === $currency) { | 
					
						
							| 
									
										
										
										
											2025-09-15 19:20:51 +02:00
										 |  |  |             $message = sprintf('Could not find a transaction currency with ID #%d in %s', $currencyId, __METHOD__); | 
					
						
							| 
									
										
										
										
											2025-09-07 14:54:44 +02:00
										 |  |  |             Log::error($message); | 
					
						
							| 
									
										
										
										
											2025-09-07 14:58:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-07 14:54:44 +02:00
										 |  |  |             throw new FireflyException($message); | 
					
						
							| 
									
										
										
										
											2025-09-07 14:49:49 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         $instance->setPreference($key, $currency); | 
					
						
							| 
									
										
										
										
											2025-09-07 14:58:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-07 14:49:49 +02:00
										 |  |  |         return $currency; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function getTransactionCurrencyByCode(string $code): TransactionCurrency | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $instance = PreferencesSingleton::getInstance(); | 
					
						
							|  |  |  |         $key      = sprintf('transaction_currency_%s', $code); | 
					
						
							| 
									
										
										
										
											2025-09-07 14:58:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         /** @var null|TransactionCurrency $pref */ | 
					
						
							| 
									
										
										
										
											2025-09-15 19:25:59 +02:00
										 |  |  |         $pref     = $instance->getPreference($key); | 
					
						
							| 
									
										
										
										
											2025-09-07 14:49:49 +02:00
										 |  |  |         if (null !== $pref) { | 
					
						
							|  |  |  |             return $pref; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $currency = TransactionCurrency::whereCode($code)->first(); | 
					
						
							|  |  |  |         if (null === $currency) { | 
					
						
							| 
									
										
										
										
											2025-09-15 19:20:51 +02:00
										 |  |  |             $message = sprintf('Could not find a transaction currency with code "%s" in %s', $code, __METHOD__); | 
					
						
							| 
									
										
										
										
											2025-09-07 14:54:44 +02:00
										 |  |  |             Log::error($message); | 
					
						
							| 
									
										
										
										
											2025-09-07 14:58:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-07 14:54:44 +02:00
										 |  |  |             throw new FireflyException($message); | 
					
						
							| 
									
										
										
										
											2025-09-07 14:49:49 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         $instance->setPreference($key, $currency); | 
					
						
							| 
									
										
										
										
											2025-09-07 14:58:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-07 14:49:49 +02:00
										 |  |  |         return $currency; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-31 20:24:19 +02:00
										 |  |  |     public function convertToPrimary(?User $user = null): bool | 
					
						
							| 
									
										
										
										
											2025-01-19 18:53:32 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2025-08-08 15:44:15 +02:00
										 |  |  |         $instance = PreferencesSingleton::getInstance(); | 
					
						
							| 
									
										
										
										
											2025-08-08 20:18:04 +02:00
										 |  |  |         if (!$user instanceof User) { | 
					
						
							|  |  |  |             $pref = $instance->getPreference('convert_to_primary_no_user'); | 
					
						
							|  |  |  |             if (null === $pref) { | 
					
						
							| 
									
										
										
										
											2025-08-08 15:44:15 +02:00
										 |  |  |                 $res = true === Preferences::get('convert_to_primary', false)->data && true === config('cer.enabled'); | 
					
						
							| 
									
										
										
										
											2025-08-08 20:18:04 +02:00
										 |  |  |                 $instance->setPreference('convert_to_primary_no_user', $res); | 
					
						
							| 
									
										
										
										
											2025-08-08 21:03:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-08 15:44:15 +02:00
										 |  |  |                 return $res; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2025-08-08 21:03:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-08 20:18:04 +02:00
										 |  |  |             return $pref; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2025-09-15 19:25:59 +02:00
										 |  |  |         $key      = sprintf('convert_to_primary_%d', $user->id); | 
					
						
							|  |  |  |         $pref     = $instance->getPreference($key); | 
					
						
							| 
									
										
										
										
											2025-08-08 21:03:45 +02:00
										 |  |  |         if (null === $pref) { | 
					
						
							| 
									
										
										
										
											2025-08-08 15:44:15 +02:00
										 |  |  |             $res = true === Preferences::getForUser($user, 'convert_to_primary', false)->data && true === config('cer.enabled'); | 
					
						
							| 
									
										
										
										
											2025-08-08 20:18:04 +02:00
										 |  |  |             $instance->setPreference($key, $res); | 
					
						
							| 
									
										
										
										
											2025-08-08 21:03:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-08 15:44:15 +02:00
										 |  |  |             return $res; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2025-08-08 20:18:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-08 15:44:15 +02:00
										 |  |  |         return $pref; | 
					
						
							| 
									
										
										
										
											2025-01-19 18:53:32 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-31 20:24:19 +02:00
										 |  |  |     public function getPrimaryCurrency(): TransactionCurrency | 
					
						
							| 
									
										
										
										
											2017-06-20 21:04:25 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-12-29 06:17:29 +01:00
										 |  |  |         if (auth()->check()) { | 
					
						
							| 
									
										
										
										
											2024-12-29 06:08:35 +01:00
										 |  |  |             /** @var User $user */ | 
					
						
							|  |  |  |             $user = auth()->user(); | 
					
						
							| 
									
										
										
										
											2024-12-29 06:17:29 +01:00
										 |  |  |             if (null !== $user->userGroup) { | 
					
						
							| 
									
										
										
										
											2025-07-31 20:24:19 +02:00
										 |  |  |                 return $this->getPrimaryCurrencyByUserGroup($user->userGroup); | 
					
						
							| 
									
										
										
										
											2024-12-29 06:17:29 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2024-12-29 06:08:35 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-12-30 04:12:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-29 06:08:35 +01:00
										 |  |  |         return $this->getSystemCurrency(); | 
					
						
							| 
									
										
										
										
											2017-06-20 21:04:25 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-31 20:17:46 +02:00
										 |  |  |     public function getPrimaryCurrencyByUserGroup(UserGroup $userGroup): TransactionCurrency | 
					
						
							| 
									
										
										
										
											2023-10-28 06:58:33 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2025-09-15 19:25:59 +02:00
										 |  |  |         $cache   = new CacheProperties(); | 
					
						
							| 
									
										
										
										
											2025-07-31 20:17:46 +02:00
										 |  |  |         $cache->addProperty('getPrimaryCurrencyByGroup'); | 
					
						
							| 
									
										
										
										
											2023-10-28 06:58:33 +02:00
										 |  |  |         $cache->addProperty($userGroup->id); | 
					
						
							|  |  |  |         if ($cache->has()) { | 
					
						
							| 
									
										
										
										
											2025-08-03 16:45:49 +02:00
										 |  |  |             return $cache->get(); | 
					
						
							| 
									
										
										
										
											2023-10-28 06:58:33 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2025-01-04 07:39:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-31 20:17:46 +02:00
										 |  |  |         /** @var null|TransactionCurrency $primary */ | 
					
						
							|  |  |  |         $primary = $userGroup->currencies()->where('group_default', true)->first(); | 
					
						
							|  |  |  |         if (null === $primary) { | 
					
						
							|  |  |  |             $primary = $this->getSystemCurrency(); | 
					
						
							| 
									
										
										
										
											2023-11-19 02:15:04 +01:00
										 |  |  |             // could be the user group has no default right now.
 | 
					
						
							| 
									
										
										
										
											2025-07-31 20:17:46 +02:00
										 |  |  |             $userGroup->currencies()->sync([$primary->id => ['group_default' => true]]); | 
					
						
							| 
									
										
										
										
											2023-10-28 06:58:33 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2025-07-31 20:17:46 +02:00
										 |  |  |         $cache->store($primary); | 
					
						
							| 
									
										
										
										
											2023-10-28 06:58:33 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-31 20:17:46 +02:00
										 |  |  |         return $primary; | 
					
						
							| 
									
										
										
										
											2023-10-28 06:58:33 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-01-08 17:54:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-29 06:36:37 +01:00
										 |  |  |     public function getSystemCurrency(): TransactionCurrency | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2025-09-04 06:22:04 +02:00
										 |  |  |         return TransactionCurrency::whereNull('deleted_at')->where('code', 'EUR')->first(); | 
					
						
							| 
									
										
										
										
											2023-10-29 06:36:37 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-04 17:41:26 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Experimental function to see if we can quickly and quietly get the amount from a journal. | 
					
						
							|  |  |  |      * This depends on the user's default currency and the wish to have it converted. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function getAmountFromJournalObject(TransactionJournal $journal): string | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2025-09-15 19:25:59 +02:00
										 |  |  |         $convertToPrimary  = $this->convertToPrimary(); | 
					
						
							|  |  |  |         $currency          = $this->getPrimaryCurrency(); | 
					
						
							|  |  |  |         $field             = $convertToPrimary && $currency->id !== $journal->transaction_currency_id ? 'pc_amount' : 'amount'; | 
					
						
							| 
									
										
										
										
											2025-05-04 17:41:26 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         /** @var null|Transaction $sourceTransaction */ | 
					
						
							|  |  |  |         $sourceTransaction = $journal->transactions()->where('amount', '<', 0)->first(); | 
					
						
							|  |  |  |         if (null === $sourceTransaction) { | 
					
						
							|  |  |  |             return '0'; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2025-09-15 19:25:59 +02:00
										 |  |  |         $amount            = $sourceTransaction->{$field} ?? '0'; | 
					
						
							| 
									
										
										
										
											2025-07-26 19:17:26 +02:00
										 |  |  |         if ((int)$sourceTransaction->foreign_currency_id === $currency->id) { | 
					
						
							| 
									
										
										
										
											2025-05-04 17:41:26 +02:00
										 |  |  |             // use foreign amount instead!
 | 
					
						
							| 
									
										
										
										
											2025-07-26 19:17:26 +02:00
										 |  |  |             $amount = (string)$sourceTransaction->foreign_amount; // hard coded to be foreign amount.
 | 
					
						
							| 
									
										
										
										
											2025-05-04 17:41:26 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $amount; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function getCurrencies(): Collection | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         /** @var User $user */ | 
					
						
							|  |  |  |         $user = auth()->user(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $user->currencies()->orderBy('code', 'ASC')->get(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * This method returns the correct format rules required by accounting.js, | 
					
						
							|  |  |  |      * the library used to format amounts in charts. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Used only in one place. | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2023-02-22 18:03:31 +01:00
										 |  |  |      * @throws FireflyException | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |      */ | 
					
						
							|  |  |  |     public function getJsConfig(): array | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $config   = $this->getLocaleInfo(); | 
					
						
							|  |  |  |         $negative = self::getAmountJsConfig($config['n_sep_by_space'], $config['n_sign_posn'], $config['negative_sign'], $config['n_cs_precedes']); | 
					
						
							|  |  |  |         $positive = self::getAmountJsConfig($config['p_sep_by_space'], $config['p_sign_posn'], $config['positive_sign'], $config['p_cs_precedes']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return [ | 
					
						
							|  |  |  |             'mon_decimal_point' => $config['mon_decimal_point'], | 
					
						
							|  |  |  |             'mon_thousands_sep' => $config['mon_thousands_sep'], | 
					
						
							|  |  |  |             'format'            => [ | 
					
						
							|  |  |  |                 'pos'  => $positive, | 
					
						
							|  |  |  |                 'neg'  => $negative, | 
					
						
							|  |  |  |                 'zero' => $positive, | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |         ]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-22 20:11:09 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * @throws FireflyException | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     private function getLocaleInfo(): array | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // get config from preference, not from translation:
 | 
					
						
							| 
									
										
										
										
											2025-09-15 19:25:59 +02:00
										 |  |  |         $locale                    = Steam::getLocale(); | 
					
						
							|  |  |  |         $array                     = Steam::getLocaleArray($locale); | 
					
						
							| 
									
										
										
										
											2024-02-22 20:11:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         setlocale(LC_MONETARY, $array); | 
					
						
							| 
									
										
										
										
											2025-09-15 19:25:59 +02:00
										 |  |  |         $info                      = localeconv(); | 
					
						
							| 
									
										
										
										
											2024-02-22 20:11:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // correct variables
 | 
					
						
							| 
									
										
										
										
											2025-09-15 19:25:59 +02:00
										 |  |  |         $info['n_cs_precedes']     = $this->getLocaleField($info, 'n_cs_precedes'); | 
					
						
							|  |  |  |         $info['p_cs_precedes']     = $this->getLocaleField($info, 'p_cs_precedes'); | 
					
						
							| 
									
										
										
										
											2024-02-22 20:11:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-15 19:25:59 +02:00
										 |  |  |         $info['n_sep_by_space']    = $this->getLocaleField($info, 'n_sep_by_space'); | 
					
						
							|  |  |  |         $info['p_sep_by_space']    = $this->getLocaleField($info, 'p_sep_by_space'); | 
					
						
							| 
									
										
										
										
											2024-02-22 20:11:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-15 19:25:59 +02:00
										 |  |  |         $fmt                       = new NumberFormatter($locale, NumberFormatter::CURRENCY); | 
					
						
							| 
									
										
										
										
											2024-02-22 20:11:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-27 16:57:36 +02:00
										 |  |  |         $info['mon_decimal_point'] = $fmt->getSymbol(NumberFormatter::MONETARY_SEPARATOR_SYMBOL); | 
					
						
							|  |  |  |         $info['mon_thousands_sep'] = $fmt->getSymbol(NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL); | 
					
						
							| 
									
										
										
										
											2024-02-22 20:11:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return $info; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private function getLocaleField(array $info, string $field): bool | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return (is_bool($info[$field]) && true === $info[$field]) | 
					
						
							|  |  |  |                || (is_int($info[$field]) && 1 === $info[$field]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * bool $sepBySpace is $localeconv['n_sep_by_space'] | 
					
						
							|  |  |  |      * int $signPosn = $localeconv['n_sign_posn'] | 
					
						
							|  |  |  |      * string $sign = $localeconv['negative_sign'] | 
					
						
							|  |  |  |      * bool $csPrecedes = $localeconv['n_cs_precedes']. | 
					
						
							| 
									
										
										
										
											2019-02-28 19:56:41 +01:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |     public static function getAmountJsConfig(bool $sepBySpace, int $signPosn, string $sign, bool $csPrecedes): string | 
					
						
							| 
									
										
										
										
											2019-02-28 19:56:41 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |         // negative first:
 | 
					
						
							| 
									
										
										
										
											2025-05-27 17:06:15 +02:00
										 |  |  |         $space = ' '; | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // require space between symbol and amount?
 | 
					
						
							|  |  |  |         if (false === $sepBySpace) { | 
					
						
							|  |  |  |             $space = ''; // no
 | 
					
						
							| 
									
										
										
										
											2021-03-21 09:15:40 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |         // there are five possible positions for the "+" or "-" sign (if it is even used)
 | 
					
						
							|  |  |  |         // pos_a and pos_e could be the ( and ) symbol.
 | 
					
						
							| 
									
										
										
										
											2025-09-15 19:25:59 +02:00
										 |  |  |         $posA  = ''; // before everything
 | 
					
						
							|  |  |  |         $posB  = ''; // before currency symbol
 | 
					
						
							|  |  |  |         $posC  = ''; // after currency symbol
 | 
					
						
							|  |  |  |         $posD  = ''; // before amount
 | 
					
						
							|  |  |  |         $posE  = ''; // after everything
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // format would be (currency before amount)
 | 
					
						
							|  |  |  |         // AB%sC_D%vE
 | 
					
						
							|  |  |  |         // or:
 | 
					
						
							|  |  |  |         // AD%v_B%sCE (amount before currency)
 | 
					
						
							|  |  |  |         // the _ is the optional space
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // switch on how to display amount:
 | 
					
						
							|  |  |  |         switch ($signPosn) { | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |             case 0: | 
					
						
							|  |  |  |                 // ( and ) around the whole thing
 | 
					
						
							|  |  |  |                 $posA = '('; | 
					
						
							|  |  |  |                 $posE = ')'; | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |             case 1: | 
					
						
							|  |  |  |                 // The sign string precedes the quantity and currency_symbol
 | 
					
						
							|  |  |  |                 $posA = $sign; | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |             case 2: | 
					
						
							|  |  |  |                 // The sign string succeeds the quantity and currency_symbol
 | 
					
						
							|  |  |  |                 $posE = $sign; | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |             case 3: | 
					
						
							|  |  |  |                 // The sign string immediately precedes the currency_symbol
 | 
					
						
							|  |  |  |                 $posB = $sign; | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |             case 4: | 
					
						
							|  |  |  |                 // The sign string immediately succeeds the currency_symbol
 | 
					
						
							|  |  |  |                 $posC = $sign; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($csPrecedes) { | 
					
						
							| 
									
										
										
										
											2025-09-15 19:25:59 +02:00
										 |  |  |             return $posA.$posB.'%s'.$posC.$space.$posD.'%v'.$posE; | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-15 19:25:59 +02:00
										 |  |  |         return $posA.$posD.'%v'.$space.$posB.'%s'.$posC.$posE; | 
					
						
							| 
									
										
										
										
											2023-06-21 12:34:58 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-03-29 08:14:32 +02:00
										 |  |  | } |