mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-31 10:47:00 +00:00 
			
		
		
		
	Compare commits
	
		
			47 Commits
		
	
	
		
			develop-20
			...
			develop-20
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | b58d809063 | ||
|  | 9e34314dbc | ||
|  | e4aa218b5f | ||
|  | 31722477d4 | ||
|  | ec82105433 | ||
|  | 146e164f04 | ||
|  | 7d37c93988 | ||
|  | 73dffacd9a | ||
|  | d37304fa68 | ||
|  | 62f4da6063 | ||
|  | 760da08ab7 | ||
|  | e68c4d4408 | ||
|  | 46a200aa1f | ||
|  | c422039335 | ||
|  | 0579c8565d | ||
|  | 9f25880a59 | ||
|  | 05f1819f7d | ||
|  | fa2149f957 | ||
|  | c21a79e029 | ||
|  | 03e31ebb5e | ||
|  | 3c20e5f3af | ||
|  | 9a9dd9e075 | ||
|  | 7189986c03 | ||
|  | b407d8d315 | ||
|  | 41fa2a6208 | ||
|  | fe00c4c373 | ||
|  | 7248a76c63 | ||
|  | ee3c618797 | ||
|  | a1241ebedb | ||
|  | af78d998db | ||
|  | d96c235ffe | ||
|  | 79ca1b5f4e | ||
|  | 0f68735e1c | ||
|  | 82abee37de | ||
|  | 507040f1fd | ||
|  | 42dc8486e9 | ||
|  | 6c655634bc | ||
|  | f2166b97b8 | ||
|  | da88e02be0 | ||
|  | 0d56b7d251 | ||
|  | 0a089efcac | ||
|  | 89ab360391 | ||
|  | 2bd97d9a99 | ||
|  | 103b9056e4 | ||
|  | 5971d155ef | ||
|  | 9e373a9b0d | ||
|  | 4fb61646b4 | 
| @@ -29,7 +29,7 @@ $paths = [ | ||||
|     $current . '/../../database', | ||||
|     $current . '/../../routes', | ||||
|     $current . '/../../tests', | ||||
|     $current . '/../../resources/lang', | ||||
|     $current . '/../../resources/lang/en_US', | ||||
| ]; | ||||
| 
 | ||||
| $finder = PhpCsFixer\Finder::create() | ||||
|   | ||||
							
								
								
									
										26
									
								
								.ci/php-cs-fixer/composer.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										26
									
								
								.ci/php-cs-fixer/composer.lock
									
									
									
										generated
									
									
									
								
							| @@ -406,16 +406,16 @@ | ||||
|         }, | ||||
|         { | ||||
|             "name": "friendsofphp/php-cs-fixer", | ||||
|             "version": "v3.65.0", | ||||
|             "version": "v3.66.0", | ||||
|             "source": { | ||||
|                 "type": "git", | ||||
|                 "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", | ||||
|                 "reference": "79d4f3e77b250a7d8043d76c6af8f0695e8a469f" | ||||
|                 "reference": "5f5f2a142ff36b93c41885bca29cc5f861c013e6" | ||||
|             }, | ||||
|             "dist": { | ||||
|                 "type": "zip", | ||||
|                 "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/79d4f3e77b250a7d8043d76c6af8f0695e8a469f", | ||||
|                 "reference": "79d4f3e77b250a7d8043d76c6af8f0695e8a469f", | ||||
|                 "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/5f5f2a142ff36b93c41885bca29cc5f861c013e6", | ||||
|                 "reference": "5f5f2a142ff36b93c41885bca29cc5f861c013e6", | ||||
|                 "shasum": "" | ||||
|             }, | ||||
|             "require": { | ||||
| @@ -441,7 +441,7 @@ | ||||
|                 "symfony/polyfill-mbstring": "^1.28", | ||||
|                 "symfony/polyfill-php80": "^1.28", | ||||
|                 "symfony/polyfill-php81": "^1.28", | ||||
|                 "symfony/process": "^5.4 || ^6.0 || ^7.0", | ||||
|                 "symfony/process": "^5.4 || ^6.0 || ^7.0 <7.2", | ||||
|                 "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0" | ||||
|             }, | ||||
|             "require-dev": { | ||||
| @@ -497,7 +497,7 @@ | ||||
|             ], | ||||
|             "support": { | ||||
|                 "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", | ||||
|                 "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.65.0" | ||||
|                 "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.66.0" | ||||
|             }, | ||||
|             "funding": [ | ||||
|                 { | ||||
| @@ -505,7 +505,7 @@ | ||||
|                     "type": "github" | ||||
|                 } | ||||
|             ], | ||||
|             "time": "2024-11-25T00:39:24+00:00" | ||||
|             "time": "2024-12-29T13:46:23+00:00" | ||||
|         }, | ||||
|         { | ||||
|             "name": "psr/container", | ||||
| @@ -2246,16 +2246,16 @@ | ||||
|         }, | ||||
|         { | ||||
|             "name": "symfony/process", | ||||
|             "version": "v7.2.0", | ||||
|             "version": "v7.1.8", | ||||
|             "source": { | ||||
|                 "type": "git", | ||||
|                 "url": "https://github.com/symfony/process.git", | ||||
|                 "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e" | ||||
|                 "reference": "42783370fda6e538771f7c7a36e9fa2ee3a84892" | ||||
|             }, | ||||
|             "dist": { | ||||
|                 "type": "zip", | ||||
|                 "url": "https://api.github.com/repos/symfony/process/zipball/d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", | ||||
|                 "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", | ||||
|                 "url": "https://api.github.com/repos/symfony/process/zipball/42783370fda6e538771f7c7a36e9fa2ee3a84892", | ||||
|                 "reference": "42783370fda6e538771f7c7a36e9fa2ee3a84892", | ||||
|                 "shasum": "" | ||||
|             }, | ||||
|             "require": { | ||||
| @@ -2287,7 +2287,7 @@ | ||||
|             "description": "Executes commands in sub-processes", | ||||
|             "homepage": "https://symfony.com", | ||||
|             "support": { | ||||
|                 "source": "https://github.com/symfony/process/tree/v7.2.0" | ||||
|                 "source": "https://github.com/symfony/process/tree/v7.1.8" | ||||
|             }, | ||||
|             "funding": [ | ||||
|                 { | ||||
| @@ -2303,7 +2303,7 @@ | ||||
|                     "type": "tidelift" | ||||
|                 } | ||||
|             ], | ||||
|             "time": "2024-11-06T14:24:19+00:00" | ||||
|             "time": "2024-11-06T14:23:19+00:00" | ||||
|         }, | ||||
|         { | ||||
|             "name": "symfony/service-contracts", | ||||
|   | ||||
							
								
								
									
										60
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										60
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							| @@ -168,7 +168,7 @@ jobs: | ||||
|  | ||||
|           # if this is a develop build, slightly different variable names. | ||||
|           if [[ "develop" == "$version" ]]; then | ||||
|             [[ -z $(git status --untracked-files=normal --porcelain) ]] && echo "this branch is clean, no need to push..." && exit 0; | ||||
|             #[[ -z $(git status --untracked-files=normal --porcelain) ]] && echo "this branch is clean, no need to push..." && exit 0; | ||||
|             releaseName=$version-$(date +'%Y%m%d') | ||||
|             originalName=$releaseName | ||||
|             zipName=FireflyIII-develop.zip | ||||
| @@ -177,7 +177,7 @@ jobs: | ||||
|  | ||||
|           # if this is a branch build, also slightly different variable names. | ||||
|           if [[ "$version" == branch* ]]; then | ||||
|             [[ -z $(git status --untracked-files=normal --porcelain) ]] && echo "this branch is clean, no need to push..." && exit 0; | ||||
|             #[[ -z $(git status --untracked-files=normal --porcelain) ]] && echo "this branch is clean, no need to push..." && exit 0; | ||||
|             # branch builds overrule develop | ||||
|             releaseName=$version-$(date +'%Y%m%d') | ||||
|             originalName=$releaseName | ||||
| @@ -229,7 +229,7 @@ jobs: | ||||
|           # describe the development release. | ||||
|           if [[ "develop" == "$version" ]]; then | ||||
|             echo 'Develop release.' | ||||
|             rm output.txt | ||||
|             rm -f output.txt | ||||
|             touch output.txt | ||||
|             sudo chown -R runner:docker output.txt | ||||
|             echo "Weekly development release of Firefly III with the latest fixes, translations and features. Docker users can find this release under the \`develop\` tag." >> output.txt | ||||
| @@ -244,7 +244,7 @@ jobs: | ||||
|           # describe a branch release | ||||
|           if [[ "$version" == branch* ]]; then | ||||
|             echo 'Branch release.' | ||||
|             rm output.txt | ||||
|             rm -f output.txt | ||||
|             touch output.txt | ||||
|             sudo chown -R runner:docker output.txt | ||||
|             echo "Irregular BRANCH release of Firefly III. This release contains specific features or changes. Docker users can find this release under the \`$version\` tag." >> output.txt | ||||
| @@ -257,9 +257,45 @@ jobs: | ||||
|             echo ":warning: Please be careful with this branch pre-release, as it may not work as expected." >> output.txt | ||||
|           fi | ||||
|           # describe the main release | ||||
|           if [[ "develop" != "$version" ]] && [[ "$version" != branch* ]]; then | ||||
|             sudo chown -R runner:docker output.txt | ||||
|           if [[ "develop" != "$version" ]] && [[ "$version" != branch* ]] && [[ "$version" != *alpha* ]] && [[ "$version" != *beta* ]]; then | ||||
|             echo 'Main release.' | ||||
|             sudo chown -R runner:docker output.txt | ||||
|             echo '' >> output.txt | ||||
|             echo '### Instructions' >> output.txt | ||||
|             echo '' >> output.txt | ||||
|             echo "* Installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt | ||||
|             echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt | ||||
|             echo "* The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt | ||||
|  | ||||
|           fi | ||||
|  | ||||
|           # describe alpha release | ||||
|           if [[ "$version" == *alpha* ]]; then | ||||
|             echo 'ALPHA release.' | ||||
|             rm -f output.txt | ||||
|             touch output.txt | ||||
|             sudo chown -R runner:docker output.txt | ||||
|             echo "Very early ALPHA release of Firefly III. This release contains specific features or changes. Docker users can find this release under the \`$version\` tag." >> output.txt | ||||
|             echo '' >> output.txt | ||||
|             echo "This release was created on **$(date +'%Y-%m-%d')** and may contain unexpected bugs. Data loss is rare but is not impossible. The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt | ||||
|             echo '' >> output.txt | ||||
|             echo '### Instructions' >> output.txt | ||||
|             echo '' >> output.txt | ||||
|             echo "* Installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt | ||||
|             echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt | ||||
|             echo "* The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt | ||||
|  | ||||
|           fi | ||||
|  | ||||
|           # describe beta release | ||||
|           if [[ "$version" == *beta* ]]; then | ||||
|             echo 'BETA release.' | ||||
|             rm -f output.txt | ||||
|             touch output.txt | ||||
|             sudo chown -R runner:docker output.txt | ||||
|             echo "Very early BETA release of Firefly III. This release contains specific features or changes. Docker users can find this release under the \`$version\` tag." >> output.txt | ||||
|             echo '' >> output.txt | ||||
|             echo "This release was created on **$(date +'%Y-%m-%d')** and may contain unexpected bugs. Data loss is rare but is not impossible. The releases are signed, and you can verify them using the [Firefly III releases PGP key](https://docs.firefly-iii.org/explanation/more-information/signatures/)." >> output.txt | ||||
|             echo '' >> output.txt | ||||
|             echo '### Instructions' >> output.txt | ||||
|             echo '' >> output.txt | ||||
| @@ -336,12 +372,12 @@ jobs: | ||||
|             gh release upload $releaseName HEAD.txt | ||||
|  | ||||
|             # remove all temporary files | ||||
|             rm output.txt | ||||
|             rm HEAD.txt | ||||
|             rm $zipName | ||||
|             rm $zipName.sha256 | ||||
|             rm $tarName | ||||
|             rm $tarName.sha256 | ||||
|             rm -f output.txt | ||||
|             rm -f HEAD.txt | ||||
|             rm -f $zipName | ||||
|             rm -f $zipName.sha256 | ||||
|             rm -f $tarName | ||||
|             rm -f $tarName.sha256 | ||||
|  | ||||
|             # merge main back into develop | ||||
|             git checkout develop | ||||
|   | ||||
| @@ -4,6 +4,7 @@ Over time, many people have contributed to Firefly III. Their efforts are not al | ||||
| Please find below all the people who contributed to the Firefly III code. Their names are mentioned in the year of their first contribution. | ||||
| 
 | ||||
| ## 2024 | ||||
| - TasneemTantawy | ||||
| - Antônio Franco | ||||
| - yparitcher | ||||
| - Jhon Pedroza | ||||
|   | ||||
| @@ -26,9 +26,9 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete; | ||||
| 
 | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; | ||||
| use FireflyIII\Enums\AccountTypeEnum; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Support\Facades\Steam; | ||||
| use FireflyIII\Support\Http\Api\AccountFilter; | ||||
| @@ -62,7 +62,7 @@ class AccountController extends Controller | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|         $this->balanceTypes = [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE]; | ||||
|         $this->balanceTypes = [AccountTypeEnum::ASSET->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @@ -74,27 +74,27 @@ class AccountController extends Controller | ||||
|      */ | ||||
|     public function accounts(AutocompleteRequest $request): JsonResponse | ||||
|     { | ||||
|         $data            = $request->getData(); | ||||
|         $types           = $data['types']; | ||||
|         $query           = $data['query']; | ||||
|         $date            = $data['date'] ?? today(config('app.timezone')); | ||||
|         $return          = []; | ||||
|         $result          = $this->repository->searchAccount((string) $query, $types, $this->parameters->get('limit')); | ||||
| 
 | ||||
|         // TODO this code is duplicated in the V2 Autocomplete controller, which means this code is due to be deprecated.
 | ||||
|         $defaultCurrency = app('amount')->getDefaultCurrency(); | ||||
|         $data   = $request->getData(); | ||||
|         $types  = $data['types']; | ||||
|         $query  = $data['query']; | ||||
|         $date   = $data['date'] ?? today(config('app.timezone')); | ||||
|         $return = []; | ||||
|         $result = $this->repository->searchAccount((string) $query, $types, $this->parameters->get('limit')); | ||||
| 
 | ||||
|         /** @var Account $account */ | ||||
|         foreach ($result as $account) { | ||||
|             $nameWithBalance = $account->name; | ||||
|             $currency        = $this->repository->getAccountCurrency($account) ?? $defaultCurrency; | ||||
| 
 | ||||
|             $currency        = $this->repository->getAccountCurrency($account) ?? $this->defaultCurrency; | ||||
|             $useCurrency     = $currency; | ||||
|             if (in_array($account->accountType->type, $this->balanceTypes, true)) { | ||||
|                 $balance         = Steam::finalAccountBalance($account, $date); | ||||
|                 $key             = $this->convertToNative && $currency->id !== $this->defaultCurrency->id ? 'native_balance' : 'balance'; | ||||
|                 $useCurrency     = $this->convertToNative && $currency->id !== $this->defaultCurrency->id ? $this->defaultCurrency : $currency; | ||||
|                 $amount          = $balance[$key] ?? '0'; | ||||
|                 $nameWithBalance = sprintf( | ||||
|                     '%s (%s)', | ||||
|                     $account->name, | ||||
|                     app('amount')->formatAnything($currency, $balance['balance'], false) | ||||
|                     app('amount')->formatAnything($useCurrency, $amount, false) | ||||
|                 ); | ||||
|             } | ||||
| 
 | ||||
| @@ -103,11 +103,11 @@ class AccountController extends Controller | ||||
|                 'name'                    => $account->name, | ||||
|                 'name_with_balance'       => $nameWithBalance, | ||||
|                 'type'                    => $account->accountType->type, | ||||
|                 'currency_id'             => (string) $currency->id, | ||||
|                 'currency_name'           => $currency->name, | ||||
|                 'currency_code'           => $currency->code, | ||||
|                 'currency_symbol'         => $currency->symbol, | ||||
|                 'currency_decimal_places' => $currency->decimal_places, | ||||
|                 'currency_id'             => (string) $useCurrency->id, | ||||
|                 'currency_name'           => $useCurrency->name, | ||||
|                 'currency_code'           => $useCurrency->code, | ||||
|                 'currency_symbol'         => $useCurrency->symbol, | ||||
|                 'currency_decimal_places' => $useCurrency->decimal_places, | ||||
|             ]; | ||||
|         } | ||||
| 
 | ||||
| @@ -115,7 +115,7 @@ class AccountController extends Controller | ||||
|         usort( | ||||
|             $return, | ||||
|             static function (array $left, array $right) { | ||||
|                 $order = [AccountType::ASSET, AccountType::REVENUE, AccountType::EXPENSE]; | ||||
|                 $order = [AccountTypeEnum::ASSET->value, AccountTypeEnum::REVENUE->value, AccountTypeEnum::EXPENSE->value]; | ||||
|                 $posA  = (int) array_search($left['type'], $order, true); | ||||
|                 $posB  = (int) array_search($right['type'], $order, true); | ||||
| 
 | ||||
|   | ||||
| @@ -27,9 +27,9 @@ namespace FireflyIII\Api\V1\Controllers\Chart; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Api\V1\Requests\Data\DateRequest; | ||||
| use FireflyIII\Enums\AccountTypeEnum; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Models\Preference; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\ApiSupport; | ||||
| @@ -81,11 +81,10 @@ class AccountController extends Controller | ||||
|         $end        = $dates['end']; | ||||
| 
 | ||||
|         // user's preferences
 | ||||
|         $defaultSet = $this->repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray(); | ||||
|         $defaultSet = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value])->pluck('id')->toArray(); | ||||
| 
 | ||||
|         /** @var Preference $frontpage */ | ||||
|         $frontpage  = app('preferences')->get('frontpageAccounts', $defaultSet); | ||||
|         $default    = app('amount')->getDefaultCurrency(); | ||||
| 
 | ||||
|         if (!(is_array($frontpage->data) && count($frontpage->data) > 0)) { | ||||
|             $frontpage->data = $defaultSet; | ||||
| @@ -98,10 +97,8 @@ class AccountController extends Controller | ||||
| 
 | ||||
|         /** @var Account $account */ | ||||
|         foreach ($accounts as $account) { | ||||
|             $currency     = $this->repository->getAccountCurrency($account); | ||||
|             if (null === $currency) { | ||||
|                 $currency = $default; | ||||
|             } | ||||
|             $currency     = $this->repository->getAccountCurrency($account) ?? $this->defaultCurrency; | ||||
|             $field        = $this->convertToNative && $currency->id !== $this->defaultCurrency->id ? 'native_balance' : 'balance'; | ||||
|             $currentSet   = [ | ||||
|                 'label'                   => $account->name, | ||||
|                 'currency_id'             => (string) $currency->id, | ||||
| @@ -117,12 +114,11 @@ class AccountController extends Controller | ||||
|             // TODO this code is also present in the V2 chart account controller so this method is due to be deprecated.
 | ||||
|             $currentStart = clone $start; | ||||
|             $range        = app('steam')->finalAccountBalanceInRange($account, $start, clone $end, $this->convertToNative); | ||||
|             // 2022-10-11 this method no longer converts to float.
 | ||||
|             $previous     = array_values($range)[0]; | ||||
|             $previous     = array_values($range)[0][$field]; | ||||
|             while ($currentStart <= $end) { | ||||
|                 $format                        = $currentStart->format('Y-m-d'); | ||||
|                 $label                         = $currentStart->toAtomString(); | ||||
|                 $balance                       = array_key_exists($format, $range) ? $range[$format]['balance'] : $previous; | ||||
|                 $balance                       = array_key_exists($format, $range) ? $range[$format][$field] : $previous; | ||||
|                 $previous                      = $balance; | ||||
|                 $currentStart->addDay(); | ||||
|                 $currentSet['entries'][$label] = $balance; | ||||
|   | ||||
| @@ -28,6 +28,9 @@ use Carbon\Carbon; | ||||
| use Carbon\Exceptions\InvalidDateException; | ||||
| use Carbon\Exceptions\InvalidFormatException; | ||||
| use FireflyIII\Models\Preference; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use FireflyIII\Support\Facades\Steam; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Foundation\Auth\Access\AuthorizesRequests; | ||||
| use Illuminate\Foundation\Bus\DispatchesJobs; | ||||
| @@ -56,6 +59,7 @@ abstract class Controller extends BaseController | ||||
|     protected array        $allowedSort; | ||||
|     protected ParameterBag $parameters; | ||||
|     protected bool        $convertToNative = false; | ||||
|     protected TransactionCurrency $defaultCurrency; | ||||
| 
 | ||||
|     /** | ||||
|      * Controller constructor. | ||||
| @@ -68,8 +72,9 @@ abstract class Controller extends BaseController | ||||
|             function ($request, $next) { | ||||
|                 $this->parameters = $this->getParameters(); | ||||
|                 if (auth()->check()) { | ||||
|                     $language              = app('steam')->getLanguage(); | ||||
|                     $this->convertToNative = app('preferences')->get('convert_to_native', false)->data; | ||||
|                     $language              = Steam::getLanguage(); | ||||
|                     $this->convertToNative = Amount::convertToNative(); | ||||
|                     $this->defaultCurrency = Amount::getDefaultCurrency(); | ||||
|                     app()->setLocale($language); | ||||
| 
 | ||||
|                 } | ||||
|   | ||||
| @@ -26,10 +26,10 @@ namespace FireflyIII\Api\V1\Controllers\Data; | ||||
| 
 | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Api\V1\Requests\Data\DestroyRequest; | ||||
| use FireflyIII\Enums\AccountTypeEnum; | ||||
| use FireflyIII\Enums\TransactionTypeEnum; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Bill\BillRepositoryInterface; | ||||
| @@ -66,9 +66,9 @@ class DestroyController extends Controller | ||||
|         $objects         = $request->getObjects(); | ||||
|         $this->unused    = $request->boolean('unused', false); | ||||
| 
 | ||||
|         $allExceptAssets = [AccountType::BENEFICIARY, AccountType::CASH, AccountType::CREDITCARD, AccountType::DEFAULT, AccountType::EXPENSE, AccountType::IMPORT, AccountType::INITIAL_BALANCE, AccountType::LIABILITY_CREDIT, AccountType::RECONCILIATION, AccountType::REVENUE]; | ||||
|         $all             = [AccountType::ASSET, AccountType::BENEFICIARY, AccountType::CASH, AccountType::CREDITCARD, AccountType::DEBT, AccountType::DEFAULT, AccountType::EXPENSE, AccountType::IMPORT, AccountType::INITIAL_BALANCE, AccountType::LIABILITY_CREDIT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::RECONCILIATION]; | ||||
|         $liabilities     = [AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD]; | ||||
|         $allExceptAssets = [AccountTypeEnum::BENEFICIARY->value, AccountTypeEnum::CASH->value, AccountTypeEnum::CREDITCARD->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::EXPENSE->value, AccountTypeEnum::IMPORT->value, AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::LIABILITY_CREDIT->value, AccountTypeEnum::RECONCILIATION->value, AccountTypeEnum::REVENUE->value]; | ||||
|         $all             = [AccountTypeEnum::ASSET->value, AccountTypeEnum::BENEFICIARY->value, AccountTypeEnum::CASH->value, AccountTypeEnum::CREDITCARD->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::EXPENSE->value, AccountTypeEnum::IMPORT->value, AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::LIABILITY_CREDIT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::RECONCILIATION->value]; | ||||
|         $liabilities     = [AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::CREDITCARD->value]; | ||||
|         $transactions    = [TransactionTypeEnum::WITHDRAWAL->value, TransactionTypeEnum::DEPOSIT->value, TransactionTypeEnum::TRANSFER->value, TransactionTypeEnum::RECONCILIATION->value]; | ||||
| 
 | ||||
|         match ($objects) { | ||||
| @@ -82,9 +82,9 @@ class DestroyController extends Controller | ||||
|             'object_groups'          => $this->destroyObjectGroups(), | ||||
|             'not_assets_liabilities' => $this->destroyAccounts($allExceptAssets), | ||||
|             'accounts'               => $this->destroyAccounts($all), | ||||
|             'asset_accounts'         => $this->destroyAccounts([AccountType::ASSET, AccountType::DEFAULT]), | ||||
|             'expense_accounts'       => $this->destroyAccounts([AccountType::BENEFICIARY, AccountType::EXPENSE]), | ||||
|             'revenue_accounts'       => $this->destroyAccounts([AccountType::REVENUE]), | ||||
|             'asset_accounts'         => $this->destroyAccounts([AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value]), | ||||
|             'expense_accounts'       => $this->destroyAccounts([AccountTypeEnum::BENEFICIARY->value, AccountTypeEnum::EXPENSE->value]), | ||||
|             'revenue_accounts'       => $this->destroyAccounts([AccountTypeEnum::REVENUE->value]), | ||||
|             'liabilities'            => $this->destroyAccounts($liabilities), | ||||
|             'transactions'           => $this->destroyTransactions($transactions), | ||||
|             'withdrawals'            => $this->destroyTransactions([TransactionTypeEnum::WITHDRAWAL->value]), | ||||
|   | ||||
| @@ -29,7 +29,9 @@ use FireflyIII\Api\V1\Requests\Insight\GenericRequest; | ||||
| use FireflyIII\Enums\TransactionTypeEnum; | ||||
| use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Repositories\Bill\BillRepositoryInterface; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| 
 | ||||
| /** | ||||
|  * Class BillController | ||||
| @@ -63,11 +65,13 @@ class BillController extends Controller | ||||
|      */ | ||||
|     public function bill(GenericRequest $request): JsonResponse | ||||
|     { | ||||
|         $accounts   = $request->getAssetAccounts(); | ||||
|         $bills      = $request->getBills(); | ||||
|         $start      = $request->getStart(); | ||||
|         $end        = $request->getEnd(); | ||||
|         $response   = []; | ||||
|         $accounts        = $request->getAssetAccounts(); | ||||
|         $bills           = $request->getBills(); | ||||
|         $start           = $request->getStart(); | ||||
|         $end             = $request->getEnd(); | ||||
|         $convertToNative = Amount::convertToNative(); | ||||
|         $default         = Amount::getDefaultCurrency(); | ||||
|         $response        = []; | ||||
| 
 | ||||
|         // get all bills:
 | ||||
|         if (0 === $bills->count()) { | ||||
| @@ -75,17 +79,30 @@ class BillController extends Controller | ||||
|         } | ||||
| 
 | ||||
|         // collect all expenses in this period (regardless of type) by the given bills and accounts.
 | ||||
|         $collector  = app(GroupCollectorInterface::class); | ||||
|         $collector       = app(GroupCollectorInterface::class); | ||||
|         $collector->setTypes([TransactionTypeEnum::WITHDRAWAL->value])->setRange($start, $end)->setSourceAccounts($accounts); | ||||
|         $collector->setBills($bills); | ||||
| 
 | ||||
|         $genericSet = $collector->getExtractedJournals(); | ||||
|         $genericSet      = $collector->getExtractedJournals(); | ||||
|         foreach ($genericSet as $journal) { | ||||
|             $billId            = (int) $journal['bill_id']; | ||||
|             $currencyId        = (int) $journal['currency_id']; | ||||
|             $foreignCurrencyId = (int) $journal['foreign_currency_id']; | ||||
|             $key               = sprintf('%d-%d', $billId, $currencyId); | ||||
|             $foreignKey        = sprintf('%d-%d', $billId, $foreignCurrencyId); | ||||
|             $billId       = (int) $journal['bill_id']; | ||||
|             $currencyId   = (int) $journal['currency_id']; | ||||
|             $currencyCode = $journal['currency_code']; | ||||
|             $field        = 'amount'; | ||||
| 
 | ||||
|             // use the native amount if the user wants to convert to native currency
 | ||||
|             if ($convertToNative && $currencyId !== $default->id) { | ||||
|                 $currencyId   = $default->id; | ||||
|                 $currencyCode = $default->code; | ||||
|                 $field        = 'native_amount'; | ||||
|             } | ||||
|             // use foreign amount when the foreign currency IS the default currency.
 | ||||
|             if ($convertToNative && $journal['currency_id'] !== $default->id && $default->id === $journal['foreign_currency_id']) { | ||||
|                 $field = 'foreign_amount'; | ||||
|             } | ||||
|             Log::debug(sprintf('Journal #%d in bill #%d will use %s (%s %s)', $journal['transaction_group_id'], $billId, $field, $currencyCode, $journal[$field] ?? '0')); | ||||
| 
 | ||||
|             $key          = sprintf('%d-%d', $billId, $currencyId); | ||||
| 
 | ||||
|             if (0 !== $currencyId) { | ||||
|                 $response[$key] ??= [ | ||||
| @@ -94,21 +111,11 @@ class BillController extends Controller | ||||
|                     'difference'       => '0', | ||||
|                     'difference_float' => 0, | ||||
|                     'currency_id'      => (string) $currencyId, | ||||
|                     'currency_code'    => $journal['currency_code'], | ||||
|                     'currency_code'    => $currencyCode, | ||||
|                 ]; | ||||
|                 $response[$key]['difference']       = bcadd($response[$key]['difference'], $journal['amount']); | ||||
|                 $response[$key]['difference']       = bcadd($response[$key]['difference'], (string) ($journal[$field] ?? '0')); | ||||
|                 $response[$key]['difference_float'] = (float) $response[$key]['difference']; // intentional float
 | ||||
|             } | ||||
|             if (0 !== $foreignCurrencyId) { | ||||
|                 $response[$foreignKey] ??= [ | ||||
|                     'difference'       => '0', | ||||
|                     'difference_float' => 0, | ||||
|                     'currency_id'      => (string) $foreignCurrencyId, | ||||
|                     'currency_code'    => $journal['foreign_currency_code'], | ||||
|                 ]; | ||||
|                 $response[$foreignKey]['difference']       = bcadd($response[$foreignKey]['difference'], $journal['foreign_amount']); | ||||
|                 $response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference']; // intentional float
 | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return response()->json(array_values($response)); | ||||
| @@ -122,42 +129,47 @@ class BillController extends Controller | ||||
|      */ | ||||
|     public function noBill(GenericRequest $request): JsonResponse | ||||
|     { | ||||
|         $accounts   = $request->getAssetAccounts(); | ||||
|         $start      = $request->getStart(); | ||||
|         $end        = $request->getEnd(); | ||||
|         $response   = []; | ||||
|         $accounts        = $request->getAssetAccounts(); | ||||
|         $start           = $request->getStart(); | ||||
|         $end             = $request->getEnd(); | ||||
|         $convertToNative = Amount::convertToNative(); | ||||
|         $default         = Amount::getDefaultCurrency(); | ||||
|         $response        = []; | ||||
| 
 | ||||
|         // collect all expenses in this period (regardless of type) by the given bills and accounts.
 | ||||
|         $collector  = app(GroupCollectorInterface::class); | ||||
|         $collector       = app(GroupCollectorInterface::class); | ||||
|         $collector->setTypes([TransactionTypeEnum::WITHDRAWAL->value])->setRange($start, $end)->setSourceAccounts($accounts); | ||||
|         $collector->withoutBill(); | ||||
| 
 | ||||
|         $genericSet = $collector->getExtractedJournals(); | ||||
|         $genericSet      = $collector->getExtractedJournals(); | ||||
| 
 | ||||
|         foreach ($genericSet as $journal) { | ||||
|             $currencyId        = (int) $journal['currency_id']; | ||||
|             $foreignCurrencyId = (int) $journal['foreign_currency_id']; | ||||
|             $currencyId   = (int) $journal['currency_id']; | ||||
|             $currencyCode = $journal['currency_code']; | ||||
|             $field        = 'amount'; | ||||
| 
 | ||||
|             // use the native amount if the user wants to convert to native currency
 | ||||
|             if ($convertToNative && $currencyId !== $default->id) { | ||||
|                 $currencyId   = $default->id; | ||||
|                 $currencyCode = $default->code; | ||||
|                 $field        = 'native_amount'; | ||||
|             } | ||||
|             // use foreign amount when the foreign currency IS the default currency.
 | ||||
|             if ($convertToNative && $journal['currency_id'] !== $default->id && $default->id === $journal['foreign_currency_id']) { | ||||
|                 $field = 'foreign_amount'; | ||||
|             } | ||||
|             Log::debug(sprintf('Journal #%d will use %s (%s %s)', $journal['transaction_group_id'], $field, $currencyCode, $journal[$field] ?? '0')); | ||||
| 
 | ||||
|             if (0 !== $currencyId) { | ||||
|                 $response[$currencyId] ??= [ | ||||
|                     'difference'       => '0', | ||||
|                     'difference_float' => 0, | ||||
|                     'currency_id'      => (string) $currencyId, | ||||
|                     'currency_code'    => $journal['currency_code'], | ||||
|                     'currency_code'    => $currencyCode, | ||||
|                 ]; | ||||
|                 $response[$currencyId]['difference']       = bcadd($response[$currencyId]['difference'], $journal['amount']); | ||||
|                 $response[$currencyId]['difference']       = bcadd($response[$currencyId]['difference'], (string) ($journal[$field] ?? '0')); | ||||
|                 $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // intentional float
 | ||||
|             } | ||||
|             if (0 !== $foreignCurrencyId) { | ||||
|                 $response[$foreignCurrencyId] ??= [ | ||||
|                     'difference'       => '0', | ||||
|                     'difference_float' => 0, | ||||
|                     'currency_id'      => (string) $foreignCurrencyId, | ||||
|                     'currency_code'    => $journal['foreign_currency_code'], | ||||
|                 ]; | ||||
|                 $response[$foreignCurrencyId]['difference']       = bcadd($response[$foreignCurrencyId]['difference'], $journal['foreign_amount']); | ||||
|                 $response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference']; // intentional float
 | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return response()->json(array_values($response)); | ||||
|   | ||||
| @@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Api\V1\Requests\Insight\GenericRequest; | ||||
| use FireflyIII\Enums\TransactionTypeEnum; | ||||
| use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| 
 | ||||
| /** | ||||
|  * Class PeriodController | ||||
| @@ -41,39 +43,49 @@ class PeriodController extends Controller | ||||
|      */ | ||||
|     public function total(GenericRequest $request): JsonResponse | ||||
|     { | ||||
|         $accounts   = $request->getAssetAccounts(); | ||||
|         $start      = $request->getStart(); | ||||
|         $end        = $request->getEnd(); | ||||
|         $response   = []; | ||||
|         $accounts        = $request->getAssetAccounts(); | ||||
|         $start           = $request->getStart(); | ||||
|         $end             = $request->getEnd(); | ||||
|         $response        = []; | ||||
|         $convertToNative = Amount::convertToNative(); | ||||
|         $default         = Amount::getDefaultCurrency(); | ||||
| 
 | ||||
|         // collect all expenses in this period (regardless of type)
 | ||||
|         $collector  = app(GroupCollectorInterface::class); | ||||
|         $collector       = app(GroupCollectorInterface::class); | ||||
|         $collector->setTypes([TransactionTypeEnum::WITHDRAWAL->value])->setRange($start, $end)->setSourceAccounts($accounts); | ||||
|         $genericSet = $collector->getExtractedJournals(); | ||||
|         $genericSet      = $collector->getExtractedJournals(); | ||||
|         foreach ($genericSet as $journal) { | ||||
|             $currencyId        = (int) $journal['currency_id']; | ||||
|             $foreignCurrencyId = (int) $journal['foreign_currency_id']; | ||||
|             // same code as many other sumExpense methods. I think this needs some kind of generic method.
 | ||||
|             $amount                                    = '0'; | ||||
|             $currencyId                                = (int) $journal['currency_id']; | ||||
|             $currencyCode                              = $journal['currency_code']; | ||||
|             if ($convertToNative) { | ||||
|                 $amount = Amount::getAmountFromJournal($journal); | ||||
|                 if ($default->id !== (int) $journal['currency_id'] && $default->id !== (int) $journal['foreign_currency_id']) { | ||||
|                     $currencyId   = $default->id; | ||||
|                     $currencyCode = $default->code; | ||||
|                 } | ||||
|                 if ($default->id !== (int) $journal['currency_id'] && $default->id === (int) $journal['foreign_currency_id']) { | ||||
|                     $currencyId   = $journal['foreign_currency_id']; | ||||
|                     $currencyCode = $journal['foreign_currency_code']; | ||||
|                 } | ||||
|                 Log::debug(sprintf('[a] Add amount %s %s', $currencyCode, $amount)); | ||||
|             } | ||||
|             if (!$convertToNative) { | ||||
|                 // ignore the amount in foreign currency.
 | ||||
|                 Log::debug(sprintf('[b] Add amount %s %s', $currencyCode, $journal['amount'])); | ||||
|                 $amount = $journal['amount']; | ||||
|             } | ||||
| 
 | ||||
|             if (0 !== $currencyId) { | ||||
|                 $response[$currencyId] ??= [ | ||||
|                     'difference'       => '0', | ||||
|                     'difference_float' => 0, | ||||
|                     'currency_id'      => (string) $currencyId, | ||||
|                     'currency_code'    => $journal['currency_code'], | ||||
|                 ]; | ||||
|                 $response[$currencyId]['difference']       = bcadd($response[$currencyId]['difference'], $journal['amount']); | ||||
|                 $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // intentional float
 | ||||
|             } | ||||
|             if (0 !== $foreignCurrencyId) { | ||||
|                 $response[$foreignCurrencyId] ??= [ | ||||
|                     'difference'       => '0', | ||||
|                     'difference_float' => 0, | ||||
|                     'currency_id'      => (string) $foreignCurrencyId, | ||||
|                     'currency_code'    => $journal['foreign_currency_code'], | ||||
|                 ]; | ||||
|                 $response[$foreignCurrencyId]['difference']       = bcadd($response[$foreignCurrencyId]['difference'], $journal['foreign_amount']); | ||||
|                 $response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference']; // intentional float
 | ||||
|             } | ||||
| 
 | ||||
|             $response[$currencyId] ??= [ | ||||
|                 'difference'       => '0', | ||||
|                 'difference_float' => 0, | ||||
|                 'currency_id'      => (string) $currencyId, | ||||
|                 'currency_code'    => $currencyCode, | ||||
|             ]; | ||||
|             $response[$currencyId]['difference']       = bcadd($response[$currencyId]['difference'], $amount); | ||||
|             $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // intentional float
 | ||||
|         } | ||||
| 
 | ||||
|         return response()->json(array_values($response)); | ||||
|   | ||||
| @@ -29,7 +29,9 @@ use FireflyIII\Api\V1\Requests\Insight\GenericRequest; | ||||
| use FireflyIII\Enums\TransactionTypeEnum; | ||||
| use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Repositories\Tag\TagRepositoryInterface; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| 
 | ||||
| /** | ||||
|  * Class TagController | ||||
| @@ -62,42 +64,51 @@ class TagController extends Controller | ||||
|      */ | ||||
|     public function noTag(GenericRequest $request): JsonResponse | ||||
|     { | ||||
|         $accounts   = $request->getAssetAccounts(); | ||||
|         $start      = $request->getStart(); | ||||
|         $end        = $request->getEnd(); | ||||
|         $response   = []; | ||||
|         $accounts        = $request->getAssetAccounts(); | ||||
|         $start           = $request->getStart(); | ||||
|         $end             = $request->getEnd(); | ||||
|         $response        = []; | ||||
|         $convertToNative = Amount::convertToNative(); | ||||
|         $default         = Amount::getDefaultCurrency(); | ||||
| 
 | ||||
|         // collect all expenses in this period (regardless of type) by the given bills and accounts.
 | ||||
|         $collector  = app(GroupCollectorInterface::class); | ||||
|         $collector       = app(GroupCollectorInterface::class); | ||||
|         $collector->setTypes([TransactionTypeEnum::WITHDRAWAL->value])->setRange($start, $end)->setSourceAccounts($accounts); | ||||
|         $collector->withoutTags(); | ||||
| 
 | ||||
|         $genericSet = $collector->getExtractedJournals(); | ||||
|         $genericSet      = $collector->getExtractedJournals(); | ||||
| 
 | ||||
|         foreach ($genericSet as $journal) { | ||||
|             $currencyId        = (int) $journal['currency_id']; | ||||
|             $foreignCurrencyId = (int) $journal['foreign_currency_id']; | ||||
|             // same code as many other sumExpense methods. I think this needs some kind of generic method.
 | ||||
|             $amount                                    = '0'; | ||||
|             $currencyId                                = (int) $journal['currency_id']; | ||||
|             $currencyCode                              = $journal['currency_code']; | ||||
|             if ($convertToNative) { | ||||
|                 $amount = Amount::getAmountFromJournal($journal); | ||||
|                 if ($default->id !== (int) $journal['currency_id'] && $default->id !== (int) $journal['foreign_currency_id']) { | ||||
|                     $currencyId   = $default->id; | ||||
|                     $currencyCode = $default->code; | ||||
|                 } | ||||
|                 if ($default->id !== (int) $journal['currency_id'] && $default->id === (int) $journal['foreign_currency_id']) { | ||||
|                     $currencyId   = $journal['foreign_currency_id']; | ||||
|                     $currencyCode = $journal['foreign_currency_code']; | ||||
|                 } | ||||
|                 Log::debug(sprintf('[a] Add amount %s %s', $currencyCode, $amount)); | ||||
|             } | ||||
|             if (!$convertToNative) { | ||||
|                 // ignore the amount in foreign currency.
 | ||||
|                 Log::debug(sprintf('[b] Add amount %s %s', $currencyCode, $journal['amount'])); | ||||
|                 $amount = $journal['amount']; | ||||
|             } | ||||
| 
 | ||||
|             if (0 !== $currencyId) { | ||||
|                 $response[$currencyId] ??= [ | ||||
|                     'difference'       => '0', | ||||
|                     'difference_float' => 0, | ||||
|                     'currency_id'      => (string) $currencyId, | ||||
|                     'currency_code'    => $journal['currency_code'], | ||||
|                 ]; | ||||
|                 $response[$currencyId]['difference']       = bcadd($response[$currencyId]['difference'], $journal['amount']); | ||||
|                 $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // float but on purpose.
 | ||||
|             } | ||||
|             if (0 !== $foreignCurrencyId) { | ||||
|                 $response[$foreignCurrencyId] ??= [ | ||||
|                     'difference'       => '0', | ||||
|                     'difference_float' => 0, | ||||
|                     'currency_id'      => (string) $foreignCurrencyId, | ||||
|                     'currency_code'    => $journal['foreign_currency_code'], | ||||
|                 ]; | ||||
|                 $response[$foreignCurrencyId]['difference']       = bcadd($response[$foreignCurrencyId]['difference'], $journal['foreign_amount']); | ||||
|                 $response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference']; // float but on purpose.
 | ||||
|             } | ||||
|             $response[$currencyId] ??= [ | ||||
|                 'difference'       => '0', | ||||
|                 'difference_float' => 0, | ||||
|                 'currency_id'      => (string) $currencyId, | ||||
|                 'currency_code'    => $currencyCode, | ||||
|             ]; | ||||
|             $response[$currencyId]['difference']       = bcadd($response[$currencyId]['difference'], $amount); | ||||
|             $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // float but on purpose.
 | ||||
|         } | ||||
| 
 | ||||
|         return response()->json(array_values($response)); | ||||
|   | ||||
| @@ -73,6 +73,7 @@ class AccountController extends Controller | ||||
|         $start         = $request->getStart(); | ||||
|         $end           = $request->getEnd(); | ||||
|         $assetAccounts = $request->getAssetAccounts(); | ||||
| 
 | ||||
|         $income        = $this->opsRepository->sumIncomeByDestination($start, $end, $assetAccounts); | ||||
|         $result        = []; | ||||
| 
 | ||||
|   | ||||
| @@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Api\V1\Requests\Insight\GenericRequest; | ||||
| use FireflyIII\Enums\TransactionTypeEnum; | ||||
| use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| 
 | ||||
| /** | ||||
| @@ -41,42 +42,41 @@ class PeriodController extends Controller | ||||
|      */ | ||||
|     public function total(GenericRequest $request): JsonResponse | ||||
|     { | ||||
|         $accounts   = $request->getAssetAccounts(); | ||||
|         $start      = $request->getStart(); | ||||
|         $end        = $request->getEnd(); | ||||
|         $response   = []; | ||||
|         $accounts        = $request->getAssetAccounts(); | ||||
|         $start           = $request->getStart(); | ||||
|         $end             = $request->getEnd(); | ||||
|         $response        = []; | ||||
|         $convertToNative = Amount::convertToNative(); | ||||
|         $default         = Amount::getDefaultCurrency(); | ||||
| 
 | ||||
|         // collect all expenses in this period (regardless of type)
 | ||||
|         $collector  = app(GroupCollectorInterface::class); | ||||
|         $collector       = app(GroupCollectorInterface::class); | ||||
|         $collector->setTypes([TransactionTypeEnum::DEPOSIT->value])->setRange($start, $end)->setDestinationAccounts($accounts); | ||||
|         $genericSet = $collector->getExtractedJournals(); | ||||
|         $genericSet      = $collector->getExtractedJournals(); | ||||
|         foreach ($genericSet as $journal) { | ||||
|             $currencyId        = (int) $journal['currency_id']; | ||||
|             $foreignCurrencyId = (int) $journal['foreign_currency_id']; | ||||
|             // currency
 | ||||
|             $currencyId                                = $journal['currency_id']; | ||||
|             $currencyCode                              = $journal['currency_code']; | ||||
|             $field                                     = $convertToNative && $currencyId !== $default->id ? 'native_amount' : 'amount'; | ||||
| 
 | ||||
|             if (0 !== $currencyId) { | ||||
|                 $response[$currencyId] ??= [ | ||||
|                     'difference'       => '0', | ||||
|                     'difference_float' => 0, | ||||
|                     'currency_id'      => (string) $currencyId, | ||||
|                     'currency_code'    => $journal['currency_code'], | ||||
|                 ]; | ||||
|                 $response[$currencyId]['difference']       = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal['amount'])); | ||||
|                 $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // float but on purpose.
 | ||||
|             // perhaps use default currency instead?
 | ||||
|             if ($convertToNative && $journal['currency_id'] !== $default->id) { | ||||
|                 $currencyId   = $default->id; | ||||
|                 $currencyCode = $default->code; | ||||
|             } | ||||
|             if (0 !== $foreignCurrencyId) { | ||||
|                 $response[$foreignCurrencyId] ??= [ | ||||
|                     'difference'       => '0', | ||||
|                     'difference_float' => 0, | ||||
|                     'currency_id'      => (string) $foreignCurrencyId, | ||||
|                     'currency_code'    => $journal['foreign_currency_code'], | ||||
|                 ]; | ||||
|                 $response[$foreignCurrencyId]['difference']       = bcadd( | ||||
|                     $response[$foreignCurrencyId]['difference'], | ||||
|                     app('steam')->positive($journal['foreign_amount']) | ||||
|                 ); | ||||
|                 $response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference']; // float but on purpose.
 | ||||
|             // use foreign amount when the foreign currency IS the default currency.
 | ||||
|             if ($convertToNative && $journal['currency_id'] !== $default->id && $default->id === $journal['foreign_currency_id']) { | ||||
|                 $field = 'foreign_amount'; | ||||
|             } | ||||
| 
 | ||||
|             $response[$currencyId] ??= [ | ||||
|                 'difference'       => '0', | ||||
|                 'difference_float' => 0, | ||||
|                 'currency_id'      => (string) $currencyId, | ||||
|                 'currency_code'    => $currencyCode, | ||||
|             ]; | ||||
|             $response[$currencyId]['difference']       = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal[$field])); | ||||
|             $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // float but on purpose.
 | ||||
|         } | ||||
| 
 | ||||
|         return response()->json(array_values($response)); | ||||
|   | ||||
| @@ -29,6 +29,7 @@ use FireflyIII\Api\V1\Requests\Insight\GenericRequest; | ||||
| use FireflyIII\Enums\TransactionTypeEnum; | ||||
| use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Repositories\Tag\TagRepositoryInterface; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| 
 | ||||
| /** | ||||
| @@ -63,45 +64,45 @@ class TagController extends Controller | ||||
|      */ | ||||
|     public function noTag(GenericRequest $request): JsonResponse | ||||
|     { | ||||
|         $accounts   = $request->getAssetAccounts(); | ||||
|         $start      = $request->getStart(); | ||||
|         $end        = $request->getEnd(); | ||||
|         $response   = []; | ||||
|         $accounts        = $request->getAssetAccounts(); | ||||
|         $start           = $request->getStart(); | ||||
|         $end             = $request->getEnd(); | ||||
|         $response        = []; | ||||
|         $convertToNative = Amount::convertToNative(); | ||||
|         $default         = Amount::getDefaultCurrency(); | ||||
| 
 | ||||
|         // collect all expenses in this period (regardless of type) by the given bills and accounts.
 | ||||
|         $collector  = app(GroupCollectorInterface::class); | ||||
|         $collector       = app(GroupCollectorInterface::class); | ||||
|         $collector->setTypes([TransactionTypeEnum::DEPOSIT->value])->setRange($start, $end)->setDestinationAccounts($accounts); | ||||
|         $collector->withoutTags(); | ||||
| 
 | ||||
|         $genericSet = $collector->getExtractedJournals(); | ||||
|         $genericSet      = $collector->getExtractedJournals(); | ||||
| 
 | ||||
|         foreach ($genericSet as $journal) { | ||||
|             $currencyId        = (int) $journal['currency_id']; | ||||
|             $foreignCurrencyId = (int) $journal['foreign_currency_id']; | ||||
|             // currency
 | ||||
|             $currencyId                                = $journal['currency_id']; | ||||
|             $currencyCode                              = $journal['currency_code']; | ||||
|             $field                                     = $convertToNative && $currencyId !== $default->id ? 'native_amount' : 'amount'; | ||||
| 
 | ||||
|             if (0 !== $currencyId) { | ||||
|                 $response[$currencyId] ??= [ | ||||
|                     'difference'       => '0', | ||||
|                     'difference_float' => 0, | ||||
|                     'currency_id'      => (string) $currencyId, | ||||
|                     'currency_code'    => $journal['currency_code'], | ||||
|                 ]; | ||||
|                 $response[$currencyId]['difference']       = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal['amount'])); | ||||
|                 $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; | ||||
|             // perhaps use default currency instead?
 | ||||
|             if ($convertToNative && $journal['currency_id'] !== $default->id) { | ||||
|                 $currencyId   = $default->id; | ||||
|                 $currencyCode = $default->code; | ||||
|             } | ||||
|             if (0 !== $foreignCurrencyId) { | ||||
|                 $response[$foreignCurrencyId] ??= [ | ||||
|                     'difference'       => '0', | ||||
|                     'difference_float' => 0, | ||||
|                     'currency_id'      => (string) $foreignCurrencyId, | ||||
|                     'currency_code'    => $journal['foreign_currency_code'], | ||||
|                 ]; | ||||
|                 $response[$foreignCurrencyId]['difference']       = bcadd( | ||||
|                     $response[$foreignCurrencyId]['difference'], | ||||
|                     app('steam')->positive($journal['foreign_amount']) | ||||
|                 ); | ||||
|                 $response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference']; | ||||
|             // use foreign amount when the foreign currency IS the default currency.
 | ||||
|             if ($convertToNative && $journal['currency_id'] !== $default->id && $default->id === $journal['foreign_currency_id']) { | ||||
|                 $field = 'foreign_amount'; | ||||
|             } | ||||
| 
 | ||||
|             $response[$currencyId] ??= [ | ||||
|                 'difference'       => '0', | ||||
|                 'difference_float' => 0, | ||||
|                 'currency_id'      => (string) $currencyId, | ||||
|                 'currency_code'    => $currencyCode, | ||||
|             ]; | ||||
|             $response[$currencyId]['difference']       = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal[$field])); | ||||
|             $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         return response()->json(array_values($response)); | ||||
|   | ||||
| @@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Api\V1\Requests\Insight\GenericRequest; | ||||
| use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| 
 | ||||
| /** | ||||
| @@ -41,42 +42,42 @@ class PeriodController extends Controller | ||||
|      */ | ||||
|     public function total(GenericRequest $request): JsonResponse | ||||
|     { | ||||
|         $accounts   = $request->getAssetAccounts(); | ||||
|         $start      = $request->getStart(); | ||||
|         $end        = $request->getEnd(); | ||||
|         $response   = []; | ||||
|         $accounts        = $request->getAssetAccounts(); | ||||
|         $start           = $request->getStart(); | ||||
|         $end             = $request->getEnd(); | ||||
|         $response        = []; | ||||
|         $convertToNative = Amount::convertToNative(); | ||||
|         $default         = Amount::getDefaultCurrency(); | ||||
| 
 | ||||
|         // collect all expenses in this period (regardless of type)
 | ||||
|         $collector  = app(GroupCollectorInterface::class); | ||||
|         $collector       = app(GroupCollectorInterface::class); | ||||
|         $collector->setTypes([TransactionType::TRANSFER])->setRange($start, $end)->setDestinationAccounts($accounts); | ||||
|         $genericSet = $collector->getExtractedJournals(); | ||||
|         $genericSet      = $collector->getExtractedJournals(); | ||||
|         foreach ($genericSet as $journal) { | ||||
|             $currencyId        = (int) $journal['currency_id']; | ||||
|             $foreignCurrencyId = (int) $journal['foreign_currency_id']; | ||||
|             // currency
 | ||||
|             $currencyId                                = $journal['currency_id']; | ||||
|             $currencyCode                              = $journal['currency_code']; | ||||
|             $field                                     = $convertToNative && $currencyId !== $default->id ? 'native_amount' : 'amount'; | ||||
| 
 | ||||
|             if (0 !== $currencyId) { | ||||
|                 $response[$currencyId] ??= [ | ||||
|                     'difference'       => '0', | ||||
|                     'difference_float' => 0, | ||||
|                     'currency_id'      => (string) $currencyId, | ||||
|                     'currency_code'    => $journal['currency_code'], | ||||
|                 ]; | ||||
|                 $response[$currencyId]['difference']       = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal['amount'])); | ||||
|                 $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; | ||||
|             // perhaps use default currency instead?
 | ||||
|             if ($convertToNative && $journal['currency_id'] !== $default->id) { | ||||
|                 $currencyId   = $default->id; | ||||
|                 $currencyCode = $default->code; | ||||
|             } | ||||
|             if (0 !== $foreignCurrencyId) { | ||||
|                 $response[$foreignCurrencyId] ??= [ | ||||
|                     'difference'       => '0', | ||||
|                     'difference_float' => 0, | ||||
|                     'currency_id'      => (string) $foreignCurrencyId, | ||||
|                     'currency_code'    => $journal['foreign_currency_code'], | ||||
|                 ]; | ||||
|                 $response[$foreignCurrencyId]['difference']       = bcadd( | ||||
|                     $response[$foreignCurrencyId]['difference'], | ||||
|                     app('steam')->positive($journal['foreign_amount']) | ||||
|                 ); | ||||
|                 $response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference']; | ||||
|             // use foreign amount when the foreign currency IS the default currency.
 | ||||
|             if ($convertToNative && $journal['currency_id'] !== $default->id && $default->id === $journal['foreign_currency_id']) { | ||||
|                 $field = 'foreign_amount'; | ||||
|             } | ||||
| 
 | ||||
|             $response[$currencyId] ??= [ | ||||
|                 'difference'       => '0', | ||||
|                 'difference_float' => 0, | ||||
|                 'currency_id'      => (string) $currencyId, | ||||
|                 'currency_code'    => $currencyCode, | ||||
|             ]; | ||||
|             $response[$currencyId]['difference']       = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal[$field])); | ||||
|             $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         return response()->json(array_values($response)); | ||||
|   | ||||
| @@ -29,6 +29,7 @@ use FireflyIII\Api\V1\Requests\Insight\GenericRequest; | ||||
| use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Repositories\Tag\TagRepositoryInterface; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| 
 | ||||
| /** | ||||
| @@ -61,45 +62,46 @@ class TagController extends Controller | ||||
|      */ | ||||
|     public function noTag(GenericRequest $request): JsonResponse | ||||
|     { | ||||
|         $accounts   = $request->getAssetAccounts(); | ||||
|         $start      = $request->getStart(); | ||||
|         $end        = $request->getEnd(); | ||||
|         $response   = []; | ||||
|         $accounts        = $request->getAssetAccounts(); | ||||
|         $start           = $request->getStart(); | ||||
|         $end             = $request->getEnd(); | ||||
|         $response        = []; | ||||
|         $convertToNative = Amount::convertToNative(); | ||||
|         $default         = Amount::getDefaultCurrency(); | ||||
| 
 | ||||
| 
 | ||||
|         // collect all expenses in this period (regardless of type) by the given bills and accounts.
 | ||||
|         $collector  = app(GroupCollectorInterface::class); | ||||
|         $collector       = app(GroupCollectorInterface::class); | ||||
|         $collector->setTypes([TransactionType::TRANSFER])->setRange($start, $end)->setDestinationAccounts($accounts); | ||||
|         $collector->withoutTags(); | ||||
| 
 | ||||
|         $genericSet = $collector->getExtractedJournals(); | ||||
|         $genericSet      = $collector->getExtractedJournals(); | ||||
| 
 | ||||
|         foreach ($genericSet as $journal) { | ||||
|             $currencyId        = (int) $journal['currency_id']; | ||||
|             $foreignCurrencyId = (int) $journal['foreign_currency_id']; | ||||
|             // currency
 | ||||
|             $currencyId                                = $journal['currency_id']; | ||||
|             $currencyCode                              = $journal['currency_code']; | ||||
|             $field                                     = $convertToNative && $currencyId !== $default->id ? 'native_amount' : 'amount'; | ||||
| 
 | ||||
|             if (0 !== $currencyId) { | ||||
|                 $response[$currencyId] ??= [ | ||||
|                     'difference'       => '0', | ||||
|                     'difference_float' => 0, | ||||
|                     'currency_id'      => (string) $currencyId, | ||||
|                     'currency_code'    => $journal['currency_code'], | ||||
|                 ]; | ||||
|                 $response[$currencyId]['difference']       = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal['amount'])); | ||||
|                 $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; | ||||
|             // perhaps use default currency instead?
 | ||||
|             if ($convertToNative && $journal['currency_id'] !== $default->id) { | ||||
|                 $currencyId   = $default->id; | ||||
|                 $currencyCode = $default->code; | ||||
|             } | ||||
|             if (0 !== $foreignCurrencyId) { | ||||
|                 $response[$foreignCurrencyId] ??= [ | ||||
|                     'difference'       => '0', | ||||
|                     'difference_float' => 0, | ||||
|                     'currency_id'      => (string) $foreignCurrencyId, | ||||
|                     'currency_code'    => $journal['foreign_currency_code'], | ||||
|                 ]; | ||||
|                 $response[$foreignCurrencyId]['difference']       = bcadd( | ||||
|                     $response[$foreignCurrencyId]['difference'], | ||||
|                     app('steam')->positive($journal['foreign_amount']) | ||||
|                 ); | ||||
|                 $response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference']; | ||||
|             // use foreign amount when the foreign currency IS the default currency.
 | ||||
|             if ($convertToNative && $journal['currency_id'] !== $default->id && $default->id === $journal['foreign_currency_id']) { | ||||
|                 $field = 'foreign_amount'; | ||||
|             } | ||||
| 
 | ||||
|             $response[$currencyId] ??= [ | ||||
|                 'difference'       => '0', | ||||
|                 'difference_float' => 0, | ||||
|                 'currency_id'      => (string) $currencyId, | ||||
|                 'currency_code'    => $currencyCode, | ||||
|             ]; | ||||
|             $response[$currencyId]['difference']       = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal[$field])); | ||||
|             $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         return response()->json(array_values($response)); | ||||
|   | ||||
| @@ -105,19 +105,18 @@ class ShowController extends Controller | ||||
|     public function show(TransactionCurrency $currency): JsonResponse | ||||
|     { | ||||
|         /** @var User $user */ | ||||
|         $user            = auth()->user(); | ||||
|         $manager         = $this->getManager(); | ||||
|         $defaultCurrency = app('amount')->getDefaultCurrencyByUserGroup($user->userGroup); | ||||
|         $this->parameters->set('defaultCurrency', $defaultCurrency); | ||||
|         $user        = auth()->user(); | ||||
|         $manager     = $this->getManager(); | ||||
|         $this->parameters->set('defaultCurrency', $this->defaultCurrency); | ||||
| 
 | ||||
|         // update fields with user info.
 | ||||
|         $currency->refreshForUser($user); | ||||
| 
 | ||||
|         /** @var CurrencyTransformer $transformer */ | ||||
|         $transformer     = app(CurrencyTransformer::class); | ||||
|         $transformer = app(CurrencyTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
| 
 | ||||
|         $resource        = new Item($currency, $transformer, 'currencies'); | ||||
|         $resource    = new Item($currency, $transformer, 'currencies'); | ||||
| 
 | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
| @@ -135,7 +134,7 @@ class ShowController extends Controller | ||||
|         /** @var User $user */ | ||||
|         $user        = auth()->user(); | ||||
|         $manager     = $this->getManager(); | ||||
|         $currency    = app('amount')->getDefaultCurrencyByUserGroup($user->userGroup); | ||||
|         $currency    = $this->defaultCurrency; | ||||
| 
 | ||||
|         // update fields with user info.
 | ||||
|         $currency->refreshForUser($user); | ||||
|   | ||||
| @@ -103,10 +103,10 @@ class BasicController extends Controller | ||||
|         $billData     = $this->getBillInformation($start, $end); | ||||
|         $spentData    = $this->getLeftToSpendInfo($start, $end); | ||||
|         $netWorthData = $this->getNetWorthInfo($start, $end); | ||||
|         //        $balanceData  = [];
 | ||||
|         //        $billData     = [];
 | ||||
|         //        $spentData    = [];
 | ||||
|         //        $netWorthData = [];
 | ||||
|         //                $balanceData  = [];
 | ||||
|         //                $billData     = [];
 | ||||
|         //                $spentData    = [];
 | ||||
|         //                $netWorthData = [];
 | ||||
|         $total        = array_merge($balanceData, $billData, $spentData, $netWorthData); | ||||
| 
 | ||||
|         // give new keys
 | ||||
| @@ -123,8 +123,8 @@ class BasicController extends Controller | ||||
|     private function getBalanceInformation(Carbon $start, Carbon $end): array | ||||
|     { | ||||
|         // some config settings
 | ||||
|         $convertToNative = app('preferences')->get('convert_to_native', false)->data; | ||||
|         $default         = app('amount')->getDefaultCurrency(); | ||||
|         $convertToNative = Amount::convertToNative(); | ||||
|         $default         = Amount::getDefaultCurrency(); | ||||
|         // prep some arrays:
 | ||||
|         $incomes         = []; | ||||
|         $expenses        = []; | ||||
| @@ -276,13 +276,13 @@ class BasicController extends Controller | ||||
|      */ | ||||
|     private function getLeftToSpendInfo(Carbon $start, Carbon $end): array | ||||
|     { | ||||
|         Log::debug(sprintf('Now in getLeftToSpendInfo("%s", "%s")', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s'))); | ||||
|         $return    = []; | ||||
|         $today     = today(config('app.timezone')); | ||||
|         $available = $this->abRepository->getAvailableBudgetWithCurrency($start, $end); | ||||
|         $budgets   = $this->budgetRepository->getActiveBudgets(); | ||||
|         $spent     = $this->opsRepository->sumExpenses($start, $end, null, $budgets); | ||||
|         $days      = (int) $today->diffInDays($end, true) + 1; | ||||
|         Log::debug(sprintf('Now in getLeftToSpendInfo("%s", "%s")', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s'))); | ||||
| 
 | ||||
|         foreach ($spent as $row) { | ||||
|             // either an amount was budgeted or 0 is available.
 | ||||
|   | ||||
| @@ -1,113 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| /* | ||||
|  * AccountController.php | ||||
|  * Copyright (c) 2024 james@firefly-iii.org. | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see https://www.gnu.org/licenses/. | ||||
|  */ | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\Api\V2\Controllers\JsonApi; | ||||
| 
 | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\JsonApi\V2\Accounts\AccountCollectionQuery; | ||||
| use FireflyIII\JsonApi\V2\Accounts\AccountSchema; | ||||
| use FireflyIII\JsonApi\V2\Accounts\AccountSingleQuery; | ||||
| use FireflyIII\Models\Account; | ||||
| use Illuminate\Contracts\Support\Responsable; | ||||
| use Illuminate\Http\Response; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use LaravelJsonApi\Core\Responses\DataResponse; | ||||
| use LaravelJsonApi\Laravel\Http\Controllers\Actions; | ||||
| 
 | ||||
| /** | ||||
|  * Class AccountController | ||||
|  * | ||||
|  * This class handles api/v2 requests for accounts. | ||||
|  * Most stuff is default stuff. | ||||
|  */ | ||||
| class AccountController extends Controller | ||||
| { | ||||
|     use Actions\AttachRelationship; | ||||
|     use Actions\Destroy; | ||||
|     use Actions\DetachRelationship; | ||||
| 
 | ||||
|     use Actions\FetchMany; | ||||
| 
 | ||||
|     // use Actions\FetchOne;
 | ||||
|     use Actions\FetchRelated; | ||||
|     use Actions\FetchRelationship; | ||||
|     use Actions\Store; | ||||
|     use Actions\Update; | ||||
|     use Actions\UpdateRelationship; | ||||
| 
 | ||||
|     /** | ||||
|      * Fetch zero to many JSON API resources. | ||||
|      * | ||||
|      * @return Responsable|Response | ||||
|      */ | ||||
|     public function index(AccountSchema $schema, AccountCollectionQuery $request) | ||||
|     { | ||||
|         Log::debug(__METHOD__); | ||||
|         $models = $schema | ||||
|             ->repository() | ||||
|             ->queryAll() | ||||
|             ->withRequest($request) | ||||
|             ->get() | ||||
|         ; | ||||
| 
 | ||||
|         // do something custom...
 | ||||
| 
 | ||||
|         return new DataResponse($models); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Fetch zero to one JSON API resource by id. | ||||
|      * | ||||
|      * @return Responsable|Response | ||||
|      */ | ||||
|     public function show(AccountSchema $schema, AccountSingleQuery $request, Account $account) | ||||
|     { | ||||
|         Log::debug(__METHOD__); | ||||
|         $model = $schema->repository() | ||||
|             ->queryOne($account) | ||||
|             ->withRequest($request) | ||||
|             ->first() | ||||
|         ; | ||||
|         Log::debug(sprintf('%s again!', __METHOD__)); | ||||
| 
 | ||||
|         // do something custom...
 | ||||
| 
 | ||||
|         return new DataResponse($model); | ||||
|     } | ||||
| 
 | ||||
|     //    public function readAccountBalances(AnonymousQuery $query, AccountBalanceSchema $schema, Account $account): Responsable
 | ||||
|     //    {
 | ||||
|     //        $schema = JsonApi::server()->schemas()->schemaFor('account-balances');
 | ||||
|     //
 | ||||
|     //        $models = $schema
 | ||||
|     //            ->repository()
 | ||||
|     //            ->queryAll()
 | ||||
|     //            ->withRequest($query)
 | ||||
|     //            ->withAccount($account)
 | ||||
|     //            ->get()
 | ||||
|     //        ;
 | ||||
|     //
 | ||||
|     //        return DataResponse::make($models);
 | ||||
|     //    }
 | ||||
| } | ||||
| @@ -25,7 +25,6 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Api\V2\Request\Chart; | ||||
| 
 | ||||
| use FireflyIII\Enums\UserRoleEnum; | ||||
| use FireflyIII\Support\Http\Api\ParsesQueryFilters; | ||||
| use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; | ||||
| use FireflyIII\Support\Request\ChecksLogin; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| @@ -40,7 +39,6 @@ class ChartRequest extends FormRequest | ||||
| { | ||||
|     use ChecksLogin; | ||||
|     use ConvertsDataTypes; | ||||
|     use ParsesQueryFilters; | ||||
|     use ValidatesUserGroupTrait; | ||||
| 
 | ||||
|     protected array $acceptedRoles = [UserRoleEnum::READ_ONLY]; | ||||
|   | ||||
| @@ -74,7 +74,7 @@ class CorrectsDatabase extends Command | ||||
|             'correction:recalculates-liabilities', | ||||
|             'correction:preferences', | ||||
|             // 'correction:transaction-types', // resource heavy, disabled.
 | ||||
|             // 'correction:recalculate-native-amounts', // not necessary, disabled.
 | ||||
|             'correction:recalculate-native-amounts', // not necessary, disabled.
 | ||||
|             'firefly-iii:report-integrity', | ||||
|         ]; | ||||
|         foreach ($commands as $command) { | ||||
|   | ||||
| @@ -59,6 +59,11 @@ class CorrectsNativeAmounts extends Command | ||||
|      */ | ||||
|     public function handle(): int | ||||
|     { | ||||
|         if (!config('cer.enabled')) { | ||||
|             $this->friendlyInfo('This command will not run because currency exchange rates are disabled.'); | ||||
| 
 | ||||
|             return 0; | ||||
|         } | ||||
|         Log::debug('Will update all native amounts. This may take some time.'); | ||||
|         $this->friendlyWarning('Recalculating native amounts for all objects. This may take some time!'); | ||||
| 
 | ||||
| @@ -124,8 +129,8 @@ class CorrectsNativeAmounts extends Command | ||||
| 
 | ||||
|             foreach ($piggyBank->accounts as $account) { | ||||
|                 $account->pivot->native_current_amount = null; | ||||
|                 if (0 !== bccomp($account->pivot->current_amount, '0')) { | ||||
|                     $account->pivot->native_current_amount = $converter->convert($piggyBank->transactionCurrency, $currency, today(), $account->pivot->current_amount); | ||||
|                 if (0 !== bccomp((string) $account->pivot->current_amount, '0')) { | ||||
|                     $account->pivot->native_current_amount = $converter->convert($piggyBank->transactionCurrency, $currency, today(), (string) $account->pivot->current_amount); | ||||
|                 } | ||||
|                 $account->pivot->save(); | ||||
|             } | ||||
|   | ||||
| @@ -45,7 +45,6 @@ class ReportsIntegrity extends Command | ||||
|             return 1; | ||||
|         } | ||||
|         $commands = [ | ||||
|             // 'firefly-iii:add-timezones-to-dates',
 | ||||
|             'integrity:empty-objects', | ||||
|             'integrity:total-sums', | ||||
|         ]; | ||||
|   | ||||
| @@ -76,9 +76,6 @@ class AddsTransactionIdentifiers extends Command | ||||
|             $this->updateJournalIdentifiers($journal); | ||||
|         } | ||||
| 
 | ||||
|         if (0 === $this->count) { | ||||
|             $this->friendlyPositive('All split journal transaction identifiers are OK.'); | ||||
|         } | ||||
|         if (0 !== $this->count) { | ||||
|             $this->friendlyInfo(sprintf('Fixed %d split journal transaction identifier(s).', $this->count)); | ||||
|         } | ||||
|   | ||||
| @@ -70,7 +70,6 @@ class RemovesDatabaseDecryption extends Command | ||||
|     private function decryptTable(string $table, array $fields): void | ||||
|     { | ||||
|         if ($this->isDecrypted($table)) { | ||||
|             $this->friendlyInfo(sprintf('No decryption required for table "%s".', $table)); | ||||
| 
 | ||||
|             return; | ||||
|         } | ||||
|   | ||||
| @@ -62,9 +62,6 @@ class UpgradesAccountCurrencies extends Command | ||||
|         } | ||||
|         $this->updateAccountCurrencies(); | ||||
| 
 | ||||
|         if (0 === $this->count) { | ||||
|             $this->friendlyPositive('All account currencies are OK.'); | ||||
|         } | ||||
|         if (0 !== $this->count) { | ||||
|             $this->friendlyInfo(sprintf('Corrected %d account(s).', $this->count)); | ||||
|         } | ||||
|   | ||||
| @@ -73,9 +73,6 @@ class UpgradesAccountMetaData extends Command | ||||
| 
 | ||||
|         $this->markAsExecuted(); | ||||
| 
 | ||||
|         if (0 === $count) { | ||||
|             $this->friendlyPositive('All account meta is OK.'); | ||||
|         } | ||||
|         if (0 !== $count) { | ||||
|             $this->friendlyInfo(sprintf('Renamed %d account meta entries (entry).', $count)); | ||||
|         } | ||||
|   | ||||
| @@ -79,9 +79,6 @@ class UpgradesAttachments extends Command | ||||
|                 ++$count; | ||||
|             } | ||||
|         } | ||||
|         if (0 === $count) { | ||||
|             $this->friendlyPositive('All attachments are OK.'); | ||||
|         } | ||||
|         if (0 !== $count) { | ||||
|             $this->friendlyInfo(sprintf('Updated %d attachment(s).', $count)); | ||||
|         } | ||||
|   | ||||
| @@ -73,9 +73,6 @@ class UpgradesBillsToRules extends Command | ||||
|             $this->migrateUser($user); | ||||
|         } | ||||
| 
 | ||||
|         if (0 === $this->count) { | ||||
|             $this->friendlyPositive('All bills are OK.'); | ||||
|         } | ||||
|         if (0 !== $this->count) { | ||||
|             $this->friendlyInfo(sprintf('Verified and fixed %d bill(s).', $this->count)); | ||||
|         } | ||||
|   | ||||
| @@ -77,9 +77,6 @@ class UpgradesBudgetLimits extends Command | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         if (0 === $count) { | ||||
|             $this->friendlyPositive('All budget limits are OK.'); | ||||
|         } | ||||
|         $this->markAsExecuted(); | ||||
| 
 | ||||
|         return 0; | ||||
|   | ||||
| @@ -55,7 +55,6 @@ class UpgradesCreditCardLiabilities extends Command | ||||
|         $ccType   = AccountType::where('type', AccountType::CREDITCARD)->first(); | ||||
|         $debtType = AccountType::where('type', AccountType::DEBT)->first(); | ||||
|         if (null === $ccType || null === $debtType) { | ||||
|             $this->friendlyPositive('No incorrectly stored credit card liabilities.'); | ||||
|             $this->markAsExecuted(); | ||||
| 
 | ||||
|             return 0; | ||||
| @@ -73,9 +72,6 @@ class UpgradesCreditCardLiabilities extends Command | ||||
|                 'Credit card liability types are no longer supported and have been converted to generic debts. See: https://bit.ly/FF3-credit-cards' | ||||
|             ); | ||||
|         } | ||||
|         if (0 === $accounts->count()) { | ||||
|             $this->friendlyPositive('No incorrectly stored credit card liabilities.'); | ||||
|         } | ||||
|         $this->markAsExecuted(); | ||||
| 
 | ||||
|         return 0; | ||||
|   | ||||
| @@ -57,7 +57,6 @@ class UpgradesDatabase extends Command | ||||
|             'upgrade:480-account-meta', | ||||
|             'upgrade:481-recurrence-meta', | ||||
|             'upgrade:500-tag-locations', | ||||
|             'upgrade:550-recurrence-type', | ||||
|             'upgrade:560-liabilities', | ||||
|             'upgrade:600-liabilities', | ||||
|             'upgrade:550-budget-limit-periods', | ||||
|   | ||||
| @@ -68,7 +68,7 @@ class UpgradesJournalMetaData extends Command | ||||
| 
 | ||||
|     private function isMigrated(): bool | ||||
|     { | ||||
|         $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); | ||||
|         $configVar = app('fireflyconfig')->get(UpgradesToGroups::CONFIG_NAME, false); | ||||
| 
 | ||||
|         return (bool) $configVar->data; | ||||
|     } | ||||
|   | ||||
| @@ -72,9 +72,6 @@ class UpgradesJournalNotes extends Command | ||||
|             ++$count; | ||||
|         } | ||||
| 
 | ||||
|         if (0 === $count) { | ||||
|             $this->friendlyPositive('No notes to migrate.'); | ||||
|         } | ||||
|         if (0 !== $count) { | ||||
|             $this->friendlyInfo(sprintf('Migrated %d note(s).', $count)); | ||||
|         } | ||||
|   | ||||
| @@ -52,9 +52,6 @@ class UpgradesRecurrenceMetaData extends Command | ||||
|         } | ||||
|         $count = $this->migrateMetaData(); | ||||
| 
 | ||||
|         if (0 === $count) { | ||||
|             $this->friendlyPositive('No recurrence meta data migrated.'); | ||||
|         } | ||||
|         if ($count > 0) { | ||||
|             $this->friendlyInfo(sprintf('Migrated %d meta data entries', $count)); | ||||
|         } | ||||
|   | ||||
| @@ -1,67 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| /* | ||||
|  * MigrateRecurrenceType.php | ||||
|  * Copyright (c) 2021 james@firefly-iii.org | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\Console\Commands\Upgrade; | ||||
| 
 | ||||
| use FireflyIII\Console\Commands\ShowsFriendlyMessages; | ||||
| use Illuminate\Console\Command; | ||||
| 
 | ||||
| class UpgradesRecurrenceType extends Command | ||||
| { | ||||
|     use ShowsFriendlyMessages; | ||||
| 
 | ||||
|     public const string CONFIG_NAME = '550_migrate_recurrence_type'; | ||||
| 
 | ||||
|     protected $description          = 'Migrate transaction type of recurring transaction.'; | ||||
| 
 | ||||
|     protected $signature            = 'upgrade:550-recurrence-type {--F|force : Force the execution of this command.}'; | ||||
| 
 | ||||
|     /** | ||||
|      * Execute the console command. | ||||
|      */ | ||||
|     public function handle(): int | ||||
|     { | ||||
|         if ($this->isExecuted() && true !== $this->option('force')) { | ||||
|             $this->friendlyInfo('This command has already been executed.'); | ||||
| 
 | ||||
|             return 0; | ||||
|         } | ||||
|         $this->friendlyWarning('This command has been disabled.'); | ||||
|         $this->markAsExecuted(); | ||||
| 
 | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     private function isExecuted(): bool | ||||
|     { | ||||
|         $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); | ||||
| 
 | ||||
|         return (bool) $configVar?->data; | ||||
|     } | ||||
| 
 | ||||
|     private function markAsExecuted(): void | ||||
|     { | ||||
|         app('fireflyconfig')->set(self::CONFIG_NAME, true); | ||||
|     } | ||||
| } | ||||
| @@ -72,9 +72,6 @@ class UpgradesToGroups extends Command | ||||
|         if (0 !== $this->count) { | ||||
|             $this->friendlyInfo(sprintf('Migrated %d transaction journal(s).', $this->count)); | ||||
|         } | ||||
|         if (0 === $this->count) { | ||||
|             $this->friendlyPositive('No journals to migrate to groups.'); | ||||
|         } | ||||
|         $this->markAsMigrated(); | ||||
| 
 | ||||
|         return 0; | ||||
| @@ -363,9 +360,6 @@ class UpgradesToGroups extends Command | ||||
|                 $this->giveGroup($array); | ||||
|             } | ||||
|         } | ||||
|         if (0 === $total) { | ||||
|             $this->friendlyPositive('No need to convert transaction journals.'); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private function giveGroup(array $array): void | ||||
|   | ||||
| @@ -68,15 +68,10 @@ class UpgradesTransferCurrencies extends Command | ||||
| 
 | ||||
|         $this->startUpdateRoutine(); | ||||
|         $this->markAsExecuted(); | ||||
| 
 | ||||
|         if (0 === $this->count) { | ||||
|             $this->friendlyPositive('All transfers have correct currency information.'); | ||||
| 
 | ||||
|             return 0; | ||||
|         if ($this->count > 0) { | ||||
|             $this->friendlyInfo(sprintf('Verified currency information of %d transfer(s).', $this->count)); | ||||
|         } | ||||
| 
 | ||||
|         $this->friendlyInfo(sprintf('Verified currency information of %d transfer(s).', $this->count)); | ||||
| 
 | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|   | ||||
| @@ -36,8 +36,6 @@ use Illuminate\Session\TokenMismatchException; | ||||
| use Illuminate\Support\Arr; | ||||
| use Illuminate\Validation\ValidationException as LaravelValidationException; | ||||
| use Laravel\Passport\Exceptions\OAuthServerException as LaravelOAuthException; | ||||
| use LaravelJsonApi\Core\Exceptions\JsonApiException; | ||||
| use LaravelJsonApi\Exceptions\ExceptionParser; | ||||
| use League\OAuth2\Server\Exception\OAuthServerException; | ||||
| use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException; | ||||
| use Symfony\Component\HttpFoundation\Response; | ||||
| @@ -65,18 +63,12 @@ class Handler extends ExceptionHandler | ||||
|             HttpException::class, | ||||
|             SuspiciousOperationException::class, | ||||
|             BadHttpHeaderException::class, | ||||
|             JsonApiException::class, | ||||
|         ]; | ||||
| 
 | ||||
|     /** | ||||
|      * Register the exception handling callbacks for the application. | ||||
|      */ | ||||
|     public function register(): void | ||||
|     { | ||||
|         $this->renderable( | ||||
|             ExceptionParser::make()->renderable() | ||||
|         ); | ||||
|     } | ||||
|     public function register(): void {} | ||||
| 
 | ||||
|     /** | ||||
|      * Render an exception into an HTTP response. It's complex but lucky for us, we never use it because | ||||
|   | ||||
| @@ -43,11 +43,11 @@ class PiggyBankFactory | ||||
| 
 | ||||
|     public User                          $user { | ||||
|         set(User $value) { | ||||
|             $this->user = $value; | ||||
|             $this->currencyRepository->setUser($value); | ||||
|             $this->accountRepository->setUser($value); | ||||
|             $this->piggyBankRepository->setUser($value); | ||||
|         } | ||||
|         $this->user = $value; | ||||
|         $this->currencyRepository->setUser($value); | ||||
|         $this->accountRepository->setUser($value); | ||||
|         $this->piggyBankRepository->setUser($value); | ||||
|     } | ||||
|     } | ||||
|     private AccountRepositoryInterface   $accountRepository; | ||||
|     private CurrencyRepositoryInterface  $currencyRepository; | ||||
| @@ -62,15 +62,11 @@ class PiggyBankFactory | ||||
| 
 | ||||
|     /** | ||||
|      * Store a piggy bank or come back with an exception. | ||||
|      * | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return PiggyBank | ||||
|      */ | ||||
|     public function store(array $data): PiggyBank | ||||
|     { | ||||
| 
 | ||||
|         $piggyBankData = $data; | ||||
|         $piggyBankData                            = $data; | ||||
| 
 | ||||
|         // unset some fields
 | ||||
|         unset($piggyBankData['object_group_title'], $piggyBankData['transaction_currency_code'], $piggyBankData['transaction_currency_id'], $piggyBankData['accounts'], $piggyBankData['object_group_id'], $piggyBankData['notes']); | ||||
| @@ -94,11 +90,11 @@ class PiggyBankFactory | ||||
| 
 | ||||
|             throw new FireflyException('400005: Could not store new piggy bank.', 0, $e); | ||||
|         } | ||||
|         $piggyBank = $this->setOrder($piggyBank, $data); | ||||
|         $piggyBank                                = $this->setOrder($piggyBank, $data); | ||||
|         $this->linkToAccountIds($piggyBank, $data['accounts']); | ||||
|         $this->piggyBankRepository->updateNote($piggyBank, $data['notes']); | ||||
| 
 | ||||
|         $objectGroupTitle = $data['object_group_title'] ?? ''; | ||||
|         $objectGroupTitle                         = $data['object_group_title'] ?? ''; | ||||
|         if ('' !== $objectGroupTitle) { | ||||
|             $objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle); | ||||
|             if (null !== $objectGroup) { | ||||
| @@ -106,7 +102,7 @@ class PiggyBankFactory | ||||
|             } | ||||
|         } | ||||
|         // try also with ID
 | ||||
|         $objectGroupId = (int) ($data['object_group_id'] ?? 0); | ||||
|         $objectGroupId                            = (int) ($data['object_group_id'] ?? 0); | ||||
|         if (0 !== $objectGroupId) { | ||||
|             $objectGroup = $this->findObjectGroupById($objectGroupId); | ||||
|             if (null !== $objectGroup) { | ||||
| @@ -114,9 +110,10 @@ class PiggyBankFactory | ||||
|             } | ||||
|         } | ||||
|         Log::debug('Touch piggy bank'); | ||||
|         $piggyBank->encrypted = false; | ||||
|         $piggyBank->encrypted                     = false; | ||||
|         $piggyBank->save(); | ||||
|         $piggyBank->touch(); | ||||
| 
 | ||||
|         return $piggyBank; | ||||
|     } | ||||
| 
 | ||||
| @@ -132,6 +129,7 @@ class PiggyBankFactory | ||||
|             $currency = $this->currencyRepository->find((int) ($data['transaction_currency_id'] ?? 0)); | ||||
|         } | ||||
|         $currency ??= $defaultCurrency; | ||||
| 
 | ||||
|         return $currency; | ||||
|     } | ||||
| 
 | ||||
| @@ -144,12 +142,12 @@ class PiggyBankFactory | ||||
|         } | ||||
|         // first find by ID:
 | ||||
|         if ($piggyBankId > 0) { | ||||
|             $piggyBank = PiggyBank | ||||
|                 ::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id') | ||||
|             $piggyBank = PiggyBank::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id') | ||||
|                 ->leftJoin('accounts', 'accounts.id', '=', 'account_piggy_bank.account_id') | ||||
|                 ->where('accounts.user_id', $this->user->id) | ||||
|                 ->where('piggy_banks.id', $piggyBankId) | ||||
|                 ->first(['piggy_banks.*']); | ||||
|                 ->first(['piggy_banks.*']) | ||||
|             ; | ||||
|             if (null !== $piggyBank) { | ||||
|                 return $piggyBank; | ||||
|             } | ||||
| @@ -169,23 +167,24 @@ class PiggyBankFactory | ||||
| 
 | ||||
|     public function findByName(string $name): ?PiggyBank | ||||
|     { | ||||
|         return PiggyBank | ||||
|             ::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id') | ||||
|         return PiggyBank::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id') | ||||
|             ->leftJoin('accounts', 'accounts.id', '=', 'account_piggy_bank.account_id') | ||||
|             ->where('accounts.user_id', $this->user->id) | ||||
|             ->where('piggy_banks.name', $name) | ||||
|             ->first(['piggy_banks.*']); | ||||
|             ->first(['piggy_banks.*']) | ||||
|         ; | ||||
|     } | ||||
| 
 | ||||
|     private function setOrder(PiggyBank $piggyBank, array $data): PiggyBank | ||||
|     { | ||||
|         $this->resetOrder(); | ||||
|         $order = $this->getMaxOrder() + 1; | ||||
|         $order            = $this->getMaxOrder() + 1; | ||||
|         if (array_key_exists('order', $data)) { | ||||
|             $order = $data['order']; | ||||
|         } | ||||
|         $piggyBank->order = $order; | ||||
|         $piggyBank->saveQuietly(); | ||||
| 
 | ||||
|         return $piggyBank; | ||||
| 
 | ||||
|     } | ||||
| @@ -193,8 +192,7 @@ class PiggyBankFactory | ||||
|     public function resetOrder(): void | ||||
|     { | ||||
|         // TODO duplicate code
 | ||||
|         $set     = PiggyBank | ||||
|             ::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id') | ||||
|         $set     = PiggyBank::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id') | ||||
|             ->leftJoin('accounts', 'accounts.id', '=', 'account_piggy_bank.account_id') | ||||
|             ->where('accounts.user_id', $this->user->id) | ||||
|             ->with( | ||||
| @@ -202,7 +200,8 @@ class PiggyBankFactory | ||||
|                     'objectGroups', | ||||
|                 ] | ||||
|             ) | ||||
|             ->orderBy('piggy_banks.order', 'ASC')->get(['piggy_banks.*']); | ||||
|             ->orderBy('piggy_banks.order', 'ASC')->get(['piggy_banks.*']) | ||||
|         ; | ||||
|         $current = 1; | ||||
|         foreach ($set as $piggyBank) { | ||||
|             if ($piggyBank->order !== $current) { | ||||
| @@ -214,7 +213,6 @@ class PiggyBankFactory | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     private function getMaxOrder(): int | ||||
|     { | ||||
|         return (int) $this->piggyBankRepository->getPiggyBanks()->max('order'); | ||||
|   | ||||
| @@ -32,6 +32,7 @@ use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\BudgetLimit; | ||||
| use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use Psr\Container\ContainerExceptionInterface; | ||||
| use Psr\Container\NotFoundExceptionInterface; | ||||
| use Spatie\Period\Boundaries; | ||||
| @@ -45,20 +46,20 @@ class BudgetLimitHandler | ||||
| { | ||||
|     public function created(Created $event): void | ||||
|     { | ||||
|         app('log')->debug(sprintf('BudgetLimitHandler::created(#%s)', $event->budgetLimit->id)); | ||||
|         Log::debug(sprintf('BudgetLimitHandler::created(#%s)', $event->budgetLimit->id)); | ||||
|         $this->updateAvailableBudget($event->budgetLimit); | ||||
|     } | ||||
| 
 | ||||
|     private function updateAvailableBudget(BudgetLimit $budgetLimit): void | ||||
|     { | ||||
|         app('log')->debug(sprintf('Now in updateAvailableBudget(#%d)', $budgetLimit->id)); | ||||
|         Log::debug(sprintf('Now in updateAvailableBudget(limit #%d)', $budgetLimit->id)); | ||||
|         $budget      = Budget::find($budgetLimit->budget_id); | ||||
|         if (null === $budget) { | ||||
|             app('log')->warning('Budget is null, probably deleted, find deleted version.'); | ||||
|             Log::warning('Budget is null, probably deleted, find deleted version.'); | ||||
|             $budget = Budget::withTrashed()->find($budgetLimit->budget_id); | ||||
|         } | ||||
|         if (null === $budget) { | ||||
|             app('log')->warning('Budget is still null, cannot continue, will delete budget limit.'); | ||||
|             Log::warning('Budget is still null, cannot continue, will delete budget limit.'); | ||||
|             $budgetLimit->forceDelete(); | ||||
| 
 | ||||
|             return; | ||||
| @@ -69,7 +70,7 @@ class BudgetLimitHandler | ||||
| 
 | ||||
|         // sanity check. It happens when the budget has been deleted so the original user is unknown.
 | ||||
|         if (null === $user) { | ||||
|             app('log')->warning('User is null, cannot continue.'); | ||||
|             Log::warning('User is null, cannot continue.'); | ||||
|             $budgetLimit->forceDelete(); | ||||
| 
 | ||||
|             return; | ||||
| @@ -82,7 +83,7 @@ class BudgetLimitHandler | ||||
|         try { | ||||
|             $viewRange = app('preferences')->getForUser($user, 'viewRange', '1M')->data; | ||||
|         } catch (ContainerExceptionInterface|NotFoundExceptionInterface $e) { | ||||
|             app('log')->error($e->getMessage()); | ||||
|             Log::error($e->getMessage()); | ||||
|             $viewRange = '1M'; | ||||
|         } | ||||
|         // safety catch
 | ||||
| @@ -97,7 +98,7 @@ class BudgetLimitHandler | ||||
| 
 | ||||
|         // limit period in total is:
 | ||||
|         $limitPeriod = Period::make($start, $end, precision: Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE()); | ||||
|         app('log')->debug(sprintf('Limit period is from %s to %s', $start->format('Y-m-d'), $end->format('Y-m-d'))); | ||||
|         Log::debug(sprintf('Limit period is from %s to %s', $start->format('Y-m-d'), $end->format('Y-m-d'))); | ||||
| 
 | ||||
|         // from the start until the end of the budget limit, need to loop!
 | ||||
|         $current     = clone $start; | ||||
| @@ -106,16 +107,14 @@ class BudgetLimitHandler | ||||
| 
 | ||||
|             // create or find AB for this particular period, and set the amount accordingly.
 | ||||
|             /** @var null|AvailableBudget $availableBudget */ | ||||
|             $availableBudget = $user->availableBudgets()->where('start_date', $current->format('Y-m-d'))->where( | ||||
|                 'end_date', | ||||
|                 $currentEnd->format('Y-m-d') | ||||
|             )->where('transaction_currency_id', $budgetLimit->transaction_currency_id)->first(); | ||||
|             $availableBudget = $user->availableBudgets()->where('start_date', $current->format('Y-m-d'))->where('end_date', $currentEnd->format('Y-m-d'))->where('transaction_currency_id', $budgetLimit->transaction_currency_id)->first(); | ||||
| 
 | ||||
|             if (null !== $availableBudget) { | ||||
|                 app('log')->debug('Found 1 AB, will update.'); | ||||
|                 Log::debug('Found 1 AB, will update.'); | ||||
|                 $this->calculateAmount($availableBudget); | ||||
|             } | ||||
|             if (null === $availableBudget) { | ||||
|                 Log::debug('No AB found, will create.'); | ||||
|                 // if not exists:
 | ||||
|                 $currentPeriod = Period::make($current, $currentEnd, precision: Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE()); | ||||
|                 $daily         = $this->getDailyAmount($budgetLimit); | ||||
| @@ -126,10 +125,10 @@ class BudgetLimitHandler | ||||
|                     $amount = 0 === $budgetLimit->id ? '0' : $budgetLimit->amount; | ||||
|                 } | ||||
|                 if (0 === bccomp($amount, '0')) { | ||||
|                     app('log')->debug('Amount is zero, will not create AB.'); | ||||
|                     Log::debug('Amount is zero, will not create AB.'); | ||||
|                 } | ||||
|                 if (0 !== bccomp($amount, '0')) { | ||||
|                     app('log')->debug(sprintf('Will create AB for period %s to %s', $current->format('Y-m-d'), $currentEnd->format('Y-m-d'))); | ||||
|                     Log::debug(sprintf('Will create AB for period %s to %s', $current->format('Y-m-d'), $currentEnd->format('Y-m-d'))); | ||||
|                     $availableBudget = new AvailableBudget( | ||||
|                         [ | ||||
|                             'user_id'                 => $user->id, | ||||
| @@ -143,7 +142,8 @@ class BudgetLimitHandler | ||||
|                         ] | ||||
|                     ); | ||||
|                     $availableBudget->save(); | ||||
|                     app('log')->debug(sprintf('ID of new AB is #%d', $availableBudget->id)); | ||||
|                     Log::debug(sprintf('ID of new AB is #%d', $availableBudget->id)); | ||||
|                     $this->calculateAmount($availableBudget); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
| @@ -158,7 +158,7 @@ class BudgetLimitHandler | ||||
|         $repository->setUser($availableBudget->user); | ||||
|         $newAmount               = '0'; | ||||
|         $abPeriod                = Period::make($availableBudget->start_date, $availableBudget->end_date, Precision::DAY()); | ||||
|         app('log')->debug( | ||||
|         Log::debug( | ||||
|             sprintf( | ||||
|                 'Now at AB #%d, ("%s" to "%s")', | ||||
|                 $availableBudget->id, | ||||
| @@ -168,11 +168,11 @@ class BudgetLimitHandler | ||||
|         ); | ||||
|         // have to recalculate everything just in case.
 | ||||
|         $set                     = $repository->getAllBudgetLimitsByCurrency($availableBudget->transactionCurrency, $availableBudget->start_date, $availableBudget->end_date); | ||||
|         app('log')->debug(sprintf('Found %d interesting budget limit(s).', $set->count())); | ||||
|         Log::debug(sprintf('Found %d interesting budget limit(s).', $set->count())); | ||||
| 
 | ||||
|         /** @var BudgetLimit $budgetLimit */ | ||||
|         foreach ($set as $budgetLimit) { | ||||
|             app('log')->debug( | ||||
|             Log::debug( | ||||
|                 sprintf( | ||||
|                     'Found interesting budget limit #%d ("%s" to "%s")', | ||||
|                     $budgetLimit->id, | ||||
| @@ -189,16 +189,16 @@ class BudgetLimitHandler | ||||
|             ); | ||||
|             // if both equal each other, amount from this BL must be added to the AB
 | ||||
|             if ($limitPeriod->equals($abPeriod)) { | ||||
|                 app('log')->debug('This budget limit is equal to the available budget period.'); | ||||
|                 Log::debug('This budget limit is equal to the available budget period.'); | ||||
|                 $newAmount = bcadd($newAmount, $budgetLimit->amount); | ||||
|             } | ||||
|             // if budget limit period is inside AB period, it can be added in full.
 | ||||
|             if (!$limitPeriod->equals($abPeriod) && $abPeriod->contains($limitPeriod)) { | ||||
|                 app('log')->debug('This budget limit is smaller than the available budget period.'); | ||||
|                 Log::debug('This budget limit is smaller than the available budget period.'); | ||||
|                 $newAmount = bcadd($newAmount, $budgetLimit->amount); | ||||
|             } | ||||
|             if (!$limitPeriod->equals($abPeriod) && !$abPeriod->contains($limitPeriod) && $abPeriod->overlapsWith($limitPeriod)) { | ||||
|                 app('log')->debug('This budget limit is something else entirely!'); | ||||
|                 Log::debug('This budget limit is something else entirely!'); | ||||
|                 $overlap = $abPeriod->overlap($limitPeriod); | ||||
|                 if (null !== $overlap) { | ||||
|                     $length    = $overlap->length(); | ||||
| @@ -208,12 +208,12 @@ class BudgetLimitHandler | ||||
|             } | ||||
|         } | ||||
|         if (0 === bccomp('0', $newAmount)) { | ||||
|             app('log')->debug('New amount is zero, deleting AB.'); | ||||
|             Log::debug('New amount is zero, deleting AB.'); | ||||
|             $availableBudget->delete(); | ||||
| 
 | ||||
|             return; | ||||
|         } | ||||
|         app('log')->debug(sprintf('Concluded new amount for this AB must be %s', $newAmount)); | ||||
|         Log::debug(sprintf('Concluded new amount for this AB must be %s', $newAmount)); | ||||
|         $availableBudget->amount = app('steam')->bcround($newAmount, $availableBudget->transactionCurrency->decimal_places); | ||||
|         $availableBudget->save(); | ||||
|     } | ||||
| @@ -231,7 +231,7 @@ class BudgetLimitHandler | ||||
|         ); | ||||
|         $days        = $limitPeriod->length(); | ||||
|         $amount      = bcdiv($budgetLimit->amount, (string) $days, 12); | ||||
|         app('log')->debug( | ||||
|         Log::debug( | ||||
|             sprintf('Total amount for budget limit #%d is %s. Nr. of days is %d. Amount per day is %s', $budgetLimit->id, $budgetLimit->amount, $days, $amount) | ||||
|         ); | ||||
| 
 | ||||
| @@ -240,7 +240,7 @@ class BudgetLimitHandler | ||||
| 
 | ||||
|     public function deleted(Deleted $event): void | ||||
|     { | ||||
|         app('log')->debug(sprintf('BudgetLimitHandler::deleted(#%s)', $event->budgetLimit->id)); | ||||
|         Log::debug(sprintf('BudgetLimitHandler::deleted(#%s)', $event->budgetLimit->id)); | ||||
|         $budgetLimit     = $event->budgetLimit; | ||||
|         $budgetLimit->id = 0; | ||||
|         $this->updateAvailableBudget($event->budgetLimit); | ||||
| @@ -248,7 +248,7 @@ class BudgetLimitHandler | ||||
| 
 | ||||
|     public function updated(Updated $event): void | ||||
|     { | ||||
|         app('log')->debug(sprintf('BudgetLimitHandler::updated(#%s)', $event->budgetLimit->id)); | ||||
|         Log::debug(sprintf('BudgetLimitHandler::updated(#%s)', $event->budgetLimit->id)); | ||||
|         $this->updateAvailableBudget($event->budgetLimit); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -30,7 +30,9 @@ use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\UserGroup; | ||||
| use FireflyIII\Repositories\UserGroups\Budget\BudgetRepositoryInterface; | ||||
| use FireflyIII\Repositories\UserGroups\PiggyBank\PiggyBankRepositoryInterface; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use Illuminate\Database\Query\Builder; | ||||
| use Illuminate\Support\Facades\Artisan; | ||||
| use Illuminate\Support\Facades\DB; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| 
 | ||||
| @@ -57,6 +59,10 @@ class PreferencesEventHandler | ||||
|         $this->resetPiggyBanks($event->userGroup); | ||||
|         $this->resetBudgets($event->userGroup); | ||||
|         $this->resetTransactions($event->userGroup); | ||||
|         // fire laravel command to recalculate them all.
 | ||||
|         if (Amount::convertToNative()) { | ||||
|             Artisan::call('correction:recalculate-native-amounts'); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private function resetPiggyBanks(UserGroup $userGroup): void | ||||
| @@ -130,6 +136,6 @@ class PreferencesEventHandler | ||||
|             }) | ||||
|             ->update(['native_amount' => null, 'native_foreign_amount' => null]) | ||||
|         ; | ||||
|         Log::debug(sprintf('Updated %d transactions.', $success)); | ||||
|         Log::debug(sprintf('Reset %d transactions.', $success)); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -27,6 +27,7 @@ namespace FireflyIII\Handlers\Observer; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use FireflyIII\Support\Http\Api\ExchangeRateConverter; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| 
 | ||||
| @@ -43,6 +44,9 @@ class AccountObserver | ||||
| 
 | ||||
|     private function updateNativeAmount(Account $account): void | ||||
|     { | ||||
|         if (!Amount::convertToNative($account->user)) { | ||||
|             return; | ||||
|         } | ||||
|         $userCurrency = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup); | ||||
|         $repository   = app(AccountRepositoryInterface::class); | ||||
|         $currency     = $repository->getAccountCurrency($account); | ||||
|   | ||||
| @@ -25,6 +25,7 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Handlers\Observer; | ||||
| 
 | ||||
| use FireflyIII\Models\AutoBudget; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use FireflyIII\Support\Http\Api\ExchangeRateConverter; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| 
 | ||||
| @@ -44,6 +45,9 @@ class AutoBudgetObserver | ||||
| 
 | ||||
|     private function updateNativeAmount(AutoBudget $autoBudget): void | ||||
|     { | ||||
|         if (!Amount::convertToNative($autoBudget->budget->user)) { | ||||
|             return; | ||||
|         } | ||||
|         $userCurrency              = app('amount')->getDefaultCurrencyByUserGroup($autoBudget->budget->user->userGroup); | ||||
|         $autoBudget->native_amount = null; | ||||
|         if ($autoBudget->transactionCurrency->id !== $userCurrency->id) { | ||||
|   | ||||
| @@ -25,6 +25,7 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Handlers\Observer; | ||||
| 
 | ||||
| use FireflyIII\Models\AvailableBudget; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use FireflyIII\Support\Http\Api\ExchangeRateConverter; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| 
 | ||||
| @@ -32,18 +33,23 @@ class AvailableBudgetObserver | ||||
| { | ||||
|     public function created(AvailableBudget $availableBudget): void | ||||
|     { | ||||
|         Log::debug('Observe "created" of an available budget.'); | ||||
|         // Log::debug('Observe "created" of an available budget.');
 | ||||
|         $this->updateNativeAmount($availableBudget); | ||||
|     } | ||||
| 
 | ||||
|     public function updated(AvailableBudget $availableBudget): void | ||||
|     { | ||||
|         Log::debug('Observe "updated" of an available budget.'); | ||||
|         // Log::debug('Observe "updated" of an available budget.');
 | ||||
|         $this->updateNativeAmount($availableBudget); | ||||
|     } | ||||
| 
 | ||||
|     private function updateNativeAmount(AvailableBudget $availableBudget): void | ||||
|     { | ||||
|         if (!Amount::convertToNative($availableBudget->user)) { | ||||
|             // Log::debug('Do not update native available amount of the available budget.');
 | ||||
| 
 | ||||
|             return; | ||||
|         } | ||||
|         $userCurrency                   = app('amount')->getDefaultCurrencyByUserGroup($availableBudget->user->userGroup); | ||||
|         $availableBudget->native_amount = null; | ||||
|         if ($availableBudget->transactionCurrency->id !== $userCurrency->id) { | ||||
|   | ||||
| @@ -24,6 +24,7 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Handlers\Observer; | ||||
| 
 | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use FireflyIII\Support\Http\Api\ExchangeRateConverter; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| 
 | ||||
| @@ -55,6 +56,9 @@ class BillObserver | ||||
| 
 | ||||
|     private function updateNativeAmount(Bill $bill): void | ||||
|     { | ||||
|         if (!Amount::convertToNative($bill->user)) { | ||||
|             return; | ||||
|         } | ||||
|         $userCurrency            = app('amount')->getDefaultCurrencyByUserGroup($bill->user->userGroup); | ||||
|         $bill->native_amount_min = null; | ||||
|         $bill->native_amount_max = null; | ||||
|   | ||||
| @@ -25,6 +25,7 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Handlers\Observer; | ||||
| 
 | ||||
| use FireflyIII\Models\BudgetLimit; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use FireflyIII\Support\Http\Api\ExchangeRateConverter; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| 
 | ||||
| @@ -44,6 +45,11 @@ class BudgetLimitObserver | ||||
| 
 | ||||
|     private function updateNativeAmount(BudgetLimit $budgetLimit): void | ||||
|     { | ||||
|         if (!Amount::convertToNative($budgetLimit->budget->user)) { | ||||
|             // Log::debug('Do not update native amount of the budget limit.');
 | ||||
| 
 | ||||
|             return; | ||||
|         } | ||||
|         $userCurrency               = app('amount')->getDefaultCurrencyByUserGroup($budgetLimit->budget->user->userGroup); | ||||
|         $budgetLimit->native_amount = null; | ||||
|         if ($budgetLimit->transactionCurrency->id !== $userCurrency->id) { | ||||
|   | ||||
| @@ -25,6 +25,7 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Handlers\Observer; | ||||
| 
 | ||||
| use FireflyIII\Models\PiggyBankEvent; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use FireflyIII\Support\Http\Api\ExchangeRateConverter; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| 
 | ||||
| @@ -44,6 +45,9 @@ class PiggyBankEventObserver | ||||
| 
 | ||||
|     private function updateNativeAmount(PiggyBankEvent $event): void | ||||
|     { | ||||
|         if (!Amount::convertToNative($event->piggyBank->accounts()->first()->user)) { | ||||
|             return; | ||||
|         } | ||||
|         $userCurrency         = app('amount')->getDefaultCurrencyByUserGroup($event->piggyBank->accounts()->first()->user->userGroup); | ||||
|         $event->native_amount = null; | ||||
|         if ($event->piggyBank->transactionCurrency->id !== $userCurrency->id) { | ||||
|   | ||||
| @@ -78,6 +78,7 @@ class PiggyBankObserver | ||||
|         if ($piggyBank->transactionCurrency->id !== $userCurrency->id) { | ||||
|             $converter                       = new ExchangeRateConverter(); | ||||
|             $converter->setIgnoreSettings(true); | ||||
|             $converter->setUserGroup($group); | ||||
|             $piggyBank->native_target_amount = $converter->convert($piggyBank->transactionCurrency, $userCurrency, today(), $piggyBank->target_amount); | ||||
|         } | ||||
|         $piggyBank->saveQuietly(); | ||||
|   | ||||
| @@ -24,6 +24,7 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Handlers\Observer; | ||||
| 
 | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use FireflyIII\Support\Http\Api\ExchangeRateConverter; | ||||
| use FireflyIII\Support\Models\AccountBalanceCalculator; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| @@ -55,7 +56,7 @@ class TransactionObserver | ||||
| 
 | ||||
|     public function updated(Transaction $transaction): void | ||||
|     { | ||||
|         Log::debug('Observe "updated" of a transaction.'); | ||||
|         //        Log::debug('Observe "updated" of a transaction.');
 | ||||
|         if (config('firefly.feature_flags.running_balance_column') && self::$recalculate) { | ||||
|             if (1 === bccomp($transaction->amount, '0')) { | ||||
|                 Log::debug('Trigger recalculateForJournal'); | ||||
| @@ -67,6 +68,9 @@ class TransactionObserver | ||||
| 
 | ||||
|     private function updateNativeAmount(Transaction $transaction): void | ||||
|     { | ||||
|         if (!Amount::convertToNative($transaction->transactionJournal->user)) { | ||||
|             return; | ||||
|         } | ||||
|         $userCurrency                       = app('amount')->getDefaultCurrencyByUserGroup($transaction->transactionJournal->user->userGroup); | ||||
|         $transaction->native_amount         = null; | ||||
|         $transaction->native_foreign_amount = null; | ||||
|   | ||||
| @@ -66,7 +66,7 @@ class NetWorth implements NetWorthInterface | ||||
|     public function byAccounts(Collection $accounts, Carbon $date): array | ||||
|     { | ||||
|         // start in the past, end in the future? use $date
 | ||||
|         $convertToNative = app('preferences')->get('convert_to_native', false)->data; | ||||
|         $convertToNative = Amount::convertToNative(); | ||||
|         $ids             = implode(',', $accounts->pluck('id')->toArray()); | ||||
|         $cache           = new CacheProperties(); | ||||
|         $cache->addProperty($date); | ||||
|   | ||||
| @@ -76,7 +76,6 @@ class CreateController extends Controller | ||||
|      */ | ||||
|     public function create(Request $request, string $objectType) | ||||
|     { | ||||
|         $defaultCurrency     = app('amount')->getDefaultCurrency(); | ||||
|         $subTitleIcon        = config(sprintf('firefly.subIconsByIdentifier.%s', $objectType)); | ||||
|         $subTitle            = (string) trans(sprintf('firefly.make_new_%s_account', $objectType)); | ||||
|         $roles               = $this->getRoles(); | ||||
| @@ -106,7 +105,7 @@ class CreateController extends Controller | ||||
|         $request->session()->flash( | ||||
|             'preFilled', | ||||
|             [ | ||||
|                 'currency_id'       => $defaultCurrency->id, | ||||
|                 'currency_id'       => $this->defaultCurrency->id, | ||||
|                 'include_net_worth' => $hasOldInput ? (bool) $request->old('include_net_worth') : true, | ||||
|             ] | ||||
|         ); | ||||
|   | ||||
| @@ -90,6 +90,7 @@ class EditController extends Controller | ||||
|         $latitude             = null !== $location ? $location->latitude : config('firefly.default_location.latitude'); | ||||
|         $longitude            = null !== $location ? $location->longitude : config('firefly.default_location.longitude'); | ||||
|         $zoomLevel            = null !== $location ? $location->zoom_level : config('firefly.default_location.zoom_level'); | ||||
|         $canEditCurrency      = 0 === $account->piggyBanks()->count(); | ||||
|         $hasLocation          = null !== $location; | ||||
|         $locations            = [ | ||||
|             'location' => [ | ||||
| @@ -123,7 +124,7 @@ class EditController extends Controller | ||||
|             $openingBalanceAmount = ''; | ||||
|         } | ||||
|         $openingBalanceDate   = $repository->getOpeningBalanceDate($account); | ||||
|         $currency             = $this->repository->getAccountCurrency($account) ?? app('amount')->getDefaultCurrency(); | ||||
|         $currency             = $this->repository->getAccountCurrency($account) ?? $this->defaultCurrency; | ||||
| 
 | ||||
|         // include this account in net-worth charts?
 | ||||
|         $includeNetWorth      = $repository->getMetaValue($account, 'include_net_worth'); | ||||
| @@ -162,7 +163,7 @@ class EditController extends Controller | ||||
| 
 | ||||
|         $request->session()->flash('preFilled', $preFilled); | ||||
| 
 | ||||
|         return view('accounts.edit', compact('account', 'currency', 'showNetWorth', 'subTitle', 'subTitleIcon', 'locations', 'liabilityDirections', 'objectType', 'roles', 'preFilled', 'liabilityTypes', 'interestPeriods')); | ||||
|         return view('accounts.edit', compact('account', 'currency', 'canEditCurrency', 'showNetWorth', 'subTitle', 'subTitleIcon', 'locations', 'liabilityDirections', 'objectType', 'roles', 'preFilled', 'liabilityTypes', 'interestPeriods')); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|   | ||||
| @@ -86,7 +86,7 @@ class ReconcileController extends Controller | ||||
| 
 | ||||
|             return redirect(route('accounts.index', [config(sprintf('firefly.shortNamesByFullName.%s', $account->accountType->type))])); | ||||
|         } | ||||
|         $currency        = $this->accountRepos->getAccountCurrency($account) ?? app('amount')->getDefaultCurrency(); | ||||
|         $currency        = $this->accountRepos->getAccountCurrency($account) ?? $this->defaultCurrency; | ||||
| 
 | ||||
|         // no start or end:
 | ||||
|         $range           = app('navigation')->getViewRange(false); | ||||
| @@ -197,7 +197,7 @@ class ReconcileController extends Controller | ||||
|         } | ||||
| 
 | ||||
|         $reconciliation = $this->accountRepos->getReconciliation($account); | ||||
|         $currency       = $this->accountRepos->getAccountCurrency($account) ?? app('amount')->getDefaultCurrency(); | ||||
|         $currency       = $this->accountRepos->getAccountCurrency($account) ?? $this->defaultCurrency; | ||||
|         $source         = $reconciliation; | ||||
|         $destination    = $account; | ||||
|         if (1 === bccomp($difference, '0')) { | ||||
|   | ||||
| @@ -30,7 +30,6 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use FireflyIII\Support\Facades\Steam; | ||||
| use FireflyIII\Support\Http\Controllers\PeriodOverview; | ||||
| use Illuminate\Contracts\View\Factory; | ||||
| @@ -101,7 +100,7 @@ class ShowController extends Controller | ||||
|         $page             = (int) $request->get('page'); | ||||
|         $pageSize         = (int) app('preferences')->get('listPageSize', 50)->data; | ||||
|         $accountCurrency  = $this->repository->getAccountCurrency($account); | ||||
|         $currency         = $accountCurrency ?? Amount::getDefaultCurrency(); | ||||
|         $currency         = $accountCurrency ?? $this->defaultCurrency; | ||||
|         $fStart           = $start->isoFormat($this->monthAndDayFormat); | ||||
|         $fEnd             = $end->isoFormat($this->monthAndDayFormat); | ||||
|         $subTitle         = (string) trans('firefly.journals_in_period_for_account', ['name' => $account->name, 'start' => $fStart, 'end' => $fEnd]); | ||||
| @@ -178,7 +177,7 @@ class ShowController extends Controller | ||||
|         $subTitleIcon    = config('firefly.subIconsByIdentifier.'.$account->accountType->type); | ||||
|         $page            = (int) $request->get('page'); | ||||
|         $pageSize        = (int) app('preferences')->get('listPageSize', 50)->data; | ||||
|         $currency        = $this->repository->getAccountCurrency($account) ?? Amount::getDefaultCurrency(); | ||||
|         $currency        = $this->repository->getAccountCurrency($account) ?? $this->defaultCurrency; | ||||
|         $subTitle        = (string) trans('firefly.all_journals_for_account', ['name' => $account->name]); | ||||
|         $periods         = new Collection(); | ||||
| 
 | ||||
|   | ||||
| @@ -77,7 +77,7 @@ class CreateController extends Controller | ||||
|             $periods[$current] = (string) trans('firefly.repeat_freq_'.$current); | ||||
|         } | ||||
|         $subTitle        = (string) trans('firefly.create_new_bill'); | ||||
|         $defaultCurrency = app('amount')->getDefaultCurrency(); | ||||
|         $defaultCurrency = $this->defaultCurrency; | ||||
| 
 | ||||
|         // put previous url in session if not redirect from store (not "create another").
 | ||||
|         if (true !== session('bills.create.fromStore')) { | ||||
|   | ||||
| @@ -85,11 +85,10 @@ class EditController extends Controller | ||||
|             $this->rememberPreviousUrl('bills.edit.url'); | ||||
|         } | ||||
| 
 | ||||
|         $currency         = app('amount')->getDefaultCurrency(); | ||||
|         $bill->amount_min = app('steam')->bcround($bill->amount_min, $currency->decimal_places); | ||||
|         $bill->amount_max = app('steam')->bcround($bill->amount_max, $currency->decimal_places); | ||||
|         $bill->amount_min = app('steam')->bcround($bill->amount_min, $bill->transactionCurrency->decimal_places); | ||||
|         $bill->amount_max = app('steam')->bcround($bill->amount_max, $bill->transactionCurrency->decimal_places); | ||||
|         $rules            = $this->repository->getRulesForBill($bill); | ||||
|         $defaultCurrency  = app('amount')->getDefaultCurrency(); | ||||
|         $defaultCurrency  = $this->defaultCurrency; | ||||
| 
 | ||||
|         // code to handle active-checkboxes
 | ||||
|         $hasOldInput      = null !== $request->old('_token'); | ||||
|   | ||||
| @@ -86,11 +86,10 @@ class CreateController extends Controller | ||||
|             'half_year' => (string) trans('firefly.auto_budget_period_half_year'), | ||||
|             'yearly'    => (string) trans('firefly.auto_budget_period_yearly'), | ||||
|         ]; | ||||
|         $currency          = app('amount')->getDefaultCurrency(); | ||||
| 
 | ||||
|         $preFilled         = [ | ||||
|             'auto_budget_period'      => $hasOldInput ? (bool) $request->old('auto_budget_period') : 'monthly', | ||||
|             'auto_budget_currency_id' => $hasOldInput ? (int) $request->old('auto_budget_currency_id') : $currency->id, | ||||
|             'auto_budget_currency_id' => $hasOldInput ? (int) $request->old('auto_budget_currency_id') : $this->defaultCurrency->id, | ||||
|         ]; | ||||
| 
 | ||||
|         $request->session()->flash('preFilled', $preFilled); | ||||
|   | ||||
| @@ -91,10 +91,9 @@ class EditController extends Controller | ||||
| 
 | ||||
|         // code to handle active-checkboxes
 | ||||
|         $hasOldInput       = null !== $request->old('_token'); | ||||
|         $currency          = app('amount')->getDefaultCurrency(); | ||||
|         $preFilled         = [ | ||||
|             'active'                  => $hasOldInput ? (bool) $request->old('active') : $budget->active, | ||||
|             'auto_budget_currency_id' => $hasOldInput ? (int) $request->old('auto_budget_currency_id') : $currency->id, | ||||
|             'auto_budget_currency_id' => $hasOldInput ? (int) $request->old('auto_budget_currency_id') : $this->defaultCurrency->id, | ||||
|         ]; | ||||
|         if (null !== $autoBudget) { | ||||
|             $amount                          = $hasOldInput ? $request->old('auto_budget_amount') : $autoBudget->amount; | ||||
|   | ||||
| @@ -42,6 +42,7 @@ use Illuminate\Contracts\View\Factory; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Collection; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use Illuminate\View\View; | ||||
| 
 | ||||
| /** | ||||
| @@ -106,7 +107,6 @@ class IndexController extends Controller | ||||
|             $end   ??= session('end', today(config('app.timezone'))->endOfMonth()); | ||||
|         } | ||||
| 
 | ||||
|         $defaultCurrency  = app('amount')->getDefaultCurrency(); | ||||
|         $currencies       = $this->currencyRepository->get(); | ||||
|         $budgeted         = '0'; | ||||
|         $spent            = '0'; | ||||
| @@ -119,14 +119,14 @@ class IndexController extends Controller | ||||
|         // get all available budgets:
 | ||||
|         $availableBudgets = $this->getAllAvailableBudgets($start, $end); | ||||
|         // get all active budgets:
 | ||||
|         $budgets          = $this->getAllBudgets($start, $end, $currencies, $defaultCurrency); | ||||
|         $budgets          = $this->getAllBudgets($start, $end, $currencies, $this->defaultCurrency); | ||||
|         $sums             = $this->getSums($budgets); | ||||
| 
 | ||||
|         // get budgeted for default currency:
 | ||||
|         if (0 === count($availableBudgets)) { | ||||
|             $budgeted = $this->blRepository->budgeted($start, $end, $defaultCurrency); | ||||
|             $spentArr = $this->opsRepository->sumExpenses($start, $end, null, null, $defaultCurrency); | ||||
|             $spent    = $spentArr[$defaultCurrency->id]['sum'] ?? '0'; | ||||
|             $budgeted = $this->blRepository->budgeted($start, $end, $this->defaultCurrency); | ||||
|             $spentArr = $this->opsRepository->sumExpenses($start, $end, null, null, $this->defaultCurrency); | ||||
|             $spent    = $spentArr[$this->defaultCurrency->id]['sum'] ?? '0'; | ||||
|             unset($spentArr); | ||||
|         } | ||||
| 
 | ||||
| @@ -136,6 +136,7 @@ class IndexController extends Controller | ||||
| 
 | ||||
|         // get all inactive budgets, and simply list them:
 | ||||
|         $inactive         = $this->repository->getInactiveBudgets(); | ||||
|         $defaultCurrency  = $this->defaultCurrency; | ||||
| 
 | ||||
|         return view( | ||||
|             'budgets.index', | ||||
| @@ -162,6 +163,7 @@ class IndexController extends Controller | ||||
| 
 | ||||
|     private function getAllAvailableBudgets(Carbon $start, Carbon $end): array | ||||
|     { | ||||
|         Log::debug(sprintf('Start of getAllAvailableBudgets("%s", "%s")', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s'))); | ||||
|         $converter        = new ExchangeRateConverter(); | ||||
|         // get all available budgets.
 | ||||
|         $ab               = $this->abRepository->get($start, $end); | ||||
|   | ||||
| @@ -103,7 +103,6 @@ class AccountController extends Controller | ||||
|         $currencies    = []; | ||||
|         $chartData     = []; | ||||
|         $tempData      = []; | ||||
|         $default       = Amount::getDefaultCurrency(); | ||||
| 
 | ||||
|         // grab all accounts and names
 | ||||
|         $accounts      = $this->accountRepository->getAccountsByType([AccountTypeEnum::EXPENSE->value]); | ||||
| @@ -138,13 +137,13 @@ class AccountController extends Controller | ||||
| 
 | ||||
|                     continue; | ||||
|                 } | ||||
|                 Log::debug(sprintf('Will process expense array "%s" with amount %s', $key, $endBalance)); | ||||
|                 $searchCode   = $this->convertToNative ? $default->code : $key; | ||||
|                 Log::debug(sprintf('Search code is %s', $searchCode)); | ||||
|                 // Log::debug(sprintf('Will process expense array "%s" with amount %s', $key, $endBalance));
 | ||||
|                 $searchCode   = $this->convertToNative ? $this->defaultCurrency->code : $key; | ||||
|                 // Log::debug(sprintf('Search code is %s', $searchCode));
 | ||||
|                 // see if there is an accompanying start amount.
 | ||||
|                 // grab the difference and find the currency.
 | ||||
|                 $startBalance = ($startBalances[$account->id][$key] ?? '0'); | ||||
|                 Log::debug(sprintf('Start balance is %s', $startBalance)); | ||||
|                 //                Log::debug(sprintf('Start balance is %s', $startBalance));
 | ||||
|                 $diff         = bcsub($endBalance, $startBalance); | ||||
|                 $currencies[$searchCode] ??= $this->currencyRepository->findByCode($searchCode); | ||||
|                 if (0 !== bccomp($diff, '0')) { | ||||
| @@ -562,7 +561,6 @@ class AccountController extends Controller | ||||
|         $currencies    = []; | ||||
|         $chartData     = []; | ||||
|         $tempData      = []; | ||||
|         $default       = Amount::getDefaultCurrency(); | ||||
| 
 | ||||
|         // grab all accounts and names
 | ||||
|         $accounts      = $this->accountRepository->getAccountsByType([AccountTypeEnum::REVENUE->value]); | ||||
| @@ -598,13 +596,13 @@ class AccountController extends Controller | ||||
| 
 | ||||
|                     continue; | ||||
|                 } | ||||
|                 Log::debug(sprintf('Will process expense array "%s" with amount %s', $key, $endBalance)); | ||||
|                 $searchCode   = $this->convertToNative ? $default->code : $key; | ||||
|                 Log::debug(sprintf('Search code is %s', $searchCode)); | ||||
|                 // Log::debug(sprintf('Will process expense array "%s" with amount %s', $key, $endBalance));
 | ||||
|                 $searchCode   = $this->convertToNative ? $this->defaultCurrency->code : $key; | ||||
|                 // Log::debug(sprintf('Search code is %s', $searchCode));
 | ||||
|                 // see if there is an accompanying start amount.
 | ||||
|                 // grab the difference and find the currency.
 | ||||
|                 $startBalance = ($startBalances[$account->id][$key] ?? '0'); | ||||
|                 Log::debug(sprintf('Start balance is %s', $startBalance)); | ||||
|                 // Log::debug(sprintf('Start balance is %s', $startBalance));
 | ||||
|                 $diff         = bcsub($endBalance, $startBalance); | ||||
|                 $currencies[$searchCode] ??= $this->currencyRepository->findByCode($searchCode); | ||||
|                 if (0 !== bccomp($diff, '0')) { | ||||
|   | ||||
| @@ -234,8 +234,12 @@ class BudgetController extends Controller | ||||
|             $key                    = sprintf('%d-%d', $journal['source_account_id'], $journal['currency_id']); | ||||
|             $amount                 = $journal['amount']; | ||||
| 
 | ||||
|             $symbol                 = $journal['currency_symbol']; | ||||
|             $code                   = $journal['currency_code']; | ||||
|             $name                   = $journal['currency_name']; | ||||
| 
 | ||||
|             // if convert to native, use the native things, unless it's the foreign amount which is in the native currency.
 | ||||
|             if ($this->convertToNative && $journal['currency_id'] !== $this->defaultCurrency->id && $journal['foreign_currency_id'] !== $this->defaultCurrency->id) { | ||||
|             if ($this->convertToNative && $journal['currency_id'] !== $this->defaultCurrency->id) { | ||||
|                 $key    = sprintf('%d-%d', $journal['source_account_id'], $this->defaultCurrency->id); | ||||
|                 $symbol = $this->defaultCurrency->symbol; | ||||
|                 $code   = $this->defaultCurrency->code; | ||||
| @@ -243,11 +247,7 @@ class BudgetController extends Controller | ||||
|                 $amount = $journal['native_amount']; | ||||
|             } | ||||
| 
 | ||||
|             if ($this->convertToNative && $journal['currency_id'] !== $this->defaultCurrency->id && $journal['foreign_currency_id'] === $this->defaultCurrency->id) { | ||||
|                 $key    = sprintf('%d-%d', $journal['source_account_id'], $this->defaultCurrency->id); | ||||
|                 $symbol = $this->defaultCurrency->symbol; | ||||
|                 $code   = $this->defaultCurrency->code; | ||||
|                 $name   = $this->defaultCurrency->name; | ||||
|             if ($journal['foreign_currency_id'] === $this->defaultCurrency->id) { | ||||
|                 $amount = $journal['foreign_amount']; | ||||
|             } | ||||
| 
 | ||||
| @@ -465,7 +465,7 @@ class BudgetController extends Controller | ||||
|         $chartGenerator->setStart($start); | ||||
|         $chartGenerator->setEnd($end); | ||||
|         $chartGenerator->convertToNative = $this->convertToNative; | ||||
|         $chartGenerator->default         = Amount::getDefaultCurrency(); | ||||
|         $chartGenerator->default         = $this->defaultCurrency; | ||||
| 
 | ||||
|         $chartData                       = $chartGenerator->generate(); | ||||
|         $data                            = $this->generator->multiSet($chartData); | ||||
|   | ||||
| @@ -197,11 +197,11 @@ class CategoryController extends Controller | ||||
| 
 | ||||
|             $chartData[$inKey] | ||||
|                           = [ | ||||
|                     'label'           => sprintf('%s (%s)', (string) trans('firefly.earned'), $currencyInfo['currency_name']), | ||||
|                     'entries'         => [], | ||||
|                     'type'            => 'bar', | ||||
|                     'backgroundColor' => 'rgba(0, 141, 76, 0.5)', // green
 | ||||
|                 ]; | ||||
|                               'label'           => sprintf('%s (%s)', (string) trans('firefly.earned'), $currencyInfo['currency_name']), | ||||
|                               'entries'         => [], | ||||
|                               'type'            => 'bar', | ||||
|                               'backgroundColor' => 'rgba(0, 141, 76, 0.5)', // green
 | ||||
|                           ]; | ||||
|             // loop empty periods:
 | ||||
|             foreach (array_keys($periods) as $period) { | ||||
|                 $label                                 = $periods[$period]; | ||||
|   | ||||
| @@ -24,6 +24,7 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Http\Controllers; | ||||
| 
 | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use FireflyIII\Support\Facades\Steam; | ||||
| use FireflyIII\Support\Http\Controllers\RequestInformation; | ||||
| use FireflyIII\Support\Http\Controllers\UserNavigation; | ||||
| @@ -117,11 +118,11 @@ abstract class Controller extends BaseController | ||||
|                 $this->defaultCurrency   =null; | ||||
|                 // get shown-intro-preference:
 | ||||
|                 if (auth()->check()) { | ||||
|                     $this->defaultCurrency   = app('amount')->getDefaultCurrency(); | ||||
|                     $this->defaultCurrency   = Amount::getDefaultCurrency(); | ||||
|                     $language  = Steam::getLanguage(); | ||||
|                     $locale    = Steam::getLocale(); | ||||
|                     $darkMode  = app('preferences')->get('darkMode', 'browser')->data; | ||||
|                     $this->convertToNative =app('preferences')->get('convert_to_native', false)->data; | ||||
|                     $this->convertToNative =Amount::convertToNative(); | ||||
|                     $page      = $this->getPageName(); | ||||
|                     $shownDemo = $this->hasSeenDemo(); | ||||
|                     View::share('language', $language); | ||||
|   | ||||
| @@ -160,8 +160,8 @@ class DebugController extends Controller | ||||
|         Artisan::call('view:clear'); | ||||
| 
 | ||||
|         // also do some recalculations.
 | ||||
|         Artisan::call('firefly-iii:trigger-credit-recalculation'); | ||||
|         AccountBalanceCalculator::recalculateAll(true); | ||||
|         Artisan::call('correction:recalculates-liabilities'); | ||||
|         AccountBalanceCalculator::recalculateAll(false); | ||||
| 
 | ||||
|         try { | ||||
|             Artisan::call('twig:clean'); | ||||
|   | ||||
| @@ -27,6 +27,7 @@ namespace FireflyIII\Http\Controllers\ExchangeRates; | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use Illuminate\View\View; | ||||
| use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; | ||||
| 
 | ||||
| class IndexController extends Controller | ||||
| { | ||||
| @@ -46,6 +47,9 @@ class IndexController extends Controller | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|         if (!config('cer.enabled')) { | ||||
|             throw new NotFoundHttpException(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public function index(): View | ||||
|   | ||||
| @@ -78,8 +78,7 @@ class BoxController extends Controller | ||||
|         $incomes   = []; | ||||
|         $expenses  = []; | ||||
|         $sums      = []; | ||||
|         $currency  = app('amount')->getDefaultCurrency(); | ||||
| 
 | ||||
|         $currency  = $this->defaultCurrency; | ||||
| 
 | ||||
|         // collect income of user:
 | ||||
|         /** @var GroupCollectorInterface $collector */ | ||||
| @@ -91,7 +90,7 @@ class BoxController extends Controller | ||||
| 
 | ||||
|         /** @var array $journal */ | ||||
|         foreach ($set as $journal) { | ||||
|             $currencyId           = $this->convertToNative ? $currency->id : (int) $journal['currency_id']; | ||||
|             $currencyId           = $this->convertToNative && $this->defaultCurrency->id !== (int) $journal['currency_id'] ? $this->defaultCurrency->id : (int) $journal['currency_id']; | ||||
|             $amount               = Amount::getAmountFromJournal($journal); | ||||
|             $incomes[$currencyId] ??= '0'; | ||||
|             $incomes[$currencyId] = bcadd($incomes[$currencyId], app('steam')->positive($amount)); | ||||
| @@ -109,7 +108,7 @@ class BoxController extends Controller | ||||
| 
 | ||||
|         /** @var array $journal */ | ||||
|         foreach ($set as $journal) { | ||||
|             $currencyId            = $this->convertToNative ? $currency->id : (int) $journal['currency_id']; | ||||
|             $currencyId            = $this->convertToNative ? $this->defaultCurrency->id : (int) $journal['currency_id']; | ||||
|             $amount                = Amount::getAmountFromJournal($journal); | ||||
|             $expenses[$currencyId] ??= '0'; | ||||
|             $expenses[$currencyId] = bcadd($expenses[$currencyId], $amount); | ||||
| @@ -126,10 +125,10 @@ class BoxController extends Controller | ||||
|             $expenses[$currencyId] = app('amount')->formatAnything($currency, $expenses[$currencyId] ?? '0', false); | ||||
|         } | ||||
|         if (0 === count($sums)) { | ||||
|             $currency                = app('amount')->getDefaultCurrency(); | ||||
|             $sums[$currency->id]     = app('amount')->formatAnything($currency, '0', false); | ||||
|             $incomes[$currency->id]  = app('amount')->formatAnything($currency, '0', false); | ||||
|             $expenses[$currency->id] = app('amount')->formatAnything($currency, '0', false); | ||||
|             $currency                             = $this->defaultCurrency; | ||||
|             $sums[$this->defaultCurrency->id]     = app('amount')->formatAnything($this->defaultCurrency, '0', false); | ||||
|             $incomes[$this->defaultCurrency->id]  = app('amount')->formatAnything($this->defaultCurrency, '0', false); | ||||
|             $expenses[$this->defaultCurrency->id] = app('amount')->formatAnything($this->defaultCurrency, '0', false); | ||||
|         } | ||||
| 
 | ||||
|         $response  = [ | ||||
|   | ||||
| @@ -73,7 +73,7 @@ class ReconcileController extends Controller | ||||
|     { | ||||
|         $startBalance    = $request->get('startBalance'); | ||||
|         $endBalance      = $request->get('endBalance'); | ||||
|         $accountCurrency = $this->accountRepos->getAccountCurrency($account) ?? app('amount')->getDefaultCurrency(); | ||||
|         $accountCurrency = $this->accountRepos->getAccountCurrency($account) ?? $this->defaultCurrency; | ||||
|         $amount          = '0'; | ||||
|         $clearedAmount   = '0'; | ||||
| 
 | ||||
| @@ -193,7 +193,7 @@ class ReconcileController extends Controller | ||||
|         $startDate->subDay(); | ||||
|         $end->endOfDay(); | ||||
| 
 | ||||
|         $currency       = $this->accountRepos->getAccountCurrency($account) ?? app('amount')->getDefaultCurrency(); | ||||
|         $currency       = $this->accountRepos->getAccountCurrency($account) ?? $this->defaultCurrency; | ||||
|         $startBalance   = Steam::finalAccountBalance($account, $startDate)['balance']; | ||||
|         $endBalance     = Steam::finalAccountBalance($account, $end)['balance']; | ||||
| 
 | ||||
|   | ||||
| @@ -23,6 +23,7 @@ declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\Http\Controllers; | ||||
| 
 | ||||
| use FireflyIII\Events\Preferences\UserGroupChangedDefaultCurrency; | ||||
| use FireflyIII\Events\Test\UserTestNotificationChannel; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Http\Requests\PreferencesRequest; | ||||
| @@ -35,6 +36,7 @@ use Illuminate\Contracts\View\Factory; | ||||
| use Illuminate\Http\RedirectResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Routing\Redirector; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use Illuminate\View\View; | ||||
| 
 | ||||
| /** | ||||
| @@ -258,6 +260,11 @@ class PreferencesController extends Controller | ||||
| 
 | ||||
|         // convert native
 | ||||
|         $convertToNative   = 1 === (int) $request->get('convertToNative'); | ||||
|         if ($convertToNative && !$this->convertToNative) { | ||||
|             // set to true!
 | ||||
|             Log::debug('User sets convertToNative to true.'); | ||||
|             event(new UserGroupChangedDefaultCurrency(auth()->user()->userGroup)); | ||||
|         } | ||||
|         app('preferences')->set('convert_to_native', $convertToNative); | ||||
| 
 | ||||
|         // custom fiscal year
 | ||||
|   | ||||
| @@ -84,7 +84,7 @@ class CreateController extends Controller | ||||
|     { | ||||
|         $budgets           = app('expandedform')->makeSelectListWithEmpty($this->budgetRepos->getActiveBudgets()); | ||||
|         $bills             = app('expandedform')->makeSelectListWithEmpty($this->billRepository->getActiveBills()); | ||||
|         $defaultCurrency   = app('amount')->getDefaultCurrency(); | ||||
|         $defaultCurrency   = $this->defaultCurrency; | ||||
|         $tomorrow          = today(config('app.timezone')); | ||||
|         $oldRepetitionType = $request->old('repetition_type'); | ||||
|         $tomorrow->addDay(); | ||||
| @@ -129,7 +129,7 @@ class CreateController extends Controller | ||||
|     { | ||||
|         $budgets           = app('expandedform')->makeSelectListWithEmpty($this->budgetRepos->getActiveBudgets()); | ||||
|         $bills             = app('expandedform')->makeSelectListWithEmpty($this->billRepository->getActiveBills()); | ||||
|         $defaultCurrency   = app('amount')->getDefaultCurrency(); | ||||
|         $defaultCurrency   = $this->defaultCurrency; | ||||
|         $tomorrow          = today(config('app.timezone')); | ||||
|         $oldRepetitionType = $request->old('repetition_type'); | ||||
|         $tomorrow->addDay(); | ||||
|   | ||||
| @@ -62,8 +62,6 @@ class InstallController extends Controller | ||||
|             'migrate'                            => ['--seed' => true, '--force' => true], | ||||
|             'generate-keys'                      => [], // an exception :(
 | ||||
|             'firefly-iii:upgrade-database'       => [], | ||||
|             'firefly-iii:correct-database'       => [], | ||||
|             'firefly-iii:report-integrity'       => [], | ||||
|             'firefly-iii:set-latest-version'     => ['--james-is-cool' => true], | ||||
|             'firefly-iii:verify-security-alerts' => [], | ||||
|         ]; | ||||
|   | ||||
| @@ -216,15 +216,14 @@ class ConvertController extends Controller | ||||
|     private function getLiabilities(): array | ||||
|     { | ||||
|         // make repositories
 | ||||
|         $accountList     = $this->accountRepository->getActiveAccountsByType([AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE]); | ||||
|         $defaultCurrency = app('amount')->getDefaultCurrency(); | ||||
|         $grouped         = []; | ||||
|         $accountList = $this->accountRepository->getActiveAccountsByType([AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE]); | ||||
|         $grouped     = []; | ||||
| 
 | ||||
|         // group accounts:
 | ||||
|         /** @var Account $account */ | ||||
|         foreach ($accountList as $account) { | ||||
|             $balance                     = Steam::finalAccountBalance($account, today()->endOfDay())['balance']; | ||||
|             $currency                    = $this->accountRepository->getAccountCurrency($account) ?? $defaultCurrency; | ||||
|             $currency                    = $this->accountRepository->getAccountCurrency($account) ?? $this->defaultCurrency; | ||||
|             $role                        = 'l_'.$account->accountType->type; | ||||
|             $key                         = (string) trans('firefly.opt_group_'.$role); | ||||
|             $grouped[$key][$account->id] = $account->name.' ('.app('amount')->formatAnything($currency, $balance, false).')'; | ||||
| @@ -239,15 +238,14 @@ class ConvertController extends Controller | ||||
|     private function getAssetAccounts(): array | ||||
|     { | ||||
|         // make repositories
 | ||||
|         $accountList     = $this->accountRepository->getActiveAccountsByType([AccountType::ASSET]); | ||||
|         $defaultCurrency = app('amount')->getDefaultCurrency(); | ||||
|         $grouped         = []; | ||||
|         $accountList = $this->accountRepository->getActiveAccountsByType([AccountType::ASSET]); | ||||
|         $grouped     = []; | ||||
| 
 | ||||
|         // group accounts:
 | ||||
|         /** @var Account $account */ | ||||
|         foreach ($accountList as $account) { | ||||
|             $balance                     = Steam::finalAccountBalance($account, today()->endOfDay())['balance']; | ||||
|             $currency                    = $this->accountRepository->getAccountCurrency($account) ?? $defaultCurrency; | ||||
|             $currency                    = $this->accountRepository->getAccountCurrency($account) ?? $this->defaultCurrency; | ||||
|             $role                        = (string) $this->accountRepository->getMetaValue($account, 'account_role'); | ||||
|             if ('' === $role) { | ||||
|                 $role = 'no_account_type'; | ||||
|   | ||||
| @@ -114,7 +114,7 @@ class CreateController extends Controller | ||||
|         $optionalFields             = app('preferences')->get('transaction_journal_optional_fields', [])->data; | ||||
|         $allowedOpposingTypes       = config('firefly.allowed_opposing_types'); | ||||
|         $accountToTypes             = config('firefly.account_to_transaction'); | ||||
|         $defaultCurrency            = app('amount')->getDefaultCurrency(); | ||||
|         $defaultCurrency            = $this->defaultCurrency; | ||||
|         $previousUrl                = $this->rememberPreviousUrl('transactions.create.url'); | ||||
|         $parts                      = parse_url($previousUrl); | ||||
|         $search                     = sprintf('?%s', $parts['query'] ?? ''); | ||||
|   | ||||
| @@ -82,7 +82,7 @@ class EditController extends Controller | ||||
|         $title                      = $transactionGroup->transactionJournals()->count() > 1 ? $transactionGroup->title : $transactionGroup->transactionJournals()->first()->description; | ||||
|         $subTitle                   = (string) trans('firefly.edit_transaction_title', ['description' => $title]); | ||||
|         $subTitleIcon               = 'fa-plus'; | ||||
|         $defaultCurrency            = app('amount')->getDefaultCurrency(); | ||||
|         $defaultCurrency            = $this->defaultCurrency; | ||||
|         $cash                       = $repository->getCashAccount(); | ||||
|         $previousUrl                = $this->rememberPreviousUrl('transactions.edit.url'); | ||||
|         $parts                      = parse_url($previousUrl); | ||||
|   | ||||
| @@ -25,6 +25,7 @@ namespace FireflyIII\Http\Middleware; | ||||
| 
 | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Repositories\Journal\JournalRepositoryInterface; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use FireflyIII\Support\Http\Controllers\RequestInformation; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| @@ -108,7 +109,7 @@ class Range | ||||
|         setlocale(LC_TIME, $localeArray); | ||||
|         $moneyResult       = setlocale(LC_MONETARY, $localeArray); | ||||
| 
 | ||||
|         // send error to view, if could not set money format
 | ||||
|         // send error to view, if it could not set money format
 | ||||
|         if (false === $moneyResult) { | ||||
|             app('log')->error('Could not set locale. The following array doesnt work: ', $localeArray); | ||||
|             app('view')->share('invalidMonetaryLocale', true); | ||||
| @@ -117,7 +118,7 @@ class Range | ||||
|         // save some formats:
 | ||||
|         $monthAndDayFormat = (string) trans('config.month_and_day_js', [], $locale); | ||||
|         $dateTimeFormat    = (string) trans('config.date_time_js', [], $locale); | ||||
|         $defaultCurrency   = app('amount')->getDefaultCurrency(); | ||||
|         $defaultCurrency   = Amount::getDefaultCurrency(); | ||||
| 
 | ||||
|         // also format for moment JS:
 | ||||
|         $madMomentJS       = (string) trans('config.month_and_day_moment_js', [], $locale); | ||||
|   | ||||
| @@ -26,6 +26,7 @@ namespace FireflyIII\Http\Requests; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Rules\IsValidPositiveAmount; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use FireflyIII\Support\Request\ChecksLogin; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| @@ -125,7 +126,7 @@ class PiggyBankStoreRequest extends FormRequest | ||||
|         $currencyId = (int) ($data['transaction_currency_id'] ?? 0); | ||||
|         $currency   = TransactionCurrency::find($currencyId); | ||||
|         if (null === $currency) { | ||||
|             return app('amount')->getDefaultCurrency(); | ||||
|             return Amount::getDefaultCurrency(); | ||||
|         } | ||||
| 
 | ||||
|         return $currency; | ||||
|   | ||||
| @@ -27,6 +27,7 @@ use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Rules\IsValidPositiveAmount; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use FireflyIII\Support\Request\ChecksLogin; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| @@ -128,7 +129,7 @@ class PiggyBankUpdateRequest extends FormRequest | ||||
|         $currencyId = (int) ($data['transaction_currency_id'] ?? 0); | ||||
|         $currency   = TransactionCurrency::find($currencyId); | ||||
|         if (null === $currency) { | ||||
|             return app('amount')->getDefaultCurrency(); | ||||
|             return Amount::getDefaultCurrency(); | ||||
|         } | ||||
| 
 | ||||
|         return $currency; | ||||
|   | ||||
| @@ -1,54 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| /* | ||||
|  * IsValidFilter.php | ||||
|  * Copyright (c) 2024 james@firefly-iii.org. | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see https://www.gnu.org/licenses/. | ||||
|  */ | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\JsonApi\Rules; | ||||
| 
 | ||||
| use Illuminate\Contracts\Validation\ValidationRule; | ||||
| 
 | ||||
| class IsValidFilter implements ValidationRule | ||||
| { | ||||
|     private array $allowed; | ||||
| 
 | ||||
|     public function __construct(array $keys) | ||||
|     { | ||||
|         $this->allowed   = $keys; | ||||
|         $this->allowed[] = 'user_group_id'; | ||||
|     } | ||||
| 
 | ||||
|     #[\Override]
 | ||||
|     public function validate(string $attribute, mixed $value, \Closure $fail): void | ||||
|     { | ||||
|         if ('filter' !== $attribute) { | ||||
|             $fail('validation.bad_api_filter')->translate(); | ||||
|         } | ||||
|         if (!is_array($value)) { | ||||
|             $value = explode(',', $value); | ||||
|         } | ||||
|         foreach ($value as $key => $val) { | ||||
|             if (!in_array($key, $this->allowed, true)) { | ||||
|                 $fail('validation.bad_api_filter')->translate(['filter' => $key]); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,53 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| /* | ||||
|  * IsValidFilter.php | ||||
|  * Copyright (c) 2024 james@firefly-iii.org. | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see https://www.gnu.org/licenses/. | ||||
|  */ | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\JsonApi\Rules; | ||||
| 
 | ||||
| use Illuminate\Contracts\Validation\ValidationRule; | ||||
| 
 | ||||
| class IsValidPage implements ValidationRule | ||||
| { | ||||
|     private array $allowed; | ||||
| 
 | ||||
|     public function __construct(array $keys) | ||||
|     { | ||||
|         $this->allowed = $keys; | ||||
|     } | ||||
| 
 | ||||
|     #[\Override]
 | ||||
|     public function validate(string $attribute, mixed $value, \Closure $fail): void | ||||
|     { | ||||
|         if ('page' !== $attribute) { | ||||
|             $fail('validation.bad_api_filter')->translate(); | ||||
|         } | ||||
|         if (!is_array($value)) { | ||||
|             $value = explode(',', $value); | ||||
|         } | ||||
|         foreach ($value as $key => $val) { | ||||
|             if (!in_array($key, $this->allowed, true)) { | ||||
|                 $fail('validation.bad_api_page')->translate(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,46 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| /* | ||||
|  * AccountBalanceRepository.php | ||||
|  * Copyright (c) 2024 james@firefly-iii.org. | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see https://www.gnu.org/licenses/. | ||||
|  */ | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\JsonApi\V2\AccountBalances; | ||||
| 
 | ||||
| use FireflyIII\Entities\AccountBalance; | ||||
| use LaravelJsonApi\Contracts\Store\QueriesAll; | ||||
| use LaravelJsonApi\NonEloquent\AbstractRepository; | ||||
| 
 | ||||
| class AccountBalanceRepository extends AbstractRepository implements QueriesAll | ||||
| { | ||||
|     #[\Override]
 | ||||
|     public function find(string $resourceId): ?object | ||||
|     { | ||||
|         return AccountBalance::fromArray(); | ||||
|     } | ||||
| 
 | ||||
|     public function queryAll(): Capabilities\AccountBalanceQuery | ||||
|     { | ||||
|         return Capabilities\AccountBalanceQuery::make() | ||||
|             ->withServer($this->server) | ||||
|             ->withSchema($this->schema) | ||||
|         ; | ||||
|     } | ||||
| } | ||||
| @@ -1,44 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\JsonApi\V2\AccountBalances; | ||||
| 
 | ||||
| use Illuminate\Http\Request; | ||||
| use LaravelJsonApi\Core\Resources\JsonApiResource; | ||||
| 
 | ||||
| class AccountBalanceResource extends JsonApiResource | ||||
| { | ||||
|     /** | ||||
|      * Get the resource's attributes. | ||||
|      * | ||||
|      * @param null|Request $request | ||||
|      */ | ||||
|     public function attributes($request): iterable | ||||
|     { | ||||
|         return [ | ||||
|             'name'   => $this->resource->amount, | ||||
|             'amount' => $this->resource->amount, | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get the resource id. | ||||
|      */ | ||||
|     public function id(): string | ||||
|     { | ||||
|         return $this->resource->id; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get the resource's relationships. | ||||
|      * | ||||
|      * @param null|Request $request | ||||
|      */ | ||||
|     public function relationships($request): iterable | ||||
|     { | ||||
|         return [ | ||||
|             $this->relation('account')->withData($this->resource->getAccount()), | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| @@ -1,50 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\JsonApi\V2\AccountBalances; | ||||
| 
 | ||||
| use FireflyIII\Entities\AccountBalance; | ||||
| use LaravelJsonApi\Core\Schema\Schema; | ||||
| use LaravelJsonApi\Eloquent\Fields\Relations\HasOne; | ||||
| use LaravelJsonApi\NonEloquent\Fields\Attribute; | ||||
| use LaravelJsonApi\NonEloquent\Fields\ID; | ||||
| 
 | ||||
| class AccountBalanceSchema extends Schema | ||||
| { | ||||
|     /** | ||||
|      * The model the schema corresponds to. | ||||
|      */ | ||||
|     public static string $model = AccountBalance::class; | ||||
| 
 | ||||
|     /** | ||||
|      * Get the resource fields. | ||||
|      */ | ||||
|     public function fields(): array | ||||
|     { | ||||
|         return [ | ||||
|             ID::make(), | ||||
|             Attribute::make('name'), | ||||
|             Attribute::make('amount'), | ||||
|             HasOne::make('account'), | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get the resource filters. | ||||
|      */ | ||||
|     public function filters(): array | ||||
|     { | ||||
|         return [ | ||||
|             // Filter::make('id'),
 | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     public function repository(): AccountBalanceRepository | ||||
|     { | ||||
|         return AccountBalanceRepository::make() | ||||
|             ->withServer($this->server) | ||||
|             ->withSchema($this) | ||||
|         ; | ||||
|     } | ||||
| } | ||||
| @@ -1,59 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| /* | ||||
|  * AccountBalanceQuery.php | ||||
|  * Copyright (c) 2024 james@firefly-iii.org. | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see https://www.gnu.org/licenses/. | ||||
|  */ | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\JsonApi\V2\AccountBalances\Capabilities; | ||||
| 
 | ||||
| use FireflyIII\Entities\AccountBalance; | ||||
| use FireflyIII\Models\Account; | ||||
| use LaravelJsonApi\NonEloquent\Capabilities\QueryAll; | ||||
| 
 | ||||
| class AccountBalanceQuery extends QueryAll | ||||
| { | ||||
|     private Account $account; | ||||
| 
 | ||||
|     /** | ||||
|      * QuerySites constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|     } | ||||
| 
 | ||||
|     public function get(): iterable | ||||
|     { | ||||
|         return [ | ||||
|             AccountBalance::fromArray(), | ||||
|             AccountBalance::fromArray(), | ||||
|             AccountBalance::fromArray(), | ||||
|             AccountBalance::fromArray(), | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     public function withAccount(Account $account): self | ||||
|     { | ||||
|         $this->account = $account; | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| } | ||||
| @@ -1,77 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\JsonApi\V2\Accounts; | ||||
| 
 | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Rules\Account\IsValidAccountType; | ||||
| use FireflyIII\Rules\IsAllowedGroupAction; | ||||
| use FireflyIII\Rules\IsDateOrTime; | ||||
| use FireflyIII\Rules\IsValidDateRange; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use LaravelJsonApi\Laravel\Http\Requests\ResourceQuery; | ||||
| use LaravelJsonApi\Validation\Rule as JsonApiRule; | ||||
| 
 | ||||
| class AccountCollectionQuery extends ResourceQuery | ||||
| { | ||||
|     /** | ||||
|      * Get the validation rules that apply to the request query parameters. | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         Log::debug(__METHOD__); | ||||
|         $validFilters = config('api.valid_api_filters')[Account::class]; | ||||
| 
 | ||||
|         return [ | ||||
|             'fields'      => [ | ||||
|                 'nullable', | ||||
|                 'array', | ||||
|                 JsonApiRule::fieldSets(), | ||||
|             ], | ||||
|             'userGroupId' => [ | ||||
|                 'nullable', | ||||
|                 'integer', | ||||
|                 new IsAllowedGroupAction(Account::class, request()->method()), | ||||
|             ], | ||||
|             'startPeriod' => [ | ||||
|                 'nullable', | ||||
|                 'date', | ||||
|                 new IsDateOrTime(), | ||||
|                 new IsValidDateRange(), | ||||
|             ], | ||||
|             'endPeriod'   => [ | ||||
|                 'nullable', | ||||
|                 'date', | ||||
|                 new IsDateOrTime(), | ||||
|                 new IsValidDateRange(), | ||||
|             ], | ||||
|             'filter'      => [ | ||||
|                 'nullable', | ||||
|                 'array', | ||||
|                 JsonApiRule::filter($validFilters), | ||||
|                 new IsValidAccountType(), | ||||
|             ], | ||||
|             'include'     => [ | ||||
|                 'nullable', | ||||
|                 'string', | ||||
|                 JsonApiRule::includePaths(), | ||||
|             ], | ||||
|             'page'        => [ | ||||
|                 'nullable', | ||||
|                 'array', | ||||
|                 JsonApiRule::page(), | ||||
|             ], | ||||
|             'sort'        => [ | ||||
|                 'nullable', | ||||
|                 'string', | ||||
|                 JsonApiRule::sort(), | ||||
|             ], | ||||
|             'withCount'   => [ | ||||
|                 'nullable', | ||||
|                 'string', | ||||
|                 JsonApiRule::countable(), | ||||
|             ], | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| @@ -1,113 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| /* | ||||
|  * AccountRepository.php | ||||
|  * Copyright (c) 2024 james@firefly-iii.org. | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see https://www.gnu.org/licenses/. | ||||
|  */ | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\JsonApi\V2\Accounts; | ||||
| 
 | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Support\JsonApi\Concerns\UsergroupAware; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use LaravelJsonApi\Contracts\Store\CreatesResources; | ||||
| use LaravelJsonApi\Contracts\Store\QueriesAll; | ||||
| use LaravelJsonApi\NonEloquent\AbstractRepository; | ||||
| use LaravelJsonApi\NonEloquent\Capabilities\CrudRelations; | ||||
| use LaravelJsonApi\NonEloquent\Concerns\HasCrudCapability; | ||||
| use LaravelJsonApi\NonEloquent\Concerns\HasRelationsCapability; | ||||
| 
 | ||||
| /** | ||||
|  * Class AccountRepository | ||||
|  * | ||||
|  * The repository collects a single or many (account) objects from the database and returns them to the | ||||
|  * account resource. The account resource links all account properties to the JSON properties. | ||||
|  * | ||||
|  * For the queryAll thing, a separate query is constructed that does the actual querying of the database. | ||||
|  * This is necessary because the user can't just query all accounts (it would return other user's data) | ||||
|  * and because we also need to collect all kinds of metadata, like the currency and user info. | ||||
|  */ | ||||
| class AccountRepository extends AbstractRepository implements QueriesAll, CreatesResources | ||||
| { | ||||
|     use HasCrudCapability; | ||||
|     use HasRelationsCapability; | ||||
|     use UsergroupAware; | ||||
| 
 | ||||
|     /** | ||||
|      * SiteRepository constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         Log::debug(__METHOD__); | ||||
|     } | ||||
| 
 | ||||
|     public function exists(string $resourceId): bool | ||||
|     { | ||||
|         $result = null !== Account::find((int) $resourceId); | ||||
|         Log::debug(sprintf('%s: %s', __METHOD__, var_export($result, true))); | ||||
| 
 | ||||
|         return $result; | ||||
|     } | ||||
| 
 | ||||
|     public function find(string $resourceId): ?object | ||||
|     { | ||||
|         exit(__METHOD__); | ||||
|         Log::debug(__METHOD__); | ||||
|         //        throw new \RuntimeException('trace me');
 | ||||
|         $account    = Account::find((int) $resourceId); | ||||
|         if (null === $account) { | ||||
|             return null; | ||||
|         } | ||||
|         // enrich the collected data
 | ||||
|         $enrichment = new AccountEnrichment(); | ||||
| 
 | ||||
|         return $enrichment->enrichSingle($account); | ||||
|     } | ||||
| 
 | ||||
|     public function queryAll(): Capabilities\AccountQuery | ||||
|     { | ||||
|         Log::debug(__METHOD__); | ||||
| 
 | ||||
|         return Capabilities\AccountQuery::make() | ||||
|             ->withUserGroup($this->userGroup) | ||||
|             ->withServer($this->server) | ||||
|             ->withSchema($this->schema) | ||||
|         ; | ||||
|     } | ||||
| 
 | ||||
|     protected function crud(): Capabilities\CrudAccount | ||||
|     { | ||||
|         Log::debug(__METHOD__); | ||||
| 
 | ||||
|         return Capabilities\CrudAccount::make(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * TODO piggy banks | ||||
|      * TODO transactions | ||||
|      */ | ||||
|     protected function relations(): CrudRelations | ||||
|     { | ||||
|         Log::debug(__METHOD__); | ||||
| 
 | ||||
|         return Capabilities\CrudAccountRelations::make(); | ||||
|     } | ||||
| } | ||||
| @@ -1,53 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\JsonApi\V2\Accounts; | ||||
| 
 | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use LaravelJsonApi\Laravel\Http\Requests\ResourceRequest; | ||||
| 
 | ||||
| class AccountRequest extends ResourceRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
| 
 | ||||
|     /** | ||||
|      * Get the validation rules for the resource. | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         Log::debug(__METHOD__); | ||||
|         $accountRoles   = implode(',', config('firefly.accountRoles')); | ||||
|         $ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes'))); | ||||
|         $types          = implode(',', array_keys(config('firefly.subTitlesByIdentifier'))); | ||||
|         $type           = $this->convertString('type'); | ||||
|         // var_dump($types);exit;
 | ||||
| 
 | ||||
|         return [ | ||||
|             'name'         => ['required', 'max:1024', 'min:1'], // , new IsUniqueAccount()
 | ||||
|             'account_type' => ['required', 'max:1024', 'min:1', sprintf('in:%s', $types)], | ||||
|             //            'iban'                 => ['iban', 'nullable', new UniqueIban(null, $type)],
 | ||||
|             //            'bic'                  => 'bic|nullable',
 | ||||
|             //            'account_number'       => ['min:1', 'max:255', 'nullable', new UniqueAccountNumber(null, $type)],
 | ||||
|             //            'opening_balance'      => 'numeric|required_with:opening_balance_date|nullable',
 | ||||
|             //            'opening_balance_date' => 'date|required_with:opening_balance|nullable',
 | ||||
|             //            'virtual_balance'      => 'numeric|nullable',
 | ||||
|             //            'order'                => 'numeric|nullable',
 | ||||
|             //            'currency_id'          => 'numeric|exists:transaction_currencies,id',
 | ||||
|             //            'currency_code'        => 'min:3|max:3|exists:transaction_currencies,code',
 | ||||
|             //            'active'               => [new IsBoolean()],
 | ||||
|             //            'include_net_worth'    => [new IsBoolean()],
 | ||||
|             //            'account_role'         => sprintf('nullable|in:%s|required_if:type,asset', $accountRoles),
 | ||||
|             //            'credit_card_type'     => sprintf('nullable|in:%s|required_if:account_role,ccAsset', $ccPaymentTypes),
 | ||||
|             //            'monthly_payment_date' => 'nullable|date|required_if:account_role,ccAsset|required_if:credit_card_type,monthlyFull',
 | ||||
|             //            'liability_type'       => 'nullable|required_if:type,liability|required_if:type,liabilities|in:loan,debt,mortgage',
 | ||||
|             //            'liability_amount'     => ['required_with:liability_start_date', new IsValidPositiveAmount()],
 | ||||
|             //            'liability_start_date' => 'required_with:liability_amount|date',
 | ||||
|             //            'liability_direction'  => 'nullable|required_if:type,liability|required_if:type,liabilities|in:credit,debit',
 | ||||
|             //            'interest'             => 'min:0|max:100|numeric',
 | ||||
|             //            'interest_period'      => sprintf('nullable|in:%s', implode(',', config('firefly.interest_periods'))),
 | ||||
|             //            'notes'                => 'min:0|max:32768',
 | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| @@ -1,83 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\JsonApi\V2\Accounts; | ||||
| 
 | ||||
| use FireflyIII\Models\Account; | ||||
| use Illuminate\Http\Request; | ||||
| use LaravelJsonApi\Core\Resources\JsonApiResource; | ||||
| 
 | ||||
| /** | ||||
|  * @property Account $resource | ||||
|  */ | ||||
| class AccountResource extends JsonApiResource | ||||
| { | ||||
|     /** | ||||
|      * Get the resource's attributes. | ||||
|      * | ||||
|      * @param null|Request $request | ||||
|      */ | ||||
|     public function attributes($request): iterable | ||||
|     { | ||||
|         // Log::debug(__METHOD__);
 | ||||
| 
 | ||||
|         return [ | ||||
|             'created_at'              => $this->resource->created_at, | ||||
|             'updated_at'              => $this->resource->updated_at, | ||||
|             'name'                    => $this->resource->name, | ||||
|             'active'                  => $this->resource->active, | ||||
|             'order'                   => $this->resource->order, | ||||
|             'iban'                    => $this->resource->iban, | ||||
|             'account_type'            => $this->resource->account_type_string, | ||||
|             'account_role'            => $this->resource->account_role, | ||||
|             'account_number'          => '' === $this->resource->account_number ? null : $this->resource->account_number, | ||||
| 
 | ||||
|             // currency (if the account has a currency setting, otherwise NULL).
 | ||||
|             'currency_id'             => $this->resource->currency_id, | ||||
|             'currency_name'           => $this->resource->currency_name, | ||||
|             'currency_code'           => $this->resource->currency_code, | ||||
|             'currency_symbol'         => $this->resource->currency_symbol, | ||||
|             'currency_decimal_places' => $this->resource->currency_decimal_places, | ||||
|             'is_multi_currency'       => '1' === $this->resource->is_multi_currency, | ||||
| 
 | ||||
|             // balances
 | ||||
|             'balance'                 => $this->resource->balance, | ||||
|             'native_balance'          => $this->resource->native_balance, | ||||
| 
 | ||||
|             // liability things
 | ||||
|             'liability_direction'     => $this->resource->liability_direction, | ||||
|             'interest'                => $this->resource->interest, | ||||
|             'interest_period'         => $this->resource->interest_period, | ||||
|             'current_debt'            => $this->resource->current_debt, // TODO may be removed in the future.
 | ||||
| 
 | ||||
|             // other things
 | ||||
|             'last_activity'           => $this->resource->last_activity, | ||||
| 
 | ||||
|             // object group
 | ||||
|             'object_group_id'         => $this->resource->object_group_id, | ||||
|             'object_group_title'      => $this->resource->object_group_title, | ||||
|             'object_group_order'      => $this->resource->object_group_order, | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get the resource id. | ||||
|      */ | ||||
|     public function id(): string | ||||
|     { | ||||
|         return (string) $this->resource->id; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get the resource's relationships. | ||||
|      * | ||||
|      * @param null|Request $request | ||||
|      */ | ||||
|     public function relationships($request): iterable | ||||
|     { | ||||
|         return [ | ||||
|             $this->relation('user')->withData($this->resource->user), | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| @@ -1,115 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\JsonApi\V2\Accounts; | ||||
| 
 | ||||
| use FireflyIII\Models\Account; | ||||
| use Illuminate\Http\Request; | ||||
| use LaravelJsonApi\Core\Resources\JsonApiResource; | ||||
| 
 | ||||
| /** | ||||
|  * @property Account $resource | ||||
|  * | ||||
|  * This class collects the resources attributes, the account in this case. | ||||
|  * Generally speaking, each property here is directly related to a property on the account object itself. | ||||
|  * However, many properties are collected from other sources, like the user or the currency. | ||||
|  * As a result, the account repository is where it's at, which is where the collection takes place and is optimised. | ||||
|  */ | ||||
| class AccountResourceOld extends JsonApiResource | ||||
| { | ||||
|     /** | ||||
|      * Get the resource's attributes. | ||||
|      * | ||||
|      * @param null|Request $request | ||||
|      */ | ||||
|     public function attributes($request): iterable | ||||
|     { | ||||
|         // fields removed here have been migrated.
 | ||||
|         return [ | ||||
|             'created_at' => $this->resource->created_at, | ||||
|             'updated_at' => $this->resource->updated_at, | ||||
|             'name'       => $this->resource->name, | ||||
| 
 | ||||
|             //            'virtual_balance' => $this->resource->virtual_balance,
 | ||||
|             //            'native_balance'  => $this->resource->native_balance,
 | ||||
|             // 'user' => $this->resource->user_array,
 | ||||
|             //            'balances' => []
 | ||||
|             //
 | ||||
| 
 | ||||
|             // balance (in currency, on date)
 | ||||
|             //            'current_balance'         => $this->resource->current_balance,
 | ||||
|             //            'current_balance'         => app('steam')->bcround(app('steam')->balance($account, $date), $decimalPlaces),
 | ||||
|             //            'current_balance_date'    => $date->toAtomString(),
 | ||||
| 
 | ||||
|             //            'notes'                   => $this->repository->getNoteText($account),
 | ||||
|             //            'monthly_payment_date'    => $monthlyPaymentDate,
 | ||||
|             //            'credit_card_type'        => $creditCardType,
 | ||||
|             //            'account_number'          => $this->repository->getMetaValue($account, 'account_number'),
 | ||||
|             //            'bic'                     => $this->repository->getMetaValue($account, 'BIC'),
 | ||||
|             //            'opening_balance'         => $openingBalance,
 | ||||
|             //            'opening_balance_date'    => $openingBalanceDate,
 | ||||
|             //            'liability_type'          => $liabilityType,
 | ||||
|             //            'liability_direction'     => $liabilityDirection,
 | ||||
|             //            'interest'                => $interest,
 | ||||
|             //            'interest_period'         => $interestPeriod,
 | ||||
|             //            'current_debt'            => $this->repository->getMetaValue($account, 'current_debt'),
 | ||||
|             //            'include_net_worth'       => $includeNetWorth,
 | ||||
|             //            'longitude'               => $longitude,
 | ||||
|             //            'latitude'                => $latitude,
 | ||||
|             //            'zoom_level'              => $zoomLevel,
 | ||||
| 
 | ||||
|             //            'order'                          => $order,
 | ||||
| 
 | ||||
|             //            'native_currency_id'             => (string) $this->default->id,
 | ||||
|             //            'native_currency_code'           => $this->default->code,
 | ||||
|             //            'native_currency_symbol'         => $this->default->symbol,
 | ||||
|             //            'native_currency_decimal_places' => $this->default->decimal_places,
 | ||||
|             //
 | ||||
|             //            // balance:
 | ||||
|             //            'current_balance'                => $balance,
 | ||||
|             //            'native_current_balance'         => $nativeBalance,
 | ||||
|             //            'current_balance_date'           => $this->getDate()->endOfDay()->toAtomString(),
 | ||||
|             //
 | ||||
|             //            // balance difference
 | ||||
|             //            'balance_difference'             => $balanceDiff,
 | ||||
|             //            'native_balance_difference'      => $nativeBalanceDiff,
 | ||||
|             //            'balance_difference_start'       => $diffStart,
 | ||||
|             //            'balance_difference_end'         => $diffEnd,
 | ||||
|             //
 | ||||
|             //
 | ||||
|             //            // liability stuff
 | ||||
|             //            'liability_type'                 => $liabilityType,
 | ||||
|             //
 | ||||
|             //            // object group
 | ||||
|             //            'object_group_id'                => null !== $objectGroupId ? (string) $objectGroupId : null,
 | ||||
|             //            'object_group_order'             => $objectGroupOrder,
 | ||||
|             //            'object_group_title'             => $objectGroupTitle,
 | ||||
|             //            'notes'                   => $this->repository->getNoteText($account),
 | ||||
|             //            'monthly_payment_date'    => $monthlyPaymentDate,
 | ||||
|             //            'credit_card_type'        => $creditCardType,
 | ||||
|             //            'bic'                     => $this->repository->getMetaValue($account, 'BIC'),
 | ||||
|             //            'virtual_balance'         => number_format((float) $account->virtual_balance, $decimalPlaces, '.', ''),
 | ||||
|             //            'opening_balance'         => $openingBalance,
 | ||||
|             //            'opening_balance_date'    => $openingBalanceDate,
 | ||||
|             //            'include_net_worth'       => $includeNetWorth,
 | ||||
|             //            'longitude'               => $longitude,
 | ||||
|             //            'latitude'                => $latitude,
 | ||||
|             //            'zoom_level'              => $zoomLevel,
 | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get the resource's relationships. | ||||
|      * | ||||
|      * @param null|Request $request | ||||
|      */ | ||||
|     public function relationships($request): iterable | ||||
|     { | ||||
|         return [ | ||||
|             $this->relation('user')->withData($this->resource->user), | ||||
|             $this->relation('currency')->withData($this->resource->transactionCurrency), | ||||
|             // $this->relation('account_balances')->withData($this->resource->balances),
 | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| @@ -1,112 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\JsonApi\V2\Accounts; | ||||
| 
 | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Support\JsonApi\Concerns\UsergroupAware; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use LaravelJsonApi\Core\Schema\Schema; | ||||
| use LaravelJsonApi\Eloquent\Fields\Relations\HasOne; | ||||
| use LaravelJsonApi\NonEloquent\Fields\Attribute; | ||||
| use LaravelJsonApi\NonEloquent\Fields\ID; | ||||
| use LaravelJsonApi\NonEloquent\Filters\Filter; | ||||
| use LaravelJsonApi\NonEloquent\Pagination\EnumerablePagination; | ||||
| 
 | ||||
| class AccountSchema extends Schema | ||||
| { | ||||
|     use UsergroupAware; | ||||
| 
 | ||||
|     /** | ||||
|      * The model the schema corresponds to. | ||||
|      */ | ||||
|     public static string $model = Account::class; | ||||
| 
 | ||||
|     /** | ||||
|      * Get the resource fields. | ||||
|      */ | ||||
|     public function fields(): array | ||||
|     { | ||||
|         return [ | ||||
|             ID::make(), | ||||
|             Attribute::make('created_at'), | ||||
|             Attribute::make('updated_at'), | ||||
| 
 | ||||
|             // basic info and meta data
 | ||||
|             Attribute::make('name')->sortable(), | ||||
|             Attribute::make('active')->sortable(), | ||||
|             Attribute::make('order')->sortable(), | ||||
|             Attribute::make('iban')->sortable(), | ||||
|             Attribute::make('account_type'), | ||||
|             Attribute::make('account_role'), | ||||
|             Attribute::make('account_number')->sortable(), | ||||
| 
 | ||||
|             // currency
 | ||||
|             Attribute::make('currency_id'), | ||||
|             Attribute::make('currency_name'), | ||||
|             Attribute::make('currency_code'), | ||||
|             Attribute::make('currency_symbol'), | ||||
|             Attribute::make('currency_decimal_places'), | ||||
|             Attribute::make('is_multi_currency'), | ||||
| 
 | ||||
|             // balance
 | ||||
|             Attribute::make('balance')->sortable(), | ||||
|             Attribute::make('native_balance')->sortable(), | ||||
| 
 | ||||
|             // liability things
 | ||||
|             Attribute::make('liability_direction'), | ||||
|             Attribute::make('interest'), | ||||
|             Attribute::make('interest_period'), | ||||
|             // Attribute::make('current_debt')->sortable(),
 | ||||
| 
 | ||||
|             // TODO credit card fields.
 | ||||
| 
 | ||||
|             // dynamic data
 | ||||
|             Attribute::make('last_activity')->sortable(), | ||||
|             Attribute::make('balance_difference')->sortable(), // only used for sort.
 | ||||
| 
 | ||||
|             // group
 | ||||
|             Attribute::make('object_group_id'), | ||||
|             Attribute::make('object_group_title'), | ||||
|             Attribute::make('object_group_order'), | ||||
| 
 | ||||
|             // relations.
 | ||||
|             HasOne::make('user')->readOnly(), | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get the resource filters. | ||||
|      */ | ||||
|     public function filters(): array | ||||
|     { | ||||
|         Log::debug(__METHOD__); | ||||
|         $array  = []; | ||||
|         $config = config('api.valid_api_filters')[Account::class]; | ||||
|         foreach ($config as $entry) { | ||||
|             $array[] = Filter::make($entry); | ||||
|         } | ||||
| 
 | ||||
|         return $array; | ||||
|     } | ||||
| 
 | ||||
|     public function pagination(): EnumerablePagination | ||||
|     { | ||||
|         Log::debug(__METHOD__); | ||||
| 
 | ||||
|         return EnumerablePagination::make(); | ||||
|     } | ||||
| 
 | ||||
|     public function repository(): AccountRepository | ||||
|     { | ||||
|         Log::debug(__METHOD__); | ||||
|         $this->setUserGroup($this->server->getUsergroup()); | ||||
| 
 | ||||
|         return AccountRepository::make() | ||||
|             ->withServer($this->server) | ||||
|             ->withSchema($this) | ||||
|             ->withUserGroup($this->userGroup) | ||||
|         ; | ||||
|     } | ||||
| } | ||||
| @@ -1,69 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\JsonApi\V2\Accounts; | ||||
| 
 | ||||
| use FireflyIII\Models\Account; | ||||
| use LaravelJsonApi\Eloquent\Contracts\Paginator; | ||||
| use LaravelJsonApi\Eloquent\Fields\DateTime; | ||||
| use LaravelJsonApi\Eloquent\Fields\ID; | ||||
| use LaravelJsonApi\Eloquent\Fields\Relations\HasOne; | ||||
| use LaravelJsonApi\Eloquent\Fields\Str; | ||||
| use LaravelJsonApi\Eloquent\Filters\WhereIdIn; | ||||
| use LaravelJsonApi\Eloquent\Pagination\PagePagination; | ||||
| use LaravelJsonApi\Eloquent\Schema; | ||||
| 
 | ||||
| /** | ||||
|  * Class AccountSchema | ||||
|  * | ||||
|  * This is the schema of all fields that an account exposes to the world. | ||||
|  * Fields do not have to have a relation to the actual model. | ||||
|  * Fields mentioned here still need to be filled in by the AccountResource. | ||||
|  */ | ||||
| class AccountSchemaOld extends Schema | ||||
| { | ||||
|     /** | ||||
|      * The model the schema corresponds to. | ||||
|      */ | ||||
|     public static string $model = Account::class; | ||||
| 
 | ||||
|     /** | ||||
|      * Get the resource fields. | ||||
|      */ | ||||
|     public function fields(): array | ||||
|     { | ||||
|         return [ | ||||
|             ID::make(), | ||||
|             DateTime::make('created_at')->sortable()->readOnly(), | ||||
|             DateTime::make('updated_at')->sortable()->readOnly(), | ||||
|             Str::make('name')->sortable(), | ||||
|             //            Str::make('account_type'),
 | ||||
|             //            Str::make('virtual_balance'),
 | ||||
|             //            Str::make('iban'),
 | ||||
|             //            Boolean::make('active'),
 | ||||
|             //            Number::make('order'),
 | ||||
|             HasOne::make('user')->readOnly(), | ||||
|             // HasMany::make('account_balances'),
 | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Filters mentioned here can be used to filter the results. | ||||
|      * TODO write down exactly how this works. | ||||
|      */ | ||||
|     public function filters(): array | ||||
|     { | ||||
|         return [ | ||||
|             WhereIdIn::make($this), | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get the resource paginator. | ||||
|      */ | ||||
|     public function pagination(): ?Paginator | ||||
|     { | ||||
|         return PagePagination::make(); | ||||
|     } | ||||
| } | ||||
| @@ -1,45 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\JsonApi\V2\Accounts; | ||||
| 
 | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use LaravelJsonApi\Laravel\Http\Requests\ResourceQuery; | ||||
| use LaravelJsonApi\Validation\Rule as JsonApiRule; | ||||
| 
 | ||||
| class AccountSingleQuery extends ResourceQuery | ||||
| { | ||||
|     /** | ||||
|      * Get the validation rules that apply to the request query parameters. | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         Log::debug(__METHOD__); | ||||
| 
 | ||||
|         return [ | ||||
|             'fields'    => [ | ||||
|                 'nullable', | ||||
|                 'array', | ||||
|                 JsonApiRule::fieldSets(), | ||||
|             ], | ||||
|             'filter'    => [ | ||||
|                 'nullable', | ||||
|                 'array', | ||||
|                 JsonApiRule::filter()->forget('id'), | ||||
|             ], | ||||
|             'include'   => [ | ||||
|                 'nullable', | ||||
|                 'string', | ||||
|                 JsonApiRule::includePaths(), | ||||
|             ], | ||||
|             'page'      => JsonApiRule::notSupported(), | ||||
|             'sort'      => JsonApiRule::notSupported(), | ||||
|             'withCount' => [ | ||||
|                 'nullable', | ||||
|                 'string', | ||||
|                 JsonApiRule::countable(), | ||||
|             ], | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| @@ -1,142 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| /* | ||||
|  * AccountQuery.php | ||||
|  * Copyright (c) 2024 james@firefly-iii.org. | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see https://www.gnu.org/licenses/. | ||||
|  */ | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\JsonApi\V2\Accounts\Capabilities; | ||||
| 
 | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Support\Http\Api\AccountFilter; | ||||
| use FireflyIII\Support\JsonApi\CollectsCustomParameters; | ||||
| use FireflyIII\Support\JsonApi\Concerns\UsergroupAware; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment; | ||||
| use FireflyIII\Support\JsonApi\ExpandsQuery; | ||||
| use FireflyIII\Support\JsonApi\FiltersPagination; | ||||
| use FireflyIII\Support\JsonApi\SortsCollection; | ||||
| use FireflyIII\Support\JsonApi\SortsQueryResults; | ||||
| use FireflyIII\Support\JsonApi\ValidateSortParameters; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use LaravelJsonApi\Contracts\Pagination\Page; | ||||
| use LaravelJsonApi\Contracts\Store\HasPagination; | ||||
| use LaravelJsonApi\NonEloquent\Capabilities\QueryAll; | ||||
| 
 | ||||
| class AccountQuery extends QueryAll implements HasPagination | ||||
| { | ||||
|     use AccountFilter; | ||||
|     use CollectsCustomParameters; | ||||
|     use ExpandsQuery; | ||||
|     use FiltersPagination; | ||||
|     use SortsCollection; | ||||
|     use SortsQueryResults; | ||||
|     use UsergroupAware; | ||||
|     use ValidateSortParameters; | ||||
| 
 | ||||
|     // use PaginatesEnumerables;
 | ||||
| 
 | ||||
|     #[\Override]
 | ||||
|     /** | ||||
|      * This method returns all accounts, given a bunch of filters and sort fields, together with pagination. | ||||
|      * | ||||
|      * It is only used on the index, and nowhere else. | ||||
|      */ | ||||
|     public function get(): iterable | ||||
|     { | ||||
|         Log::debug(__METHOD__); | ||||
|         // collect sort options
 | ||||
|         $sort        = $this->queryParameters->sortFields(); | ||||
| 
 | ||||
|         // collect pagination based on the page
 | ||||
|         $pagination  = $this->filtersPagination($this->queryParameters->page()); | ||||
| 
 | ||||
|         // check if we need all accounts, regardless of pagination
 | ||||
|         // This is necessary when the user wants to sort on specific params.
 | ||||
|         $needsAll    = $this->needsFullDataset(Account::class, $sort); | ||||
| 
 | ||||
|         // params that were not recognised, may be my own custom stuff.
 | ||||
|         $otherParams = $this->getOtherParams($this->queryParameters->unrecognisedParameters()); | ||||
| 
 | ||||
|         // start the query
 | ||||
|         $query       = $this->userGroup->accounts(); | ||||
| 
 | ||||
|         // add sort and filter parameters to the query.
 | ||||
|         $query       = $this->addSortParams(Account::class, $query, $sort); | ||||
|         $query       = $this->addFilterParams(Account::class, $query, $this->queryParameters->filter()); | ||||
| 
 | ||||
|         // collect the result.
 | ||||
|         $collection  = $query->get(['accounts.*']); | ||||
|         // sort the data after the query, and return it right away.
 | ||||
|         $collection  = $this->sortCollection(Account::class, $collection, $sort); | ||||
| 
 | ||||
|         // if the entire collection needs to be enriched and sorted, do so now:
 | ||||
|         $totalCount  = $collection->count(); | ||||
|         Log::debug(sprintf('Total is %d', $totalCount)); | ||||
|         if ($needsAll) { | ||||
|             Log::debug('Needs the entire collection'); | ||||
|             // enrich the entire collection
 | ||||
|             $enrichment  = new AccountEnrichment(); | ||||
|             $enrichment->setStart($otherParams['start'] ?? null); | ||||
|             $enrichment->setEnd($otherParams['end'] ?? null); | ||||
|             $collection  = $enrichment->enrich($collection); | ||||
| 
 | ||||
|             // TODO sort the set based on post-query sort options:
 | ||||
|             $collection  = $this->postQuerySort(Account::class, $collection, $sort); | ||||
| 
 | ||||
|             // take the current page from the enriched set.
 | ||||
|             $currentPage = $collection->skip(($pagination['number'] - 1) * $pagination['size'])->take($pagination['size']); | ||||
|         } | ||||
|         if (!$needsAll) { | ||||
|             Log::debug('Needs only partial collection'); | ||||
|             // take from the collection the filtered page + page number:
 | ||||
|             $currentPage = $collection->skip(($pagination['number'] - 1) * $pagination['size'])->take($pagination['size']); | ||||
| 
 | ||||
|             // enrich only the current page.
 | ||||
|             $enrichment  = new AccountEnrichment(); | ||||
|             $enrichment->setStart($otherParams['start'] ?? null); | ||||
|             $enrichment->setEnd($otherParams['end'] ?? null); | ||||
|             $currentPage = $enrichment->enrich($currentPage); | ||||
|         } | ||||
|         // get current page?
 | ||||
|         Log::debug(sprintf('Skip %d, take %d', ($pagination['number'] - 1) * $pagination['size'], $pagination['size'])); | ||||
|         // $currentPage = $collection->skip(($pagination['number'] - 1) * $pagination['size'])->take($pagination['size']);
 | ||||
|         Log::debug(sprintf('New collection size: %d', $currentPage->count())); | ||||
| 
 | ||||
|         // TODO add filters after the query, if there are filters that cannot be applied to the database
 | ||||
|         // TODO same for sort things.
 | ||||
| 
 | ||||
|         return new LengthAwarePaginator($currentPage, $totalCount, $pagination['size'], $pagination['number']); | ||||
|     } | ||||
| 
 | ||||
|     #[\Override]
 | ||||
|     public function getOrPaginate(?array $page): iterable | ||||
|     { | ||||
|         exit('here weare'); | ||||
|         // TODO: Implement getOrPaginate() method.
 | ||||
|     } | ||||
| 
 | ||||
|     #[\Override]
 | ||||
|     public function paginate(array $page): Page | ||||
|     { | ||||
|         exit('here weare'); | ||||
|         // TODO: Implement paginate() method.
 | ||||
|     } | ||||
| } | ||||
| @@ -1,61 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| /* | ||||
|  * CrudAccount.php | ||||
|  * Copyright (c) 2024 james@firefly-iii.org. | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see https://www.gnu.org/licenses/. | ||||
|  */ | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\JsonApi\V2\Accounts\Capabilities; | ||||
| 
 | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Support\JsonApi\CollectsCustomParameters; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use LaravelJsonApi\NonEloquent\Capabilities\CrudResource; | ||||
| 
 | ||||
| class CrudAccount extends CrudResource | ||||
| { | ||||
|     use CollectsCustomParameters; | ||||
| 
 | ||||
|     public function create(array $validatedData): Account | ||||
|     { | ||||
|         var_dump($validatedData); | ||||
| 
 | ||||
|         exit; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Read the supplied site. | ||||
|      */ | ||||
|     public function read(Account $account): ?Account | ||||
|     { | ||||
|         $otherParams = $this->getOtherParams($this->request->query->all()); | ||||
| 
 | ||||
|         Log::debug(__METHOD__); | ||||
|         // enrich the collected data
 | ||||
|         $enrichment  = new AccountEnrichment(); | ||||
| 
 | ||||
|         // set start and date, if present.
 | ||||
|         $enrichment->setStart($otherParams['start'] ?? null); | ||||
|         $enrichment->setEnd($otherParams['end'] ?? null); | ||||
| 
 | ||||
|         return $enrichment->enrichSingle($account); | ||||
|     } | ||||
| } | ||||
| @@ -1,29 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| /* | ||||
|  * CrudAccountRelations.php | ||||
|  * Copyright (c) 2024 james@firefly-iii.org. | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see https://www.gnu.org/licenses/. | ||||
|  */ | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\JsonApi\V2\Accounts\Capabilities; | ||||
| 
 | ||||
| use LaravelJsonApi\NonEloquent\Capabilities\CrudRelations; | ||||
| 
 | ||||
| class CrudAccountRelations extends CrudRelations {} | ||||
| @@ -1,53 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\JsonApi\V2; | ||||
| 
 | ||||
| use FireflyIII\JsonApi\V2\Accounts\AccountSchema; | ||||
| use FireflyIII\JsonApi\V2\Users\UserSchema; | ||||
| use FireflyIII\Support\JsonApi\Concerns\UsergroupAware; | ||||
| use FireflyIII\Support\JsonApi\Concerns\UserGroupDetectable; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use LaravelJsonApi\Core\Server\Server as BaseServer; | ||||
| 
 | ||||
| /** | ||||
|  * Class Server | ||||
|  * | ||||
|  * This class serves as a generic class for the v2 API "server". | ||||
|  */ | ||||
| class Server extends BaseServer | ||||
| { | ||||
|     use UsergroupAware; | ||||
|     use UserGroupDetectable; | ||||
| 
 | ||||
|     /** | ||||
|      * The base URI namespace for this server. | ||||
|      */ | ||||
|     protected string $baseUri = '/api/v2'; | ||||
| 
 | ||||
|     /** | ||||
|      * Bootstrap the server when it is handling an HTTP request. | ||||
|      */ | ||||
|     public function serving(): void | ||||
|     { | ||||
|         Log::debug(__METHOD__); | ||||
|         // at this point the user may not actually have access to this user group.
 | ||||
|         $res = $this->detectUserGroup(); | ||||
|         $this->setUserGroup($res); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get the server's list of schemas. | ||||
|      */ | ||||
|     protected function allSchemas(): array | ||||
|     { | ||||
|         // Log::debug(__METHOD__);
 | ||||
| 
 | ||||
|         return [ | ||||
|             AccountSchema::class, | ||||
|             UserSchema::class, | ||||
|             // AccountBalanceSchema::class,
 | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| @@ -1,41 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\JsonApi\V2\Users; | ||||
| 
 | ||||
| use FireflyIII\Models\User; | ||||
| use Illuminate\Http\Request; | ||||
| use LaravelJsonApi\Core\Resources\JsonApiResource; | ||||
| 
 | ||||
| /** | ||||
|  * @property User $resource | ||||
|  */ | ||||
| class UserResource extends JsonApiResource | ||||
| { | ||||
|     /** | ||||
|      * Get the resource's attributes. | ||||
|      * | ||||
|      * @param null|Request $request | ||||
|      */ | ||||
|     public function attributes($request): iterable | ||||
|     { | ||||
|         return [ | ||||
|             'created_at' => $this->resource->created_at, | ||||
|             'updated_at' => $this->resource->updated_at, | ||||
|             'email'      => $this->resource->email, | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get the resource's relationships. | ||||
|      * | ||||
|      * @param null|Request $request | ||||
|      */ | ||||
|     public function relationships($request): iterable | ||||
|     { | ||||
|         return [ | ||||
|             // @TODO
 | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| @@ -1,55 +0,0 @@ | ||||
| <?php | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\JsonApi\V2\Users; | ||||
| 
 | ||||
| use FireflyIII\User; | ||||
| use LaravelJsonApi\Eloquent\Contracts\Paginator; | ||||
| use LaravelJsonApi\Eloquent\Fields\DateTime; | ||||
| use LaravelJsonApi\Eloquent\Fields\ID; | ||||
| use LaravelJsonApi\Eloquent\Fields\Relations\HasMany; | ||||
| use LaravelJsonApi\Eloquent\Fields\Str; | ||||
| use LaravelJsonApi\Eloquent\Filters\WhereIdIn; | ||||
| use LaravelJsonApi\Eloquent\Pagination\PagePagination; | ||||
| use LaravelJsonApi\Eloquent\Schema; | ||||
| 
 | ||||
| class UserSchema extends Schema | ||||
| { | ||||
|     /** | ||||
|      * The model the schema corresponds to. | ||||
|      */ | ||||
|     public static string $model = User::class; | ||||
| 
 | ||||
|     /** | ||||
|      * Get the resource fields. | ||||
|      */ | ||||
|     public function fields(): array | ||||
|     { | ||||
|         return [ | ||||
|             ID::make(), | ||||
|             DateTime::make('created_at')->sortable()->readOnly(), | ||||
|             DateTime::make('updated_at')->sortable()->readOnly(), | ||||
|             Str::make('email'), | ||||
|             HasMany::make('accounts'), | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get the resource filters. | ||||
|      */ | ||||
|     public function filters(): array | ||||
|     { | ||||
|         return [ | ||||
|             WhereIdIn::make($this), | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get the resource paginator. | ||||
|      */ | ||||
|     public function pagination(): ?Paginator | ||||
|     { | ||||
|         return PagePagination::make(); | ||||
|     } | ||||
| } | ||||
| @@ -26,7 +26,6 @@ namespace FireflyIII\Models; | ||||
| use FireflyIII\Support\Models\ReturnsIntegerIdTrait; | ||||
| use FireflyIII\Support\Models\ReturnsIntegerUserIdTrait; | ||||
| use FireflyIII\User; | ||||
| use GeneaLabs\LaravelModelCaching\Traits\Cachable; | ||||
| use Illuminate\Database\Eloquent\Builder as EloquentBuilder; | ||||
| use Illuminate\Database\Eloquent\Casts\Attribute; | ||||
| use Illuminate\Database\Eloquent\Factories\HasFactory; | ||||
| @@ -44,7 +43,6 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; | ||||
|  */ | ||||
| class Account extends Model | ||||
| { | ||||
|     use Cachable; | ||||
|     use HasFactory; | ||||
|     use ReturnsIntegerIdTrait; | ||||
|     use ReturnsIntegerUserIdTrait; | ||||
| @@ -52,13 +50,14 @@ class Account extends Model | ||||
| 
 | ||||
|     protected $casts | ||||
|                                      = [ | ||||
|             'created_at'      => 'datetime', | ||||
|             'updated_at'      => 'datetime', | ||||
|             'user_id'         => 'integer', | ||||
|             'deleted_at'      => 'datetime', | ||||
|             'active'          => 'boolean', | ||||
|             'encrypted'       => 'boolean', | ||||
|             'virtual_balance' => 'string', | ||||
|             'created_at'             => 'datetime', | ||||
|             'updated_at'             => 'datetime', | ||||
|             'user_id'                => 'integer', | ||||
|             'deleted_at'             => 'datetime', | ||||
|             'active'                 => 'boolean', | ||||
|             'encrypted'              => 'boolean', | ||||
|             'virtual_balance'        => 'string', | ||||
|             'native_virtual_balance' => 'string', | ||||
|         ]; | ||||
| 
 | ||||
|     protected $fillable              = ['user_id', 'user_group_id', 'account_type_id', 'name', 'active', 'virtual_balance', 'iban', 'native_virtual_balance']; | ||||
|   | ||||
| @@ -38,19 +38,20 @@ class AutoBudget extends Model | ||||
|     use ReturnsIntegerIdTrait; | ||||
|     use SoftDeletes; | ||||
| 
 | ||||
|     #[\Deprecated]
 | ||||
|     #[\Deprecated] /** @deprecated  */
 | ||||
|     public const int AUTO_BUDGET_ADJUSTED = 3; | ||||
| 
 | ||||
|     #[\Deprecated]
 | ||||
|     #[\Deprecated] /** @deprecated  */
 | ||||
|     public const int AUTO_BUDGET_RESET    = 1; | ||||
| 
 | ||||
|     #[\Deprecated]
 | ||||
|     #[\Deprecated] /** @deprecated  */
 | ||||
|     public const int AUTO_BUDGET_ROLLOVER = 2; | ||||
|     protected $casts | ||||
|                                           = [ | ||||
|             'amount' => 'string', | ||||
|             'amount'        => 'string', | ||||
|             'native_amount' => 'string', | ||||
|         ]; | ||||
|     protected $fillable                   = ['budget_id', 'amount', 'period']; | ||||
|     protected $fillable                   = ['budget_id', 'amount', 'period', 'native_amount']; | ||||
| 
 | ||||
|     public function budget(): BelongsTo | ||||
|     { | ||||
|   | ||||
| @@ -23,6 +23,7 @@ declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\Models; | ||||
| 
 | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Support\Models\ReturnsIntegerIdTrait; | ||||
| use FireflyIII\Support\Models\ReturnsIntegerUserIdTrait; | ||||
| use FireflyIII\User; | ||||
| @@ -50,9 +51,10 @@ class AvailableBudget extends Model | ||||
|             'end_date'                => 'date', | ||||
|             'transaction_currency_id' => 'int', | ||||
|             'amount'                  => 'string', | ||||
|             'native_amount'           => 'string', | ||||
|         ]; | ||||
| 
 | ||||
|     protected $fillable = ['user_id', 'user_group_id', 'transaction_currency_id', 'amount', 'start_date', 'end_date', 'start_date_tz', 'end_date_tz']; | ||||
|     protected $fillable = ['user_id', 'user_group_id', 'transaction_currency_id', 'amount', 'start_date', 'end_date', 'start_date_tz', 'end_date_tz', 'native_amount']; | ||||
| 
 | ||||
|     /** | ||||
|      * Route binder. Converts the key in the URL to the specified object (or throw 404). | ||||
| @@ -100,4 +102,20 @@ class AvailableBudget extends Model | ||||
|             get: static fn ($value) => (int) $value, | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     protected function startDate(): Attribute | ||||
|     { | ||||
|         return Attribute::make( | ||||
|             get: fn (string $value) => Carbon::parse($value), | ||||
|             set: fn (Carbon $value) => $value->format('Y-m-d'), | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     protected function endDate(): Attribute | ||||
|     { | ||||
|         return Attribute::make( | ||||
|             get: fn (string $value) => Carbon::parse($value), | ||||
|             set: fn (Carbon $value) => $value->format('Y-m-d'), | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user