mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-28 22:26:22 +00:00 
			
		
		
		
	Compare commits
	
		
			154 Commits
		
	
	
		
			v6.2.0
			...
			develop-20
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | c0204c810c | ||
|  | 944c107e26 | ||
|  | 18e05c06fd | ||
|  | fb79dbf17c | ||
|  | 31a8163c61 | ||
|  | 8bcd729250 | ||
|  | 80c4e69528 | ||
|  | 7f6d8fdb87 | ||
|  | c8e301326e | ||
|  | 4820ef6580 | ||
|  | 4cb775cf4b | ||
|  | c371662c51 | ||
|  | ffaa164aa5 | ||
|  | 344bfbe059 | ||
|  | 6c38b87ec5 | ||
|  | dfcd5d79be | ||
|  | 07631eea28 | ||
|  | 26c4fe36cc | ||
|  | 90fc4b44f2 | ||
|  | f755dd2d48 | ||
|  | d2647f96e7 | ||
|  | 9f94ec067a | ||
|  | a795755618 | ||
|  | 8457a1c881 | ||
|  | fc9429bf3e | ||
|  | b6e8b66035 | ||
|  | 7504b21c3e | ||
|  | b7dad8166d | ||
|  | 2da1b43c37 | ||
|  | a606315884 | ||
|  | 295feedd77 | ||
|  | d3b2748c8f | ||
|  | 1b4655fd70 | ||
|  | 05f67ef584 | ||
|  | 04ab7ba07d | ||
|  | 5806323970 | ||
|  | ee260a3df7 | ||
|  | 7cb41fb333 | ||
|  | d38adbfdc2 | ||
|  | e6a6766ef1 | ||
|  | a1e596491c | ||
|  | 9c920908a6 | ||
|  | 0014bffeb8 | ||
|  | 63c17f99b2 | ||
|  | ec1e0e2807 | ||
|  | 2f16419a7b | ||
|  | 02c13859e7 | ||
|  | 57ec9b8e36 | ||
|  | 41ad35880d | ||
|  | 3aa946e028 | ||
|  | 53e46895aa | ||
|  | c61389037d | ||
|  | 6172d60e00 | ||
|  | f909f1d9ff | ||
|  | 55018ca046 | ||
|  | 19c746a865 | ||
|  | 503d2aa786 | ||
|  | 70d83ab501 | ||
|  | edab602bb7 | ||
|  | f9bcc4b1fa | ||
|  | f3fe86167c | ||
|  | 2189fb46a2 | ||
|  | 7ff4178c8b | ||
|  | fffd695ef8 | ||
|  | ee592de035 | ||
|  | 7394e50ae2 | ||
|  | f42fcff04a | ||
|  | 4eb3ce7c14 | ||
|  | a977c567ce | ||
|  | 785bd7e905 | ||
|  | df19f699d4 | ||
|  | 5e6e932e7e | ||
|  | 5bc397f01a | ||
|  | 42209e367f | ||
|  | d53b1670d3 | ||
|  | a6d450ba18 | ||
|  | e8c1a95128 | ||
|  | edb201f210 | ||
|  | fe57367a8c | ||
|  | 134194a95b | ||
|  | 41c0e6fe2d | ||
|  | c07914e733 | ||
|  | 52e2302f4f | ||
|  | 0a6b34b4f2 | ||
|  | 1e06b4dd0b | ||
|  | 5701f95e0b | ||
|  | 60d3572d37 | ||
|  | ffa6e6a571 | ||
|  | d6453cd735 | ||
|  | fd79f9df44 | ||
|  | 4587340293 | ||
|  | 90bfdc7573 | ||
|  | eca12f661f | ||
|  | f85878b843 | ||
|  | 6499b5eaab | ||
|  | 7e4fece63d | ||
|  | 512eddf8be | ||
|  | f0fa93a811 | ||
|  | 3c8de21709 | ||
|  | 81173e8340 | ||
|  | 35a8fa5f02 | ||
|  | 443036936d | ||
|  | ac88007593 | ||
|  | 2297589dca | ||
|  | 6ada5fa560 | ||
|  | 8f6eefb5e7 | ||
|  | b36a50381b | ||
|  | 51f84b3060 | ||
|  | 72132a19b0 | ||
|  | 065d165211 | ||
|  | cabedf39b2 | ||
|  | 5d3806fcd4 | ||
|  | 01695b3342 | ||
|  | 71fb5fe077 | ||
|  | 3bec106840 | ||
|  | fb01c36be1 | ||
|  | 26d851e69e | ||
|  | 28c18c046b | ||
|  | 318cef7e3b | ||
|  | e8dc8f25be | ||
|  | 10ccc30240 | ||
|  | 5adc877d5e | ||
|  | 30923afb2b | ||
|  | 4eb6813b43 | ||
|  | 7521a31619 | ||
|  | fc05beb452 | ||
|  | 1103428a83 | ||
|  | d06d521bf0 | ||
|  | 8f64f1c0eb | ||
|  | d11c232171 | ||
|  | 93c73248de | ||
|  | 5bed081ab9 | ||
|  | c5188c503e | ||
|  | 98ffcac7b6 | ||
|  | df1e81d611 | ||
|  | 9711170b08 | ||
|  | e43264bdce | ||
|  | e0643bed7a | ||
|  | 7f0eb3b064 | ||
|  | f38e510526 | ||
|  | 25f99b23b2 | ||
|  | 44281fc8a0 | ||
|  | eed3902cb7 | ||
|  | 94a3bb0443 | ||
|  | 8dcc36880e | ||
|  | 695bb31894 | ||
|  | f8ded66869 | ||
|  | 8e4bdbc584 | ||
|  | f7b14b01bc | ||
|  | 705b9bf0f2 | ||
|  | f0226dbc54 | ||
|  | 1b1dfb0d7b | ||
|  | 8ed5092a76 | ||
|  | d609821be6 | 
							
								
								
									
										48
									
								
								.ci/php-cs-fixer/composer.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										48
									
								
								.ci/php-cs-fixer/composer.lock
									
									
									
										generated
									
									
									
								
							| @@ -406,16 +406,16 @@ | ||||
|         }, | ||||
|         { | ||||
|             "name": "friendsofphp/php-cs-fixer", | ||||
|             "version": "v3.68.5", | ||||
|             "version": "v3.69.0", | ||||
|             "source": { | ||||
|                 "type": "git", | ||||
|                 "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", | ||||
|                 "reference": "7bedb718b633355272428c60736dc97fb96daf27" | ||||
|                 "reference": "630a59448c00729bc235d5e95cfedefeaca37523" | ||||
|             }, | ||||
|             "dist": { | ||||
|                 "type": "zip", | ||||
|                 "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/7bedb718b633355272428c60736dc97fb96daf27", | ||||
|                 "reference": "7bedb718b633355272428c60736dc97fb96daf27", | ||||
|                 "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/630a59448c00729bc235d5e95cfedefeaca37523", | ||||
|                 "reference": "630a59448c00729bc235d5e95cfedefeaca37523", | ||||
|                 "shasum": "" | ||||
|             }, | ||||
|             "require": { | ||||
| @@ -432,7 +432,7 @@ | ||||
|                 "react/promise": "^2.0 || ^3.0", | ||||
|                 "react/socket": "^1.0", | ||||
|                 "react/stream": "^1.0", | ||||
|                 "sebastian/diff": "^4.0 || ^5.1 || ^6.0", | ||||
|                 "sebastian/diff": "^4.0 || ^5.1 || ^6.0 || ^7.0", | ||||
|                 "symfony/console": "^5.4 || ^6.4 || ^7.0", | ||||
|                 "symfony/event-dispatcher": "^5.4 || ^6.4 || ^7.0", | ||||
|                 "symfony/filesystem": "^5.4 || ^6.4 || ^7.0", | ||||
| @@ -445,18 +445,18 @@ | ||||
|                 "symfony/stopwatch": "^5.4 || ^6.4 || ^7.0" | ||||
|             }, | ||||
|             "require-dev": { | ||||
|                 "facile-it/paraunit": "^1.3.1 || ^2.4", | ||||
|                 "infection/infection": "^0.29.8", | ||||
|                 "facile-it/paraunit": "^1.3.1 || ^2.5", | ||||
|                 "infection/infection": "^0.29.10", | ||||
|                 "justinrainbow/json-schema": "^5.3 || ^6.0", | ||||
|                 "keradus/cli-executor": "^2.1", | ||||
|                 "mikey179/vfsstream": "^1.6.12", | ||||
|                 "php-coveralls/php-coveralls": "^2.7", | ||||
|                 "php-cs-fixer/accessible-object": "^1.1", | ||||
|                 "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.5", | ||||
|                 "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.5", | ||||
|                 "phpunit/phpunit": "^9.6.22 || ^10.5.40 || ^11.5.2", | ||||
|                 "symfony/var-dumper": "^5.4.48 || ^6.4.15 || ^7.2.0", | ||||
|                 "symfony/yaml": "^5.4.45 || ^6.4.13 || ^7.2.0" | ||||
|                 "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6", | ||||
|                 "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6", | ||||
|                 "phpunit/phpunit": "^9.6.22 || ^10.5.45 || ^11.5.7", | ||||
|                 "symfony/var-dumper": "^5.4.48 || ^6.4.18 || ^7.2.0", | ||||
|                 "symfony/yaml": "^5.4.45 || ^6.4.18 || ^7.2.0" | ||||
|             }, | ||||
|             "suggest": { | ||||
|                 "ext-dom": "For handling output formats in XML", | ||||
| @@ -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.68.5" | ||||
|                 "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.69.0" | ||||
|             }, | ||||
|             "funding": [ | ||||
|                 { | ||||
| @@ -505,7 +505,7 @@ | ||||
|                     "type": "github" | ||||
|                 } | ||||
|             ], | ||||
|             "time": "2025-01-30T17:00:50+00:00" | ||||
|             "time": "2025-02-14T16:19:23+00:00" | ||||
|         }, | ||||
|         { | ||||
|             "name": "psr/container", | ||||
| @@ -1188,29 +1188,29 @@ | ||||
|         }, | ||||
|         { | ||||
|             "name": "sebastian/diff", | ||||
|             "version": "6.0.2", | ||||
|             "version": "7.0.0", | ||||
|             "source": { | ||||
|                 "type": "git", | ||||
|                 "url": "https://github.com/sebastianbergmann/diff.git", | ||||
|                 "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" | ||||
|                 "reference": "7ab1ea946c012266ca32390913653d844ecd085f" | ||||
|             }, | ||||
|             "dist": { | ||||
|                 "type": "zip", | ||||
|                 "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", | ||||
|                 "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", | ||||
|                 "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7ab1ea946c012266ca32390913653d844ecd085f", | ||||
|                 "reference": "7ab1ea946c012266ca32390913653d844ecd085f", | ||||
|                 "shasum": "" | ||||
|             }, | ||||
|             "require": { | ||||
|                 "php": ">=8.2" | ||||
|                 "php": ">=8.3" | ||||
|             }, | ||||
|             "require-dev": { | ||||
|                 "phpunit/phpunit": "^11.0", | ||||
|                 "symfony/process": "^4.2 || ^5" | ||||
|                 "phpunit/phpunit": "^12.0", | ||||
|                 "symfony/process": "^7.2" | ||||
|             }, | ||||
|             "type": "library", | ||||
|             "extra": { | ||||
|                 "branch-alias": { | ||||
|                     "dev-main": "6.0-dev" | ||||
|                     "dev-main": "7.0-dev" | ||||
|                 } | ||||
|             }, | ||||
|             "autoload": { | ||||
| @@ -1243,7 +1243,7 @@ | ||||
|             "support": { | ||||
|                 "issues": "https://github.com/sebastianbergmann/diff/issues", | ||||
|                 "security": "https://github.com/sebastianbergmann/diff/security/policy", | ||||
|                 "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" | ||||
|                 "source": "https://github.com/sebastianbergmann/diff/tree/7.0.0" | ||||
|             }, | ||||
|             "funding": [ | ||||
|                 { | ||||
| @@ -1251,7 +1251,7 @@ | ||||
|                     "type": "github" | ||||
|                 } | ||||
|             ], | ||||
|             "time": "2024-07-03T04:53:05+00:00" | ||||
|             "time": "2025-02-07T04:55:46+00:00" | ||||
|         }, | ||||
|         { | ||||
|             "name": "symfony/console", | ||||
|   | ||||
| @@ -189,7 +189,7 @@ SEND_REPORT_JOURNALS=true | ||||
| ENABLE_EXTERNAL_MAP=false | ||||
|  | ||||
| # | ||||
| # Enable or disable exchange rate conversion. This function isn't used yet by Firefly III | ||||
| # Enable or disable exchange rate conversion. | ||||
| # | ||||
| ENABLE_EXCHANGE_RATES=false | ||||
|  | ||||
|   | ||||
							
								
								
									
										33
									
								
								.github/label-actions.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										33
									
								
								.github/label-actions.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,16 +1,29 @@ | ||||
| # Configuration for Label Actions - https://github.com/dessant/label-actions | ||||
|  | ||||
| # The `feature` label is added to issues | ||||
| fixed: | ||||
|   issues: | ||||
|     # Post a comment, `{issue-author}` is an optional placeholder | ||||
|     comment: | | ||||
|       Hi there! | ||||
|  | ||||
|       This is an automatic reply. `Share and enjoy` | ||||
|  | ||||
|       This issue has been marked as fixed. Thanks for reporting! A new version will be released in due time. Unfortunately, [I cannot give an estimate](https://docs.firefly-iii.org/references/faq/firefly-iii/general/#when-will-you-release-version-the-next-version), but [the roadmap](https://roadmap.firefly-iii.org/) is available for your reading pleasure. | ||||
|  | ||||
|       There is no need to close the issue. It will be closed automatically. | ||||
|  | ||||
|       Thank you for your contributions. | ||||
| feature: | ||||
|   issues: | ||||
|     # Post a comment, `{issue-author}` is an optional placeholder | ||||
|     unlabel: feature | ||||
|     comment: | | ||||
|       Hi there!  | ||||
|       Hi there! | ||||
|  | ||||
|       This is an automatic reply. `Share and enjoy` | ||||
|  | ||||
|       This issue has been marked as a feature request. The requested (new) feature will become a part of Firefly III or the data importer in due course. | ||||
|       This issue has been marked as a feature request. | ||||
|  | ||||
|       If you come across this issue, please be aware there is NO need to reply with "+1" or "me too" or "I need this too" or whatever. Such comments are not helpful, and do not influence [the roadmap](https://roadmap.firefly-iii.org/). Your comment may be :skull: deleted. You can subscribe to this issue to get updates. | ||||
|  | ||||
| @@ -20,13 +33,13 @@ epic: | ||||
|   issues: | ||||
|     # Post a comment, `{issue-author}` is an optional placeholder | ||||
|     comment: | | ||||
|       Hi there!  | ||||
|       Hi there! | ||||
|  | ||||
|       This is an automatic reply. `Share and enjoy` | ||||
|  | ||||
|       This issue has been marked as an epic. In epics, large amounts of works are collected that will be part of a major new feature. If you have more ideas that could be a part of this epic, feel free to reply. | ||||
|  | ||||
|       *However*, please be aware there is NO need to reply with "+1" or "me too" or "I need this too" or whatever. Such comments are not helpful, and do not influence [the roadmap](https://roadmap.firefly-iii.org/). Your comment may be :skull: deleted.  | ||||
|       *However*, please be aware there is NO need to reply with "+1" or "me too" or "I need this too" or whatever. Such comments are not helpful, and do not influence [the roadmap](https://roadmap.firefly-iii.org/). Your comment may be :skull: deleted. | ||||
|  | ||||
|       If you are merely interested in this epic's progress, you can subscribe to this issue to get updates. | ||||
|  | ||||
| @@ -37,11 +50,11 @@ enhancement: | ||||
|   issues: | ||||
|     # Post a comment, `{issue-author}` is an optional placeholder | ||||
|     comment: | | ||||
|       Hi there!  | ||||
|       Hi there! | ||||
|  | ||||
|       This is an automatic reply. `Share and enjoy` | ||||
|  | ||||
|       This issue has been marked as an enhancement. The requested enhancement to an existing feature will become a part of Firefly III or the data importer in due course. | ||||
|       This issue has been marked as an enhancement. | ||||
|  | ||||
|       If you come across this issue, please be aware there is NO need to reply with "+1" or "me too" or "I need this too" or whatever. Such comments are not helpful, and do not influence [the roadmap](https://roadmap.firefly-iii.org/). Your comment may be :skull: deleted. You can subscribe to this issue to get updates. | ||||
|  | ||||
| @@ -51,7 +64,7 @@ triage: | ||||
|   issues: | ||||
|     # Post a comment, `{issue-author}` is an optional placeholder | ||||
|     comment: | | ||||
|       Hi there!  | ||||
|       Hi there! | ||||
|  | ||||
|       This is an automatic reply. `Share and enjoy` | ||||
|  | ||||
| @@ -62,7 +75,7 @@ triage: | ||||
| needs-moar-debug: | ||||
|   issues: | ||||
|     comment: | | ||||
|       Hi there!  | ||||
|       Hi there! | ||||
|  | ||||
|       This is an automatic reply. `Share and enjoy` | ||||
|  | ||||
| @@ -80,7 +93,7 @@ needs-moar-debug: | ||||
| needs-moar-logs: | ||||
|   issues: | ||||
|     comment: | | ||||
|       Hi there!  | ||||
|       Hi there! | ||||
|  | ||||
|       This is an automatic reply. `Share and enjoy` | ||||
|  | ||||
| @@ -96,7 +109,7 @@ needs-moar-logs: | ||||
| v2-layout-issue: | ||||
|   issues: | ||||
|     comment: | | ||||
|       Hi there!  | ||||
|       Hi there! | ||||
|  | ||||
|       This is an automatic reply. `Share and enjoy` | ||||
|  | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/closed-issues.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/closed-issues.yml
									
									
									
									
										vendored
									
									
								
							| @@ -8,7 +8,7 @@ jobs: | ||||
|   command_and_close: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - uses: aws-actions/closed-issue-message@v1 | ||||
|       - uses: aws-actions/closed-issue-message@v2 | ||||
|         with: | ||||
|           message: | | ||||
|             Hi there! This is an automatic reply. `Share and enjoy` | ||||
|   | ||||
| @@ -3,6 +3,9 @@ | ||||
| Over time, many people have contributed to Firefly III. Their efforts are not always visible, but always remembered and appreciated. | ||||
| Please find below all the people who contributed to the Firefly III code. Their names are mentioned in the year of their first contribution. | ||||
| 
 | ||||
| ## 2025 | ||||
| - SoftBrix | ||||
| 
 | ||||
| ## 2024 | ||||
| - Sobuno | ||||
| - TasneemTantawy | ||||
|   | ||||
| @@ -34,6 +34,7 @@ use FireflyIII\Support\Facades\Steam; | ||||
| use FireflyIII\Support\Http\Api\AccountFilter; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| 
 | ||||
| /** | ||||
|  * Class AccountController | ||||
| @@ -41,7 +42,8 @@ use Illuminate\Http\JsonResponse; | ||||
| class AccountController extends Controller | ||||
| { | ||||
|     use AccountFilter; | ||||
|     protected array $accepts = ['application/json']; | ||||
|     // this array only exists to test if the constructor will use it properly.
 | ||||
|     protected array $accepts = ['application/json', 'application/vnd.api+json']; | ||||
| 
 | ||||
|     /** @var array<int, string> */ | ||||
|     private array                      $balanceTypes; | ||||
| @@ -82,12 +84,17 @@ class AccountController extends Controller | ||||
|         $return = []; | ||||
|         $result = $this->repository->searchAccount((string) $query, $types, $this->parameters->get('limit')); | ||||
| 
 | ||||
|         // set date to subday + end-of-day for account balance. so it is at $date 23:59:59
 | ||||
|         $date->subDay()->endOfDay(); | ||||
| 
 | ||||
|         /** @var Account $account */ | ||||
|         foreach ($result as $account) { | ||||
|             $nameWithBalance = $account->name; | ||||
|             $currency        = $this->repository->getAccountCurrency($account) ?? $this->nativeCurrency; | ||||
|             $useCurrency     = $currency; | ||||
|             if (in_array($account->accountType->type, $this->balanceTypes, true)) { | ||||
|                 // this one is correct.
 | ||||
|                 Log::debug(sprintf('accounts: Call finalAccountBalance with date/time "%s"', $date->toIso8601String())); | ||||
|                 $balance         = Steam::finalAccountBalance($account, $date); | ||||
|                 $key             = $this->convertToNative && $currency->id !== $this->nativeCurrency->id ? 'native_balance' : 'balance'; | ||||
|                 $useCurrency     = $this->convertToNative && $currency->id !== $this->nativeCurrency->id ? $this->nativeCurrency : $currency; | ||||
| @@ -100,15 +107,20 @@ class AccountController extends Controller | ||||
|             } | ||||
| 
 | ||||
|             $return[]        = [ | ||||
|                 'id'                      => (string) $account->id, | ||||
|                 'name'                    => $account->name, | ||||
|                 'name_with_balance'       => $nameWithBalance, | ||||
|                 'type'                    => $account->accountType->type, | ||||
|                 'currency_id'             => (string) $useCurrency->id, | ||||
|                 'currency_name'           => $useCurrency->name, | ||||
|                 'currency_code'           => $useCurrency->code, | ||||
|                 'currency_symbol'         => $useCurrency->symbol, | ||||
|                 'currency_decimal_places' => $useCurrency->decimal_places, | ||||
|                 'id'                              => (string) $account->id, | ||||
|                 'name'                            => $account->name, | ||||
|                 'name_with_balance'               => $nameWithBalance, | ||||
|                 'type'                            => $account->accountType->type, | ||||
|                 'currency_id'                     => (string) $useCurrency->id, | ||||
|                 'currency_name'                   => $useCurrency->name, | ||||
|                 'currency_code'                   => $useCurrency->code, | ||||
|                 'currency_symbol'                 => $useCurrency->symbol, | ||||
|                 'currency_decimal_places'         => $useCurrency->decimal_places, | ||||
|                 'account_currency_id'             => (string) $currency->id, | ||||
|                 'account_currency_name'           => $currency->name, | ||||
|                 'account_currency_code'           => $currency->code, | ||||
|                 'account_currency_symbol'         => $currency->symbol, | ||||
|                 'account_currency_decimal_places' => $currency->decimal_places, | ||||
|             ]; | ||||
|         } | ||||
| 
 | ||||
|   | ||||
| @@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete; | ||||
| 
 | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; | ||||
| use FireflyIII\Enums\UserRoleEnum; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Repositories\Journal\JournalRepositoryInterface; | ||||
| use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface; | ||||
| @@ -41,6 +42,8 @@ class TransactionController extends Controller | ||||
|     private TransactionGroupRepositoryInterface $groupRepository; | ||||
|     private JournalRepositoryInterface          $repository; | ||||
| 
 | ||||
|     protected array $acceptedRoles = [UserRoleEnum::READ_ONLY]; | ||||
| 
 | ||||
|     /** | ||||
|      * TransactionController constructor. | ||||
|      */ | ||||
| @@ -51,10 +54,12 @@ class TransactionController extends Controller | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user                  = auth()->user(); | ||||
|                 $userGroup             = $this->validateUserGroup($request); | ||||
|                 $this->repository      = app(JournalRepositoryInterface::class); | ||||
|                 $this->groupRepository = app(TransactionGroupRepositoryInterface::class); | ||||
|                 $this->repository->setUser($user); | ||||
|                 $this->groupRepository->setUser($user); | ||||
|                 $this->groupRepository->setUserGroup($userGroup); | ||||
| 
 | ||||
|                 return $next($request); | ||||
|             } | ||||
|   | ||||
| @@ -32,6 +32,7 @@ use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Preference; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Support\Facades\Steam; | ||||
| use FireflyIII\Support\Http\Api\ApiSupport; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| @@ -80,6 +81,10 @@ class AccountController extends Controller | ||||
|         /** @var Carbon $end */ | ||||
|         $end        = $dates['end']; | ||||
| 
 | ||||
|         // set dates to end of day + start of day:
 | ||||
|         $start->startOfDay(); | ||||
|         $end->endOfDay(); | ||||
| 
 | ||||
|         // user's preferences
 | ||||
|         $defaultSet = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value])->pluck('id')->toArray(); | ||||
| 
 | ||||
| @@ -113,7 +118,7 @@ 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); | ||||
|             $range        = Steam::finalAccountBalanceInRange($account, $start, clone $end, $this->convertToNative); | ||||
|             $previous     = array_values($range)[0][$field]; | ||||
|             while ($currentStart <= $end) { | ||||
|                 $format                        = $currentStart->format('Y-m-d'); | ||||
|   | ||||
| @@ -31,6 +31,7 @@ use FireflyIII\Models\Preference; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use FireflyIII\Support\Facades\Steam; | ||||
| use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; | ||||
| use FireflyIII\Transformers\V2\AbstractTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| @@ -59,6 +60,7 @@ abstract class Controller extends BaseController | ||||
|     use AuthorizesRequests; | ||||
|     use DispatchesJobs; | ||||
|     use ValidatesRequests; | ||||
|     use ValidatesUserGroupTrait; | ||||
| 
 | ||||
|     protected const string CONTENT_TYPE      = 'application/vnd.api+json'; | ||||
|     protected const string JSON_CONTENT_TYPE = 'application/json'; | ||||
| @@ -67,7 +69,7 @@ abstract class Controller extends BaseController | ||||
|     protected array        $allowedSort; | ||||
|     protected ParameterBag $parameters; | ||||
|     protected bool        $convertToNative   = false; | ||||
|     protected array $accepts                 = ['application/json']; | ||||
|     protected array $accepts                 = ['application/json', 'application/vnd.api+json']; | ||||
|     protected TransactionCurrency $nativeCurrency; | ||||
| 
 | ||||
|     /** | ||||
|   | ||||
| @@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment; | ||||
| use FireflyIII\Transformers\AttachmentTransformer; | ||||
| use FireflyIII\Transformers\PiggyBankTransformer; | ||||
| use FireflyIII\Transformers\TransactionGroupTransformer; | ||||
| @@ -140,18 +141,18 @@ class ListController extends Controller | ||||
|      */ | ||||
|     public function transactions(Request $request, Account $account): JsonResponse | ||||
|     { | ||||
|         $pageSize    = $this->parameters->get('limit'); | ||||
|         $type        = $request->get('type') ?? 'default'; | ||||
|         $pageSize     = $this->parameters->get('limit'); | ||||
|         $type         = $request->get('type') ?? 'default'; | ||||
|         $this->parameters->set('type', $type); | ||||
|         $types       = $this->mapTransactionTypes($this->parameters->get('type')); | ||||
|         $manager     = $this->getManager(); | ||||
|         $types        = $this->mapTransactionTypes($this->parameters->get('type')); | ||||
|         $manager      = $this->getManager(); | ||||
| 
 | ||||
|         /** @var User $admin */ | ||||
|         $admin       = auth()->user(); | ||||
|         $admin        = auth()->user(); | ||||
| 
 | ||||
|         // use new group collector:
 | ||||
|         /** @var GroupCollectorInterface $collector */ | ||||
|         $collector   = app(GroupCollectorInterface::class); | ||||
|         $collector    = app(GroupCollectorInterface::class); | ||||
|         $collector->setUser($admin)->setAccounts(new Collection([$account])) | ||||
|             ->withAPIInformation()->setLimit($pageSize)->setPage($this->parameters->get('page'))->setTypes($types) | ||||
|         ; | ||||
| @@ -163,15 +164,19 @@ class ListController extends Controller | ||||
|             $collector->setEnd($this->parameters->get('end')); | ||||
|         } | ||||
| 
 | ||||
|         $paginator   = $collector->getPaginatedGroups(); | ||||
|         $paginator    = $collector->getPaginatedGroups(); | ||||
|         $paginator->setPath(route('api.v1.accounts.transactions', [$account->id]).$this->buildParams()); | ||||
|         $groups      = $paginator->getCollection(); | ||||
| 
 | ||||
|         // enrich
 | ||||
|         $enrichment   = new TransactionGroupEnrichment(); | ||||
|         $enrichment->setUser($admin); | ||||
|         $transactions = $enrichment->enrich($paginator->getCollection()); | ||||
| 
 | ||||
|         /** @var TransactionGroupTransformer $transformer */ | ||||
|         $transformer = app(TransactionGroupTransformer::class); | ||||
|         $transformer  = app(TransactionGroupTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
| 
 | ||||
|         $resource    = new FractalCollection($groups, $transformer, 'transactions'); | ||||
|         $resource     = new FractalCollection($transactions, $transformer, 'transactions'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
| 
 | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|   | ||||
| @@ -29,7 +29,9 @@ use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\AccountFilter; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment; | ||||
| use FireflyIII\Transformers\AccountTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| @@ -88,9 +90,17 @@ class ShowController extends Controller | ||||
|         $count       = $collection->count(); | ||||
| 
 | ||||
|         // continue sort:
 | ||||
| 
 | ||||
|         $accounts    = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
| 
 | ||||
|         // enrich
 | ||||
|         /** @var User $admin */ | ||||
|         $admin       = auth()->user(); | ||||
|         $enrichment  = new AccountEnrichment(); | ||||
|         $enrichment->setUser($admin); | ||||
|         $enrichment->setConvertToNative($this->convertToNative); | ||||
|         $enrichment->setNative($this->nativeCurrency); | ||||
|         $accounts    = $enrichment->enrich($accounts); | ||||
| 
 | ||||
|         // make paginator:
 | ||||
|         $paginator   = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.accounts.index').$this->buildParams()); | ||||
| @@ -118,6 +128,16 @@ class ShowController extends Controller | ||||
|         $account->refresh(); | ||||
|         $manager     = $this->getManager(); | ||||
| 
 | ||||
|         // enrich
 | ||||
|         /** @var User $admin */ | ||||
|         $admin       = auth()->user(); | ||||
|         $enrichment  = new AccountEnrichment(); | ||||
|         $enrichment->setUser($admin); | ||||
|         $enrichment->setConvertToNative($this->convertToNative); | ||||
|         $enrichment->setNative($this->nativeCurrency); | ||||
|         $account     = $enrichment->enrichSingle($account); | ||||
| 
 | ||||
| 
 | ||||
|         /** @var AccountTransformer $transformer */ | ||||
|         $transformer = app(AccountTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|   | ||||
| @@ -27,7 +27,9 @@ namespace FireflyIII\Api\V1\Controllers\Models\Account; | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Api\V1\Requests\Models\Account\StoreRequest; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment; | ||||
| use FireflyIII\Transformers\AccountTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use League\Fractal\Resource\Item; | ||||
| 
 | ||||
| @@ -69,6 +71,15 @@ class StoreController extends Controller | ||||
|         $account     = $this->repository->store($data); | ||||
|         $manager     = $this->getManager(); | ||||
| 
 | ||||
|         // enrich
 | ||||
|         /** @var User $admin */ | ||||
|         $admin       = auth()->user(); | ||||
|         $enrichment  = new AccountEnrichment(); | ||||
|         $enrichment->setUser($admin); | ||||
|         $enrichment->setConvertToNative($this->convertToNative); | ||||
|         $enrichment->setNative($this->nativeCurrency); | ||||
|         $account     = $enrichment->enrichSingle($account); | ||||
| 
 | ||||
|         /** @var AccountTransformer $transformer */ | ||||
|         $transformer = app(AccountTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|   | ||||
| @@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Api\V1\Requests\Models\Account\UpdateRequest; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment; | ||||
| use FireflyIII\Transformers\AccountTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use League\Fractal\Resource\Item; | ||||
| 
 | ||||
| @@ -73,6 +75,15 @@ class UpdateController extends Controller | ||||
|         $account->refresh(); | ||||
|         app('preferences')->mark(); | ||||
| 
 | ||||
|         // enrich
 | ||||
|         /** @var User $admin */ | ||||
|         $admin        = auth()->user(); | ||||
|         $enrichment   = new AccountEnrichment(); | ||||
|         $enrichment->setUser($admin); | ||||
|         $enrichment->setConvertToNative($this->convertToNative); | ||||
|         $enrichment->setNative($this->nativeCurrency); | ||||
|         $account      = $enrichment->enrichSingle($account); | ||||
| 
 | ||||
|         /** @var AccountTransformer $transformer */ | ||||
|         $transformer  = app(AccountTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|   | ||||
| @@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Repositories\Bill\BillRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment; | ||||
| use FireflyIII\Transformers\AttachmentTransformer; | ||||
| use FireflyIII\Transformers\RuleTransformer; | ||||
| use FireflyIII\Transformers\TransactionGroupTransformer; | ||||
| @@ -176,7 +177,11 @@ class ListController extends Controller | ||||
|         // get paginator.
 | ||||
|         $paginator    = $collector->getPaginatedGroups(); | ||||
|         $paginator->setPath(route('api.v1.bills.transactions', [$bill->id]).$this->buildParams()); | ||||
|         $transactions = $paginator->getCollection(); | ||||
| 
 | ||||
|         // enrich
 | ||||
|         $enrichment   = new TransactionGroupEnrichment(); | ||||
|         $enrichment->setUser($admin); | ||||
|         $transactions = $enrichment->enrich($paginator->getCollection()); | ||||
| 
 | ||||
|         /** @var TransactionGroupTransformer $transformer */ | ||||
|         $transformer  = app(TransactionGroupTransformer::class); | ||||
|   | ||||
| @@ -32,6 +32,7 @@ use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface; | ||||
| use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment; | ||||
| use FireflyIII\Transformers\AttachmentTransformer; | ||||
| use FireflyIII\Transformers\BudgetLimitTransformer; | ||||
| use FireflyIII\Transformers\TransactionGroupTransformer; | ||||
| @@ -172,7 +173,11 @@ class ListController extends Controller | ||||
| 
 | ||||
|         $paginator    = $collector->getPaginatedGroups(); | ||||
|         $paginator->setPath(route('api.v1.budgets.transactions', [$budget->id]).$this->buildParams()); | ||||
|         $transactions = $paginator->getCollection(); | ||||
| 
 | ||||
|         // enrich
 | ||||
|         $enrichment   = new TransactionGroupEnrichment(); | ||||
|         $enrichment->setUser($admin); | ||||
|         $transactions = $enrichment->enrich($paginator->getCollection()); | ||||
| 
 | ||||
|         /** @var TransactionGroupTransformer $transformer */ | ||||
|         $transformer  = app(TransactionGroupTransformer::class); | ||||
| @@ -232,7 +237,11 @@ class ListController extends Controller | ||||
| 
 | ||||
|         $paginator    = $collector->getPaginatedGroups(); | ||||
|         $paginator->setPath(route('api.v1.budgets.without-budget').$this->buildParams()); | ||||
|         $transactions = $paginator->getCollection(); | ||||
| 
 | ||||
|         // enrich
 | ||||
|         $enrichment   = new TransactionGroupEnrichment(); | ||||
|         $enrichment->setUser($admin); | ||||
|         $transactions = $enrichment->enrich($paginator->getCollection()); | ||||
| 
 | ||||
|         /** @var TransactionGroupTransformer $transformer */ | ||||
|         $transformer  = app(TransactionGroupTransformer::class); | ||||
|   | ||||
| @@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\BudgetLimit; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment; | ||||
| use FireflyIII\Transformers\TransactionGroupTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| @@ -84,7 +85,11 @@ class ListController extends Controller | ||||
|         $collector->setTypes($types); | ||||
|         $paginator    = $collector->getPaginatedGroups(); | ||||
|         $paginator->setPath(route('api.v1.budgets.limits.transactions', [$budget->id, $budgetLimit->id]).$this->buildParams()); | ||||
|         $transactions = $paginator->getCollection(); | ||||
| 
 | ||||
|         // enrich
 | ||||
|         $enrichment   = new TransactionGroupEnrichment(); | ||||
|         $enrichment->setUser($admin); | ||||
|         $transactions = $enrichment->enrich($paginator->getCollection()); | ||||
| 
 | ||||
|         /** @var TransactionGroupTransformer $transformer */ | ||||
|         $transformer  = app(TransactionGroupTransformer::class); | ||||
|   | ||||
| @@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Models\Category; | ||||
| use FireflyIII\Repositories\Category\CategoryRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment; | ||||
| use FireflyIII\Transformers\AttachmentTransformer; | ||||
| use FireflyIII\Transformers\TransactionGroupTransformer; | ||||
| use FireflyIII\User; | ||||
| @@ -139,7 +140,11 @@ class ListController extends Controller | ||||
| 
 | ||||
|         $paginator    = $collector->getPaginatedGroups(); | ||||
|         $paginator->setPath(route('api.v1.categories.transactions', [$category->id]).$this->buildParams()); | ||||
|         $transactions = $paginator->getCollection(); | ||||
| 
 | ||||
|         // enrich
 | ||||
|         $enrichment   = new TransactionGroupEnrichment(); | ||||
|         $enrichment->setUser($admin); | ||||
|         $transactions = $enrichment->enrich($paginator->getCollection()); | ||||
| 
 | ||||
|         /** @var TransactionGroupTransformer $transformer */ | ||||
|         $transformer  = app(TransactionGroupTransformer::class); | ||||
|   | ||||
| @@ -57,11 +57,11 @@ class IndexController extends Controller | ||||
| 
 | ||||
|     public function index(): JsonResponse | ||||
|     { | ||||
|         $piggies     = $this->repository->getAll(); | ||||
|         $entries     = $this->repository->getAll(); | ||||
|         $pageSize    = $this->parameters->get('limit'); | ||||
|         $count       = $piggies->count(); | ||||
|         $piggies     = $piggies->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|         $paginator   = new LengthAwarePaginator($piggies, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $count       = $entries->count(); | ||||
|         $entries     = $entries->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|         $paginator   = new LengthAwarePaginator($entries, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $transformer = new ExchangeRateTransformer(); | ||||
|         $transformer->setParameters($this->parameters); // give params to transformer
 | ||||
| 
 | ||||
|   | ||||
| @@ -28,9 +28,11 @@ use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment; | ||||
| use FireflyIII\Transformers\AccountTransformer; | ||||
| use FireflyIII\Transformers\AttachmentTransformer; | ||||
| use FireflyIII\Transformers\PiggyBankEventTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| @@ -75,17 +77,26 @@ class ListController extends Controller | ||||
| 
 | ||||
|         $collection  = $piggyBank->accounts; | ||||
|         $count       = $collection->count(); | ||||
|         $events      = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|         $accounts    = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
| 
 | ||||
|         // enrich
 | ||||
|         /** @var User $admin */ | ||||
|         $admin       = auth()->user(); | ||||
|         $enrichment  = new AccountEnrichment(); | ||||
|         $enrichment->setUser($admin); | ||||
|         $enrichment->setConvertToNative($this->convertToNative); | ||||
|         $enrichment->setNative($this->nativeCurrency); | ||||
|         $accounts    = $enrichment->enrich($accounts); | ||||
| 
 | ||||
|         // make paginator:
 | ||||
|         $paginator   = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator   = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.piggy-banks.accounts', [$piggyBank->id]).$this->buildParams()); | ||||
| 
 | ||||
|         /** @var AccountTransformer $transformer */ | ||||
|         $transformer = app(AccountTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
| 
 | ||||
|         $resource    = new FractalCollection($events, $transformer, 'accounts'); | ||||
|         $resource    = new FractalCollection($accounts, $transformer, 'accounts'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
| 
 | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|   | ||||
| @@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Models\Recurrence; | ||||
| use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment; | ||||
| use FireflyIII\Transformers\TransactionGroupTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| @@ -110,7 +111,11 @@ class ListController extends Controller | ||||
| 
 | ||||
|         $paginator    = $collector->getPaginatedGroups(); | ||||
|         $paginator->setPath(route('api.v1.transactions.index').$this->buildParams()); | ||||
|         $transactions = $paginator->getCollection(); | ||||
| 
 | ||||
|         // enrich
 | ||||
|         $enrichment   = new TransactionGroupEnrichment(); | ||||
|         $enrichment->setUser($admin); | ||||
|         $transactions = $enrichment->enrich($paginator->getCollection()); | ||||
| 
 | ||||
|         /** @var TransactionGroupTransformer $transformer */ | ||||
|         $transformer  = app(TransactionGroupTransformer::class); | ||||
|   | ||||
| @@ -29,6 +29,7 @@ use FireflyIII\Api\V1\Requests\Models\Rule\TestRequest; | ||||
| use FireflyIII\Api\V1\Requests\Models\Rule\TriggerRequest; | ||||
| use FireflyIII\Models\Rule; | ||||
| use FireflyIII\Repositories\Rule\RuleRepositoryInterface; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment; | ||||
| use FireflyIII\TransactionRules\Engine\RuleEngineInterface; | ||||
| use FireflyIII\Transformers\TransactionGroupTransformer; | ||||
| use FireflyIII\User; | ||||
| @@ -94,6 +95,11 @@ class TriggerController extends Controller | ||||
|         $transactions = $ruleEngine->find(); | ||||
|         $count        = $transactions->count(); | ||||
| 
 | ||||
|         // enrich
 | ||||
|         $enrichment   = new TransactionGroupEnrichment(); | ||||
|         $enrichment->setUser($rule->user); | ||||
|         $transactions = $enrichment->enrich($transactions); | ||||
| 
 | ||||
|         $paginator    = new LengthAwarePaginator($transactions, $count, 31337, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.rules.test', [$rule->id]).$this->buildParams()); | ||||
| 
 | ||||
|   | ||||
| @@ -30,6 +30,7 @@ use FireflyIII\Api\V1\Requests\Models\RuleGroup\TriggerRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\RuleGroup; | ||||
| use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment; | ||||
| use FireflyIII\TransactionRules\Engine\RuleEngineInterface; | ||||
| use FireflyIII\Transformers\TransactionGroupTransformer; | ||||
| use FireflyIII\User; | ||||
| @@ -100,6 +101,11 @@ class TriggerController extends Controller | ||||
|         $transactions = $ruleEngine->find(); | ||||
|         $count        = $transactions->count(); | ||||
| 
 | ||||
|         // enrich
 | ||||
|         $enrichment   = new TransactionGroupEnrichment(); | ||||
|         $enrichment->setUser($group->user); | ||||
|         $transactions = $enrichment->enrich($transactions); | ||||
| 
 | ||||
|         $paginator    = new LengthAwarePaginator($transactions, $count, 31337, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.rule-groups.test', [$group->id]).$this->buildParams()); | ||||
| 
 | ||||
|   | ||||
| @@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Models\Tag; | ||||
| use FireflyIII\Repositories\Tag\TagRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment; | ||||
| use FireflyIII\Transformers\AttachmentTransformer; | ||||
| use FireflyIII\Transformers\TransactionGroupTransformer; | ||||
| use FireflyIII\User; | ||||
| @@ -141,7 +142,12 @@ class ListController extends Controller | ||||
|         } | ||||
|         $paginator    = $collector->getPaginatedGroups(); | ||||
|         $paginator->setPath(route('api.v1.tags.transactions', [$tag->id]).$this->buildParams()); | ||||
|         $transactions = $paginator->getCollection(); | ||||
| 
 | ||||
|         // enrich
 | ||||
|         $enrichment   = new TransactionGroupEnrichment(); | ||||
|         $enrichment->setUser($admin); | ||||
|         $transactions = $enrichment->enrich($paginator->getCollection()); | ||||
| 
 | ||||
| 
 | ||||
|         /** @var TransactionGroupTransformer $transformer */ | ||||
|         $transformer  = app(TransactionGroupTransformer::class); | ||||
|   | ||||
| @@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Models\TransactionGroup; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment; | ||||
| use FireflyIII\Transformers\TransactionGroupTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| @@ -85,7 +86,11 @@ class ShowController extends Controller | ||||
|         } | ||||
|         $paginator    = $collector->getPaginatedGroups(); | ||||
|         $paginator->setPath(route('api.v1.transactions.index').$this->buildParams()); | ||||
|         $transactions = $paginator->getCollection(); | ||||
| 
 | ||||
|         // enrich
 | ||||
|         $enrichment   = new TransactionGroupEnrichment(); | ||||
|         $enrichment->setUser($admin); | ||||
|         $transactions = $enrichment->enrich($paginator->getCollection()); | ||||
| 
 | ||||
|         /** @var TransactionGroupTransformer $transformer */ | ||||
|         $transformer  = app(TransactionGroupTransformer::class); | ||||
| @@ -137,6 +142,11 @@ class ShowController extends Controller | ||||
|             throw new NotFoundHttpException(); | ||||
|         } | ||||
| 
 | ||||
|         // enrich
 | ||||
|         $enrichment    = new TransactionGroupEnrichment(); | ||||
|         $enrichment->setUser($admin); | ||||
|         $selectedGroup = $enrichment->enrichSingle($selectedGroup); | ||||
| 
 | ||||
|         /** @var TransactionGroupTransformer $transformer */ | ||||
|         $transformer   = app(TransactionGroupTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|   | ||||
| @@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Models\Transaction; | ||||
| 
 | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Api\V1\Requests\Models\Transaction\StoreRequest; | ||||
| use FireflyIII\Enums\UserRoleEnum; | ||||
| use FireflyIII\Events\StoredTransactionGroup; | ||||
| use FireflyIII\Exceptions\DuplicateTransactionException; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| @@ -33,10 +34,12 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface; | ||||
| use FireflyIII\Rules\IsDuplicateTransaction; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment; | ||||
| use FireflyIII\Transformers\TransactionGroupTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use Illuminate\Support\Facades\Validator; | ||||
| use Illuminate\Validation\ValidationException; | ||||
| use League\Fractal\Resource\Item; | ||||
| 
 | ||||
| @@ -49,6 +52,8 @@ class StoreController extends Controller | ||||
| 
 | ||||
|     private TransactionGroupRepositoryInterface $groupRepository; | ||||
| 
 | ||||
|     protected array $acceptedRoles = [UserRoleEnum::MANAGE_TRANSACTIONS]; | ||||
| 
 | ||||
|     /** | ||||
|      * TransactionController constructor. | ||||
|      */ | ||||
| @@ -59,9 +64,11 @@ class StoreController extends Controller | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $admin */ | ||||
|                 $admin                 = auth()->user(); | ||||
|                 $userGroup             = $this->validateUserGroup($request); | ||||
| 
 | ||||
|                 $this->groupRepository = app(TransactionGroupRepositoryInterface::class); | ||||
|                 $this->groupRepository->setUser($admin); | ||||
|                 $this->groupRepository->setUserGroup($userGroup); | ||||
| 
 | ||||
|                 return $next($request); | ||||
|             } | ||||
| @@ -79,61 +86,63 @@ class StoreController extends Controller | ||||
|     public function store(StoreRequest $request): JsonResponse | ||||
|     { | ||||
|         app('log')->debug('Now in API StoreController::store()'); | ||||
|         $data          = $request->getAll(); | ||||
|         $data['user']  = auth()->user()->id; | ||||
|         $data               = $request->getAll(); | ||||
|         $data['user']       = auth()->user(); | ||||
|         $data['user_group'] = $this->userGroup; | ||||
| 
 | ||||
|         Log::channel('audit') | ||||
|             ->info('Store new transaction over API.', $data) | ||||
|         ; | ||||
|         Log::channel('audit')->info('Store new transaction over API.', $data); | ||||
| 
 | ||||
|         try { | ||||
|             $transactionGroup = $this->groupRepository->store($data); | ||||
|         } catch (DuplicateTransactionException $e) { | ||||
|             app('log')->warning('Caught a duplicate transaction. Return error message.'); | ||||
|             $validator = \Validator::make( | ||||
|                 ['transactions' => [['description' => $e->getMessage()]]], | ||||
|                 ['transactions.0.description' => new IsDuplicateTransaction()] | ||||
|             ); | ||||
|             $validator = Validator::make(['transactions' => [['description' => $e->getMessage()]]], ['transactions.0.description' => new IsDuplicateTransaction()]); | ||||
| 
 | ||||
|             throw new ValidationException($validator); | ||||
|         } catch (FireflyException $e) { | ||||
|             app('log')->warning('Caught an exception. Return error message.'); | ||||
|             app('log')->error($e->getMessage()); | ||||
|             $message   = sprintf('Internal exception: %s', $e->getMessage()); | ||||
|             $validator = \Validator::make(['transactions' => [['description' => $message]]], ['transactions.0.description' => new IsDuplicateTransaction()]); | ||||
|             $validator = Validator::make(['transactions' => [['description' => $message]]], ['transactions.0.description' => new IsDuplicateTransaction()]); | ||||
| 
 | ||||
|             throw new ValidationException($validator); | ||||
|         } | ||||
|         app('preferences')->mark(); | ||||
|         $applyRules    = $data['apply_rules'] ?? true; | ||||
|         $fireWebhooks  = $data['fire_webhooks'] ?? true; | ||||
|         $applyRules         = $data['apply_rules'] ?? true; | ||||
|         $fireWebhooks       = $data['fire_webhooks'] ?? true; | ||||
|         event(new StoredTransactionGroup($transactionGroup, $applyRules, $fireWebhooks)); | ||||
| 
 | ||||
|         $manager       = $this->getManager(); | ||||
|         $manager            = $this->getManager(); | ||||
| 
 | ||||
|         /** @var User $admin */ | ||||
|         $admin         = auth()->user(); | ||||
|         $admin              = auth()->user(); | ||||
| 
 | ||||
|         // use new group collector:
 | ||||
|         /** @var GroupCollectorInterface $collector */ | ||||
|         $collector     = app(GroupCollectorInterface::class); | ||||
|         $collector          = app(GroupCollectorInterface::class); | ||||
|         $collector | ||||
|             ->setUser($admin) | ||||
|             ->setUserGroup($this->userGroup) | ||||
|             // filter on transaction group.
 | ||||
|             ->setTransactionGroup($transactionGroup) | ||||
|             // all info needed for the API:
 | ||||
|             ->withAPIInformation() | ||||
|         ; | ||||
| 
 | ||||
|         $selectedGroup = $collector->getGroups()->first(); | ||||
|         $selectedGroup      = $collector->getGroups()->first(); | ||||
|         if (null === $selectedGroup) { | ||||
|             throw new FireflyException('200032: Cannot find transaction. Possibly, a rule deleted this transaction after its creation.'); | ||||
|         } | ||||
| 
 | ||||
|         // enrich
 | ||||
|         $enrichment         = new TransactionGroupEnrichment(); | ||||
|         $enrichment->setUser($admin); | ||||
|         $selectedGroup      = $enrichment->enrichSingle($selectedGroup); | ||||
| 
 | ||||
|         /** @var TransactionGroupTransformer $transformer */ | ||||
|         $transformer   = app(TransactionGroupTransformer::class); | ||||
|         $transformer        = app(TransactionGroupTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|         $resource      = new Item($selectedGroup, $transformer, 'transactions'); | ||||
|         $resource           = new Item($selectedGroup, $transformer, 'transactions'); | ||||
| 
 | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|   | ||||
| @@ -30,6 +30,7 @@ use FireflyIII\Events\UpdatedTransactionGroup; | ||||
| use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Models\TransactionGroup; | ||||
| use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment; | ||||
| use FireflyIII\Transformers\TransactionGroupTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| @@ -99,6 +100,11 @@ class UpdateController extends Controller | ||||
|             throw new NotFoundHttpException(); | ||||
|         } | ||||
| 
 | ||||
|         // enrich
 | ||||
|         $enrichment       = new TransactionGroupEnrichment(); | ||||
|         $enrichment->setUser($admin); | ||||
|         $selectedGroup    = $enrichment->enrichSingle($selectedGroup); | ||||
| 
 | ||||
|         /** @var TransactionGroupTransformer $transformer */ | ||||
|         $transformer      = app(TransactionGroupTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|   | ||||
| @@ -42,6 +42,8 @@ use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; | ||||
| use FireflyIII\Repositories\Rule\RuleRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\AccountFilter; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment; | ||||
| use FireflyIII\Transformers\AccountTransformer; | ||||
| use FireflyIII\Transformers\AvailableBudgetTransformer; | ||||
| use FireflyIII\Transformers\BillTransformer; | ||||
| @@ -100,6 +102,15 @@ class ListController extends Controller | ||||
|         $count             = $collection->count(); | ||||
|         $accounts          = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
| 
 | ||||
|         // enrich
 | ||||
|         /** @var User $admin */ | ||||
|         $admin             = auth()->user(); | ||||
|         $enrichment        = new AccountEnrichment(); | ||||
|         $enrichment->setUser($admin); | ||||
|         $enrichment->setConvertToNative($this->convertToNative); | ||||
|         $enrichment->setNative($this->nativeCurrency); | ||||
|         $accounts          = $enrichment->enrich($accounts); | ||||
| 
 | ||||
|         // make paginator:
 | ||||
|         $paginator         = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.currencies.accounts', [$currency->code]).$this->buildParams()); | ||||
| @@ -236,7 +247,7 @@ class ListController extends Controller | ||||
|         // get list of budgets. Count it and split it.
 | ||||
|         /** @var RecurringRepositoryInterface $recurringRepos */ | ||||
|         $recurringRepos = app(RecurringRepositoryInterface::class); | ||||
|         $unfiltered     = $recurringRepos->getAll(); | ||||
|         $unfiltered     = $recurringRepos->get(); | ||||
| 
 | ||||
|         // filter selection
 | ||||
|         $collection     = $unfiltered->filter( | ||||
| @@ -360,7 +371,11 @@ class ListController extends Controller | ||||
|         } | ||||
|         $paginator    = $collector->getPaginatedGroups(); | ||||
|         $paginator->setPath(route('api.v1.currencies.transactions', [$currency->code]).$this->buildParams()); | ||||
|         $transactions = $paginator->getCollection(); | ||||
| 
 | ||||
|         // enrich
 | ||||
|         $enrichment   = new TransactionGroupEnrichment(); | ||||
|         $enrichment->setUser($admin); | ||||
|         $transactions = $enrichment->enrich($paginator->getCollection()); | ||||
| 
 | ||||
|         /** @var TransactionGroupTransformer $transformer */ | ||||
|         $transformer  = app(TransactionGroupTransformer::class); | ||||
|   | ||||
| @@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Models\LinkType; | ||||
| use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment; | ||||
| use FireflyIII\Transformers\TransactionGroupTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| @@ -109,7 +110,11 @@ class ListController extends Controller | ||||
|         } | ||||
|         $paginator    = $collector->getPaginatedGroups(); | ||||
|         $paginator->setPath(route('api.v1.transactions.index').$this->buildParams()); | ||||
|         $transactions = $paginator->getCollection(); | ||||
| 
 | ||||
|         // enrich
 | ||||
|         $enrichment   = new TransactionGroupEnrichment(); | ||||
|         $enrichment->setUser($admin); | ||||
|         $transactions = $enrichment->enrich($paginator->getCollection()); | ||||
| 
 | ||||
|         /** @var TransactionGroupTransformer $transformer */ | ||||
|         $transformer  = app(TransactionGroupTransformer::class); | ||||
|   | ||||
| @@ -26,8 +26,10 @@ namespace FireflyIII\Api\V1\Controllers\Search; | ||||
| 
 | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Support\Http\Api\AccountFilter; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment; | ||||
| use FireflyIII\Support\Search\AccountSearch; | ||||
| use FireflyIII\Transformers\AccountTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Http\Response; | ||||
| @@ -81,6 +83,15 @@ class AccountController extends Controller | ||||
| 
 | ||||
|         $accounts    = $search->search(); | ||||
| 
 | ||||
|         // enrich
 | ||||
|         /** @var User $admin */ | ||||
|         $admin       = auth()->user(); | ||||
|         $enrichment  = new AccountEnrichment(); | ||||
|         $enrichment->setUser($admin); | ||||
|         $enrichment->setConvertToNative($this->convertToNative); | ||||
|         $enrichment->setNative($this->nativeCurrency); | ||||
|         $accounts    = $enrichment->enrich($accounts); | ||||
| 
 | ||||
|         /** @var AccountTransformer $transformer */ | ||||
|         $transformer = app(AccountTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|   | ||||
| @@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Search; | ||||
| 
 | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment; | ||||
| use FireflyIII\Support\Search\SearchInterface; | ||||
| use FireflyIII\Transformers\TransactionGroupTransformer; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| @@ -57,7 +58,11 @@ class TransactionController extends Controller | ||||
|         $parameters   = ['search' => $fullQuery]; | ||||
|         $url          = route('api.v1.search.transactions').'?'.http_build_query($parameters); | ||||
|         $groups->setPath($url); | ||||
|         $transactions = $groups->getCollection(); | ||||
| 
 | ||||
|         // enrich
 | ||||
|         $enrichment   = new TransactionGroupEnrichment(); | ||||
|         $enrichment->setUser(auth()->user()); | ||||
|         $transactions = $enrichment->enrich($groups->getCollection()); | ||||
| 
 | ||||
|         /** @var TransactionGroupTransformer $transformer */ | ||||
|         $transformer  = app(TransactionGroupTransformer::class); | ||||
|   | ||||
| @@ -102,7 +102,7 @@ class BasicController extends Controller | ||||
|         $balanceData  = $this->getBalanceInformation($start, $end); | ||||
|         $billData     = $this->getBillInformation($start, $end); | ||||
|         $spentData    = $this->getLeftToSpendInfo($start, $end); | ||||
|         $netWorthData = $this->getNetWorthInfo($start, $end); | ||||
|         $netWorthData = $this->getNetWorthInfo($end); | ||||
|         //                $balanceData  = [];
 | ||||
|         //                $billData     = [];
 | ||||
|         //                $spentData    = [];
 | ||||
| @@ -319,18 +319,13 @@ class BasicController extends Controller | ||||
|         return $return; | ||||
|     } | ||||
| 
 | ||||
|     private function getNetWorthInfo(Carbon $start, Carbon $end): array | ||||
|     private function getNetWorthInfo(Carbon $end): array | ||||
|     { | ||||
|         Log::debug('getNetWorthInfo'); | ||||
|         $end->endOfDay(); | ||||
| 
 | ||||
|         /** @var User $user */ | ||||
|         $user           = auth()->user(); | ||||
|         $date           = now(config('app.timezone')); | ||||
|         // start and end in the future? use $end
 | ||||
|         if ($this->notInDateRange($date, $start, $end)) { | ||||
|             /** @var Carbon $date */ | ||||
|             $date = session('end', today(config('app.timezone'))->endOfMonth()); | ||||
|         } | ||||
|         Log::debug(sprintf('getNetWorthInfo up until "%s".', $end->format('Y-m-d H:i:s'))); | ||||
| 
 | ||||
|         /** @var NetWorthInterface $netWorthHelper */ | ||||
|         $netWorthHelper = app(NetWorthInterface::class); | ||||
| @@ -346,7 +341,7 @@ class BasicController extends Controller | ||||
|             } | ||||
|         ); | ||||
| 
 | ||||
|         $netWorthSet    = $netWorthHelper->byAccounts($filtered, $date); | ||||
|         $netWorthSet    = $netWorthHelper->byAccounts($filtered, $end); | ||||
|         $return         = []; | ||||
|         foreach ($netWorthSet as $key => $data) { | ||||
|             if ('native' === $key) { | ||||
| @@ -370,6 +365,22 @@ class BasicController extends Controller | ||||
|                 'sub_title'               => '', | ||||
|             ]; | ||||
|         } | ||||
|         if (0 === count($return)) { | ||||
|             $return[] = [ | ||||
|                 'key'                     => sprintf('net-worth-in-%s', $this->nativeCurrency->code), | ||||
|                 'title'                   => trans('firefly.box_net_worth_in_currency', ['currency' => $this->nativeCurrency->symbol]), | ||||
|                 'monetary_value'          => '0', | ||||
|                 'currency_id'             => (string) $this->nativeCurrency->id, | ||||
|                 'currency_code'           => $this->nativeCurrency->code, | ||||
|                 'currency_symbol'         => $this->nativeCurrency->symbol, | ||||
|                 'currency_decimal_places' => $this->nativeCurrency->decimal_places, | ||||
|                 'value_parsed'            => app('amount')->formatFlat($this->nativeCurrency->symbol, $this->nativeCurrency->decimal_places, '0', false), | ||||
|                 'local_icon'              => 'line-chart', | ||||
|                 'sub_title'               => '', | ||||
|             ]; | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         Log::debug('End of getNetWorthInfo'); | ||||
| 
 | ||||
|         return $return; | ||||
|   | ||||
| @@ -27,6 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\System; | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Transformers\UserTransformer; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Support\Facades\DB; | ||||
| use League\Fractal\Resource\Item; | ||||
| 
 | ||||
| /** | ||||
| @@ -48,7 +49,7 @@ class AboutController extends Controller | ||||
|         $replace       = ['\~', '# ']; | ||||
|         $phpVersion    = str_replace($search, $replace, PHP_VERSION); | ||||
|         $phpOs         = str_replace($search, $replace, PHP_OS); | ||||
|         $currentDriver = \DB::getDriverName(); | ||||
|         $currentDriver = DB::getDriverName(); | ||||
|         $data | ||||
|                        = [ | ||||
|                            'version'     => config('firefly.version'), | ||||
|   | ||||
| @@ -65,7 +65,7 @@ class TestRequest extends FormRequest | ||||
| 
 | ||||
|     private function getAccounts(): array | ||||
|     { | ||||
|         return $this->get('accounts'); | ||||
|         return $this->get('accounts') ?? []; | ||||
|     } | ||||
| 
 | ||||
|     public function rules(): array | ||||
|   | ||||
| @@ -59,7 +59,7 @@ class TestRequest extends FormRequest | ||||
| 
 | ||||
|     private function getAccounts(): array | ||||
|     { | ||||
|         return $this->get('accounts'); | ||||
|         return $this->get('accounts') ?? []; | ||||
|     } | ||||
| 
 | ||||
|     public function rules(): array | ||||
|   | ||||
| @@ -31,6 +31,7 @@ use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Support\Chart\ChartData; | ||||
| use FireflyIII\Support\Facades\Steam; | ||||
| use FireflyIII\Support\Http\Api\CleansChartData; | ||||
| use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter; | ||||
| use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; | ||||
| @@ -118,7 +119,7 @@ class AccountController extends Controller | ||||
|             'native_entries'                 => [], | ||||
|         ]; | ||||
|         $currentStart   = clone $params['start']; | ||||
|         $range          = app('steam')->finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $this->convertToNative); | ||||
|         $range          = Steam::finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $this->convertToNative); | ||||
| 
 | ||||
|         $previous       = array_values($range)[0]['balance']; | ||||
|         $previousNative = array_values($range)[0]['native_balance']; | ||||
|   | ||||
| @@ -21,25 +21,6 @@ | ||||
|  */ | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| /* | ||||
|  * ConvertDatesToUTC.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/. | ||||
|  */ | ||||
| 
 | ||||
| namespace FireflyIII\Console\Commands\Correction; | ||||
| 
 | ||||
|   | ||||
| @@ -25,6 +25,7 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Console\Commands\Correction; | ||||
| 
 | ||||
| use FireflyIII\Console\Commands\ShowsFriendlyMessages; | ||||
| use FireflyIII\Enums\TransactionTypeEnum; | ||||
| use FireflyIII\Models\AutoBudget; | ||||
| use FireflyIII\Models\AvailableBudget; | ||||
| use FireflyIII\Models\Bill; | ||||
| @@ -33,8 +34,14 @@ use FireflyIII\Models\CurrencyExchangeRate; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\RecurrenceTransaction; | ||||
| use FireflyIII\Models\RuleTrigger; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use Illuminate\Console\Command; | ||||
| use Illuminate\Support\Facades\DB; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| 
 | ||||
| class CorrectsAmounts extends Command | ||||
| { | ||||
| @@ -45,6 +52,8 @@ class CorrectsAmounts extends Command | ||||
| 
 | ||||
|     public function handle(): int | ||||
|     { | ||||
|         // transfers must not have foreign currency info if both accounts have the same currency.
 | ||||
|         $this->correctTransfers(); | ||||
|         // auto budgets must be positive
 | ||||
|         $this->fixAutoBudgets(); | ||||
|         // available budgets must be positive
 | ||||
| @@ -62,6 +71,7 @@ class CorrectsAmounts extends Command | ||||
|         // rule_triggers must be positive or zero (amount_less, amount_more, amount_is)
 | ||||
|         $this->fixRuleTriggers(); | ||||
| 
 | ||||
| 
 | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
| @@ -182,4 +192,63 @@ class CorrectsAmounts extends Command | ||||
| 
 | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     private function correctTransfers(): void | ||||
|     { | ||||
|         /** @var AccountRepositoryInterface $repository */ | ||||
|         $repository = app(AccountRepositoryInterface::class); | ||||
|         $type       = TransactionType::where('type', TransactionTypeEnum::TRANSFER->value)->first(); | ||||
|         $journals   = TransactionJournal::where('transaction_type_id', $type->id)->get(); | ||||
| 
 | ||||
|         /** @var TransactionJournal $journal */ | ||||
|         foreach ($journals as $journal) { | ||||
|             $repository->setUser($journal->user); | ||||
|             $native         = Amount::getNativeCurrencyByUserGroup($journal->userGroup); | ||||
| 
 | ||||
|             /** @var null|Transaction $source */ | ||||
|             $source         = $journal->transactions()->where('amount', '<', 0)->first(); | ||||
| 
 | ||||
|             /** @var null|Transaction $destination */ | ||||
|             $destination    = $journal->transactions()->where('amount', '>', 0)->first(); | ||||
|             if (null === $source || null === $destination) { | ||||
|                 continue; | ||||
|             } | ||||
|             if (null === $source->foreign_currency_id || null === $destination->foreign_currency_id) { | ||||
|                 continue; | ||||
|             } | ||||
|             $sourceAccount  = $source->account; | ||||
|             $destAccount    = $destination->account; | ||||
|             if (null === $sourceAccount || null === $destAccount) { | ||||
|                 continue; | ||||
|             } | ||||
|             $sourceCurrency = $repository->getAccountCurrency($sourceAccount) ?? $native; | ||||
|             $destCurrency   = $repository->getAccountCurrency($destAccount) ?? $native; | ||||
| 
 | ||||
|             if ($sourceCurrency->id === $destCurrency->id) { | ||||
|                 Log::debug('Both accounts have the same currency. Removing foreign currency info.'); | ||||
|                 $source->foreign_currency_id      = null; | ||||
|                 $source->foreign_amount           = null; | ||||
|                 $source->save(); | ||||
|                 $destination->foreign_currency_id = null; | ||||
|                 $destination->foreign_amount      = null; | ||||
|                 $destination->save(); | ||||
| 
 | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             // validate source
 | ||||
|             if ($destCurrency->id !== $source->foreign_currency_id) { | ||||
|                 Log::debug(sprintf('Journal #%d: Transaction #%d refers to "%s" but should refer to "%s".', $journal->id, $source->id, $source->foreignCurrency->code, $destCurrency->code)); | ||||
|                 $source->foreign_currency_id = $destCurrency->id; | ||||
|                 $source->save(); | ||||
|             } | ||||
| 
 | ||||
|             // validate destination:
 | ||||
|             if ($sourceCurrency->id !== $destination->foreign_currency_id) { | ||||
|                 Log::debug(sprintf('Journal #%d: Transaction #%d refers to "%s" but should refer to "%s".', $journal->id, $destination->id, $destination->foreignCurrency->code, $sourceCurrency->code)); | ||||
|                 $destination->foreign_currency_id = $sourceCurrency->id; | ||||
|                 $destination->save(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -30,6 +30,7 @@ use FireflyIII\Handlers\Events\UpdatedGroupEventHandler; | ||||
| use FireflyIII\Models\TransactionGroup; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Illuminate\Console\Command; | ||||
| use Illuminate\Support\Facades\DB; | ||||
| 
 | ||||
| class CorrectsGroupAccounts extends Command | ||||
| { | ||||
| @@ -45,7 +46,7 @@ class CorrectsGroupAccounts extends Command | ||||
|     { | ||||
|         $groups  = []; | ||||
|         $res     = TransactionJournal::groupBy('transaction_group_id') | ||||
|             ->get(['transaction_group_id', \DB::raw('COUNT(transaction_group_id) as the_count')])// @phpstan-ignore-line
 | ||||
|             ->get(['transaction_group_id', DB::raw('COUNT(transaction_group_id) as the_count')])// @phpstan-ignore-line
 | ||||
|         ; | ||||
| 
 | ||||
|         /** @var TransactionJournal $journal */ | ||||
|   | ||||
| @@ -33,6 +33,7 @@ use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\Category; | ||||
| use FireflyIII\Models\CurrencyExchangeRate; | ||||
| use FireflyIII\Models\ObjectGroup; | ||||
| use FireflyIII\Models\Preference; | ||||
| use FireflyIII\Models\Recurrence; | ||||
| use FireflyIII\Models\Rule; | ||||
| use FireflyIII\Models\RuleGroup; | ||||
| @@ -89,6 +90,7 @@ class CorrectsGroupInformation extends Command | ||||
|             Category::class, | ||||
|             ObjectGroup::class, | ||||
|             CurrencyExchangeRate::class, | ||||
|             Preference::class, | ||||
|             Recurrence::class, | ||||
|             RuleGroup::class, | ||||
|             Rule::class, | ||||
|   | ||||
| @@ -102,7 +102,14 @@ class CorrectsNativeAmounts extends Command | ||||
|     { | ||||
|         $set = $userGroup->accounts()->where(function (EloquentBuilder $q): void { | ||||
|             $q->whereNotNull('virtual_balance'); | ||||
|             $q->orWhere('virtual_balance', '!=', ''); | ||||
| 
 | ||||
|             // this needs a different piece of code for postgres.
 | ||||
|             if ('pgsql' === config('database.default')) { | ||||
|                 $q->orWhere(DB::raw('CAST(virtual_balance AS TEXT)'), '!=', ''); | ||||
|             } | ||||
|             if ('pgsql' !== config('database.default')) { | ||||
|                 $q->orWhere('virtual_balance', '!=', ''); | ||||
|             } | ||||
|         })->get(); | ||||
| 
 | ||||
|         /** @var Account $account */ | ||||
| @@ -218,7 +225,6 @@ class CorrectsNativeAmounts extends Command | ||||
|         $set                              = DB::table('transactions') | ||||
|             ->join('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') | ||||
|             ->where('transaction_journals.user_group_id', $userGroup->id) | ||||
| 
 | ||||
|             ->where(function (DatabaseBuilder $q1) use ($currency): void { | ||||
|                 $q1->where(function (DatabaseBuilder $q2) use ($currency): void { | ||||
|                     $q2->whereNot('transactions.transaction_currency_id', $currency->id)->whereNull('transactions.foreign_currency_id'); | ||||
|   | ||||
| @@ -21,25 +21,6 @@ | ||||
|  */ | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| /* | ||||
|  * AddTimezonesToDates.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/. | ||||
|  */ | ||||
| 
 | ||||
| namespace FireflyIII\Console\Commands\Correction; | ||||
| 
 | ||||
|   | ||||
| @@ -30,6 +30,7 @@ use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Support\Models\AccountBalanceCalculator; | ||||
| use Illuminate\Console\Command; | ||||
| use Illuminate\Support\Facades\DB; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| 
 | ||||
| class CorrectsUnevenAmount extends Command | ||||
| @@ -118,10 +119,10 @@ class CorrectsUnevenAmount extends Command | ||||
| 
 | ||||
|     private function fixUnevenAmounts(): void | ||||
|     { | ||||
|         $journals = \DB::table('transactions') | ||||
|         $journals = DB::table('transactions') | ||||
|             ->groupBy('transaction_journal_id') | ||||
|             ->whereNull('deleted_at') | ||||
|             ->get(['transaction_journal_id', \DB::raw('SUM(amount) AS the_sum')])  // @phpstan-ignore-line
 | ||||
|             ->get(['transaction_journal_id', DB::raw('SUM(amount) AS the_sum')])  // @phpstan-ignore-line
 | ||||
|         ; | ||||
| 
 | ||||
|         /** @var \stdClass $entry */ | ||||
| @@ -262,7 +263,7 @@ class CorrectsUnevenAmount extends Command | ||||
|     private function matchCurrencies(): void | ||||
|     { | ||||
|         $journals = TransactionJournal::leftJoin('transactions', 'transaction_journals.id', 'transactions.transaction_journal_id') | ||||
|             ->where('transactions.transaction_currency_id', '!=', \DB::raw('transaction_journals.transaction_currency_id')) | ||||
|             ->where('transactions.transaction_currency_id', '!=', DB::raw('transaction_journals.transaction_currency_id')) | ||||
|             ->get(['transaction_journals.*']) | ||||
|         ; | ||||
| 
 | ||||
|   | ||||
| @@ -29,6 +29,7 @@ use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Illuminate\Console\Command; | ||||
| use Illuminate\Database\QueryException; | ||||
| use Illuminate\Support\Facades\DB; | ||||
| 
 | ||||
| class RemovesEmptyJournals extends Command | ||||
| { | ||||
| @@ -56,7 +57,7 @@ class RemovesEmptyJournals extends Command | ||||
|     { | ||||
|         $set   = Transaction::whereNull('deleted_at') | ||||
|             ->groupBy('transactions.transaction_journal_id') | ||||
|             ->get([\DB::raw('COUNT(transactions.transaction_journal_id) as the_count'), 'transaction_journal_id']) // @phpstan-ignore-line
 | ||||
|             ->get([DB::raw('COUNT(transactions.transaction_journal_id) as the_count'), 'transaction_journal_id']) // @phpstan-ignore-line
 | ||||
|         ; | ||||
|         $total = 0; | ||||
| 
 | ||||
|   | ||||
| @@ -57,7 +57,7 @@ class ExportsData extends Command | ||||
|     {--export-tags : Create a file with all your tags and some meta data.} | ||||
|     {--export-recurring : Create a file with all your recurring transactions and some meta data.} | ||||
|     {--export-rules : Create a file with all your rules and some meta data.} | ||||
|     {--export-bills : Create a file with all your bills and some meta data.} | ||||
|     {--export-subscriptions : Create a file with all your subscriptions and some meta data.} | ||||
|     {--export-piggies : Create a file with all your piggy banks and some meta data.} | ||||
|     {--force : Force overwriting of previous exports if found.}'; | ||||
|     private AccountRepositoryInterface $accountRepository; | ||||
| @@ -157,7 +157,7 @@ class ExportsData extends Command | ||||
|                 'tags'         => $this->option('export-tags'), | ||||
|                 'recurring'    => $this->option('export-recurring'), | ||||
|                 'rules'        => $this->option('export-rules'), | ||||
|                 'bills'        => $this->option('export-bills'), | ||||
|                 'bills'        => $this->option('export-subscriptions'), | ||||
|                 'piggies'      => $this->option('export-piggies'), | ||||
|             ], | ||||
|             'start'     => $start, | ||||
|   | ||||
| @@ -31,6 +31,7 @@ use FireflyIII\Support\Cronjobs\AutoBudgetCronjob; | ||||
| use FireflyIII\Support\Cronjobs\BillWarningCronjob; | ||||
| use FireflyIII\Support\Cronjobs\ExchangeRatesCronjob; | ||||
| use FireflyIII\Support\Cronjobs\RecurringCronjob; | ||||
| use FireflyIII\Support\Cronjobs\UpdateCheckCronjob; | ||||
| use Illuminate\Console\Command; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| 
 | ||||
| @@ -43,6 +44,7 @@ class Cron extends Command | ||||
|     protected $signature   = 'firefly-iii:cron | ||||
|         {--F|force : Force the cron job(s) to execute.} | ||||
|         {--date= : Set the date in YYYY-MM-DD to make Firefly III think that\'s the current date.} | ||||
|         {--check-version : Check if there is a new Firefly III version. Other tasks will be skipped unless also requested.} | ||||
|         {--download-cer : Download exchange rates. Other tasks will be skipped unless also requested.} | ||||
|         {--create-recurring : Create recurring transactions. Other tasks will be skipped unless also requested.} | ||||
|         {--create-auto-budgets : Create auto budgets. Other tasks will be skipped unless also requested.} | ||||
| @@ -51,7 +53,11 @@ class Cron extends Command | ||||
| 
 | ||||
|     public function handle(): int | ||||
|     { | ||||
|         $doAll = !$this->option('download-cer') && !$this->option('create-recurring') && !$this->option('create-auto-budgets') && !$this->option('send-bill-warnings'); | ||||
|         $doAll = !$this->option('download-cer') | ||||
|                  && !$this->option('create-recurring') | ||||
|                  && !$this->option('create-auto-budgets') | ||||
|                  && !$this->option('send-bill-warnings') | ||||
|                  && !$this->option('check-version'); | ||||
|         $date  = null; | ||||
| 
 | ||||
|         try { | ||||
| @@ -72,6 +78,17 @@ class Cron extends Command | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // check for new version
 | ||||
|         if ($doAll || $this->option('check-version')) { | ||||
|             try { | ||||
|                 $this->checkForUpdates($force); | ||||
|             } catch (FireflyException $e) { | ||||
|                 app('log')->error($e->getMessage()); | ||||
|                 app('log')->error($e->getTraceAsString()); | ||||
|                 $this->friendlyError($e->getMessage()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Fire recurring transaction cron job.
 | ||||
|         if ($doAll || $this->option('create-recurring')) { | ||||
|             try { | ||||
| @@ -204,4 +221,21 @@ class Cron extends Command | ||||
|             $this->friendlyPositive(sprintf('"Send bill warnings" cron ran with success: %s', $autoBudget->message)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private function checkForUpdates(bool $force): void | ||||
|     { | ||||
|         $updateCheck = new UpdateCheckCronjob(); | ||||
|         $updateCheck->setForce($force); | ||||
|         $updateCheck->fire(); | ||||
| 
 | ||||
|         if ($updateCheck->jobErrored) { | ||||
|             $this->friendlyError(sprintf('Error in "update check" cron: %s', $updateCheck->message)); | ||||
|         } | ||||
|         if ($updateCheck->jobFired) { | ||||
|             $this->friendlyInfo(sprintf('"Update check" cron fired: %s', $updateCheck->message)); | ||||
|         } | ||||
|         if ($updateCheck->jobSucceeded) { | ||||
|             $this->friendlyPositive(sprintf('"Update check" cron ran with success: %s', $updateCheck->message)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -29,6 +29,7 @@ use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\Preference; | ||||
| use Illuminate\Console\Command; | ||||
| use Illuminate\Contracts\Encryption\DecryptException; | ||||
| use Illuminate\Support\Facades\DB; | ||||
| 
 | ||||
| class RemovesDatabaseDecryption extends Command | ||||
| { | ||||
| @@ -101,7 +102,7 @@ class RemovesDatabaseDecryption extends Command | ||||
| 
 | ||||
|     private function decryptField(string $table, string $field): void | ||||
|     { | ||||
|         $rows = \DB::table($table)->get(['id', $field]); | ||||
|         $rows = DB::table($table)->get(['id', $field]); | ||||
| 
 | ||||
|         /** @var \stdClass $row */ | ||||
|         foreach ($rows as $row) { | ||||
| @@ -135,7 +136,7 @@ class RemovesDatabaseDecryption extends Command | ||||
|         } | ||||
| 
 | ||||
|         if ($value !== $original) { | ||||
|             \DB::table($table)->where('id', $id)->update([$field => $value]); | ||||
|             DB::table($table)->where('id', $id)->update([$field => $value]); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|   | ||||
| @@ -26,6 +26,7 @@ namespace FireflyIII\Console\Commands\Upgrade; | ||||
| 
 | ||||
| use FireflyIII\Console\Commands\ShowsFriendlyMessages; | ||||
| use Illuminate\Console\Command; | ||||
| use Illuminate\Support\Facades\DB; | ||||
| 
 | ||||
| class RepairsPostgresSequences extends Command | ||||
| { | ||||
| @@ -40,7 +41,7 @@ class RepairsPostgresSequences extends Command | ||||
|      */ | ||||
|     public function handle(): int | ||||
|     { | ||||
|         if ('pgsql' !== \DB::connection()->getName()) { | ||||
|         if ('pgsql' !== DB::connection()->getName()) { | ||||
|             return 0; | ||||
|         } | ||||
|         $this->friendlyLine('Going to verify PostgreSQL table sequences.'); | ||||
| @@ -49,8 +50,8 @@ class RepairsPostgresSequences extends Command | ||||
|         foreach ($tablesToCheck as $tableToCheck) { | ||||
|             $this->friendlyLine(sprintf('Checking the next id sequence for table "%s".', $tableToCheck)); | ||||
| 
 | ||||
|             $highestId = \DB::table($tableToCheck)->select(\DB::raw('MAX(id)'))->first(); | ||||
|             $nextId    = \DB::table($tableToCheck)->select(\DB::raw(sprintf('nextval(\'%s_id_seq\')', $tableToCheck)))->first(); | ||||
|             $highestId = DB::table($tableToCheck)->select(DB::raw('MAX(id)'))->first(); | ||||
|             $nextId    = DB::table($tableToCheck)->select(DB::raw(sprintf('nextval(\'%s_id_seq\')', $tableToCheck)))->first(); | ||||
|             if (null === $nextId) { | ||||
|                 $this->friendlyInfo(sprintf('nextval is NULL for table "%s", go to next table.', $tableToCheck)); | ||||
| 
 | ||||
| @@ -58,9 +59,9 @@ class RepairsPostgresSequences extends Command | ||||
|             } | ||||
| 
 | ||||
|             if ($nextId->nextval < $highestId->max) { // @phpstan-ignore-line
 | ||||
|                 \DB::select(sprintf('SELECT setval(\'%s_id_seq\', %d)', $tableToCheck, $highestId->max)); | ||||
|                 $highestId = \DB::table($tableToCheck)->select(\DB::raw('MAX(id)'))->first(); | ||||
|                 $nextId    = \DB::table($tableToCheck)->select(\DB::raw(sprintf('nextval(\'%s_id_seq\')', $tableToCheck)))->first(); | ||||
|                 DB::select(sprintf('SELECT setval(\'%s_id_seq\', %d)', $tableToCheck, $highestId->max)); | ||||
|                 $highestId = DB::table($tableToCheck)->select(DB::raw('MAX(id)'))->first(); | ||||
|                 $nextId    = DB::table($tableToCheck)->select(DB::raw(sprintf('nextval(\'%s_id_seq\')', $tableToCheck)))->first(); | ||||
|                 if ($nextId->nextval > $highestId->max) { // @phpstan-ignore-line
 | ||||
|                     $this->friendlyInfo(sprintf('Table "%s" autoincrement corrected.', $tableToCheck)); | ||||
|                 } | ||||
|   | ||||
| @@ -31,6 +31,7 @@ use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Illuminate\Console\Command; | ||||
| use Illuminate\Support\Collection; | ||||
| use Illuminate\Support\Facades\DB; | ||||
| 
 | ||||
| class UpgradesJournalMetaData extends Command | ||||
| { | ||||
| @@ -86,8 +87,8 @@ class UpgradesJournalMetaData extends Command | ||||
|         $this->migrateCategories(); | ||||
| 
 | ||||
|         // empty tables
 | ||||
|         \DB::table('budget_transaction')->delete(); | ||||
|         \DB::table('category_transaction')->delete(); | ||||
|         DB::table('budget_transaction')->delete(); | ||||
|         DB::table('category_transaction')->delete(); | ||||
|     } | ||||
| 
 | ||||
|     private function migrateBudgets(): void | ||||
| @@ -108,12 +109,12 @@ class UpgradesJournalMetaData extends Command | ||||
| 
 | ||||
|     private function getIdsForBudgets(): array | ||||
|     { | ||||
|         $transactions = \DB::table('budget_transaction')->distinct()->pluck('transaction_id')->toArray(); | ||||
|         $transactions = DB::table('budget_transaction')->distinct()->pluck('transaction_id')->toArray(); | ||||
|         $array        = []; | ||||
|         $chunks       = array_chunk($transactions, 500); | ||||
| 
 | ||||
|         foreach ($chunks as $chunk) { | ||||
|             $set   = \DB::table('transactions')->whereIn('transactions.id', $chunk)->pluck('transaction_journal_id')->toArray(); | ||||
|             $set   = DB::table('transactions')->whereIn('transactions.id', $chunk)->pluck('transaction_journal_id')->toArray(); | ||||
|             $array = array_merge($array, $set); | ||||
|         } | ||||
| 
 | ||||
| @@ -171,12 +172,12 @@ class UpgradesJournalMetaData extends Command | ||||
| 
 | ||||
|     private function getIdsForCategories(): array | ||||
|     { | ||||
|         $transactions = \DB::table('category_transaction')->distinct()->pluck('transaction_id')->toArray(); | ||||
|         $transactions = DB::table('category_transaction')->distinct()->pluck('transaction_id')->toArray(); | ||||
|         $array        = []; | ||||
|         $chunks       = array_chunk($transactions, 500); | ||||
| 
 | ||||
|         foreach ($chunks as $chunk) { | ||||
|             $set   = \DB::table('transactions') | ||||
|             $set   = DB::table('transactions') | ||||
|                 ->whereIn('transactions.id', $chunk) | ||||
|                 ->pluck('transaction_journal_id')->toArray() | ||||
|             ; | ||||
|   | ||||
| @@ -35,6 +35,7 @@ use FireflyIII\Repositories\Journal\JournalRepositoryInterface; | ||||
| use FireflyIII\Services\Internal\Destroy\JournalDestroyService; | ||||
| use Illuminate\Console\Command; | ||||
| use Illuminate\Support\Collection; | ||||
| use Illuminate\Support\Facades\DB; | ||||
| 
 | ||||
| class UpgradesToGroups extends Command | ||||
| { | ||||
| @@ -364,7 +365,7 @@ class UpgradesToGroups extends Command | ||||
| 
 | ||||
|     private function giveGroup(array $array): void | ||||
|     { | ||||
|         $groupId = \DB::table('transaction_groups')->insertGetId( | ||||
|         $groupId = DB::table('transaction_groups')->insertGetId( | ||||
|             [ | ||||
|                 'created_at' => date('Y-m-d H:i:s'), | ||||
|                 'updated_at' => date('Y-m-d H:i:s'), | ||||
| @@ -372,7 +373,7 @@ class UpgradesToGroups extends Command | ||||
|                 'user_id'    => $array['user_id'], | ||||
|             ] | ||||
|         ); | ||||
|         \DB::table('transaction_journals')->where('id', $array['id'])->update(['transaction_group_id' => $groupId]); | ||||
|         DB::table('transaction_journals')->where('id', $array['id'])->update(['transaction_group_id' => $groupId]); | ||||
|         ++$this->count; | ||||
|     } | ||||
| 
 | ||||
|   | ||||
| @@ -26,6 +26,7 @@ namespace FireflyIII\Factory; | ||||
| 
 | ||||
| use FireflyIII\Models\Location; | ||||
| use FireflyIII\Models\Tag; | ||||
| use FireflyIII\Models\UserGroup; | ||||
| use FireflyIII\User; | ||||
| 
 | ||||
| /** | ||||
| @@ -34,6 +35,7 @@ use FireflyIII\User; | ||||
| class TagFactory | ||||
| { | ||||
|     private User $user; | ||||
|     private UserGroup $userGroup; | ||||
| 
 | ||||
|     public function findOrCreate(string $tag): ?Tag | ||||
|     { | ||||
| @@ -74,7 +76,7 @@ class TagFactory | ||||
|         $longitude = 0.0 === (float) $data['longitude'] ? null : (float) $data['longitude']; // intentional float
 | ||||
|         $array     = [ | ||||
|             'user_id'       => $this->user->id, | ||||
|             'user_group_id' => $this->user->user_group_id, | ||||
|             'user_group_id' => $this->userGroup->id, | ||||
|             'tag'           => trim($data['tag']), | ||||
|             'tagMode'       => 'nothing', | ||||
|             'date'          => $data['date'], | ||||
| @@ -101,6 +103,12 @@ class TagFactory | ||||
| 
 | ||||
|     public function setUser(User $user): void | ||||
|     { | ||||
|         $this->user = $user; | ||||
|         $this->user      = $user; | ||||
|         $this->userGroup = $user->userGroup; | ||||
|     } | ||||
| 
 | ||||
|     public function setUserGroup(UserGroup $userGroup): void | ||||
|     { | ||||
|         $this->userGroup = $userGroup; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -31,7 +31,6 @@ use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Rules\UniqueIban; | ||||
| use FireflyIII\Services\Internal\Update\AccountUpdateService; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Database\QueryException; | ||||
| 
 | ||||
| /** | ||||
| @@ -216,12 +215,4 @@ class TransactionFactory | ||||
|     { | ||||
|         $this->reconciled = $reconciled; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @SuppressWarnings("PHPMD.UnusedFormalParameter") | ||||
|      */ | ||||
|     public function setUser(User $user): void | ||||
|     { | ||||
|         // empty function.
 | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -27,6 +27,7 @@ namespace FireflyIII\Factory; | ||||
| use FireflyIII\Exceptions\DuplicateTransactionException; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\TransactionGroup; | ||||
| use FireflyIII\Models\UserGroup; | ||||
| use FireflyIII\User; | ||||
| 
 | ||||
| /** | ||||
| @@ -36,6 +37,7 @@ class TransactionGroupFactory | ||||
| { | ||||
|     private TransactionJournalFactory $journalFactory; | ||||
|     private User                      $user; | ||||
|     private UserGroup $userGroup; | ||||
| 
 | ||||
|     /** | ||||
|      * TransactionGroupFactory constructor. | ||||
| @@ -54,7 +56,8 @@ class TransactionGroupFactory | ||||
|     public function create(array $data): TransactionGroup | ||||
|     { | ||||
|         app('log')->debug('Now in TransactionGroupFactory::create()'); | ||||
|         $this->journalFactory->setUser($this->user); | ||||
|         $this->journalFactory->setUser($data['user']); | ||||
|         $this->journalFactory->setUserGroup($data['user_group']); | ||||
|         $this->journalFactory->setErrorOnHash($data['error_if_duplicate_hash'] ?? false); | ||||
| 
 | ||||
|         try { | ||||
| @@ -76,7 +79,7 @@ class TransactionGroupFactory | ||||
| 
 | ||||
|         $group        = new TransactionGroup(); | ||||
|         $group->user()->associate($this->user); | ||||
|         $group->userGroup()->associate($data['user_group'] ?? $this->user->userGroup); | ||||
|         $group->userGroup()->associate($this->userGroup); | ||||
|         $group->title = $title; | ||||
|         $group->save(); | ||||
| 
 | ||||
| @@ -90,6 +93,12 @@ class TransactionGroupFactory | ||||
|      */ | ||||
|     public function setUser(User $user): void | ||||
|     { | ||||
|         $this->user = $user; | ||||
|         $this->user      = $user; | ||||
|         $this->userGroup = $user->userGroup; | ||||
|     } | ||||
| 
 | ||||
|     public function setUserGroup(UserGroup $userGroup): void | ||||
|     { | ||||
|         $this->userGroup = $userGroup; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -34,6 +34,7 @@ use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Models\TransactionJournalMeta; | ||||
| use FireflyIII\Models\UserGroup; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Bill\BillRepositoryInterface; | ||||
| use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| @@ -69,6 +70,7 @@ class TransactionJournalFactory | ||||
|     private PiggyBankRepositoryInterface       $piggyRepository; | ||||
|     private TransactionTypeRepositoryInterface $typeRepository; | ||||
|     private User                               $user; | ||||
|     private UserGroup $userGroup; | ||||
| 
 | ||||
|     /** | ||||
|      * Constructor. | ||||
| @@ -176,7 +178,6 @@ class TransactionJournalFactory | ||||
|         if (true === FireflyConfig::get('utc', false)->data) { | ||||
|             $carbon->setTimezone('UTC'); | ||||
|         } | ||||
|         // $carbon->setTimezone('UTC');
 | ||||
| 
 | ||||
|         try { | ||||
|             // validate source and destination using a new Validator.
 | ||||
| @@ -228,7 +229,7 @@ class TransactionJournalFactory | ||||
|         $journal               = TransactionJournal::create( | ||||
|             [ | ||||
|                 'user_id'                 => $this->user->id, | ||||
|                 'user_group_id'           => $this->user->user_group_id, | ||||
|                 'user_group_id'           => $this->userGroup->id, | ||||
|                 'transaction_type_id'     => $type->id, | ||||
|                 'bill_id'                 => $billId, | ||||
|                 'transaction_currency_id' => $currency->id, | ||||
| @@ -244,7 +245,6 @@ class TransactionJournalFactory | ||||
| 
 | ||||
|         /** Create two transactions. */ | ||||
|         $transactionFactory    = app(TransactionFactory::class); | ||||
|         $transactionFactory->setUser($this->user); | ||||
|         $transactionFactory->setJournal($journal); | ||||
|         $transactionFactory->setAccount($sourceAccount); | ||||
|         $transactionFactory->setCurrency($currency); | ||||
| @@ -263,7 +263,6 @@ class TransactionJournalFactory | ||||
| 
 | ||||
|         /** @var TransactionFactory $transactionFactory */ | ||||
|         $transactionFactory    = app(TransactionFactory::class); | ||||
|         $transactionFactory->setUser($this->user); | ||||
|         $transactionFactory->setJournal($journal); | ||||
|         $transactionFactory->setAccount($destinationAccount); | ||||
|         $transactionFactory->setAccountInformation($destInfo); | ||||
| @@ -404,7 +403,8 @@ class TransactionJournalFactory | ||||
|      */ | ||||
|     public function setUser(User $user): void | ||||
|     { | ||||
|         $this->user = $user; | ||||
|         $this->user      = $user; | ||||
|         $this->userGroup = $user->userGroup; | ||||
|         $this->currencyRepository->setUser($this->user); | ||||
|         $this->tagFactory->setUser($user); | ||||
|         $this->billRepository->setUser($this->user); | ||||
| @@ -414,6 +414,18 @@ class TransactionJournalFactory | ||||
|         $this->accountRepository->setUser($this->user); | ||||
|     } | ||||
| 
 | ||||
|     public function setUserGroup(UserGroup $userGroup): void | ||||
|     { | ||||
|         $this->userGroup = $userGroup; | ||||
|         $this->currencyRepository->setUserGroup($userGroup); | ||||
|         $this->tagFactory->setUserGroup($userGroup); | ||||
|         $this->billRepository->setUserGroup($userGroup); | ||||
|         $this->budgetRepository->setUserGroup($userGroup); | ||||
|         $this->categoryRepository->setUserGroup($userGroup); | ||||
|         $this->piggyRepository->setUserGroup($userGroup); | ||||
|         $this->accountRepository->setUserGroup($userGroup); | ||||
|     } | ||||
| 
 | ||||
|     private function reconciliationSanityCheck(?Account $sourceAccount, ?Account $destinationAccount): array | ||||
|     { | ||||
|         app('log')->debug(sprintf('Now in %s', __METHOD__)); | ||||
|   | ||||
| @@ -33,6 +33,7 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Journal\JournalRepositoryInterface; | ||||
| use FireflyIII\Support\Facades\Steam; | ||||
| use Illuminate\Support\Collection; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| 
 | ||||
| /** | ||||
|  * Class MonthReportGenerator. | ||||
| @@ -52,7 +53,9 @@ class MonthReportGenerator implements ReportGeneratorInterface | ||||
|     { | ||||
|         $auditData   = []; | ||||
|         $dayBefore   = clone $this->start; | ||||
|         $dayBefore->subDay(); | ||||
| 
 | ||||
|         // set date to subday + end-of-day for account balance. so it is at $date 23:59:59
 | ||||
|         $dayBefore->subDay()->endOfDay(); | ||||
| 
 | ||||
|         /** @var Account $account */ | ||||
|         foreach ($this->accounts as $account) { | ||||
| @@ -133,6 +136,8 @@ class MonthReportGenerator implements ReportGeneratorInterface | ||||
|         ; | ||||
|         $journals          = $collector->getExtractedJournals(); | ||||
|         $journals          = array_reverse($journals, true); | ||||
|         // this call is correct.
 | ||||
|         Log::debug(sprintf('getAuditReport: Call finalAccountBalance with date/time "%s"', $date->toIso8601String())); | ||||
|         $dayBeforeBalance  = Steam::finalAccountBalance($account, $date); | ||||
|         $startBalance      = $dayBeforeBalance['balance']; | ||||
|         $defaultCurrency   = app('amount')->getNativeCurrencyByUserGroup($account->user->userGroup); | ||||
| @@ -167,6 +172,8 @@ class MonthReportGenerator implements ReportGeneratorInterface | ||||
|             $journals[$index]['invoice_date']   = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'invoice_date'); | ||||
|         } | ||||
|         $locale            = app('steam')->getLocale(); | ||||
|         // call is correct.
 | ||||
|         Log::debug(sprintf('getAuditReport end: Call finalAccountBalance with date/time "%s"', $this->end->toIso8601String())); | ||||
| 
 | ||||
|         return [ | ||||
|             'journals'         => $journals, | ||||
|   | ||||
| @@ -61,8 +61,12 @@ class PreferencesEventHandler | ||||
|         $this->resetTransactions($event->userGroup); | ||||
|         // fire laravel command to recalculate them all.
 | ||||
|         if (Amount::convertToNative()) { | ||||
|             Log::debug('Will now convert to native.'); | ||||
|             Artisan::call('correction:recalculate-native-amounts'); | ||||
| 
 | ||||
|             return; | ||||
|         } | ||||
|         Log::debug('Will NOT convert to native.'); | ||||
|     } | ||||
| 
 | ||||
|     private function resetPiggyBanks(UserGroup $userGroup): void | ||||
|   | ||||
| @@ -38,10 +38,17 @@ use Illuminate\Support\Collection; | ||||
|  */ | ||||
| class StoredGroupEventHandler | ||||
| { | ||||
|     public function runAllHandlers(StoredTransactionGroup $event): void | ||||
|     { | ||||
|         $this->processRules($event); | ||||
|         $this->recalculateCredit($event); | ||||
|         $this->triggerWebhooks($event); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * This method grabs all the users rules and processes them. | ||||
|      */ | ||||
|     public function processRules(StoredTransactionGroup $storedGroupEvent): void | ||||
|     private function processRules(StoredTransactionGroup $storedGroupEvent): void | ||||
|     { | ||||
|         if (false === $storedGroupEvent->applyRules) { | ||||
|             app('log')->info(sprintf('Will not run rules on group #%d', $storedGroupEvent->transactionGroup->id)); | ||||
| @@ -76,7 +83,7 @@ class StoredGroupEventHandler | ||||
|         $newRuleEngine->fire(); | ||||
|     } | ||||
| 
 | ||||
|     public function recalculateCredit(StoredTransactionGroup $event): void | ||||
|     private function recalculateCredit(StoredTransactionGroup $event): void | ||||
|     { | ||||
|         $group  = $event->transactionGroup; | ||||
| 
 | ||||
| @@ -89,7 +96,7 @@ class StoredGroupEventHandler | ||||
|     /** | ||||
|      * This method processes all webhooks that respond to the "stored transaction group" trigger (100) | ||||
|      */ | ||||
|     public function triggerWebhooks(StoredTransactionGroup $storedGroupEvent): void | ||||
|     private function triggerWebhooks(StoredTransactionGroup $storedGroupEvent): void | ||||
|     { | ||||
|         app('log')->debug(__METHOD__); | ||||
|         $group  = $storedGroupEvent->transactionGroup; | ||||
|   | ||||
| @@ -41,10 +41,19 @@ use Illuminate\Support\Collection; | ||||
|  */ | ||||
| class UpdatedGroupEventHandler | ||||
| { | ||||
|     public function runAllHandlers(UpdatedTransactionGroup $event): void | ||||
|     { | ||||
|         $this->unifyAccounts($event); | ||||
|         $this->processRules($event); | ||||
|         $this->recalculateCredit($event); | ||||
|         $this->triggerWebhooks($event); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * This method will check all the rules when a journal is updated. | ||||
|      */ | ||||
|     public function processRules(UpdatedTransactionGroup $updatedGroupEvent): void | ||||
|     private function processRules(UpdatedTransactionGroup $updatedGroupEvent): void | ||||
|     { | ||||
|         if (false === $updatedGroupEvent->applyRules) { | ||||
|             app('log')->info(sprintf('Will not run rules on group #%d', $updatedGroupEvent->transactionGroup->id)); | ||||
| @@ -76,7 +85,7 @@ class UpdatedGroupEventHandler | ||||
|         $newRuleEngine->fire(); | ||||
|     } | ||||
| 
 | ||||
|     public function recalculateCredit(UpdatedTransactionGroup $event): void | ||||
|     private function recalculateCredit(UpdatedTransactionGroup $event): void | ||||
|     { | ||||
|         $group  = $event->transactionGroup; | ||||
| 
 | ||||
| @@ -86,7 +95,7 @@ class UpdatedGroupEventHandler | ||||
|         $object->recalculate(); | ||||
|     } | ||||
| 
 | ||||
|     public function triggerWebhooks(UpdatedTransactionGroup $updatedGroupEvent): void | ||||
|     private function triggerWebhooks(UpdatedTransactionGroup $updatedGroupEvent): void | ||||
|     { | ||||
|         app('log')->debug(__METHOD__); | ||||
|         $group  = $updatedGroupEvent->transactionGroup; | ||||
|   | ||||
| @@ -28,6 +28,7 @@ use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Update\UpdateTrait; | ||||
| use FireflyIII\Models\Configuration; | ||||
| use FireflyIII\Repositories\User\UserRepositoryInterface; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| 
 | ||||
| /** | ||||
|  * Class VersionCheckEventHandler | ||||
| @@ -45,13 +46,13 @@ class VersionCheckEventHandler | ||||
|      */ | ||||
|     public function checkForUpdates(RequestedVersionCheckStatus $event): void | ||||
|     { | ||||
|         app('log')->debug('Now in checkForUpdates()'); | ||||
|         Log::debug('Now in checkForUpdates()'); | ||||
| 
 | ||||
|         // should not check for updates:
 | ||||
|         $permission    = app('fireflyconfig')->get('permission_update_check', -1); | ||||
|         $value         = (int) $permission->data; | ||||
|         if (1 !== $value) { | ||||
|             app('log')->debug('Update check is not enabled.'); | ||||
|             Log::debug('Update check is not enabled.'); | ||||
|             $this->warnToCheckForUpdates($event); | ||||
| 
 | ||||
|             return; | ||||
| @@ -61,7 +62,7 @@ class VersionCheckEventHandler | ||||
|         $repository    = app(UserRepositoryInterface::class); | ||||
|         $user          = $event->user; | ||||
|         if (!$repository->hasRole($user, 'owner')) { | ||||
|             app('log')->debug('User is not admin, done.'); | ||||
|             Log::debug('User is not admin, done.'); | ||||
| 
 | ||||
|             return; | ||||
|         } | ||||
| @@ -70,14 +71,14 @@ class VersionCheckEventHandler | ||||
|         $lastCheckTime = app('fireflyconfig')->get('last_update_check', time()); | ||||
|         $now           = time(); | ||||
|         $diff          = $now - $lastCheckTime->data; | ||||
|         app('log')->debug(sprintf('Last check time is %d, current time is %d, difference is %d', $lastCheckTime->data, $now, $diff)); | ||||
|         Log::debug(sprintf('Last check time is %d, current time is %d, difference is %d', $lastCheckTime->data, $now, $diff)); | ||||
|         if ($diff < 604800) { | ||||
|             app('log')->debug(sprintf('Checked for updates less than a week ago (on %s).', date('Y-m-d H:i:s', $lastCheckTime->data))); | ||||
|             Log::debug(sprintf('Checked for updates less than a week ago (on %s).', date('Y-m-d H:i:s', $lastCheckTime->data))); | ||||
| 
 | ||||
|             return; | ||||
|         } | ||||
|         // last check time was more than a week ago.
 | ||||
|         app('log')->debug('Have not checked for a new version in a week!'); | ||||
|         Log::debug('Have not checked for a new version in a week!'); | ||||
|         $release       = $this->getLatestRelease(); | ||||
| 
 | ||||
|         session()->flash($release['level'], $release['message']); | ||||
| @@ -93,7 +94,7 @@ class VersionCheckEventHandler | ||||
|         $repository    = app(UserRepositoryInterface::class); | ||||
|         $user          = $event->user; | ||||
|         if (!$repository->hasRole($user, 'owner')) { | ||||
|             app('log')->debug('User is not admin, done.'); | ||||
|             Log::debug('User is not admin, done.'); | ||||
| 
 | ||||
|             return; | ||||
|         } | ||||
| @@ -102,14 +103,14 @@ class VersionCheckEventHandler | ||||
|         $lastCheckTime = app('fireflyconfig')->get('last_update_warning', time()); | ||||
|         $now           = time(); | ||||
|         $diff          = $now - $lastCheckTime->data; | ||||
|         app('log')->debug(sprintf('Last warning time is %d, current time is %d, difference is %d', $lastCheckTime->data, $now, $diff)); | ||||
|         Log::debug(sprintf('Last warning time is %d, current time is %d, difference is %d', $lastCheckTime->data, $now, $diff)); | ||||
|         if ($diff < 604800 * 4) { | ||||
|             app('log')->debug(sprintf('Warned about updates less than four weeks ago (on %s).', date('Y-m-d H:i:s', $lastCheckTime->data))); | ||||
|             Log::debug(sprintf('Warned about updates less than four weeks ago (on %s).', date('Y-m-d H:i:s', $lastCheckTime->data))); | ||||
| 
 | ||||
|             return; | ||||
|         } | ||||
|         // last check time was more than a week ago.
 | ||||
|         app('log')->debug('Have warned about a new version in four weeks!'); | ||||
|         Log::debug('Have warned about a new version in four weeks!'); | ||||
| 
 | ||||
|         session()->flash('info', (string) trans('firefly.disabled_but_check')); | ||||
|         app('fireflyconfig')->set('last_update_warning', time()); | ||||
|   | ||||
| @@ -25,10 +25,15 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Handlers\Observer; | ||||
| 
 | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\Attachment; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionGroup; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface; | ||||
| use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use FireflyIII\Support\Http\Api\ExchangeRateConverter; | ||||
| use Illuminate\Support\Facades\DB; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| 
 | ||||
| /** | ||||
| @@ -52,6 +57,7 @@ class AccountObserver | ||||
|         $currency     = $repository->getAccountCurrency($account); | ||||
|         if (null !== $currency && $currency->id !== $userCurrency->id && '' !== (string) $account->virtual_balance && 0 !== bccomp($account->virtual_balance, '0')) { | ||||
|             $converter                       = new ExchangeRateConverter(); | ||||
|             $converter->setUserGroup($account->user->userGroup); | ||||
|             $converter->setIgnoreSettings(true); | ||||
|             $account->native_virtual_balance = $converter->convert($currency, $userCurrency, today(), $account->virtual_balance); | ||||
| 
 | ||||
| @@ -69,19 +75,31 @@ class AccountObserver | ||||
|      */ | ||||
|     public function deleting(Account $account): void | ||||
|     { | ||||
|         //        app('log')->debug('Observe "deleting" of an account.');
 | ||||
|         $account->accountMeta()->delete(); | ||||
|         app('log')->debug('Observe "deleting" of an account.'); | ||||
| 
 | ||||
|         /** @var PiggyBank $piggy */ | ||||
|         foreach ($account->piggyBanks()->get() as $piggy) { | ||||
|             $piggy->accounts()->detach($account); | ||||
|         } | ||||
|         $repository = app(AttachmentRepositoryInterface::class); | ||||
|         $repository->setUser($account->user); | ||||
| 
 | ||||
|         DB::table('account_piggy_bank')->where('account_id', $account->id)->delete(); | ||||
| 
 | ||||
|         /** @var Attachment $attachment */ | ||||
|         foreach ($account->attachments()->get() as $attachment) { | ||||
|             $attachment->delete(); | ||||
|             $repository->destroy($attachment); | ||||
|         } | ||||
|         foreach ($account->transactions()->get() as $transaction) { | ||||
|             $transaction->delete(); | ||||
| 
 | ||||
|         $journalIds = Transaction::where('account_id', $account->id)->get(['transactions.transaction_journal_id'])->pluck('transaction_journal_id')->toArray(); | ||||
|         $groupIds   = TransactionJournal::whereIn('id', $journalIds)->get(['transaction_journals.transaction_group_id'])->pluck('transaction_group_id')->toArray(); | ||||
|         if (count($journalIds) > 0) { | ||||
|             Transaction::whereIn('transaction_journal_id', $journalIds)->delete(); | ||||
|             TransactionJournal::whereIn('id', $journalIds)->delete(); | ||||
|         } | ||||
|         if (count($groupIds) > 0) { | ||||
|             TransactionGroup::whereIn('id', $groupIds)->delete(); | ||||
|         } | ||||
| 
 | ||||
|         Log::debug(sprintf('Delete %d journal(s)', count($journalIds))); | ||||
|         Log::debug(sprintf('Delete %d group(s)', count($groupIds))); | ||||
| 
 | ||||
|         $account->notes()->delete(); | ||||
|         $account->locations()->delete(); | ||||
|     } | ||||
|   | ||||
| @@ -52,6 +52,7 @@ class AutoBudgetObserver | ||||
|         $autoBudget->native_amount = null; | ||||
|         if ($autoBudget->transactionCurrency->id !== $userCurrency->id) { | ||||
|             $converter                 = new ExchangeRateConverter(); | ||||
|             $converter->setUserGroup($autoBudget->budget->user->userGroup); | ||||
|             $converter->setIgnoreSettings(true); | ||||
|             $autoBudget->native_amount = $converter->convert($autoBudget->transactionCurrency, $userCurrency, today(), $autoBudget->amount); | ||||
|         } | ||||
|   | ||||
| @@ -23,7 +23,9 @@ declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\Handlers\Observer; | ||||
| 
 | ||||
| use FireflyIII\Models\Attachment; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface; | ||||
| use FireflyIII\Support\Facades\Amount; | ||||
| use FireflyIII\Support\Http\Api\ExchangeRateConverter; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| @@ -41,9 +43,13 @@ class BillObserver | ||||
| 
 | ||||
|     public function deleting(Bill $bill): void | ||||
|     { | ||||
|         $repository = app(AttachmentRepositoryInterface::class); | ||||
|         $repository->setUser($bill->user); | ||||
| 
 | ||||
|         //        app('log')->debug('Observe "deleting" of a bill.');
 | ||||
|         /** @var Attachment $attachment */ | ||||
|         foreach ($bill->attachments()->get() as $attachment) { | ||||
|             $attachment->delete(); | ||||
|             $repository->destroy($attachment); | ||||
|         } | ||||
|         $bill->notes()->delete(); | ||||
|     } | ||||
| @@ -64,6 +70,7 @@ class BillObserver | ||||
|         $bill->native_amount_max = null; | ||||
|         if ($bill->transactionCurrency->id !== $userCurrency->id) { | ||||
|             $converter               = new ExchangeRateConverter(); | ||||
|             $converter->setUserGroup($bill->user->userGroup); | ||||
|             $converter->setIgnoreSettings(true); | ||||
|             $bill->native_amount_min = $converter->convert($bill->transactionCurrency, $userCurrency, today(), $bill->amount_min); | ||||
|             $bill->native_amount_max = $converter->convert($bill->transactionCurrency, $userCurrency, today(), $bill->amount_max); | ||||
|   | ||||
| @@ -54,6 +54,7 @@ class BudgetLimitObserver | ||||
|         $budgetLimit->native_amount = null; | ||||
|         if ($budgetLimit->transactionCurrency->id !== $userCurrency->id) { | ||||
|             $converter                  = new ExchangeRateConverter(); | ||||
|             $converter->setUserGroup($budgetLimit->budget->user->userGroup); | ||||
|             $converter->setIgnoreSettings(true); | ||||
|             $budgetLimit->native_amount = $converter->convert($budgetLimit->transactionCurrency, $userCurrency, today(), $budgetLimit->amount); | ||||
|         } | ||||
|   | ||||
| @@ -23,8 +23,10 @@ declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\Handlers\Observer; | ||||
| 
 | ||||
| use FireflyIII\Models\Attachment; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\BudgetLimit; | ||||
| use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface; | ||||
| 
 | ||||
| /** | ||||
|  * Class BudgetObserver | ||||
| @@ -34,8 +36,13 @@ class BudgetObserver | ||||
|     public function deleting(Budget $budget): void | ||||
|     { | ||||
|         app('log')->debug('Observe "deleting" of a budget.'); | ||||
| 
 | ||||
|         $repository   = app(AttachmentRepositoryInterface::class); | ||||
|         $repository->setUser($budget->user); | ||||
| 
 | ||||
|         /** @var Attachment $attachment */ | ||||
|         foreach ($budget->attachments()->get() as $attachment) { | ||||
|             $attachment->delete(); | ||||
|             $repository->destroy($attachment); | ||||
|         } | ||||
|         $budgetLimits = $budget->budgetlimits()->get(); | ||||
| 
 | ||||
|   | ||||
| @@ -23,7 +23,9 @@ declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\Handlers\Observer; | ||||
| 
 | ||||
| use FireflyIII\Models\Attachment; | ||||
| use FireflyIII\Models\Category; | ||||
| use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface; | ||||
| 
 | ||||
| /** | ||||
|  * Class CategoryObserver | ||||
| @@ -33,8 +35,13 @@ class CategoryObserver | ||||
|     public function deleting(Category $category): void | ||||
|     { | ||||
|         app('log')->debug('Observe "deleting" of a category.'); | ||||
| 
 | ||||
|         $repository = app(AttachmentRepositoryInterface::class); | ||||
|         $repository->setUser($category->user); | ||||
| 
 | ||||
|         /** @var Attachment $attachment */ | ||||
|         foreach ($category->attachments()->get() as $attachment) { | ||||
|             $attachment->delete(); | ||||
|             $repository->destroy($attachment); | ||||
|         } | ||||
|         $category->notes()->delete(); | ||||
|     } | ||||
|   | ||||
| @@ -52,6 +52,7 @@ class PiggyBankEventObserver | ||||
|         $event->native_amount = null; | ||||
|         if ($event->piggyBank->transactionCurrency->id !== $userCurrency->id) { | ||||
|             $converter            = new ExchangeRateConverter(); | ||||
|             $converter->setUserGroup($event->piggyBank->accounts()->first()->user->userGroup); | ||||
|             $converter->setIgnoreSettings(true); | ||||
|             $event->native_amount = $converter->convert($event->piggyBank->transactionCurrency, $userCurrency, today(), $event->amount); | ||||
|         } | ||||
|   | ||||
| @@ -24,7 +24,9 @@ declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\Handlers\Observer; | ||||
| 
 | ||||
| use FireflyIII\Models\Attachment; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\ExchangeRateConverter; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| 
 | ||||
| @@ -46,8 +48,12 @@ class PiggyBankObserver | ||||
|     { | ||||
|         app('log')->debug('Observe "deleting" of a piggy bank.'); | ||||
| 
 | ||||
|         $repository = app(AttachmentRepositoryInterface::class); | ||||
|         $repository->setUser($piggyBank->accounts()->first()->user); | ||||
| 
 | ||||
|         /** @var Attachment $attachment */ | ||||
|         foreach ($piggyBank->attachments()->get() as $attachment) { | ||||
|             $attachment->delete(); | ||||
|             $repository->destroy($attachment); | ||||
|         } | ||||
| 
 | ||||
|         $piggyBank->piggyBankEvents()->delete(); | ||||
|   | ||||
| @@ -23,7 +23,9 @@ declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\Handlers\Observer; | ||||
| 
 | ||||
| use FireflyIII\Models\Attachment; | ||||
| use FireflyIII\Models\Recurrence; | ||||
| use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface; | ||||
| 
 | ||||
| /** | ||||
|  * Class RecurrenceObserver | ||||
| @@ -33,8 +35,13 @@ class RecurrenceObserver | ||||
|     public function deleting(Recurrence $recurrence): void | ||||
|     { | ||||
|         app('log')->debug('Observe "deleting" of a recurrence.'); | ||||
| 
 | ||||
|         $repository = app(AttachmentRepositoryInterface::class); | ||||
|         $repository->setUser($recurrence->user); | ||||
| 
 | ||||
|         /** @var Attachment $attachment */ | ||||
|         foreach ($recurrence->attachments()->get() as $attachment) { | ||||
|             $attachment->delete(); | ||||
|             $repository->destroy($attachment); | ||||
|         } | ||||
| 
 | ||||
|         $recurrence->recurrenceRepetitions()->delete(); | ||||
|   | ||||
| @@ -23,7 +23,9 @@ declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\Handlers\Observer; | ||||
| 
 | ||||
| use FireflyIII\Models\Attachment; | ||||
| use FireflyIII\Models\Tag; | ||||
| use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface; | ||||
| 
 | ||||
| /** | ||||
|  * Class TagObserver | ||||
| @@ -34,8 +36,12 @@ class TagObserver | ||||
|     { | ||||
|         app('log')->debug('Observe "deleting" of a tag.'); | ||||
| 
 | ||||
|         $repository = app(AttachmentRepositoryInterface::class); | ||||
|         $repository->setUser($tag->user); | ||||
| 
 | ||||
|         /** @var Attachment $attachment */ | ||||
|         foreach ($tag->attachments()->get() as $attachment) { | ||||
|             $attachment->delete(); | ||||
|             $repository->destroy($attachment); | ||||
|         } | ||||
| 
 | ||||
|         $tag->locations()->delete(); | ||||
|   | ||||
| @@ -23,7 +23,9 @@ declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\Handlers\Observer; | ||||
| 
 | ||||
| use FireflyIII\Models\Attachment; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface; | ||||
| 
 | ||||
| /** | ||||
|  * Class TransactionJournalObserver | ||||
| @@ -34,14 +36,20 @@ class TransactionJournalObserver | ||||
|     { | ||||
|         app('log')->debug('Observe "deleting" of a transaction journal.'); | ||||
| 
 | ||||
|         $repository = app(AttachmentRepositoryInterface::class); | ||||
|         $repository->setUser($transactionJournal->user); | ||||
| 
 | ||||
| 
 | ||||
|         // to make sure the listener doesn't get back to use and loop
 | ||||
|         TransactionJournal::withoutEvents(static function () use ($transactionJournal): void { | ||||
|             foreach ($transactionJournal->transactions()->get() as $transaction) { | ||||
|                 $transaction->delete(); | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         /** @var Attachment $attachment */ | ||||
|         foreach ($transactionJournal->attachments()->get() as $attachment) { | ||||
|             $attachment->delete(); | ||||
|             $repository->destroy($attachment); | ||||
|         } | ||||
|         $transactionJournal->locations()->delete(); | ||||
|         $transactionJournal->sourceJournalLinks()->delete(); | ||||
|   | ||||
| @@ -258,7 +258,12 @@ trait AccountCollection | ||||
|                 if (null === $account) { | ||||
|                     continue; | ||||
|                 } | ||||
|                 $balance   = Steam::finalAccountBalance($account, $transaction['date']); | ||||
|                 // the balance must be found BEFORE the transaction date.
 | ||||
|                 // so sub one second. This is not perfect, but works well enough.
 | ||||
|                 $date      = clone $transaction['date']; | ||||
|                 $date->subSecond(); | ||||
|                 Log::debug(sprintf('accountBalanceIs: Call finalAccountBalance with date/time "%s"', $date->toIso8601String())); | ||||
|                 $balance   = Steam::finalAccountBalance($account, $date); | ||||
|                 $result    = bccomp($balance['balance'], $value); | ||||
|                 Log::debug(sprintf('"%s" vs "%s" is %d', $balance['balance'], $value, $result)); | ||||
| 
 | ||||
|   | ||||
| @@ -167,6 +167,7 @@ trait MetaCollection | ||||
|         $this->joinMetaDataTables(); | ||||
|         $this->query->where('journal_meta.name', '=', 'external_id'); | ||||
|         $this->query->where('journal_meta.data', '!=', sprintf('%s', json_encode($externalId))); | ||||
|         $this->query->whereNull('journal_meta.deleted_at'); | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| @@ -405,6 +406,7 @@ trait MetaCollection | ||||
|         $this->joinMetaDataTables(); | ||||
|         $this->query->where('journal_meta.name', '=', 'internal_reference'); | ||||
|         $this->query->whereLike('journal_meta.data', sprintf('%%%s%%', $internalReference)); | ||||
|         $this->query->whereNull('journal_meta.deleted_at'); | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| @@ -417,6 +419,7 @@ trait MetaCollection | ||||
|         $this->joinMetaDataTables(); | ||||
|         $this->query->where('journal_meta.name', '=', 'internal_reference'); | ||||
|         $this->query->whereNotLike('journal_meta.data', sprintf('%%%s%%', $internalReference)); | ||||
|         $this->query->whereNull('journal_meta.deleted_at'); | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| @@ -429,6 +432,7 @@ trait MetaCollection | ||||
|         $this->joinMetaDataTables(); | ||||
|         $this->query->where('journal_meta.name', '=', 'internal_reference'); | ||||
|         $this->query->whereNotLike('journal_meta.data', sprintf('%%%s"', $internalReference)); | ||||
|         $this->query->whereNull('journal_meta.deleted_at'); | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| @@ -441,6 +445,7 @@ trait MetaCollection | ||||
|         $this->joinMetaDataTables(); | ||||
|         $this->query->where('journal_meta.name', '=', 'internal_reference'); | ||||
|         $this->query->whereLike('journal_meta.data', sprintf('"%s%%', $internalReference)); | ||||
|         $this->query->whereNull('journal_meta.deleted_at'); | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| @@ -453,6 +458,7 @@ trait MetaCollection | ||||
|         $this->joinMetaDataTables(); | ||||
|         $this->query->where('journal_meta.name', '=', 'internal_reference'); | ||||
|         $this->query->whereLike('journal_meta.data', sprintf('%%%s"', $internalReference)); | ||||
|         $this->query->whereNull('journal_meta.deleted_at'); | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| @@ -465,6 +471,7 @@ trait MetaCollection | ||||
|         $this->joinMetaDataTables(); | ||||
|         $this->query->where('journal_meta.name', '=', 'internal_reference'); | ||||
|         $this->query->whereLike('journal_meta.data', sprintf('"%s%%', $internalReference)); | ||||
|         $this->query->whereNull('journal_meta.deleted_at'); | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| @@ -697,6 +704,7 @@ trait MetaCollection | ||||
|         $this->joinMetaDataTables(); | ||||
|         $this->query->where('journal_meta.name', '=', 'external_id'); | ||||
|         $this->query->where('journal_meta.data', '=', sprintf('%s', json_encode($externalId))); | ||||
|         $this->query->whereNull('journal_meta.deleted_at'); | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| @@ -706,6 +714,7 @@ trait MetaCollection | ||||
|         $this->joinMetaDataTables(); | ||||
|         $this->query->where('journal_meta.name', '=', 'external_url'); | ||||
|         $this->query->where('journal_meta.data', '=', json_encode($url)); | ||||
|         $this->query->whereNull('journal_meta.deleted_at'); | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| @@ -718,6 +727,7 @@ trait MetaCollection | ||||
|         $this->joinMetaDataTables(); | ||||
|         $this->query->where('journal_meta.name', '=', 'internal_reference'); | ||||
|         $this->query->where('journal_meta.data', '=', sprintf('%s', json_encode($internalReference))); | ||||
|         $this->query->whereNull('journal_meta.deleted_at'); | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| @@ -727,6 +737,7 @@ trait MetaCollection | ||||
|         $this->joinMetaDataTables(); | ||||
|         $this->query->where('journal_meta.name', '=', 'recurrence_id'); | ||||
|         $this->query->where('journal_meta.data', '=', sprintf('%s', json_encode($recurringId))); | ||||
|         $this->query->whereNull('journal_meta.deleted_at'); | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| @@ -862,6 +873,7 @@ trait MetaCollection | ||||
|         $this->joinMetaDataTables(); | ||||
|         $this->query->where('journal_meta.name', '=', 'external_id'); | ||||
|         $this->query->whereNotNull('journal_meta.data'); | ||||
|         $this->query->whereNull('journal_meta.deleted_at'); | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| @@ -871,6 +883,7 @@ trait MetaCollection | ||||
|         $this->joinMetaDataTables(); | ||||
|         $this->query->where('journal_meta.name', '=', 'external_url'); | ||||
|         $this->query->whereNotNull('journal_meta.data'); | ||||
|         $this->query->whereNull('journal_meta.deleted_at'); | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| @@ -915,10 +928,13 @@ trait MetaCollection | ||||
|             $q1->where(static function (Builder $q2): void { | ||||
|                 $q2->where('journal_meta.name', '=', 'external_id'); | ||||
|                 $q2->whereNull('journal_meta.data'); | ||||
|                 $q2->whereNull('journal_meta.deleted_at'); | ||||
|             })->orWhere(static function (Builder $q3): void { | ||||
|                 $q3->where('journal_meta.name', '!=', 'external_id'); | ||||
|                 $q3->whereNull('journal_meta.deleted_at'); | ||||
|             })->orWhere(static function (Builder $q4): void { | ||||
|                 $q4->whereNull('journal_meta.name'); | ||||
|                 $q4->whereNull('journal_meta.deleted_at'); | ||||
|             }); | ||||
|         }); | ||||
| 
 | ||||
| @@ -933,10 +949,13 @@ trait MetaCollection | ||||
|             $q1->where(static function (Builder $q2): void { | ||||
|                 $q2->where('journal_meta.name', '=', 'external_url'); | ||||
|                 $q2->whereNull('journal_meta.data'); | ||||
|                 $q2->whereNull('journal_meta.deleted_at'); | ||||
|             })->orWhere(static function (Builder $q3): void { | ||||
|                 $q3->where('journal_meta.name', '!=', 'external_url'); | ||||
|                 $q3->whereNull('journal_meta.deleted_at'); | ||||
|             })->orWhere(static function (Builder $q4): void { | ||||
|                 $q4->whereNull('journal_meta.name'); | ||||
|                 $q4->whereNull('journal_meta.deleted_at'); | ||||
|             }); | ||||
|         }); | ||||
| 
 | ||||
|   | ||||
| @@ -100,7 +100,7 @@ class GroupCollector implements GroupCollectorInterface | ||||
|             'category_id', | ||||
|             'budget_id', | ||||
|         ]; | ||||
|         $this->stringFields         = ['amount', 'foreign_amount']; | ||||
|         $this->stringFields         = ['amount', 'foreign_amount', 'native_amount', 'native_foreign_amount']; | ||||
|         $this->total                = 0; | ||||
|         $this->fields               = [ | ||||
|             // group
 | ||||
| @@ -710,10 +710,13 @@ class GroupCollector implements GroupCollectorInterface | ||||
|         foreach ($groups as $groudId => $group) { | ||||
|             /** @var array $transaction */ | ||||
|             foreach ($group['transactions'] as $transaction) { | ||||
|                 $currencyId                                      = (int) $transaction['currency_id']; | ||||
|                 $currencyId                                             = (int) $transaction['currency_id']; | ||||
|                 if (null === $transaction['amount']) { | ||||
|                     throw new FireflyException(sprintf('Amount is NULL for a transaction in group #%d, please investigate.', $groudId)); | ||||
|                 } | ||||
|                 $nativeAmount                                           = (string) ('' === $transaction['native_amount'] ? '0' : $transaction['native_amount']); | ||||
|                 $nativeForeignAmount                                    = (string) ('' === $transaction['native_foreign_amount'] ? '0' : $transaction['native_foreign_amount']); | ||||
|                 $foreignAmount                                          = (string) ('' === $transaction['foreign_amount'] ? '0' : $transaction['foreign_amount']); | ||||
| 
 | ||||
|                 // set default:
 | ||||
|                 if (!array_key_exists($currencyId, $groups[$groudId]['sums'])) { | ||||
| @@ -722,11 +725,13 @@ class GroupCollector implements GroupCollectorInterface | ||||
|                     $groups[$groudId]['sums'][$currencyId]['currency_symbol']         = $transaction['currency_symbol']; | ||||
|                     $groups[$groudId]['sums'][$currencyId]['currency_decimal_places'] = $transaction['currency_decimal_places']; | ||||
|                     $groups[$groudId]['sums'][$currencyId]['amount']                  = '0'; | ||||
|                     $groups[$groudId]['sums'][$currencyId]['native_amount']           = '0'; | ||||
|                 } | ||||
|                 $groups[$groudId]['sums'][$currencyId]['amount'] = bcadd($groups[$groudId]['sums'][$currencyId]['amount'], $transaction['amount']); | ||||
|                 $groups[$groudId]['sums'][$currencyId]['amount']        = bcadd($groups[$groudId]['sums'][$currencyId]['amount'], $transaction['amount']); | ||||
|                 $groups[$groudId]['sums'][$currencyId]['native_amount'] = bcadd($groups[$groudId]['sums'][$currencyId]['native_amount'], $nativeAmount); | ||||
| 
 | ||||
|                 if (null !== $transaction['foreign_amount'] && null !== $transaction['foreign_currency_id']) { | ||||
|                     $currencyId                                      = (int) $transaction['foreign_currency_id']; | ||||
|                     $currencyId                                             = (int) $transaction['foreign_currency_id']; | ||||
| 
 | ||||
|                     // set default:
 | ||||
|                     if (!array_key_exists($currencyId, $groups[$groudId]['sums'])) { | ||||
| @@ -735,8 +740,10 @@ class GroupCollector implements GroupCollectorInterface | ||||
|                         $groups[$groudId]['sums'][$currencyId]['currency_symbol']         = $transaction['foreign_currency_symbol']; | ||||
|                         $groups[$groudId]['sums'][$currencyId]['currency_decimal_places'] = $transaction['foreign_currency_decimal_places']; | ||||
|                         $groups[$groudId]['sums'][$currencyId]['amount']                  = '0'; | ||||
|                         $groups[$groudId]['sums'][$currencyId]['native_amount']           = '0'; | ||||
|                     } | ||||
|                     $groups[$groudId]['sums'][$currencyId]['amount'] = bcadd($groups[$groudId]['sums'][$currencyId]['amount'], $transaction['foreign_amount']); | ||||
|                     $groups[$groudId]['sums'][$currencyId]['amount']        = bcadd($groups[$groudId]['sums'][$currencyId]['amount'], $foreignAmount); | ||||
|                     $groups[$groudId]['sums'][$currencyId]['native_amount'] = bcadd($groups[$groudId]['sums'][$currencyId]['amount'], $nativeForeignAmount); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -79,6 +79,7 @@ class NetWorth implements NetWorthInterface | ||||
|         Log::debug(sprintf('Now in byAccounts("%s", "%s")', $ids, $date->format('Y-m-d H:i:s'))); | ||||
|         $default         = Amount::getNativeCurrency(); | ||||
|         $netWorth        = []; | ||||
|         Log::debug(sprintf('NetWorth: finalAccountsBalance("%s")', $date->format('Y-m-d H:i:s'))); | ||||
|         $balances        = Steam::finalAccountsBalance($accounts, $date); | ||||
| 
 | ||||
|         /** @var Account $account */ | ||||
| @@ -159,6 +160,7 @@ class NetWorth implements NetWorthInterface | ||||
|          */ | ||||
|         $accounts = $this->getAccounts(); | ||||
|         $return   = []; | ||||
|         Log::debug(sprintf('SumNetWorth: finalAccountsBalance("%s")', $date->format('Y-m-d H:i:s'))); | ||||
|         $balances = Steam::finalAccountsBalance($accounts, $date); | ||||
|         foreach ($accounts as $account) { | ||||
|             $currency                     = $this->getRepository()->getAccountCurrency($account); | ||||
|   | ||||
| @@ -33,6 +33,7 @@ use FireflyIII\Support\Http\Controllers\BasicDataSupport; | ||||
| use Illuminate\Contracts\View\Factory; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use Illuminate\View\View; | ||||
| 
 | ||||
| /** | ||||
| @@ -90,9 +91,11 @@ class IndexController extends Controller | ||||
|         $start->subDay(); | ||||
| 
 | ||||
|         $ids           = $accounts->pluck('id')->toArray(); | ||||
|         $startBalances = app('steam')->finalAccountsBalance($accounts, $start); | ||||
|         $endBalances   = app('steam')->finalAccountsBalance($accounts, $end); | ||||
|         $activities    = app('steam')->getLastActivities($ids); | ||||
|         Log::debug(sprintf('inactive start: finalAccountsBalance("%s")', $start->format('Y-m-d H:i:s'))); | ||||
|         Log::debug(sprintf('inactive end: finalAccountsBalance("%s")', $end->format('Y-m-d H:i:s'))); | ||||
|         $startBalances = Steam::finalAccountsBalance($accounts, $start); | ||||
|         $endBalances   = Steam::finalAccountsBalance($accounts, $end); | ||||
|         $activities    = Steam::getLastActivities($ids); | ||||
| 
 | ||||
| 
 | ||||
|         $accounts->each( | ||||
| @@ -102,7 +105,7 @@ class IndexController extends Controller | ||||
|                 $account->startBalances     = Steam::filterAccountBalance($startBalances[$account->id] ?? [], $account, $this->convertToNative, $currency); | ||||
|                 $account->endBalances       = Steam::filterAccountBalance($endBalances[$account->id] ?? [], $account, $this->convertToNative, $currency); | ||||
|                 $account->differences       = $this->subtract($account->startBalances, $account->endBalances); | ||||
|                 $account->interest          = app('steam')->bcround($this->repository->getMetaValue($account, 'interest'), 4); | ||||
|                 $account->interest          = Steam::bcround($this->repository->getMetaValue($account, 'interest'), 4); | ||||
|                 $account->interestPeriod    = (string) trans(sprintf('firefly.interest_calc_%s', $this->repository->getMetaValue($account, 'interest_period'))); | ||||
|                 $account->accountTypeString = (string) trans(sprintf('firefly.account_type_%s', $account->accountType->type)); | ||||
|                 $account->current_debt      = '0'; | ||||
| @@ -153,9 +156,11 @@ class IndexController extends Controller | ||||
|         $start->subDay(); | ||||
| 
 | ||||
|         $ids           = $accounts->pluck('id')->toArray(); | ||||
|         $startBalances = app('steam')->finalAccountsBalance($accounts, $start); | ||||
|         $endBalances   = app('steam')->finalAccountsBalance($accounts, $end); | ||||
|         $activities    = app('steam')->getLastActivities($ids); | ||||
|         Log::debug(sprintf('index start: finalAccountsBalance("%s")', $start->format('Y-m-d H:i:s'))); | ||||
|         Log::debug(sprintf('index end: finalAccountsBalance("%s")', $end->format('Y-m-d H:i:s'))); | ||||
|         $startBalances = Steam::finalAccountsBalance($accounts, $start); | ||||
|         $endBalances   = Steam::finalAccountsBalance($accounts, $end); | ||||
|         $activities    = Steam::getLastActivities($ids); | ||||
| 
 | ||||
| 
 | ||||
|         $accounts->each( | ||||
| @@ -168,7 +173,7 @@ class IndexController extends Controller | ||||
|                 $account->endBalances         = Steam::filterAccountBalance($endBalances[$account->id] ?? [], $account, $this->convertToNative, $currency); | ||||
|                 $account->differences         = $this->subtract($account->startBalances, $account->endBalances); | ||||
|                 $account->lastActivityDate    = $this->isInArrayDate($activities, $account->id); | ||||
|                 $account->interest            = app('steam')->bcround($interest, 4); | ||||
|                 $account->interest            = Steam::bcround($interest, 4); | ||||
|                 $account->interestPeriod      = (string) trans( | ||||
|                     sprintf('firefly.interest_calc_%s', $this->repository->getMetaValue($account, 'interest_period')) | ||||
|                 ); | ||||
|   | ||||
| @@ -39,6 +39,7 @@ use FireflyIII\User; | ||||
| use Illuminate\Contracts\View\Factory; | ||||
| use Illuminate\Http\RedirectResponse; | ||||
| use Illuminate\Routing\Redirector; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use Illuminate\View\View; | ||||
| 
 | ||||
| /** | ||||
| @@ -108,11 +109,17 @@ class ReconcileController extends Controller | ||||
|         if ($end->lt($start)) { | ||||
|             [$start, $end] = [$end, $start]; | ||||
|         } | ||||
|         // move dates to end of day and start of day:
 | ||||
|         $start->startOfDay(); | ||||
|         $end->endOfDay(); | ||||
| 
 | ||||
|         $startDate       = clone $start; | ||||
|         $startDate->subDay(); | ||||
|         $startBalance    = Steam::finalAccountBalance($account, $startDate)['balance']; | ||||
|         $endBalance      = Steam::finalAccountBalance($account, $end)['balance']; | ||||
|         $startDate->subDay()->endOfDay(); // this is correct, subday endofday ends at 23:59:59
 | ||||
|         // both are validated and are correct.
 | ||||
|         Log::debug(sprintf('reconcile: Call finalAccountBalance with date/time "%s"', $startDate->toIso8601String())); | ||||
|         Log::debug(sprintf('reconcile2: Call finalAccountBalance with date/time "%s"', $end->toIso8601String())); | ||||
|         $startBalance    = Steam::bcround(Steam::finalAccountBalance($account, $startDate)['balance'], $currency->decimal_places); | ||||
|         $endBalance      = Steam::bcround(Steam::finalAccountBalance($account, $end)['balance'], $currency->decimal_places); | ||||
|         $subTitleIcon    = config(sprintf('firefly.subIconsByIdentifier.%s', $account->accountType->type)); | ||||
|         $subTitle        = (string) trans('firefly.reconcile_account', ['account' => $account->name]); | ||||
| 
 | ||||
|   | ||||
| @@ -29,6 +29,7 @@ use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Support\Facades\Steam; | ||||
| use FireflyIII\Support\Http\Controllers\PeriodOverview; | ||||
| @@ -37,6 +38,7 @@ use Illuminate\Http\RedirectResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Routing\Redirector; | ||||
| use Illuminate\Support\Collection; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use Illuminate\View\View; | ||||
| 
 | ||||
| /** | ||||
| @@ -79,6 +81,7 @@ class ShowController extends Controller | ||||
|      *                                              */ | ||||
|     public function show(Request $request, Account $account, ?Carbon $start = null, ?Carbon $end = null) | ||||
|     { | ||||
| 
 | ||||
|         $objectType       = config(sprintf('firefly.shortNamesByFullName.%s', $account->accountType->type)); | ||||
| 
 | ||||
|         if (!$this->isEditableAccount($account)) { | ||||
| @@ -93,6 +96,11 @@ class ShowController extends Controller | ||||
|         if ($end->lt($start)) { | ||||
|             [$start, $end] = [$end, $start]; | ||||
|         } | ||||
| 
 | ||||
|         // make sure dates are end of day and start of day:
 | ||||
|         $start->startOfDay(); | ||||
|         $end->endOfDay(); | ||||
| 
 | ||||
|         $location         = $this->repository->getLocation($account); | ||||
|         $attachments      = $this->repository->getAttachments($account); | ||||
|         $today            = today(config('app.timezone')); | ||||
| @@ -115,12 +123,7 @@ class ShowController extends Controller | ||||
| 
 | ||||
|         /** @var GroupCollectorInterface $collector */ | ||||
|         $collector        = app(GroupCollectorInterface::class); | ||||
|         $collector | ||||
|             ->setAccounts(new Collection([$account])) | ||||
|             ->setLimit($pageSize) | ||||
|             ->setPage($page)->withAccountInformation()->withCategoryInformation() | ||||
|             ->setRange($start, $end) | ||||
|         ; | ||||
|         $collector->setAccounts(new Collection([$account]))->setLimit($pageSize)->setPage($page)->withAccountInformation()->withCategoryInformation()->setRange($start, $end); | ||||
| 
 | ||||
|         // this search will not include transaction groups where this asset account (or liability)
 | ||||
|         // is just part of ONE of the journals. To force this:
 | ||||
| @@ -130,7 +133,14 @@ class ShowController extends Controller | ||||
| 
 | ||||
|         $groups->setPath(route('accounts.show', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')])); | ||||
|         $showAll          = false; | ||||
|         $balances         = Steam::filterAccountBalance(Steam::finalAccountBalance($account, $end), $account, $this->convertToNative, $accountCurrency); | ||||
|         // correct
 | ||||
|         $now              = today()->endOfDay(); | ||||
|         if ($now->gt($end) || $now->lt($start)) { | ||||
|             $now = $end; | ||||
|         } | ||||
| 
 | ||||
|         Log::debug(sprintf('show: Call finalAccountBalance with date/time "%s"', $now->toIso8601String())); | ||||
|         $balances         = Steam::filterAccountBalance(Steam::finalAccountBalance($account, $now), $account, $this->convertToNative, $accountCurrency); | ||||
| 
 | ||||
|         return view( | ||||
|             'accounts.show', | ||||
| @@ -181,6 +191,8 @@ class ShowController extends Controller | ||||
|         $subTitle        = (string) trans('firefly.all_journals_for_account', ['name' => $account->name]); | ||||
|         $periods         = new Collection(); | ||||
| 
 | ||||
|         $end->endOfDay(); | ||||
| 
 | ||||
|         /** @var GroupCollectorInterface $collector */ | ||||
|         $collector       = app(GroupCollectorInterface::class); | ||||
|         $collector->setAccounts(new Collection([$account]))->setLimit($pageSize)->setPage($page)->withAccountInformation()->withCategoryInformation(); | ||||
| @@ -193,6 +205,8 @@ class ShowController extends Controller | ||||
|         $groups->setPath(route('accounts.show.all', [$account->id])); | ||||
|         $chartUrl        = route('chart.account.period', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')]); | ||||
|         $showAll         = true; | ||||
|         // correct
 | ||||
|         Log::debug(sprintf('showAll: Call finalAccountBalance with date/time "%s"', $end->toIso8601String())); | ||||
|         $balances        = Steam::filterAccountBalance(Steam::finalAccountBalance($account, $end), $account, $this->convertToNative, $accountCurrency); | ||||
| 
 | ||||
|         return view( | ||||
|   | ||||
| @@ -41,6 +41,7 @@ use Illuminate\Http\RedirectResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Http\Response; | ||||
| use Illuminate\Routing\Redirector; | ||||
| use Illuminate\Support\Facades\DB; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use Illuminate\Validation\ValidationException; | ||||
| 
 | ||||
| @@ -223,7 +224,7 @@ class LoginController extends Controller | ||||
|     { | ||||
|         Log::channel('audit')->info('Show login form (1.1).'); | ||||
| 
 | ||||
|         $count             = \DB::table('users')->count(); | ||||
|         $count             = DB::table('users')->count(); | ||||
|         $guard             = config('auth.defaults.guard'); | ||||
|         $title             = (string) trans('firefly.login_page_title'); | ||||
| 
 | ||||
|   | ||||
| @@ -109,8 +109,10 @@ class AccountController extends Controller | ||||
|         $accountNames  = $this->extractNames($accounts); | ||||
| 
 | ||||
|         // grab all balances
 | ||||
|         $startBalances = app('steam')->finalAccountsBalance($accounts, $start); | ||||
|         $endBalances   = app('steam')->finalAccountsBalance($accounts, $end); | ||||
|         Log::debug(sprintf('expenseAccounts: finalAccountsBalance("%s")', $start->format('Y-m-d H:i:s'))); | ||||
|         Log::debug(sprintf('expenseAccounts: finalAccountsBalance("%s")', $end->format('Y-m-d H:i:s'))); | ||||
|         $startBalances = Steam::finalAccountsBalance($accounts, $start); | ||||
|         $endBalances   = Steam::finalAccountsBalance($accounts, $end); | ||||
| 
 | ||||
|         // loop the accounts, then check for balance and currency info.
 | ||||
|         foreach ($accounts as $account) { | ||||
| @@ -139,6 +141,7 @@ class AccountController extends Controller | ||||
|                 } | ||||
|                 // Log::debug(sprintf('Will process expense array "%s" with amount %s', $key, $endBalance));
 | ||||
|                 $searchCode   = $this->convertToNative ? $this->defaultCurrency->code : $key; | ||||
|                 $searchCode   = 'balance' === $searchCode || 'native_balance' === $searchCode ? $this->defaultCurrency->code : $searchCode; | ||||
|                 // Log::debug(sprintf('Search code is %s', $searchCode));
 | ||||
|                 // see if there is an accompanying start amount.
 | ||||
|                 // grab the difference and find the currency.
 | ||||
| @@ -334,7 +337,7 @@ class AccountController extends Controller | ||||
|         $start          = clone session('start', today(config('app.timezone'))->startOfMonth()); | ||||
|         $end            = clone session('end', today(config('app.timezone'))->endOfMonth()); | ||||
|         $defaultSet     = $repository->getAccountsByType([AccountTypeEnum::DEFAULT->value, AccountTypeEnum::ASSET->value])->pluck('id')->toArray(); | ||||
|         Log::debug('Default set is ', $defaultSet); | ||||
|         // Log::debug('Default set is ', $defaultSet);
 | ||||
|         $frontpage      = app('preferences')->get('frontpageAccounts', $defaultSet); | ||||
|         $frontpageArray = !is_array($frontpage->data) ? [] : $frontpage->data; | ||||
|         Log::debug('Frontpage preference set is ', $frontpageArray); | ||||
| @@ -344,6 +347,9 @@ class AccountController extends Controller | ||||
|         } | ||||
|         $accounts       = $repository->getAccountsById($frontpageArray); | ||||
| 
 | ||||
|         // move to end of day for $end.
 | ||||
|         $end->endOfDay(); | ||||
| 
 | ||||
|         return response()->json($this->accountBalanceChart($accounts, $start, $end)); | ||||
|     } | ||||
| 
 | ||||
| @@ -416,8 +422,10 @@ class AccountController extends Controller | ||||
|      */ | ||||
|     public function period(Account $account, Carbon $start, Carbon $end): JsonResponse | ||||
|     { | ||||
|         Log::debug(sprintf('Now in period("%s", "%s")', $start->format('Y-m-d'), $end->format('Y-m-d'))); | ||||
|         $chartData       = []; | ||||
|         $start->startOfDay(); | ||||
|         $end->endOfDay(); | ||||
|         // TODO not sure if these date ranges will work as expected.
 | ||||
|         Log::debug(sprintf('Now in period("%s", "%s")', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s'))); | ||||
|         $cache           = new CacheProperties(); | ||||
|         $cache->addProperty('chart.account.period'); | ||||
|         $cache->addProperty($start); | ||||
| @@ -431,7 +439,7 @@ class AccountController extends Controller | ||||
|         // collect and filter balances for the entire period.
 | ||||
|         $step            = $this->calculateStep($start, $end); | ||||
|         Log::debug(sprintf('Step is %s', $step)); | ||||
|         $locale          = app('steam')->getLocale(); | ||||
|         $locale          = Steam::getLocale(); | ||||
|         $return          = []; | ||||
| 
 | ||||
|         // fix for issue https://github.com/firefly-iii/firefly-iii/issues/8041
 | ||||
| @@ -442,14 +450,11 @@ class AccountController extends Controller | ||||
|         $format          = (string) trans('config.month_and_day_js', [], $locale); | ||||
|         $accountCurrency = $this->accountRepository->getAccountCurrency($account); | ||||
| 
 | ||||
|         Log::debug('One'); | ||||
|         $range           = Steam::finalAccountBalanceInRange($account, $start, $end, $this->convertToNative); | ||||
|         Log::debug('Two'); | ||||
|         $range           = Steam::filterAccountBalances($range, $account, $this->convertToNative, $accountCurrency); | ||||
|         Log::debug('Three'); | ||||
| 
 | ||||
|         // temp, get end balance.
 | ||||
|         Log::debug('temp get end balance'); | ||||
|         Log::debug(sprintf('period: Call finalAccountBalance with date/time "%s"', $end->toIso8601String())); | ||||
|         Steam::finalAccountBalance($account, $end); | ||||
|         Log::debug('END temp get end balance done'); | ||||
| 
 | ||||
| @@ -462,25 +467,32 @@ class AccountController extends Controller | ||||
|         Log::debug('Balances exist at:'); | ||||
|         foreach ($range as $key => $value) { | ||||
|             $newRange[] = ['date' => $key, 'info' => $value]; | ||||
|             Log::debug(sprintf(' - %s', $key)); | ||||
|             Log::debug(sprintf('%d - %s (%s)', count($newRange) - 1, $key, json_encode($value))); | ||||
|         } | ||||
|         $carbon          = Carbon::createFromFormat('Y-m-d', $newRange[0]['date']); | ||||
|         $carbon          = Carbon::createFromFormat('Y-m-d', $newRange[0]['date'])->endOfDay(); | ||||
|         Log::debug(sprintf('Start of loop, $carbon is %s', $carbon->format('Y-m-d H:i:s'))); | ||||
|         while ($end->gte($current)) { | ||||
|             $momentBalance = $previous; | ||||
|             $theDate       = $current->format('Y-m-d'); | ||||
|             while ($carbon->lte($current) && array_key_exists($expectedIndex, $newRange)) { | ||||
|                 $momentBalance = $newRange[$expectedIndex]['info']; | ||||
|                 Log::debug(sprintf('Expected index is %d!, date is %s, current is %s', $expectedIndex, $carbon->format('Y-m-d'), $current->format('Y-m-d'))); | ||||
|                 $carbon        = Carbon::createFromFormat('Y-m-d', $newRange[$expectedIndex]['date']); | ||||
|                 ++$expectedIndex; | ||||
|             } | ||||
|             // $theDate       = $current->format('Y-m-d');
 | ||||
|             Log::debug(sprintf('Now at %s, with momentBalance %s', $current->format('Y-m-d H:i:s'), json_encode($momentBalance))); | ||||
| 
 | ||||
|             // loop over the array with balances, find one that is earlier or on the same day.
 | ||||
|             while ($carbon->lte($current) && array_key_exists($expectedIndex, $newRange)) { | ||||
|                 Log::debug(sprintf('[a] Expected index is %d, $carbon is %s, current is %s', $expectedIndex, $carbon->format('Y-m-d H:i:s'), $current->format('Y-m-d H:i:s'))); | ||||
| 
 | ||||
|                 // grab the balance from that particular $expectedIndex
 | ||||
|                 $momentBalance = $newRange[$expectedIndex]['info']; | ||||
|                 ++$expectedIndex; | ||||
| 
 | ||||
|                 // make new carbon based on the next found date. this should stop the loop.
 | ||||
|                 if (array_key_exists($expectedIndex, $newRange)) { | ||||
|                     $carbon = Carbon::createFromFormat('Y-m-d', $newRange[$expectedIndex]['date'])->endOfDay(); | ||||
|                 } | ||||
|             } | ||||
|             Log::debug(sprintf('momentBalance is now %s', json_encode($momentBalance))); | ||||
|             $return        = $this->updateChartKeys($return, $momentBalance); | ||||
|             $previous      = $momentBalance; | ||||
| 
 | ||||
|             Log::debug(sprintf('Now at %s', $theDate), $momentBalance); | ||||
| 
 | ||||
| 
 | ||||
|             // process each balance thing.
 | ||||
|             foreach ($momentBalance as $key => $amount) { | ||||
|                 $label                           = $current->isoFormat($format); | ||||
| @@ -489,15 +501,13 @@ class AccountController extends Controller | ||||
|             $current       = app('navigation')->addPeriod($current, $step, 0); | ||||
|             // here too, to fix #8041, the data is corrected to the end of the period.
 | ||||
|             $current       = app('navigation')->endOfX($current, $step, null); | ||||
|             Log::debug(sprintf('Next moment is %s', $current->format('Y-m-d'))); | ||||
| 
 | ||||
|         } | ||||
|         Log::debug('End of chart loop.'); | ||||
|         // second loop (yes) to create nice array with info! Yay!
 | ||||
|         $chartData       = []; | ||||
| 
 | ||||
|         foreach ($return as $key => $info) { | ||||
|             if (3 === strlen($key)) { | ||||
|             if ('balance' !== $key && 'native_balance' !== $key) { | ||||
|                 // assume it's a currency:
 | ||||
|                 $setCurrency             = $this->currencyRepository->findByCode($key); | ||||
|                 $info['currency_symbol'] = $setCurrency->symbol; | ||||
| @@ -567,8 +577,10 @@ class AccountController extends Controller | ||||
|         $accountNames  = $this->extractNames($accounts); | ||||
| 
 | ||||
|         // grab all balances
 | ||||
|         $startBalances = app('steam')->finalAccountsBalance($accounts, $start); | ||||
|         $endBalances   = app('steam')->finalAccountsBalance($accounts, $end); | ||||
|         Log::debug(sprintf('revAccounts: finalAccountsBalance("%s")', $start->format('Y-m-d H:i:s'))); | ||||
|         Log::debug(sprintf('revAccounts: finalAccountsBalance("%s")', $end->format('Y-m-d H:i:s'))); | ||||
|         $startBalances = Steam::finalAccountsBalance($accounts, $start); | ||||
|         $endBalances   = Steam::finalAccountsBalance($accounts, $end); | ||||
| 
 | ||||
| 
 | ||||
|         // loop the accounts, then check for balance and currency info.
 | ||||
| @@ -598,6 +610,7 @@ class AccountController extends Controller | ||||
|                 } | ||||
|                 // Log::debug(sprintf('Will process expense array "%s" with amount %s', $key, $endBalance));
 | ||||
|                 $searchCode   = $this->convertToNative ? $this->defaultCurrency->code : $key; | ||||
|                 $searchCode   = 'balance' === $searchCode || 'native_balance' === $searchCode ? $this->defaultCurrency->code : $searchCode; | ||||
|                 // Log::debug(sprintf('Search code is %s', $searchCode));
 | ||||
|                 // see if there is an accompanying start amount.
 | ||||
|                 // grab the difference and find the currency.
 | ||||
|   | ||||
| @@ -168,15 +168,14 @@ class BudgetController extends Controller | ||||
|         } | ||||
|         $locale                                 = app('steam')->getLocale(); | ||||
|         $entries                                = []; | ||||
|         $amount                                 = $budgetLimit->amount; | ||||
|         $amount                                 = $budgetLimit->amount ?? '0'; | ||||
|         $budgetCollection                       = new Collection([$budget]); | ||||
|         $currency                               = $budgetLimit->transactionCurrency; | ||||
|         if ($this->convertToNative) { | ||||
|             $amount   = $budgetLimit->native_amount; | ||||
|             $amount   = $budgetLimit->native_amount ?? '0'; | ||||
|             $currency = $this->defaultCurrency; | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         while ($start <= $end) { | ||||
|             $current          = clone $start; | ||||
|             $expenses         = $this->opsRepository->sumExpenses($current, $current, null, $budgetCollection, $budgetLimit->transactionCurrency); | ||||
|   | ||||
| @@ -100,7 +100,10 @@ class ReportController extends Controller | ||||
| 
 | ||||
|         while ($current < $end) { | ||||
|             // get balances by date, grouped by currency.
 | ||||
|             $result = $helper->byAccounts($filtered, $current); | ||||
|             $balanceCurrent = clone $current; | ||||
|             $balanceCurrent->subDay()->endOfDay(); // go to correct moment.
 | ||||
|             Log::debug(sprintf('Call byAccounts("%s")', $balanceCurrent->format('Y-m-d H:i:s'))); | ||||
|             $result         = $helper->byAccounts($filtered, $balanceCurrent); | ||||
| 
 | ||||
|             // loop result, add to array.
 | ||||
|             /** @var array $netWorthItem */ | ||||
|   | ||||
| @@ -42,6 +42,7 @@ use Illuminate\Http\RedirectResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Routing\Redirector; | ||||
| use Illuminate\Support\Facades\Artisan; | ||||
| use Illuminate\Support\Facades\DB; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use Illuminate\Support\Facades\Route; | ||||
| use Illuminate\View\View; | ||||
| @@ -259,7 +260,7 @@ class DebugController extends Controller | ||||
|         $system = $this->getSystemInformation(); | ||||
|         $docker = $this->getBuildInfo(); | ||||
|         $app    = $this->getAppInfo(); | ||||
|         $user   = $this->getuserInfo(); | ||||
|         $user   = $this->getUserInfo(); | ||||
| 
 | ||||
|         return (string) view('partials.debug-table', compact('system', 'docker', 'app', 'user')); | ||||
|     } | ||||
| @@ -268,8 +269,8 @@ class DebugController extends Controller | ||||
|     { | ||||
|         $maxFileSize   = Steam::phpBytes((string) ini_get('upload_max_filesize')); | ||||
|         $maxPostSize   = Steam::phpBytes((string) ini_get('post_max_size')); | ||||
|         $drivers       = \DB::availableDrivers(); | ||||
|         $currentDriver = \DB::getDriverName(); | ||||
|         $drivers       = DB::availableDrivers(); | ||||
|         $currentDriver = DB::getDriverName(); | ||||
| 
 | ||||
|         return [ | ||||
|             'db_version'      => app('fireflyconfig')->get('db_version', 1)->data, | ||||
| @@ -381,6 +382,7 @@ class DebugController extends Controller | ||||
|             'user_count'        => User::count(), | ||||
|             'user_flags'        => $userFlags, | ||||
|             'user_agent'        => $userAgent, | ||||
|             'native'            => Amount::getNativeCurrency(), | ||||
|             'convert_to_native' => Amount::convertToNative(), | ||||
|             'locale_attempts'   => $localeAttempts, | ||||
|             'locale'            => Steam::getLocale(), | ||||
|   | ||||
| @@ -189,20 +189,29 @@ class ReconcileController extends Controller | ||||
|         if ($end->lt($start)) { | ||||
|             [$end, $start] = [$start, $end]; | ||||
|         } | ||||
|         $start->endOfDay(); | ||||
|         $end->endOfDay(); | ||||
|         $startDate      = clone $start; | ||||
|         $startDate->subDay(); | ||||
|         $end->endOfDay(); | ||||
| 
 | ||||
|         $currency       = $this->accountRepos->getAccountCurrency($account) ?? $this->defaultCurrency; | ||||
|         $startBalance   = Steam::finalAccountBalance($account, $startDate)['balance']; | ||||
|         $endBalance     = Steam::finalAccountBalance($account, $end)['balance']; | ||||
|         // correct
 | ||||
|         Log::debug(sprintf('transactions: Call finalAccountBalance with date/time "%s"', $startDate->toIso8601String())); | ||||
|         Log::debug(sprintf('transactions2: Call finalAccountBalance with date/time "%s"', $end->toIso8601String())); | ||||
|         $startBalance   = Steam::bcround(Steam::finalAccountBalance($account, $startDate)['balance'], $currency->decimal_places); | ||||
|         $endBalance     = Steam::bcround(Steam::finalAccountBalance($account, $end)['balance'], $currency->decimal_places); | ||||
| 
 | ||||
|         // get the transactions
 | ||||
|         $selectionStart = clone $start; | ||||
|         $selectionStart->startOfDay(); | ||||
|         $selectionStart->subDays(3); | ||||
|         $selectionEnd   = clone $end; | ||||
|         $selectionEnd->endOfDay(); | ||||
|         $selectionEnd->addDays(3); | ||||
| 
 | ||||
|         // to make sure the bar is in the right place:
 | ||||
|         $start->startOfDay(); | ||||
| 
 | ||||
|         // grab transactions:
 | ||||
|         /** @var GroupCollectorInterface $collector */ | ||||
|         $collector      = app(GroupCollectorInterface::class); | ||||
|   | ||||
| @@ -68,14 +68,16 @@ class AmountController extends Controller | ||||
|      */ | ||||
|     public function add(PiggyBank $piggyBank) | ||||
|     { | ||||
|         /** @var Carbon $date */ | ||||
|         $date       = session('end', today(config('app.timezone'))); | ||||
|         $accounts   = []; | ||||
|         $total      = '0'; | ||||
|         $totalSaved = $this->piggyRepos->getCurrentAmount($piggyBank); | ||||
|         $leftToSave = bcsub($piggyBank->target_amount, $totalSaved); | ||||
|         foreach ($piggyBank->accounts as $account) { | ||||
|             $leftOnAccount = $this->piggyRepos->leftOnAccount($piggyBank, $account, today(config('app.timezone'))->endOfDay()); | ||||
|             $leftOnAccount = $this->piggyRepos->leftOnAccount($piggyBank, $account, $date); | ||||
|             $savedSoFar    = $this->piggyRepos->getCurrentAmount($piggyBank, $account); | ||||
|             $maxAmount     = 0 === bccomp($piggyBank->target_amount, '0') ? $leftToSave : min($leftOnAccount, $leftToSave); | ||||
|             $leftToSave    = bcsub($piggyBank->target_amount, $savedSoFar); | ||||
|             $maxAmount     = 0 === bccomp($piggyBank->target_amount, '0') ? $leftOnAccount : min($leftOnAccount, $leftToSave); | ||||
|             $accounts[]    = [ | ||||
|                 'account'         => $account, | ||||
|                 'left_on_account' => $leftOnAccount, | ||||
| @@ -105,12 +107,13 @@ class AmountController extends Controller | ||||
|             $leftOnAccount = $this->piggyRepos->leftOnAccount($piggyBank, $account, $date); | ||||
|             $savedSoFar    = $this->piggyRepos->getCurrentAmount($piggyBank, $account); | ||||
|             $leftToSave    = bcsub($piggyBank->target_amount, $savedSoFar); | ||||
|             $maxAmount     = 0 === bccomp($piggyBank->target_amount, '0') ? $leftOnAccount : min($leftOnAccount, $leftToSave); | ||||
|             $accounts[]    = [ | ||||
|                 'account'         => $account, | ||||
|                 'left_on_account' => $leftOnAccount, | ||||
|                 'saved_so_far'    => $savedSoFar, | ||||
|                 'left_to_save'    => $leftToSave, | ||||
|                 'max_amount'      => 0 === bccomp($piggyBank->target_amount, '0') ? $leftOnAccount : min($leftOnAccount, $leftToSave), | ||||
|                 'max_amount'      => $maxAmount, | ||||
|             ]; | ||||
|             $total         = bcadd($total, $leftOnAccount); | ||||
|         } | ||||
|   | ||||
| @@ -31,6 +31,7 @@ use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Repositories\ObjectGroup\OrganisesObjectGroups; | ||||
| use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; | ||||
| use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment; | ||||
| use FireflyIII\Transformers\AccountTransformer; | ||||
| use FireflyIII\Transformers\PiggyBankTransformer; | ||||
| use Illuminate\Contracts\View\Factory; | ||||
| @@ -81,25 +82,25 @@ class IndexController extends Controller | ||||
|     { | ||||
|         $this->cleanupObjectGroups(); | ||||
|         $this->piggyRepos->resetOrder(); | ||||
|         $collection         = $this->piggyRepos->getPiggyBanks(); | ||||
|         $collection = $this->piggyRepos->getPiggyBanks(); | ||||
| 
 | ||||
|         /** @var Carbon $end */ | ||||
|         $end                = session('end', today(config('app.timezone'))->endOfMonth()); | ||||
|         $end        = session('end', today(config('app.timezone'))->endOfMonth()); | ||||
| 
 | ||||
|         // transform piggies using the transformer:
 | ||||
|         $parameters         = new ParameterBag(); | ||||
|         $parameters->set('end', $end); | ||||
|         // $parameters         = new ParameterBag();
 | ||||
|         // $parameters->set('end', $end);
 | ||||
| 
 | ||||
| 
 | ||||
|         /** @var AccountTransformer $accountTransformer */ | ||||
|         $accountTransformer = app(AccountTransformer::class); | ||||
|         $accountTransformer->setParameters($parameters); | ||||
|         // /** @var AccountTransformer $accountTransformer */
 | ||||
|         // $accountTransformer = app(AccountTransformer::class);
 | ||||
|         // $accountTransformer->setParameters($parameters);
 | ||||
| 
 | ||||
|         // data
 | ||||
|         $piggyBanks         = $this->groupPiggyBanks($collection); | ||||
|         $accounts           = $this->collectAccounts($collection); | ||||
|         $accounts           = $this->mergeAccountsAndPiggies($piggyBanks, $accounts); | ||||
|         $piggyBanks         = $this->makeSums($piggyBanks); | ||||
|         $piggyBanks = $this->groupPiggyBanks($collection); | ||||
|         $accounts   = $this->collectAccounts($collection); | ||||
|         $accounts   = $this->mergeAccountsAndPiggies($piggyBanks, $accounts); | ||||
|         $piggyBanks = $this->makeSums($piggyBanks); | ||||
| 
 | ||||
|         ksort($piggyBanks); | ||||
| 
 | ||||
| @@ -144,6 +145,9 @@ class IndexController extends Controller | ||||
|         $accountTransformer = app(AccountTransformer::class); | ||||
|         $accountTransformer->setParameters($parameters); | ||||
| 
 | ||||
|         // enrich each account.
 | ||||
|         $enrichment         = new AccountEnrichment(); | ||||
| 
 | ||||
|         $return             = []; | ||||
| 
 | ||||
|         /** @var PiggyBank $piggy */ | ||||
| @@ -152,6 +156,7 @@ class IndexController extends Controller | ||||
| 
 | ||||
|             /** @var Account $account */ | ||||
|             foreach ($accounts as $account) { | ||||
|                 $account   = $enrichment->enrichSingle($account); | ||||
|                 $array     = $accountTransformer->transform($account); | ||||
|                 $accountId = (int) $array['id']; | ||||
|                 if (!array_key_exists($accountId, $return)) { | ||||
|   | ||||
							
								
								
									
										29
									
								
								app/Http/Controllers/Preferences/NotificationsController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								app/Http/Controllers/Preferences/NotificationsController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| <?php | ||||
| 
 | ||||
| /* | ||||
|  * NotificationsController.php | ||||
|  * Copyright (c) 2025 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\Http\Controllers\Preferences; | ||||
| 
 | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| 
 | ||||
| class NotificationsController extends Controller {} | ||||
| @@ -120,7 +120,7 @@ class PreferencesController extends Controller | ||||
|         $pushoverUserToken              = (string) Preferences::getEncrypted('pushover_user_token', '')->data; | ||||
|         $ntfyServer                     = Preferences::getEncrypted('ntfy_server', 'https://ntfy.sh')->data; | ||||
|         $ntfyTopic                      = (string) Preferences::getEncrypted('ntfy_topic', '')->data; | ||||
|         $ntfyAuth                       = Preferences::get('ntfy_auth', false)->data; | ||||
|         $ntfyAuth                       = '1' === Preferences::get('ntfy_auth', false)->data; | ||||
|         $ntfyUser                       = Preferences::getEncrypted('ntfy_user', '')->data; | ||||
|         $ntfyPass                       = (string) Preferences::getEncrypted('ntfy_pass', '')->data; | ||||
|         $channels                       = config('notifications.channels'); | ||||
| @@ -264,6 +264,7 @@ class PreferencesController extends Controller | ||||
|         if ($convertToNative && !$this->convertToNative) { | ||||
|             // set to true!
 | ||||
|             Log::debug('User sets convertToNative to true.'); | ||||
|             Preferences::set('convert_to_native', $convertToNative); | ||||
|             event(new UserGroupChangedDefaultCurrency(auth()->user()->userGroup)); | ||||
|         } | ||||
|         Preferences::set('convert_to_native', $convertToNative); | ||||
|   | ||||
| @@ -42,6 +42,7 @@ use Illuminate\Http\RedirectResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Routing\Redirector; | ||||
| use Illuminate\Support\Collection; | ||||
| use Illuminate\Support\Facades\DB; | ||||
| use Illuminate\View\View; | ||||
| use Laravel\Passport\ClientRepository; | ||||
| 
 | ||||
| @@ -139,7 +140,7 @@ class ProfileController extends Controller | ||||
|         /** @var User $user */ | ||||
|         $user           = auth()->user(); | ||||
|         $isInternalAuth = $this->internalAuth; | ||||
|         $count          = \DB::table('oauth_clients')->where('personal_access_client', true)->whereNull('user_id')->count(); | ||||
|         $count          = DB::table('oauth_clients')->where('personal_access_client', true)->whereNull('user_id')->count(); | ||||
|         $subTitle       = $user->email; | ||||
|         $userId         = $user->id; | ||||
|         $enabled2FA     = null !== $user->mfa_secret; | ||||
|   | ||||
| @@ -83,6 +83,8 @@ class ReportController extends Controller | ||||
|             return view('error')->with('message', (string) trans('firefly.end_after_start_date')); | ||||
|         } | ||||
|         $this->repository->cleanupBudgets(); | ||||
|         $start->endOfDay(); // end of day so the final balance is at the end of that day.
 | ||||
|         $end->endOfDay(); | ||||
| 
 | ||||
|         app('view')->share( | ||||
|             'subTitle', | ||||
| @@ -114,6 +116,8 @@ class ReportController extends Controller | ||||
|             return view('error')->with('message', (string) trans('firefly.end_after_start_date')); | ||||
|         } | ||||
|         $this->repository->cleanupBudgets(); | ||||
|         $start->endOfDay(); // end of day so the final balance is at the end of that day.
 | ||||
|         $end->endOfDay(); | ||||
| 
 | ||||
|         app('view')->share( | ||||
|             'subTitle', | ||||
| @@ -146,6 +150,8 @@ class ReportController extends Controller | ||||
|             return view('error')->with('message', (string) trans('firefly.end_after_start_date')); | ||||
|         } | ||||
|         $this->repository->cleanupBudgets(); | ||||
|         $start->endOfDay(); // end of day so the final balance is at the end of that day.
 | ||||
|         $end->endOfDay(); | ||||
| 
 | ||||
|         app('view')->share( | ||||
|             'subTitle', | ||||
| @@ -179,6 +185,8 @@ class ReportController extends Controller | ||||
|         } | ||||
| 
 | ||||
|         $this->repository->cleanupBudgets(); | ||||
|         $start->endOfDay(); // end of day so the final balance is at the end of that day.
 | ||||
|         $end->endOfDay(); | ||||
| 
 | ||||
|         app('view')->share( | ||||
|             'subTitle', | ||||
| @@ -211,6 +219,8 @@ class ReportController extends Controller | ||||
|         } | ||||
| 
 | ||||
|         $this->repository->cleanupBudgets(); | ||||
|         $start->endOfDay(); // end of day so the final balance is at the end of that day.
 | ||||
|         $end->endOfDay(); | ||||
| 
 | ||||
|         app('view')->share( | ||||
|             'subTitle', | ||||
| @@ -367,6 +377,8 @@ class ReportController extends Controller | ||||
|             return view('error')->with('message', (string) trans('firefly.end_after_start_date')); | ||||
|         } | ||||
|         $this->repository->cleanupBudgets(); | ||||
|         $start->endOfDay(); // end of day so the final balance is at the end of that day.
 | ||||
|         $end->endOfDay(); | ||||
| 
 | ||||
|         app('view')->share( | ||||
|             'subTitle', | ||||
|   | ||||
| @@ -43,6 +43,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; | ||||
| 
 | ||||
| /** | ||||
| @@ -223,7 +224,9 @@ class ConvertController extends Controller | ||||
|         // group accounts:
 | ||||
|         /** @var Account $account */ | ||||
|         foreach ($accountList as $account) { | ||||
|             $balance                     = Steam::finalAccountBalance($account, today()->endOfDay())['balance']; | ||||
|             $date                        = today()->endOfDay(); | ||||
|             Log::debug(sprintf('getLiabilities: Call finalAccountBalance with date/time "%s"', $date->toIso8601String())); | ||||
|             $balance                     = Steam::finalAccountBalance($account, $date)['balance']; | ||||
|             $currency                    = $this->accountRepository->getAccountCurrency($account) ?? $this->defaultCurrency; | ||||
|             $role                        = 'l_'.$account->accountType->type; | ||||
|             $key                         = (string) trans('firefly.opt_group_'.$role); | ||||
| @@ -245,7 +248,9 @@ class ConvertController extends Controller | ||||
|         // group accounts:
 | ||||
|         /** @var Account $account */ | ||||
|         foreach ($accountList as $account) { | ||||
|             $balance                     = Steam::finalAccountBalance($account, today()->endOfDay())['balance']; | ||||
|             $date                        = today()->endOfDay(); | ||||
|             Log::debug(sprintf('getAssetAccounts: Call finalAccountBalance with date/time "%s"', $date->toIso8601String())); | ||||
|             $balance                     = Steam::finalAccountBalance($account, $date)['balance']; | ||||
|             $currency                    = $this->accountRepository->getAccountCurrency($account) ?? $this->defaultCurrency; | ||||
|             $role                        = (string) $this->accountRepository->getMetaValue($account, 'account_role'); | ||||
|             if ('' === $role) { | ||||
|   | ||||
| @@ -28,6 +28,7 @@ use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Support\System\OAuthKeys; | ||||
| use Illuminate\Database\QueryException; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\DB; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| 
 | ||||
| /** | ||||
| @@ -83,7 +84,7 @@ class Installer | ||||
|         // Log::debug('Now in routine hasNoTables()');
 | ||||
| 
 | ||||
|         try { | ||||
|             \DB::table('users')->count(); | ||||
|             DB::table('users')->count(); | ||||
|         } catch (QueryException $e) { | ||||
|             $message = $e->getMessage(); | ||||
|             Log::error(sprintf('Error message trying to access users-table: %s', $message)); | ||||
|   | ||||
| @@ -380,9 +380,10 @@ class CreateRecurringTransactions implements ShouldQueue | ||||
|         } | ||||
| 
 | ||||
|         $array                      = [ | ||||
|             'user'         => $recurrence->user_id, | ||||
|             'group_title'  => $groupTitle, | ||||
|             'transactions' => $this->getTransactionData($recurrence, $repetition, $date), | ||||
|             'user'               => $recurrence->user, | ||||
|             'user_group'         => $recurrence->user->userGroup, | ||||
|             'group_title'        => $groupTitle, | ||||
|             'transactions'       => $this->getTransactionData($recurrence, $repetition, $date), | ||||
|         ]; | ||||
| 
 | ||||
|         /** @var TransactionGroup $group */ | ||||
| @@ -419,11 +420,10 @@ class CreateRecurringTransactions implements ShouldQueue | ||||
|         /** @var RecurrenceTransaction $transaction */ | ||||
|         foreach ($transactions as $index => $transaction) { | ||||
|             $single   = [ | ||||
|                 'type'                  => null === $transaction?->transactionType?->type ? | ||||
|                     strtolower($recurrence->transactionType->type) : | ||||
|                     strtolower($transaction->transactionType->type), | ||||
|                 'type'                  => null === $transaction?->transactionType?->type ? strtolower($recurrence->transactionType->type) : strtolower($transaction->transactionType->type), // @phpstan-ignore-line
 | ||||
|                 'date'                  => $date, | ||||
|                 'user'                  => $recurrence->user_id, | ||||
|                 'user'                  => $recurrence->user, | ||||
|                 'user_group'            => $recurrence->user->userGroup, | ||||
|                 'currency_id'           => $transaction->transaction_currency_id, | ||||
|                 'currency_code'         => null, | ||||
|                 'description'           => $transaction->description, | ||||
|   | ||||
| @@ -48,14 +48,15 @@ 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', | ||||
|             'native_virtual_balance' => 'string', | ||||
|             'created_at'                   => 'datetime', | ||||
|             'updated_at'                   => 'datetime', | ||||
|             'user_id'                      => 'integer', | ||||
|             'user_group_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']; | ||||
|   | ||||
| @@ -42,13 +42,15 @@ class Attachment extends Model | ||||
| 
 | ||||
|     protected $casts | ||||
|                         = [ | ||||
|             'created_at' => 'datetime', | ||||
|             'updated_at' => 'datetime', | ||||
|             'deleted_at' => 'datetime', | ||||
|             'uploaded'   => 'boolean', | ||||
|             'created_at'                   => 'datetime', | ||||
|             'updated_at'                   => 'datetime', | ||||
|             'deleted_at'                   => 'datetime', | ||||
|             'uploaded'                     => 'boolean', | ||||
|             'user_id'                      => 'integer', | ||||
|             'user_group_id'                => 'integer', | ||||
|         ]; | ||||
| 
 | ||||
|     protected $fillable = ['attachable_id', 'attachable_type', 'user_id', 'md5', 'filename', 'mime', 'title', 'description', 'size', 'uploaded']; | ||||
|     protected $fillable = ['attachable_id', 'attachable_type', 'user_id', 'user_group_id', 'md5', 'filename', 'mime', 'title', 'description', 'size', 'uploaded']; | ||||
| 
 | ||||
|     /** | ||||
|      * Route binder. Converts the key in the URL to the specified object (or throw 404). | ||||
|   | ||||
| @@ -41,14 +41,16 @@ class AvailableBudget extends Model | ||||
| 
 | ||||
|     protected $casts | ||||
|                         = [ | ||||
|             'created_at'              => 'datetime', | ||||
|             'updated_at'              => 'datetime', | ||||
|             'deleted_at'              => 'datetime', | ||||
|             'start_date'              => 'date', | ||||
|             'end_date'                => 'date', | ||||
|             'transaction_currency_id' => 'int', | ||||
|             'amount'                  => 'string', | ||||
|             'native_amount'           => 'string', | ||||
|             'created_at'                   => 'datetime', | ||||
|             'updated_at'                   => 'datetime', | ||||
|             'deleted_at'                   => 'datetime', | ||||
|             'start_date'                   => 'date', | ||||
|             'end_date'                     => 'date', | ||||
|             'transaction_currency_id'      => 'int', | ||||
|             'amount'                       => 'string', | ||||
|             'native_amount'                => 'string', | ||||
|             'user_id'                      => 'integer', | ||||
|             'user_group_id'                => 'integer', | ||||
|         ]; | ||||
| 
 | ||||
|     protected $fillable = ['user_id', 'user_group_id', 'transaction_currency_id', 'amount', 'start_date', 'end_date', 'start_date_tz', 'end_date_tz', 'native_amount']; | ||||
|   | ||||
| @@ -43,14 +43,16 @@ class Budget extends Model | ||||
| 
 | ||||
|     protected $casts | ||||
|                         = [ | ||||
|             'created_at' => 'datetime', | ||||
|             'updated_at' => 'datetime', | ||||
|             'deleted_at' => 'datetime', | ||||
|             'active'     => 'boolean', | ||||
|             'encrypted'  => 'boolean', | ||||
|             'created_at'                   => 'datetime', | ||||
|             'updated_at'                   => 'datetime', | ||||
|             'deleted_at'                   => 'datetime', | ||||
|             'active'                       => 'boolean', | ||||
|             'encrypted'                    => 'boolean', | ||||
|             'user_id'                      => 'integer', | ||||
|             'user_group_id'                => 'integer', | ||||
|         ]; | ||||
| 
 | ||||
|     protected $fillable = ['user_id', 'name', 'active', 'order', 'user_group_id']; | ||||
|     protected $fillable = ['user_id', 'user_group_id', 'name', 'active', 'order', 'user_group_id']; | ||||
| 
 | ||||
|     protected $hidden   = ['encrypted']; | ||||
| 
 | ||||
|   | ||||
| @@ -42,10 +42,12 @@ class Category extends Model | ||||
| 
 | ||||
|     protected $casts | ||||
|                         = [ | ||||
|             'created_at' => 'datetime', | ||||
|             'updated_at' => 'datetime', | ||||
|             'deleted_at' => 'datetime', | ||||
|             'encrypted'  => 'boolean', | ||||
|             'created_at'                   => 'datetime', | ||||
|             'updated_at'                   => 'datetime', | ||||
|             'deleted_at'                   => 'datetime', | ||||
|             'encrypted'                    => 'boolean', | ||||
|             'user_id'                      => 'integer', | ||||
|             'user_group_id'                => 'integer', | ||||
|         ]; | ||||
| 
 | ||||
|     protected $fillable = ['user_id', 'user_group_id', 'name']; | ||||
|   | ||||
| @@ -40,14 +40,15 @@ class CurrencyExchangeRate extends Model | ||||
| 
 | ||||
|     protected $casts | ||||
|                         = [ | ||||
|             'created_at'       => 'datetime', | ||||
|             'updated_at'       => 'datetime', | ||||
|             'user_id'          => 'int', | ||||
|             'from_currency_id' => 'int', | ||||
|             'to_currency_id'   => 'int', | ||||
|             'date'             => SeparateTimezoneCaster::class, | ||||
|             'rate'             => 'string', | ||||
|             'user_rate'        => 'string', | ||||
|             'created_at'                   => 'datetime', | ||||
|             'updated_at'                   => 'datetime', | ||||
|             'user_id'                      => 'integer', | ||||
|             'user_group_id'                => 'integer', | ||||
|             'from_currency_id'             => 'integer', | ||||
|             'to_currency_id'               => 'integer', | ||||
|             'date'                         => SeparateTimezoneCaster::class, | ||||
|             'rate'                         => 'string', | ||||
|             'user_rate'                    => 'string', | ||||
|         ]; | ||||
|     protected $fillable = ['user_id', 'from_currency_id', 'to_currency_id', 'date', 'date_tz', 'rate']; | ||||
| 
 | ||||
|   | ||||
| @@ -36,6 +36,13 @@ class GroupMembership extends Model | ||||
|     use ReturnsIntegerIdTrait; | ||||
|     use ReturnsIntegerUserIdTrait; | ||||
| 
 | ||||
|     protected $casts    = [ | ||||
|         'created_at'                   => 'datetime', | ||||
|         'updated_at'                   => 'datetime', | ||||
|         'user_id'                      => 'integer', | ||||
|         'user_group_id'                => 'integer', | ||||
|     ]; | ||||
| 
 | ||||
|     protected $fillable = ['user_id', 'user_group_id', 'user_role_id']; | ||||
| 
 | ||||
|     public function user(): BelongsTo | ||||
|   | ||||
| @@ -39,10 +39,12 @@ class InvitedUser extends Model | ||||
| 
 | ||||
|     protected $casts | ||||
|                         = [ | ||||
|             'expires'  => SeparateTimezoneCaster::class, | ||||
|             'redeemed' => 'boolean', | ||||
|             'expires'                      => SeparateTimezoneCaster::class, | ||||
|             'redeemed'                     => 'boolean', | ||||
|             'user_id'                      => 'integer', | ||||
|             'user_group_id'                => 'integer', | ||||
|         ]; | ||||
|     protected $fillable = ['user_id', 'email', 'invite_code', 'expires', 'expires_tz', 'redeemed']; | ||||
|     protected $fillable = ['user_group_id', 'user_id', 'email', 'invite_code', 'expires', 'expires_tz', 'redeemed']; | ||||
| 
 | ||||
|     /** | ||||
|      * Route binder. Converts the key in the URL to the specified object (or throw 404). | ||||
|   | ||||
| @@ -40,10 +40,11 @@ class ObjectGroup extends Model | ||||
| 
 | ||||
|     protected $casts | ||||
|                         = [ | ||||
|             'created_at' => 'datetime', | ||||
|             'updated_at' => 'datetime', | ||||
|             'user_id'    => 'integer', | ||||
|             'deleted_at' => 'datetime', | ||||
|             'created_at'                   => 'datetime', | ||||
|             'updated_at'                   => 'datetime', | ||||
|             'user_id'                      => 'integer', | ||||
|             'user_group_id'                => 'integer', | ||||
|             'deleted_at'                   => 'datetime', | ||||
|         ]; | ||||
|     protected $fillable = ['title', 'order', 'user_id', 'user_group_id']; | ||||
| 
 | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user