mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-31 02:36:28 +00:00 
			
		
		
		
	Compare commits
	
		
			317 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 5f299b895b | ||
|  | 4e1bb5fbac | ||
|  | 47ccc513ad | ||
|  | cce1a01936 | ||
|  | 6f2b1a6a76 | ||
|  | 8526907f50 | ||
|  | bc192a8e54 | ||
|  | 9ff6f8fc52 | ||
|  | 6573bd6b4b | ||
|  | 9dc3f614af | ||
|  | 3888b8cceb | ||
|  | 294df4a2b3 | ||
|  | 265dd37212 | ||
|  | eb7c79ad27 | ||
|  | de111c7100 | ||
|  | e892c9a824 | ||
|  | 5eb0e18cae | ||
|  | 27cabb398e | ||
|  | 64dbb14241 | ||
|  | bb4e2be9eb | ||
|  | 7d1de0da17 | ||
|  | bf16c9a42b | ||
|  | 1a7b1ce499 | ||
|  | efc9bc71a7 | ||
|  | fc5b315af0 | ||
|  | 7a4a78628d | ||
|  | d16fb30a62 | ||
|  | 2d177e660e | ||
|  | 2f131dc170 | ||
|  | 94810e371a | ||
|  | 59731878f6 | ||
|  | 54ede8aa18 | ||
|  | b415b6b043 | ||
|  | 70c922cdc5 | ||
|  | 068fc32cb2 | ||
|  | 3dcdacc3b8 | ||
|  | a6594358d8 | ||
|  | f98921da46 | ||
|  | 25747fbcf2 | ||
|  | aac5c2b13c | ||
|  | cc810a5b6f | ||
|  | 1b3592d959 | ||
|  | d75614e9a7 | ||
|  | 08703e282f | ||
|  | 2904baf44e | ||
|  | f99e46bf75 | ||
|  | 9f87890ead | ||
|  | 638184cf66 | ||
|  | 03babfe75c | ||
|  | 238ed3c788 | ||
|  | 6a9d931ba3 | ||
|  | a3d2a9e00b | ||
|  | 39b88e8207 | ||
|  | 449c6dfde5 | ||
|  | 7cc47ca0b1 | ||
|  | 95f4a83f41 | ||
|  | 35154dc7a3 | ||
|  | 0fd0d7d080 | ||
|  | 658265c938 | ||
|  | 38fe9e7e1c | ||
|  | 77056dcf8d | ||
|  | 026683a8e1 | ||
|  | 6ab6dd6ac3 | ||
|  | 83de3482ce | ||
|  | 919a35aed3 | ||
|  | ad3defb071 | ||
|  | 9c929ecd1b | ||
|  | f79c9f7cf1 | ||
|  | 8e75c345d9 | ||
|  | 44886d9aad | ||
|  | c2d444347d | ||
|  | 5cb497596d | ||
|  | 1857469d2f | ||
|  | ea71b4843d | ||
|  | 97727e2e3d | ||
|  | f81e7da8bb | ||
|  | 8e827bf83b | ||
|  | 9e1fa284ca | ||
|  | 3bf800be6e | ||
|  | 635b9f9dba | ||
|  | 52a0d7cf7b | ||
|  | a34516932b | ||
|  | 929a2a30a2 | ||
|  | ffa88eeb08 | ||
|  | 51b45b4ed4 | ||
|  | f263844793 | ||
|  | 18c46df9aa | ||
|  | 15846e157b | ||
|  | bc59f2db0d | ||
|  | cd2be8c1a4 | ||
|  | f958115c50 | ||
|  | e7d677bfb6 | ||
|  | 3e80ffc52b | ||
|  | d0c7a5c076 | ||
|  | f3f4e6b354 | ||
|  | 5a45b25614 | ||
|  | 0b5ee1edfc | ||
|  | da3dc599f9 | ||
|  | f013b435ab | ||
|  | 5f6975a113 | ||
|  | c5dee29e4b | ||
|  | 633ee02f13 | ||
|  | 6b750c909a | ||
|  | 5f8b6640a9 | ||
|  | dd42d8437c | ||
|  | 67a178591d | ||
|  | f5e5659c1f | ||
|  | 8b0f0fb615 | ||
|  | 209116e766 | ||
|  | 79392ab656 | ||
|  | 3ca1207231 | ||
|  | cec1b147f2 | ||
|  | 46cfcfa3e7 | ||
|  | b833e8dfa2 | ||
|  | 77b843efd8 | ||
|  | db72ad7c60 | ||
|  | eadc630fcb | ||
|  | 170c1793cc | ||
|  | 9f7c6c2d0c | ||
|  | 72d054c55c | ||
|  | 524edfe7c2 | ||
|  | c25c5623d2 | ||
|  | 4f38b77ef6 | ||
|  | 5862803434 | ||
|  | 5b3beded39 | ||
|  | c61fb7a598 | ||
|  | 33d9148029 | ||
|  | 63969f5a33 | ||
|  | edde18aeef | ||
|  | 657116d361 | ||
|  | e16269daa8 | ||
|  | c07591ff5c | ||
|  | 75a478ad54 | ||
|  | 8dae8b1a7f | ||
|  | 15fd8cf486 | ||
|  | 55333156ac | ||
|  | 8cdcba3231 | ||
|  | 8bab9e84e2 | ||
|  | 2faae83912 | ||
|  | 5a61a11a61 | ||
|  | a6d71988f2 | ||
|  | 7069e242ae | ||
|  | 56ee830558 | ||
|  | 6dd12729e6 | ||
|  | 14a48303cb | ||
|  | 72cf6c9c0f | ||
|  | 144ee6b8ca | ||
|  | 8967d86da6 | ||
|  | 18c6edbb5d | ||
|  | 53de3c4717 | ||
|  | ad577e4e81 | ||
|  | 44811a3e7c | ||
|  | 1ab3f05b3a | ||
|  | 5e76488ae7 | ||
|  | 32771fe7e1 | ||
|  | 9b40cc6881 | ||
|  | 2e35260bbb | ||
|  | a067704277 | ||
|  | de281818ac | ||
|  | c49bfad38d | ||
|  | c1ba591b26 | ||
|  | 719af38a61 | ||
|  | ac61dfae6b | ||
|  | 813fb679a7 | ||
|  | e7562781f7 | ||
|  | 56d36b7f53 | ||
|  | 53b3f7f821 | ||
|  | 08a53156bd | ||
|  | 8985cd6309 | ||
|  | 3833da7410 | ||
|  | 4210cd10db | ||
|  | a7bd1c6892 | ||
|  | 52b0111afa | ||
|  | 7921d128e4 | ||
|  | d7e838701a | ||
|  | 289bcb22aa | ||
|  | 3fe57b7983 | ||
|  | 32e92c2a16 | ||
|  | 1b3d208540 | ||
|  | 6a8bf0aa62 | ||
|  | 56715556ed | ||
|  | 838330b909 | ||
|  | 69553b138b | ||
|  | 36d7a02994 | ||
|  | 301528e2d2 | ||
|  | 0303b45707 | ||
|  | ba722e8ed5 | ||
|  | 289e5a5442 | ||
|  | fdad96e2bc | ||
|  | af994e4dae | ||
|  | 006d68e279 | ||
|  | 29dc122ad3 | ||
|  | cf4a8c6204 | ||
|  | 3c73fe92bf | ||
|  | 6637590797 | ||
|  | b8bab11acd | ||
|  | a2f600feac | ||
|  | 80dd62ef0a | ||
|  | 827b1c9cd8 | ||
|  | 2e4fcf803d | ||
|  | d00d95fc6f | ||
|  | 3e3ab9bd25 | ||
|  | 6eecc7722d | ||
|  | ada4aaf69a | ||
|  | 93244c1f78 | ||
|  | be056cea6b | ||
|  | 659ca8be14 | ||
|  | ea9af8366d | ||
|  | 80edd47d36 | ||
|  | d7746b3649 | ||
|  | c4c4fbc34c | ||
|  | 59f57c96e9 | ||
|  | a2f852fecf | ||
|  | ad114ed329 | ||
|  | c4c3d0f07f | ||
|  | 6cf8102de5 | ||
|  | e7e4aa2218 | ||
|  | 6d84f4b6c1 | ||
|  | ce3e9ffd11 | ||
|  | 3ada260e0e | ||
|  | 8fdd0cb795 | ||
|  | 913e05a2e6 | ||
|  | fa1f703ef6 | ||
|  | 4004c53e1b | ||
|  | 4838670649 | ||
|  | a985e09282 | ||
|  | 9bd1503cb4 | ||
|  | a2ccbf7844 | ||
|  | 61bbe8a905 | ||
|  | 59bc5d22d1 | ||
|  | 1423d5b314 | ||
|  | 152d0eb1d0 | ||
|  | 6426d1df06 | ||
|  | 9284eb3fe9 | ||
|  | afdae8bc1e | ||
|  | 2a7085e593 | ||
|  | 2408fb3ed4 | ||
|  | 8316afb176 | ||
|  | e59fd098a3 | ||
|  | e044199693 | ||
|  | 8f8e29fc22 | ||
|  | 8de5384158 | ||
|  | 216c659335 | ||
|  | 041ca8a5d3 | ||
|  | fe4f1b306d | ||
|  | a0972d99fb | ||
|  | e332bfef7c | ||
|  | cba5e226d8 | ||
|  | 5aff0c4943 | ||
|  | cb49c00f4d | ||
|  | e26d797d57 | ||
|  | 938581527e | ||
|  | c38ae09735 | ||
|  | 28c3cfe084 | ||
|  | 4a2823bcba | ||
|  | 18eba02026 | ||
|  | d4690ce580 | ||
|  | a785c450b1 | ||
|  | 7480dc4a19 | ||
|  | ad01891a67 | ||
|  | 67fe35d564 | ||
|  | 7f19b6957a | ||
|  | 0a54caf202 | ||
|  | 4b4c1c7f8f | ||
|  | d071f3947e | ||
|  | b3d99cd210 | ||
|  | 90e696f82c | ||
|  | 958fcd1cfa | ||
|  | 8f57c7dcb3 | ||
|  | 77262f52a4 | ||
|  | 16bfbc8a12 | ||
|  | 1fd375b875 | ||
|  | 46131ad39d | ||
|  | 0b5c5b2ae9 | ||
|  | 55be174037 | ||
|  | a17b7025f1 | ||
|  | 170cf7fd77 | ||
|  | 23cdb4d326 | ||
|  | cbbe529572 | ||
|  | 0b382426e9 | ||
|  | 1cbbf9baa4 | ||
|  | 8d41ff7b79 | ||
|  | e3b6057bf8 | ||
|  | 66a4042cad | ||
|  | 56c08d8302 | ||
|  | d4e759754d | ||
|  | a96e171cbf | ||
|  | bd4a8c8397 | ||
|  | 04f71b3b43 | ||
|  | d124de51db | ||
|  | d87d12a0f5 | ||
|  | f2b08346d0 | ||
|  | d3682a6727 | ||
|  | 371bbd9508 | ||
|  | a8a28f442f | ||
|  | 65ddd8a736 | ||
|  | 8bb27de233 | ||
|  | 37e2f097ba | ||
|  | 1966d87ce6 | ||
|  | 7b8c86e1e3 | ||
|  | de634da513 | ||
|  | 96836e2d6c | ||
|  | 8a9d576f61 | ||
|  | 791d12fbb4 | ||
|  | d1329be2fa | ||
|  | 3ed6561702 | ||
|  | 7a0587f433 | ||
|  | 0fe682bfe6 | ||
|  | 0f685e8789 | ||
|  | 420771c233 | ||
|  | 5e3e9271ca | ||
|  | 1e603c0833 | ||
|  | 03e1673e92 | ||
|  | 9f992f003d | ||
|  | f50244a41f | ||
|  | baf9ebab15 | ||
|  | fb2fa54480 | 
							
								
								
									
										12
									
								
								.env.example
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								.env.example
									
									
									
									
									
								
							| @@ -2,6 +2,7 @@ APP_ENV=production | ||||
| APP_DEBUG=false | ||||
| APP_KEY=SomeRandomStringOf32CharsExactly | ||||
|  | ||||
|  | ||||
| DB_CONNECTION=mysql | ||||
| DB_HOST=localhost | ||||
| DB_DATABASE=homestead | ||||
| @@ -11,14 +12,19 @@ DB_PASSWORD=secret | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
|  | ||||
| DEFAULT_CURRENCY=EUR | ||||
| DEFAULT_LANGUAGE=en_US | ||||
|  | ||||
| EMAIL_SMTP= | ||||
| EMAIL_DRIVER=smtp | ||||
| EMAIL_USERNAME= | ||||
| EMAIL_PASSWORD= | ||||
| ANALYTICS_ID= | ||||
| EMAIL_PRETEND=false | ||||
|  | ||||
| SHOW_INCOMPLETE_TRANSLATIONS=false | ||||
|  | ||||
| ANALYTICS_ID= | ||||
| RUNCLEANUP=true | ||||
| SITE_OWNER=mail@example.com | ||||
|  | ||||
| SENDGRID_USERNAME= | ||||
| SENDGRID_PASSWORD= | ||||
| BLOCKED_DOMAINS= | ||||
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -5,7 +5,7 @@ Thumbs.db | ||||
| .idea/ | ||||
| tests/_output/* | ||||
| _ide_helper.php | ||||
| /build/logs/clover.xml | ||||
| /build/logs | ||||
| index.html* | ||||
| app/storage/firefly-export* | ||||
| .vagrant | ||||
|   | ||||
| @@ -10,6 +10,9 @@ install: | ||||
|   - composer update | ||||
|   - php artisan env | ||||
|   - mv -v .env.testing .env | ||||
|   - touch storage/database/testing.db | ||||
|   - php artisan migrate --env=testing | ||||
|   - php artisan migrate --seed --env=testing | ||||
|  | ||||
| script: | ||||
|   - phpunit | ||||
|   | ||||
							
								
								
									
										36
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								README.md
									
									
									
									
									
								
							| @@ -11,15 +11,12 @@ | ||||
| "Firefly III" is a financial manager. It can help you keep track of expenses, income, budgets and everything in between. It even supports credit cards, shared  | ||||
| household accounts and savings accounts! It's pretty fancy. You should use it to save and organise money. | ||||
|   | ||||
| _Firefly is a system you'll have install yourself on webhosting of your choosing._ | ||||
|  | ||||
| Personal financial management is pretty difficult, and everybody has their own approach to it. Some people | ||||
| make budgets, other people limit their cashflow by throwing away their credit cards, others try to increase | ||||
| their current cashflow. There are tons of ways to save and earn money. | ||||
|  | ||||
| Firefly works on the principle that if you know where you're money is going, you can stop it from going there. | ||||
|  | ||||
|   | ||||
| To get to know Firefly, and to see if it fits you, check out these resources: | ||||
|  | ||||
| - The screenshots below on this very page. | ||||
| @@ -27,6 +24,11 @@ To get to know Firefly, and to see if it fits you, check out these resources: | ||||
| - The [full description](https://github.com/JC5/firefly-iii/wiki/full-description), which will tell you how Firefly works, | ||||
| and the philosophy behind it. | ||||
|  | ||||
| #### A quick technical overview | ||||
|  | ||||
| Firefly is a system you'll have install yourself on webhosting of your choosing. It needs PHP and MySQL. The current version of Firefly III requires PHP 5.6.4 or | ||||
| higher. Soon, this will be PHP 7.0.0 or higher. | ||||
|  | ||||
|  | ||||
| #### About the name (should you care) | ||||
|  | ||||
| @@ -61,19 +63,19 @@ Everything is organised: | ||||
|  | ||||
| _Please note that everything in these screenshots is fictional and may not be realistic._ | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| ## Running and installing | ||||
|  | ||||
| @@ -82,7 +84,19 @@ If you're still interested please read [the installation guide](https://github.c | ||||
| and the **[first use guide](https://github.com/JC5/firefly-iii/wiki/First-use)**. | ||||
|   | ||||
| If you want to try out Firefly III, you can do so on [this dedicated website](https://geld.nder.be/).  | ||||
| This site always runs the latest version of Firefly III. If you want to use it, please read the [privacy considerations](https://github.com/JC5/firefly-iii/wiki/Privacy-on-demo-site) for this demo-site. Accounts on the demo sites will stop working after one week. | ||||
| This site always runs the latest version of Firefly III. If you want to use it, please read the [privacy considerations](https://github.com/JC5/firefly-iii/wiki/Privacy-on-demo-site) for this demo-site. Accounts on the demo sites will stop working after one month. It's a trial. | ||||
|  | ||||
| ## Security | ||||
|  | ||||
| You should always run Firefly III on a site with TLS enabled (https://). Please note that although some parts of the | ||||
| database are encrypted (transaction descriptions, names, etc.) some parts are _not_ (amounts, dates, etc). If you need | ||||
| more security, you must enable transparent database encryption or a comparable technology. Please remember that this | ||||
| is open source software under active development, and it is in no way guaranteed to be safe or secure. | ||||
|  | ||||
| ## Translations | ||||
|  | ||||
| Firefly III is currently available in Dutch and English. Support for other languages is being worked on. I could use | ||||
| your help. Checkout [Crowdin](https://crowdin.com/project/firefly-iii) for more information. | ||||
|  | ||||
| ## Credits | ||||
|  | ||||
|   | ||||
| @@ -1,25 +0,0 @@ | ||||
| <?php namespace FireflyIII\Events; | ||||
|  | ||||
| use Illuminate\Queue\SerializesModels; | ||||
|  | ||||
| /** | ||||
|  * Class JournalDeleted | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @package FireflyIII\Events | ||||
|  */ | ||||
| class JournalDeleted extends Event | ||||
| { | ||||
|  | ||||
|     use SerializesModels; | ||||
|  | ||||
|     /** | ||||
|      * Create a new event instance. | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         // | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -14,15 +14,6 @@ use Illuminate\Support\Collection; | ||||
| interface AccountChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function all(Collection $accounts, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|   | ||||
| @@ -3,10 +3,8 @@ | ||||
| namespace FireflyIII\Generator\Chart\Account; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Config; | ||||
| use FireflyIII\Models\Account; | ||||
| use Illuminate\Support\Collection; | ||||
| use Preferences; | ||||
| use Steam; | ||||
|  | ||||
| /** | ||||
| @@ -17,21 +15,6 @@ use Steam; | ||||
| class ChartJsAccountChartGenerator implements AccountChartGenerator | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function all(Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         return $this->frontpage($accounts, $start, $end); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
| @@ -42,10 +25,10 @@ class ChartJsAccountChartGenerator implements AccountChartGenerator | ||||
|     public function expenseAccounts(Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $data = [ | ||||
|             'count'    => 1, | ||||
|             'labels'   => [], 'datasets' => [[ | ||||
|                                'label' => trans('firefly.spent'), | ||||
|                                'data'  => []]]]; | ||||
|             'count'  => 1, | ||||
|             'labels' => [], 'datasets' => [[ | ||||
|                                                'label' => trans('firefly.spent'), | ||||
|                                                'data'  => []]]]; | ||||
|  | ||||
|         bcscale(2); | ||||
|         $start->subDay(); | ||||
| @@ -105,21 +88,21 @@ class ChartJsAccountChartGenerator implements AccountChartGenerator | ||||
|     public function frontpage(Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         // language: | ||||
|         $language = Preferences::get('language', 'en')->data; | ||||
|         $format   = Config::get('firefly.monthAndDay.' . $language); | ||||
|         $data     = [ | ||||
|         $format  = trans('config.month_and_day'); | ||||
|         $data    = [ | ||||
|             'count'    => 0, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [], | ||||
|         ]; | ||||
|         $current  = clone $start; | ||||
|         $current = clone $start; | ||||
|         while ($current <= $end) { | ||||
|             $data['labels'][] = $current->formatLocalized($format); | ||||
|             $current->addDay(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         foreach ($accounts as $account) { | ||||
|             $set     = [ | ||||
|             $set      = [ | ||||
|                 'label'                => $account->name, | ||||
|                 'fillColor'            => 'rgba(220,220,220,0.2)', | ||||
|                 'strokeColor'          => 'rgba(220,220,220,1)', | ||||
| @@ -129,9 +112,15 @@ class ChartJsAccountChartGenerator implements AccountChartGenerator | ||||
|                 'pointHighlightStroke' => 'rgba(220,220,220,1)', | ||||
|                 'data'                 => [], | ||||
|             ]; | ||||
|             $current = clone $start; | ||||
|             $current  = clone $start; | ||||
|             $range    = Steam::balanceInRange($account, $start, clone $end); | ||||
|             $previous = array_values($range)[0]; | ||||
|             while ($current <= $end) { | ||||
|                 $set['data'][] = Steam::balance($account, $current); | ||||
|                 $format  = $current->format('Y-m-d'); | ||||
|                 $balance = isset($range[$format]) ? $range[$format] : $previous; | ||||
|  | ||||
|                 $set['data'][] = $balance; | ||||
|                 $previous      = $balance; | ||||
|                 $current->addDay(); | ||||
|             } | ||||
|             $data['datasets'][] = $set; | ||||
| @@ -151,10 +140,9 @@ class ChartJsAccountChartGenerator implements AccountChartGenerator | ||||
|     public function single(Account $account, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         // language: | ||||
|         $language = Preferences::get('language', 'en')->data; | ||||
|         $format   = Config::get('firefly.monthAndDay.' . $language); | ||||
|         $format = trans('config.month_and_day'); | ||||
|  | ||||
|         $data = [ | ||||
|         $data     = [ | ||||
|             'count'    => 1, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [ | ||||
| @@ -164,12 +152,17 @@ class ChartJsAccountChartGenerator implements AccountChartGenerator | ||||
|                 ] | ||||
|             ], | ||||
|         ]; | ||||
|  | ||||
|         $current = clone $start; | ||||
|         $range    = Steam::balanceInRange($account, $start, $end); | ||||
|         $current  = clone $start; | ||||
|         $previous = array_values($range)[0]; | ||||
|  | ||||
|         while ($end >= $current) { | ||||
|             $theDate = $current->format('Y-m-d'); | ||||
|             $balance = isset($range[$theDate]) ? $range[$theDate] : $previous; | ||||
|  | ||||
|             $data['labels'][]              = $current->formatLocalized($format); | ||||
|             $data['datasets'][0]['data'][] = Steam::balance($account, $current); | ||||
|             $data['datasets'][0]['data'][] = $balance; | ||||
|             $previous                      = $balance; | ||||
|             $current->addDay(); | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -14,12 +14,12 @@ interface BillChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $paid | ||||
|      * @param Collection $unpaid | ||||
|      * @param string $paid | ||||
|      * @param string $unpaid | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage(Collection $paid, Collection $unpaid); | ||||
|     public function frontpage($paid, $unpaid); | ||||
|  | ||||
|     /** | ||||
|      * @param Bill       $bill | ||||
|   | ||||
| @@ -2,11 +2,9 @@ | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Bill; | ||||
|  | ||||
| use Config; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Illuminate\Support\Collection; | ||||
| use Preferences; | ||||
|  | ||||
| /** | ||||
|  * Class ChartJsBillChartGenerator | ||||
| @@ -17,42 +15,23 @@ class ChartJsBillChartGenerator implements BillChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $paid | ||||
|      * @param Collection $unpaid | ||||
|      * @param string $paid | ||||
|      * @param string $unpaid | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage(Collection $paid, Collection $unpaid) | ||||
|     public function frontpage($paid, $unpaid) | ||||
|     { | ||||
|         $paidDescriptions   = []; | ||||
|         $paidAmount         = 0; | ||||
|         $unpaidDescriptions = []; | ||||
|         $unpaidAmount       = 0; | ||||
|         bcscale(2); | ||||
|  | ||||
|         /** @var TransactionJournal $entry */ | ||||
|         foreach ($paid as $entry) { // loop paid and create single entry: | ||||
|             $paidDescriptions[] = $entry->description; | ||||
|             $paidAmount         = bcadd($paidAmount, $entry->amount_positive); | ||||
|         } | ||||
|         /** @var Bill $entry */ | ||||
|         foreach ($unpaid as $entry) { // loop unpaid: | ||||
|             $description          = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')'; | ||||
|             $amount               = bcdiv(bcadd($entry[0]->amount_max, $entry[0]->amount_min), 2); | ||||
|             $unpaidDescriptions[] = $description; | ||||
|             $unpaidAmount         = bcadd($unpaidAmount, $amount); | ||||
|             unset($amount, $description); | ||||
|         } | ||||
|  | ||||
|         $data = [ | ||||
|             [ | ||||
|                 'value'     => $unpaidAmount, | ||||
|                 'value'     => round($unpaid, 2), | ||||
|                 'color'     => 'rgba(53, 124, 165,0.7)', | ||||
|                 'highlight' => 'rgba(53, 124, 165,0.9)', | ||||
|                 'label'     => trans('firefly.unpaid'), | ||||
|             ], | ||||
|             [ | ||||
|                 'value'     => $paidAmount, | ||||
|                 'value'     => round($paid * -1, 2), // paid is negative, must be positive. | ||||
|                 'color'     => 'rgba(0, 141, 76, 0.7)', | ||||
|                 'highlight' => 'rgba(0, 141, 76, 0.9)', | ||||
|                 'label'     => trans('firefly.paid'), | ||||
| @@ -70,28 +49,24 @@ class ChartJsBillChartGenerator implements BillChartGenerator | ||||
|      */ | ||||
|     public function single(Bill $bill, Collection $entries) | ||||
|     { | ||||
|         // language: | ||||
|         $language = Preferences::get('language', 'en')->data; | ||||
|         $format   = Config::get('firefly.month.' . $language); | ||||
|  | ||||
|         $data = [ | ||||
|         $format       = trans('config.month'); | ||||
|         $data         = [ | ||||
|             'count'    => 3, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [], | ||||
|         ]; | ||||
|  | ||||
|         // dataset: max amount | ||||
|         // dataset: min amount | ||||
|         // dataset: actual amount | ||||
|  | ||||
|         $minAmount    = []; | ||||
|         $maxAmount    = []; | ||||
|         $actualAmount = []; | ||||
|         /** @var TransactionJournal $entry */ | ||||
|         foreach ($entries as $entry) { | ||||
|             $data['labels'][] = $entry->date->formatLocalized($format); | ||||
|             $minAmount[]      = round($bill->amount_min, 2); | ||||
|             $maxAmount[]      = round($bill->amount_max, 2); | ||||
|             $actualAmount[]   = round(($entry->amount * -1), 2); | ||||
|             /* | ||||
|              * journalAmount has been collected in BillRepository::getJournals | ||||
|              */ | ||||
|             $actualAmount[] = round(($entry->journalAmount * -1), 2); | ||||
|         } | ||||
|  | ||||
|         $data['datasets'][] = [ | ||||
|   | ||||
| @@ -32,6 +32,13 @@ interface BudgetChartGenerator | ||||
|      */ | ||||
|     public function frontpage(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function multiYear(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $budgets | ||||
|      * @param Collection $entries | ||||
|   | ||||
| @@ -24,7 +24,7 @@ class ChartJsBudgetChartGenerator implements BudgetChartGenerator | ||||
|     public function budget(Collection $entries, $dateFormat = 'month') | ||||
|     { | ||||
|         // language: | ||||
|         $language = Preferences::get('language', 'en')->data; | ||||
|         $language = Preferences::get('language', env('DEFAULT_LANGUAGE', 'en_US'))->data; | ||||
|         $format   = Config::get('firefly.' . $dateFormat . '.' . $language); | ||||
|  | ||||
|         $data = [ | ||||
| @@ -33,7 +33,7 @@ class ChartJsBudgetChartGenerator implements BudgetChartGenerator | ||||
|                 [ | ||||
|                     'label' => 'Amount', | ||||
|                     'data'  => [], | ||||
|                 ] | ||||
|                 ], | ||||
|             ], | ||||
|         ]; | ||||
|  | ||||
| @@ -68,24 +68,24 @@ class ChartJsBudgetChartGenerator implements BudgetChartGenerator | ||||
|      */ | ||||
|     public function frontpage(Collection $entries) | ||||
|     { | ||||
|         $data = [ | ||||
|         $data      = [ | ||||
|             'count'    => 0, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [], | ||||
|         ]; | ||||
|         // dataset: left | ||||
|         // dataset: spent | ||||
|         // dataset: overspent | ||||
|         $left      = []; | ||||
|         $spent     = []; | ||||
|         $overspent = []; | ||||
|         foreach ($entries as $entry) { | ||||
|             if ($entry[1] != 0 || $entry[2] != 0 || $entry[3] != 0) { | ||||
|                 $data['labels'][] = $entry[0]; | ||||
|                 $left[]           = round($entry[1], 2); | ||||
|                 $spent[]          = round($entry[2], 2); | ||||
|                 $overspent[]      = round($entry[3], 2); | ||||
|         $filtered  = $entries->filter( | ||||
|             function ($entry) { | ||||
|                 return ($entry[1] != 0 || $entry[2] != 0 || $entry[3] != 0); | ||||
|             } | ||||
|         ); | ||||
|         foreach ($filtered as $entry) { | ||||
|             $data['labels'][] = $entry[0]; | ||||
|             $left[]           = round($entry[1], 2); | ||||
|             $spent[]          = round($entry[2] * -1, 2); // spent is coming in negative, must be positive | ||||
|             $overspent[]      = round($entry[3] * -1, 2); // same | ||||
|         } | ||||
|  | ||||
|         $data['datasets'][] = [ | ||||
| @@ -115,8 +115,7 @@ class ChartJsBudgetChartGenerator implements BudgetChartGenerator | ||||
|     public function year(Collection $budgets, Collection $entries) | ||||
|     { | ||||
|         // language: | ||||
|         $language = Preferences::get('language', 'en')->data; | ||||
|         $format   = Config::get('firefly.month.' . $language); | ||||
|         $format = trans('config.month'); | ||||
|  | ||||
|         $data = [ | ||||
|             'labels'   => [], | ||||
| @@ -141,4 +140,37 @@ class ChartJsBudgetChartGenerator implements BudgetChartGenerator | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function multiYear(Collection $entries) | ||||
|     { | ||||
|         // dataset: | ||||
|         $data = [ | ||||
|             'count'    => 0, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [], | ||||
|         ]; | ||||
|         // get labels from one of the budgets (assuming there's at least one): | ||||
|         $first = $entries->first(); | ||||
|         foreach ($first['budgeted'] as $year => $noInterest) { | ||||
|             $data['labels'][] = strval($year); | ||||
|         } | ||||
|  | ||||
|         // then, loop all entries and create datasets: | ||||
|         foreach ($entries as $entry) { | ||||
|             $name               = $entry['name']; | ||||
|             $spent              = $entry['spent']; | ||||
|             $budgeted           = $entry['budgeted']; | ||||
|             $data['datasets'][] = ['label' => 'Spent on ' . $name, 'data' => array_values($spent)]; | ||||
|             $data['datasets'][] = ['label' => 'Budgeted for ' . $name, 'data' => array_values($budgeted)]; | ||||
|         } | ||||
|         $data['count'] = count($data['datasets']); | ||||
|  | ||||
|         return $data; | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -19,6 +19,14 @@ interface CategoryChartGenerator | ||||
|      */ | ||||
|     public function all(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $categories | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function earnedInPeriod(Collection $categories, Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
| @@ -26,6 +34,13 @@ interface CategoryChartGenerator | ||||
|      */ | ||||
|     public function frontpage(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function multiYear(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
| @@ -33,20 +48,11 @@ interface CategoryChartGenerator | ||||
|      */ | ||||
|     public function period(Collection $entries); | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $categories | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function spentInYear(Collection $categories, Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $categories | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function earnedInYear(Collection $categories, Collection $entries); | ||||
|     public function spentInPeriod(Collection $categories, Collection $entries); | ||||
| } | ||||
|   | ||||
| @@ -2,9 +2,7 @@ | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Category; | ||||
|  | ||||
| use Config; | ||||
| use Illuminate\Support\Collection; | ||||
| use Preferences; | ||||
|  | ||||
|  | ||||
| /** | ||||
| @@ -51,58 +49,17 @@ class ChartJsCategoryChartGenerator implements CategoryChartGenerator | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage(Collection $entries) | ||||
|     { | ||||
|         $data = [ | ||||
|             'count'    => 1, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [ | ||||
|                 [ | ||||
|                     'label' => trans('firefly.spent'), | ||||
|                     'data'  => [] | ||||
|                 ] | ||||
|             ], | ||||
|         ]; | ||||
|         foreach ($entries as $entry) { | ||||
|             if ($entry['sum'] != 0) { | ||||
|                 $data['labels'][]              = $entry['name']; | ||||
|                 $data['datasets'][0]['data'][] = round(($entry['sum'] * -1), 2); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function period(Collection $entries) | ||||
|     { | ||||
|         return $this->all($entries); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $categories | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function spentInYear(Collection $categories, Collection $entries) | ||||
|     public function earnedInPeriod(Collection $categories, Collection $entries) | ||||
|     { | ||||
|  | ||||
|         // language: | ||||
|         $language = Preferences::get('language', 'en')->data; | ||||
|         $format   = Config::get('firefly.month.' . $language); | ||||
|         $format = trans('config.month'); | ||||
|  | ||||
|         $data = [ | ||||
|             'count'    => 0, | ||||
| @@ -125,18 +82,94 @@ class ChartJsCategoryChartGenerator implements CategoryChartGenerator | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage(Collection $entries) | ||||
|     { | ||||
|         $data = [ | ||||
|             'count'    => 1, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [ | ||||
|                 [ | ||||
|                     'label' => trans('firefly.spent'), | ||||
|                     'data'  => [] | ||||
|                 ] | ||||
|             ], | ||||
|         ]; | ||||
|         foreach ($entries as $entry) { | ||||
|             if ($entry->spent != 0) { | ||||
|                 $data['labels'][]              = $entry->name; | ||||
|                 $data['datasets'][0]['data'][] = round(($entry->spent * -1), 2); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function multiYear(Collection $entries) | ||||
|     { | ||||
|         // dataset: | ||||
|         $data = [ | ||||
|             'count'    => 0, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [], | ||||
|         ]; | ||||
|         // get labels from one of the categories (assuming there's at least one): | ||||
|         $first = $entries->first(); | ||||
|         foreach ($first['spent'] as $year => $noInterest) { | ||||
|             $data['labels'][] = strval($year); | ||||
|         } | ||||
|  | ||||
|         // then, loop all entries and create datasets: | ||||
|         foreach ($entries as $entry) { | ||||
|             $name   = $entry['name']; | ||||
|             $spent  = $entry['spent']; | ||||
|             $earned = $entry['earned']; | ||||
|             if (array_sum(array_values($spent)) != 0) { | ||||
|                 $data['datasets'][] = ['label' => 'Spent in category ' . $name, 'data' => array_values($spent)]; | ||||
|             } | ||||
|             if (array_sum(array_values($earned)) != 0) { | ||||
|                 $data['datasets'][] = ['label' => 'Earned in category ' . $name, 'data' => array_values($earned)]; | ||||
|             } | ||||
|         } | ||||
|         $data['count'] = count($data['datasets']); | ||||
|  | ||||
|         return $data; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function period(Collection $entries) | ||||
|     { | ||||
|         return $this->all($entries); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $categories | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function earnedInYear(Collection $categories, Collection $entries) | ||||
|     public function spentInPeriod(Collection $categories, Collection $entries) | ||||
|     { | ||||
|  | ||||
|         // language: | ||||
|         $language = Preferences::get('language', 'en')->data; | ||||
|         $format   = Config::get('firefly.month.' . $language); | ||||
|         $format = trans('config.month'); | ||||
|  | ||||
|         $data = [ | ||||
|             'count'    => 0, | ||||
|   | ||||
| @@ -3,9 +3,7 @@ | ||||
| namespace FireflyIII\Generator\Chart\PiggyBank; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Config; | ||||
| use Illuminate\Support\Collection; | ||||
| use Preferences; | ||||
|  | ||||
|  | ||||
| /** | ||||
| @@ -25,8 +23,7 @@ class ChartJsPiggyBankChartGenerator implements PiggyBankChartGenerator | ||||
|     { | ||||
|  | ||||
|         // language: | ||||
|         $language = Preferences::get('language', 'en')->data; | ||||
|         $format   = Config::get('firefly.monthAndDay.' . $language); | ||||
|         $format = trans('config.month_and_day'); | ||||
|  | ||||
|         $data = [ | ||||
|             'count'    => 1, | ||||
|   | ||||
| @@ -2,9 +2,7 @@ | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Report; | ||||
|  | ||||
| use Config; | ||||
| use Illuminate\Support\Collection; | ||||
| use Preferences; | ||||
|  | ||||
| /** | ||||
|  * Class ChartJsReportChartGenerator | ||||
| @@ -14,6 +12,70 @@ use Preferences; | ||||
| class ChartJsReportChartGenerator implements ReportChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Same as above but other translations. | ||||
|      * | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function multiYearInOut(Collection $entries) | ||||
|     { | ||||
|         $data = [ | ||||
|             'count'    => 2, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [ | ||||
|                 [ | ||||
|                     'label' => trans('firefly.income'), | ||||
|                     'data'  => [] | ||||
|                 ], | ||||
|                 [ | ||||
|                     'label' => trans('firefly.expenses'), | ||||
|                     'data'  => [] | ||||
|                 ] | ||||
|             ], | ||||
|         ]; | ||||
|  | ||||
|         foreach ($entries as $entry) { | ||||
|             $data['labels'][]              = $entry[0]->formatLocalized('%Y'); | ||||
|             $data['datasets'][0]['data'][] = round($entry[1], 2); | ||||
|             $data['datasets'][1]['data'][] = round($entry[2], 2); | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $income | ||||
|      * @param string $expense | ||||
|      * @param int    $count | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function multiYearInOutSummarized($income, $expense, $count) | ||||
|     { | ||||
|         $data                          = [ | ||||
|             'count'    => 2, | ||||
|             'labels'   => [trans('firefly.sum_of_years'), trans('firefly.average_of_years')], | ||||
|             'datasets' => [ | ||||
|                 [ | ||||
|                     'label' => trans('firefly.income'), | ||||
|                     'data'  => [] | ||||
|                 ], | ||||
|                 [ | ||||
|                     'label' => trans('firefly.expenses'), | ||||
|                     'data'  => [] | ||||
|                 ] | ||||
|             ], | ||||
|         ]; | ||||
|         $data['datasets'][0]['data'][] = round($income, 2); | ||||
|         $data['datasets'][1]['data'][] = round($expense, 2); | ||||
|         $data['datasets'][0]['data'][] = round(($income / $count), 2); | ||||
|         $data['datasets'][1]['data'][] = round(($expense / $count), 2); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
| @@ -22,8 +84,7 @@ class ChartJsReportChartGenerator implements ReportChartGenerator | ||||
|     public function yearInOut(Collection $entries) | ||||
|     { | ||||
|         // language: | ||||
|         $language = Preferences::get('language', 'en')->data; | ||||
|         $format   = Config::get('firefly.month.' . $language); | ||||
|         $format = trans('config.month'); | ||||
|  | ||||
|         $data = [ | ||||
|             'count'    => 2, | ||||
| @@ -74,9 +135,9 @@ class ChartJsReportChartGenerator implements ReportChartGenerator | ||||
|             ], | ||||
|         ]; | ||||
|         $data['datasets'][0]['data'][] = round($income, 2); | ||||
|         $data['datasets'][1]['data'][] = round( $expense, 2); | ||||
|         $data['datasets'][1]['data'][] = round($expense, 2); | ||||
|         $data['datasets'][0]['data'][] = round(($income / $count), 2); | ||||
|         $data['datasets'][1]['data'][] = round(( $expense / $count), 2); | ||||
|         $data['datasets'][1]['data'][] = round(($expense / $count), 2); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|   | ||||
| @@ -12,6 +12,22 @@ use Illuminate\Support\Collection; | ||||
| interface ReportChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function multiYearInOut(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param string $income | ||||
|      * @param string $expense | ||||
|      * @param int    $count | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function multiYearInOutSummarized($income, $expense, $count); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|   | ||||
| @@ -28,8 +28,6 @@ class ConnectJournalToPiggyBank | ||||
|     /** | ||||
|      * Handle the event when journal is saved. | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * | ||||
|      * @param  JournalCreated $event | ||||
|      * | ||||
|      * @return boolean | ||||
|   | ||||
| @@ -67,7 +67,9 @@ class AttachmentHelper implements AttachmentHelperInterface | ||||
|                 } | ||||
|             } | ||||
|         } else { | ||||
|             $this->processFile($files, $model); | ||||
|             if (!is_null($files)) { | ||||
|                 $this->processFile($files, $model); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|   | ||||
| @@ -3,7 +3,6 @@ | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use FireflyIII\Models\Budget as BudgetModel; | ||||
| use FireflyIII\Models\LimitRepetition; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
| @@ -26,9 +25,6 @@ class BalanceLine | ||||
|     /** @var BudgetModel */ | ||||
|     protected $budget; | ||||
|  | ||||
|     /** @var  LimitRepetition */ | ||||
|     protected $repetition; | ||||
|  | ||||
|     protected $role = self::ROLE_DEFAULTROLE; | ||||
|  | ||||
|     /** | ||||
| @@ -48,24 +44,19 @@ class BalanceLine | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getTitle() | ||||
|     public function getBalanceEntries() | ||||
|     { | ||||
|         if ($this->getBudget() instanceof BudgetModel) { | ||||
|             return $this->getBudget()->name; | ||||
|         } | ||||
|         if ($this->getRole() == self::ROLE_DEFAULTROLE) { | ||||
|             return trans('firefly.noBudget'); | ||||
|         } | ||||
|         if ($this->getRole() == self::ROLE_TAGROLE) { | ||||
|             return trans('firefly.coveredWithTags'); | ||||
|         } | ||||
|         if ($this->getRole() == self::ROLE_DIFFROLE) { | ||||
|             return trans('firefly.leftUnbalanced'); | ||||
|         } | ||||
|         return $this->balanceEntries; | ||||
|     } | ||||
|  | ||||
|         return ''; | ||||
|     /** | ||||
|      * @param Collection $balanceEntries | ||||
|      */ | ||||
|     public function setBalanceEntries($balanceEntries) | ||||
|     { | ||||
|         $this->balanceEntries = $balanceEntries; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -100,6 +91,27 @@ class BalanceLine | ||||
|         $this->role = $role; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getTitle() | ||||
|     { | ||||
|         if ($this->getBudget() instanceof BudgetModel) { | ||||
|             return $this->getBudget()->name; | ||||
|         } | ||||
|         if ($this->getRole() == self::ROLE_DEFAULTROLE) { | ||||
|             return trans('firefly.noBudget'); | ||||
|         } | ||||
|         if ($this->getRole() == self::ROLE_TAGROLE) { | ||||
|             return trans('firefly.coveredWithTags'); | ||||
|         } | ||||
|         if ($this->getRole() == self::ROLE_DIFFROLE) { | ||||
|             return trans('firefly.leftUnbalanced'); | ||||
|         } | ||||
|  | ||||
|         return ''; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * If a BalanceLine has a budget/repetition, each BalanceEntry in this BalanceLine | ||||
|      * should have a "spent" value, which is the amount of money that has been spent | ||||
| @@ -110,7 +122,7 @@ class BalanceLine | ||||
|      */ | ||||
|     public function leftOfRepetition() | ||||
|     { | ||||
|         $start = $this->getRepetition() ? $this->getRepetition()->amount : 0; | ||||
|         $start = isset($this->budget->amount) ? $this->budget->amount : 0; | ||||
|         /** @var BalanceEntry $balanceEntry */ | ||||
|         foreach ($this->getBalanceEntries() as $balanceEntry) { | ||||
|             $start += $balanceEntry->getSpent(); | ||||
| @@ -118,56 +130,4 @@ class BalanceLine | ||||
|  | ||||
|         return $start; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return LimitRepetition | ||||
|      */ | ||||
|     public function getRepetition() | ||||
|     { | ||||
|         return $this->repetition; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param LimitRepetition $repetition | ||||
|      */ | ||||
|     public function setRepetition($repetition) | ||||
|     { | ||||
|         $this->repetition = $repetition; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getBalanceEntries() | ||||
|     { | ||||
|         return $this->balanceEntries; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $balanceEntries | ||||
|      */ | ||||
|     public function setBalanceEntries($balanceEntries) | ||||
|     { | ||||
|         $this->balanceEntries = $balanceEntries; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * If the BalanceEntries for a BalanceLine have a "left" value, the amount | ||||
|      * of money left in the entire BalanceLine is returned here: | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function sumOfLeft() | ||||
|     { | ||||
|         $sum = '0'; | ||||
|         bcscale(2); | ||||
|         /** @var BalanceEntry $balanceEntry */ | ||||
|         foreach ($this->getBalanceEntries() as $balanceEntry) { | ||||
|             $sum = bcadd($sum, $balanceEntry->getLeft()); | ||||
|         } | ||||
|  | ||||
|         return $sum; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -37,6 +37,7 @@ class Category | ||||
|         // spent is minus zero for an expense report: | ||||
|         if ($category->spent < 0) { | ||||
|             $this->categories->push($category); | ||||
|             $this->addTotal($category->spent); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -55,7 +56,7 @@ class Category | ||||
|      */ | ||||
|     public function getCategories() | ||||
|     { | ||||
|         $set = $this->categories->sortByDesc( | ||||
|         $set = $this->categories->sortBy( | ||||
|             function (CategoryModel $category) { | ||||
|                 return $category->spent; | ||||
|             } | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use Crypt; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Illuminate\Support\Collection; | ||||
| use stdClass; | ||||
| @@ -33,18 +34,24 @@ class Expense | ||||
|      */ | ||||
|     public function addOrCreateExpense(TransactionJournal $entry) | ||||
|     { | ||||
|         bcscale(2); | ||||
|  | ||||
|         $accountId = $entry->account_id; | ||||
|         $amount    = strval(round($entry->journalAmount, 2)); | ||||
|         if (bccomp('0', $amount) === -1) { | ||||
|             $amount = bcmul($amount, '-1'); | ||||
|         } | ||||
|  | ||||
|         if (!$this->expenses->has($accountId)) { | ||||
|             $newObject         = new stdClass; | ||||
|             $newObject->amount = strval(round($entry->amount_positive, 2)); | ||||
|             $newObject->name   = $entry->name; | ||||
|             $newObject->amount = $amount; | ||||
|             $newObject->name   = Crypt::decrypt($entry->account_name); | ||||
|             $newObject->count  = 1; | ||||
|             $newObject->id     = $accountId; | ||||
|             $this->expenses->put($accountId, $newObject); | ||||
|         } else { | ||||
|             bcscale(2); | ||||
|             $existing         = $this->expenses->get($accountId); | ||||
|             $existing->amount = bcadd($existing->amount, $entry->amount_positive); | ||||
|             $existing->amount = bcadd($existing->amount, $amount); | ||||
|             $existing->count++; | ||||
|             $this->expenses->put($accountId, $existing); | ||||
|         } | ||||
| @@ -55,8 +62,18 @@ class Expense | ||||
|      */ | ||||
|     public function addToTotal($add) | ||||
|     { | ||||
|         $add = strval(round($add, 2)); | ||||
|         bcscale(2); | ||||
|  | ||||
|  | ||||
|         $add = strval(round($add, 2)); | ||||
|         if (bccomp('0', $add) === -1) { | ||||
|             $add = bcmul($add, '-1'); | ||||
|         } | ||||
|  | ||||
|         // if amount is positive, the original transaction | ||||
|         // was a transfer. But since this is an expense report, | ||||
|         // that amount must be negative. | ||||
|  | ||||
|         $this->total = bcadd($this->total, $add); | ||||
|     } | ||||
|  | ||||
| @@ -65,7 +82,7 @@ class Expense | ||||
|      */ | ||||
|     public function getExpenses() | ||||
|     { | ||||
|         $set = $this->expenses->sortByDesc( | ||||
|         $set = $this->expenses->sortBy( | ||||
|             function (stdClass $object) { | ||||
|                 return $object->amount; | ||||
|             } | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use Crypt; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Illuminate\Support\Collection; | ||||
| use stdClass; | ||||
| @@ -38,15 +39,15 @@ class Income | ||||
|         $accountId = $entry->account_id; | ||||
|         if (!$this->incomes->has($accountId)) { | ||||
|             $newObject         = new stdClass; | ||||
|             $newObject->amount = strval(round($entry->amount_positive, 2)); | ||||
|             $newObject->name   = $entry->name; | ||||
|             $newObject->amount = strval(round($entry->journalAmount, 2)); | ||||
|             $newObject->name   = Crypt::decrypt($entry->account_name); | ||||
|             $newObject->count  = 1; | ||||
|             $newObject->id     = $accountId; | ||||
|             $this->incomes->put($accountId, $newObject); | ||||
|         } else { | ||||
|             bcscale(2); | ||||
|             $existing         = $this->incomes->get($accountId); | ||||
|             $existing->amount = bcadd($existing->amount, $entry->amount_positive); | ||||
|             $existing->amount = bcadd($existing->amount, $entry->journalAmount); | ||||
|             $existing->count++; | ||||
|             $this->incomes->put($accountId, $existing); | ||||
|         } | ||||
|   | ||||
| @@ -17,7 +17,8 @@ class Date extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Carbon | ||||
|      * @return static | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|   | ||||
| @@ -296,7 +296,7 @@ class Importer | ||||
|  | ||||
|         // some debug info: | ||||
|         $journalId = $journal->id; | ||||
|         $type      = $journal->transactionType->type; | ||||
|         $type      = $journal->getTransactionType(); | ||||
|         /** @var Account $asset */ | ||||
|         $asset = $this->importData['asset-account-object']; | ||||
|         /** @var Account $opposing */ | ||||
| @@ -314,13 +314,13 @@ class Importer | ||||
|      */ | ||||
|     protected function getTransactionType() | ||||
|     { | ||||
|         $transactionType = TransactionType::where('type', 'Deposit')->first(); | ||||
|         $transactionType = TransactionType::where('type', TransactionType::DEPOSIT)->first(); | ||||
|         if ($this->importData['amount'] < 0) { | ||||
|             $transactionType = TransactionType::where('type', 'Withdrawal')->first(); | ||||
|             $transactionType = TransactionType::where('type', TransactionType::WITHDRAWAL)->first(); | ||||
|         } | ||||
|  | ||||
|         if (in_array($this->importData['opposing-account-object']->accountType->type, ['Asset account', 'Default account'])) { | ||||
|             $transactionType = TransactionType::where('type', 'Transfer')->first(); | ||||
|             $transactionType = TransactionType::where('type', TransactionType::TRANSFER)->first(); | ||||
|         } | ||||
|  | ||||
|         return $transactionType; | ||||
|   | ||||
| @@ -24,7 +24,7 @@ class Currency implements PostProcessorInterface | ||||
|  | ||||
|         // fix currency | ||||
|         if (is_null($this->data['currency'])) { | ||||
|             $currencyPreference     = Preferences::get('currencyPreference', 'EUR'); | ||||
|             $currencyPreference     = Preferences::get('currencyPreference', env('DEFAULT_CURRENCY', 'EUR')); | ||||
|             $this->data['currency'] = TransactionCurrency::whereCode($currencyPreference->data)->first(); | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -29,6 +29,22 @@ class RabobankDescription | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData($data) | ||||
|     { | ||||
|         $this->data = $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $row | ||||
|      */ | ||||
|     public function setRow($row) | ||||
|     { | ||||
|         $this->row = $row; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Fixes Rabobank specific thing. | ||||
|      */ | ||||
| @@ -46,21 +62,5 @@ class RabobankDescription | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData($data) | ||||
|     { | ||||
|         $this->data = $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $row | ||||
|      */ | ||||
|     public function setRow($row) | ||||
|     { | ||||
|         $this->row = $row; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| namespace FireflyIII\Helpers\Report; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use DB; | ||||
| use FireflyIII\Helpers\Collection\Account as AccountCollection; | ||||
| use FireflyIII\Helpers\Collection\Balance; | ||||
| use FireflyIII\Helpers\Collection\BalanceEntry; | ||||
| @@ -19,6 +20,9 @@ use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\Budget as BudgetModel; | ||||
| use FireflyIII\Models\LimitRepetition; | ||||
| use FireflyIII\Models\Tag; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class ReportHelper | ||||
| @@ -43,48 +47,150 @@ class ReportHelper implements ReportHelperInterface | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return CategoryCollection | ||||
|      */ | ||||
|     public function getCategoryReport(Carbon $start, Carbon $end, Collection $accounts) | ||||
|     { | ||||
|         $object = new CategoryCollection; | ||||
|  | ||||
|         /** | ||||
|          * GET CATEGORIES: | ||||
|          */ | ||||
|         /** @var \FireflyIII\Repositories\Category\CategoryRepositoryInterface $repository */ | ||||
|         $repository = app('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); | ||||
|  | ||||
|         $set = $repository->spentForAccountsPerMonth($accounts, $start, $end); | ||||
|         foreach ($set as $category) { | ||||
|             $object->addCategory($category); | ||||
|         } | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function listOfMonths(Carbon $date) | ||||
|     { | ||||
|  | ||||
|         $start  = clone $date; | ||||
|         $end    = Carbon::now(); | ||||
|         $months = []; | ||||
|         while ($start <= $end) { | ||||
|             $year = $start->year; | ||||
|  | ||||
|             if (!isset($months[$year])) { | ||||
|                 $months[$year] = [ | ||||
|                     'start'  => Carbon::createFromDate($year, 1, 1)->format('Y-m-d'), | ||||
|                     'end'    => Carbon::createFromDate($year, 12, 31)->format('Y-m-d'), | ||||
|                     'months' => [], | ||||
|                 ]; | ||||
|             } | ||||
|  | ||||
|             $currentEnd = clone $start; | ||||
|             $currentEnd->endOfMonth(); | ||||
|             $months[$year]['months'][] = [ | ||||
|                 'formatted' => $start->formatLocalized('%B %Y'), | ||||
|                 'start'     => $start->format('Y-m-d'), | ||||
|                 'end'       => $currentEnd->format('Y-m-d'), | ||||
|                 'month'     => $start->month, | ||||
|                 'year'      => $year, | ||||
|             ]; | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|  | ||||
|         return $months; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method generates a full report for the given period on all | ||||
|      * the users asset and cash accounts. | ||||
|      * given accounts | ||||
|      * | ||||
|      * @param Carbon $date | ||||
|      * @param Carbon $end | ||||
|      * @param        $shared | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return AccountCollection | ||||
|      */ | ||||
|     public function getAccountReport(Carbon $date, Carbon $end, $shared) | ||||
|     public function getAccountReport(Carbon $start, Carbon $end, Collection $accounts) | ||||
|     { | ||||
|         $startAmount = '0'; | ||||
|         $endAmount   = '0'; | ||||
|         $diff        = '0'; | ||||
|         $ids         = $accounts->pluck('id')->toArray(); | ||||
|  | ||||
|         $yesterday = clone $start; | ||||
|         $yesterday->subDay(); | ||||
|  | ||||
|         $accounts = $this->query->getAllAccounts($date, $end, $shared); | ||||
|         $start    = '0'; | ||||
|         $end      = '0'; | ||||
|         $diff     = '0'; | ||||
|         bcscale(2); | ||||
|  | ||||
|         // remove cash account, if any: | ||||
|         $accounts = $accounts->filter( | ||||
|             function (Account $account) { | ||||
|                 if ($account->accountType->type != 'Cash account') { | ||||
|                     return $account; | ||||
|         // get balances for start. | ||||
|         $startSet = Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id') | ||||
|                            ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') | ||||
|                            ->whereIn('accounts.id', $ids) | ||||
|                            ->whereNull('transaction_journals.deleted_at') | ||||
|                            ->whereNull('transactions.deleted_at') | ||||
|                            ->where('transaction_journals.date', '<=', $yesterday->format('Y-m-d')) | ||||
|                            ->groupBy('accounts.id') | ||||
|                            ->get(['accounts.id', DB::Raw('SUM(`transactions`.`amount`) as `balance`')]); | ||||
|  | ||||
|         // and for end: | ||||
|         $endSet = Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id') | ||||
|                          ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') | ||||
|                          ->whereIn('accounts.id', $ids) | ||||
|                          ->whereNull('transaction_journals.deleted_at') | ||||
|                          ->whereNull('transactions.deleted_at') | ||||
|                          ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) | ||||
|                          ->groupBy('accounts.id') | ||||
|                          ->get(['accounts.id', DB::Raw('SUM(`transactions`.`amount`) as `balance`')]); | ||||
|  | ||||
|  | ||||
|         $accounts->each( | ||||
|             function (Account $account) use ($startSet, $endSet) { | ||||
|                 /** | ||||
|                  * The balance for today always incorporates transactions | ||||
|                  * made on today. So to get todays "start" balance, we sub one | ||||
|                  * day. | ||||
|                  */ | ||||
|                 // | ||||
|                 $currentStart = $startSet->filter( | ||||
|                     function (Account $entry) use ($account) { | ||||
|                         return $account->id == $entry->id; | ||||
|                     } | ||||
|                 ); | ||||
|                 if ($currentStart->first()) { | ||||
|                     $account->startBalance = $currentStart->first()->balance; | ||||
|                 } | ||||
|  | ||||
|                 return null; | ||||
|                 $currentEnd = $endSet->filter( | ||||
|                     function (Account $entry) use ($account) { | ||||
|                         return $account->id == $entry->id; | ||||
|                     } | ||||
|                 ); | ||||
|                 if ($currentEnd->first()) { | ||||
|                     $account->endBalance = $currentEnd->first()->balance; | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|  | ||||
|         // summarize: | ||||
|         foreach ($accounts as $account) { | ||||
|             $start = bcadd($start, $account->startBalance); | ||||
|             $end   = bcadd($end, $account->endBalance); | ||||
|             $diff  = bcadd($diff, bcsub($account->endBalance, $account->startBalance)); | ||||
|             $startAmount = bcadd($startAmount, $account->startBalance); | ||||
|             $endAmount   = bcadd($endAmount, $account->endBalance); | ||||
|             $diff        = bcadd($diff, bcsub($account->endBalance, $account->startBalance)); | ||||
|         } | ||||
|  | ||||
|         $object = new AccountCollection; | ||||
|         $object->setStart($start); | ||||
|         $object->setEnd($end); | ||||
|         $object->setStart($startAmount); | ||||
|         $object->setEnd($endAmount); | ||||
|         $object->setDifference($diff); | ||||
|         $object->setAccounts($accounts); | ||||
|  | ||||
| @@ -92,37 +198,149 @@ class ReportHelper implements ReportHelperInterface | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get a full report on the users incomes during the period for the given accounts. | ||||
|      * | ||||
|      * The balance report contains a Balance object which in turn contains: | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * A BalanceHeader object which contains all relevant user asset accounts for the report. | ||||
|      * @return Income | ||||
|      */ | ||||
|     public function getIncomeReport($start, $end, Collection $accounts) | ||||
|     { | ||||
|         $object = new Income; | ||||
|         $set    = $this->query->income($accounts, $start, $end); | ||||
|  | ||||
|         foreach ($set as $entry) { | ||||
|             $object->addToTotal($entry->journalAmount); | ||||
|             $object->addOrCreateIncome($entry); | ||||
|         } | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get a full report on the users expenses during the period for a list of accounts. | ||||
|      * | ||||
|      * A number of BalanceLine objects, which hold: | ||||
|      * - A budget | ||||
|      * - A number of BalanceEntry objects. | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * The BalanceEntry object holds: | ||||
|      *   - The same budget (again) | ||||
|      *   - A user asset account as mentioned in the BalanceHeader | ||||
|      *   - The amount of money spent on the budget by the user asset account | ||||
|      * @return Expense | ||||
|      */ | ||||
|     public function getExpenseReport($start, $end, Collection $accounts) | ||||
|     { | ||||
|         $object = new Expense; | ||||
|         $set    = $this->query->expense($accounts, $start, $end); | ||||
|  | ||||
|         foreach ($set as $entry) { | ||||
|             $object->addToTotal($entry->journalAmount); // can be positive, if it's a transfer | ||||
|             $object->addOrCreateExpense($entry); | ||||
|         } | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * @return BudgetCollection | ||||
|      */ | ||||
|     public function getBudgetReport(Carbon $start, Carbon $end, Collection $accounts) | ||||
|     { | ||||
|         $object = new BudgetCollection; | ||||
|         /** @var \FireflyIII\Repositories\Budget\BudgetRepositoryInterface $repository */ | ||||
|         $repository     = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); | ||||
|         $set            = $repository->getBudgets(); | ||||
|         $allRepetitions = $repository->getAllBudgetLimitRepetitions($start, $end); | ||||
|         $allTotalSpent  = $repository->spentAllPerDayForAccounts($accounts, $start, $end); | ||||
|         bcscale(2); | ||||
|  | ||||
|         foreach ($set as $budget) { | ||||
|  | ||||
|             $repetitions = $allRepetitions->filter( | ||||
|                 function (LimitRepetition $rep) use ($budget) { | ||||
|                     return $rep->budget_id == $budget->id; | ||||
|                 } | ||||
|             ); | ||||
|             $totalSpent  = isset($allTotalSpent[$budget->id]) ? $allTotalSpent[$budget->id] : []; | ||||
|  | ||||
|             // no repetition(s) for this budget: | ||||
|             if ($repetitions->count() == 0) { | ||||
|                 $spent      = array_sum($totalSpent); | ||||
|                 $budgetLine = new BudgetLine; | ||||
|                 $budgetLine->setBudget($budget); | ||||
|                 $budgetLine->setOverspent($spent); | ||||
|                 $object->addOverspent($spent); | ||||
|                 $object->addBudgetLine($budgetLine); | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             // one or more repetitions for budget: | ||||
|             /** @var LimitRepetition $repetition */ | ||||
|             foreach ($repetitions as $repetition) { | ||||
|                 $budgetLine = new BudgetLine; | ||||
|                 $budgetLine->setBudget($budget); | ||||
|                 $budgetLine->setRepetition($repetition); | ||||
|                 $expenses = $this->getSumOfRange($start, $end, $totalSpent); | ||||
|  | ||||
|                 // 200 en -100 is 100, vergeleken met 0 === 1 | ||||
|                 // 200 en -200 is 0, vergeleken met 0 === 0 | ||||
|                 // 200 en -300 is -100, vergeleken met 0 === -1 | ||||
|  | ||||
|                 $left      = bccomp(bcadd($repetition->amount, $expenses), '0') === 1 ? bcadd($repetition->amount, $expenses) : 0; | ||||
|                 $spent     = bccomp(bcadd($repetition->amount, $expenses), '0') === 1 ? $expenses : '0'; | ||||
|                 $overspent = bccomp(bcadd($repetition->amount, $expenses), '0') === 1 ? '0' : bcadd($expenses, $repetition->amount); | ||||
|  | ||||
|                 $budgetLine->setLeft($left); | ||||
|                 $budgetLine->setSpent($spent); | ||||
|                 $budgetLine->setOverspent($overspent); | ||||
|                 $budgetLine->setBudgeted($repetition->amount); | ||||
|  | ||||
|                 $object->addBudgeted($repetition->amount); | ||||
|                 $object->addSpent($spent); | ||||
|                 $object->addLeft($left); | ||||
|                 $object->addOverspent($overspent); | ||||
|                 $object->addBudgetLine($budgetLine); | ||||
|  | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         // stuff outside of budgets: | ||||
|         $noBudget   = $repository->getWithoutBudgetSum($start, $end); | ||||
|         $budgetLine = new BudgetLine; | ||||
|         $budgetLine->setOverspent($noBudget); | ||||
|         $budgetLine->setSpent($noBudget); | ||||
|         $object->addOverspent($noBudget); | ||||
|         $object->addBudgetLine($budgetLine); | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return Balance | ||||
|      */ | ||||
|     public function getBalanceReport(Carbon $start, Carbon $end, $shared) | ||||
|     public function getBalanceReport(Carbon $start, Carbon $end, Collection $accounts) | ||||
|     { | ||||
|         $repository    = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); | ||||
|         /** @var \FireflyIII\Repositories\Budget\BudgetRepositoryInterface $repository */ | ||||
|         $repository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); | ||||
|  | ||||
|         /** @var \FireflyIII\Repositories\Tag\TagRepositoryInterface $tagRepository */ | ||||
|         $tagRepository = app('FireflyIII\Repositories\Tag\TagRepositoryInterface'); | ||||
|         $balance       = new Balance; | ||||
|  | ||||
|         $balance = new Balance; | ||||
|  | ||||
|         // build a balance header: | ||||
|         $header = new BalanceHeader; | ||||
|  | ||||
|         $accounts = $this->query->getAllAccounts($start, $end, $shared); | ||||
|         $budgets  = $repository->getBudgets(); | ||||
|         $header    = new BalanceHeader; | ||||
|         $budgets   = $repository->getBudgetsAndLimitsInRange($start, $end); | ||||
|         $spentData = $repository->spentPerBudgetPerAccount($budgets, $accounts, $start, $end); | ||||
|         foreach ($accounts as $account) { | ||||
|             $header->addAccount($account); | ||||
|         } | ||||
| @@ -132,18 +350,21 @@ class ReportHelper implements ReportHelperInterface | ||||
|             $line = new BalanceLine; | ||||
|             $line->setBudget($budget); | ||||
|  | ||||
|             // get budget amount for current period: | ||||
|             $rep = $repository->getCurrentRepetition($budget, $start, $end); | ||||
|             $line->setRepetition($rep); | ||||
|  | ||||
|             // loop accounts: | ||||
|             foreach ($accounts as $account) { | ||||
|                 $balanceEntry = new BalanceEntry; | ||||
|                 $balanceEntry->setAccount($account); | ||||
|  | ||||
|                 // get spent: | ||||
|                 $spent = $this->query->spentInBudgetCorrected($account, $budget, $start, $end); // I think shared is irrelevant. | ||||
|  | ||||
|                 $entry = $spentData->filter( | ||||
|                     function (TransactionJournal $model) use ($budget, $account) { | ||||
|                         return $model->account_id == $account->id && $model->budget_id == $budget->id; | ||||
|                     } | ||||
|                 ); | ||||
|                 $spent = 0; | ||||
|                 if (!is_null($entry->first())) { | ||||
|                     $spent = $entry->first()->spent; | ||||
|                 } | ||||
|                 $balanceEntry->setSpent($spent); | ||||
|                 $line->addBalanceEntry($balanceEntry); | ||||
|             } | ||||
| @@ -153,18 +374,36 @@ class ReportHelper implements ReportHelperInterface | ||||
|  | ||||
|         // then a new line for without budget. | ||||
|         // and one for the tags: | ||||
|         // and one for "left unbalanced". | ||||
|         $empty    = new BalanceLine; | ||||
|         $tags     = new BalanceLine; | ||||
|         $diffLine = new BalanceLine; | ||||
|         $tagsLeft = $tagRepository->allCoveredByBalancingActs($accounts, $start, $end); | ||||
|  | ||||
|         $tags->setRole(BalanceLine::ROLE_TAGROLE); | ||||
|         $diffLine->setRole(BalanceLine::ROLE_DIFFROLE); | ||||
|  | ||||
|         foreach ($accounts as $account) { | ||||
|             $spent = $this->query->spentNoBudget($account, $start, $end); | ||||
|             $left  = $tagRepository->coveredByBalancingActs($account, $start, $end); | ||||
|             $entry = $spentData->filter( | ||||
|                 function (TransactionJournal $model) use ($budget, $account) { | ||||
|                     return $model->account_id == $account->id && is_null($model->budget_id); | ||||
|                 } | ||||
|             ); | ||||
|             $spent = 0; | ||||
|             if (!is_null($entry->first())) { | ||||
|                 $spent = $entry->first()->spent; | ||||
|             } | ||||
|             $leftEntry = $tagsLeft->filter( | ||||
|                 function (Tag $tag) use ($account) { | ||||
|                     return $tag->account_id == $account->id; | ||||
|                 } | ||||
|             ); | ||||
|             $left      = 0; | ||||
|             if (!is_null($leftEntry->first())) { | ||||
|                 $left = $leftEntry->first()->sum; | ||||
|             } | ||||
|             bcscale(2); | ||||
|             $diff = bcsub($spent, $left); | ||||
|             $diff = bcadd($spent, $left); | ||||
|  | ||||
|             // budget | ||||
|             $budgetEntry = new BalanceEntry; | ||||
| @@ -199,16 +438,20 @@ class ReportHelper implements ReportHelperInterface | ||||
|      * This method generates a full report for the given period on all | ||||
|      * the users bills and their payments. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * Excludes bills which have not had a payment on the mentioned accounts. | ||||
|      * | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return BillCollection | ||||
|      */ | ||||
|     public function getBillReport(Carbon $start, Carbon $end) | ||||
|     public function getBillReport(Carbon $start, Carbon $end, Collection $accounts) | ||||
|     { | ||||
|         /** @var \FireflyIII\Repositories\Bill\BillRepositoryInterface $repository */ | ||||
|         $repository = app('FireflyIII\Repositories\Bill\BillRepositoryInterface'); | ||||
|         $bills      = $repository->getBills(); | ||||
|         $bills      = $repository->getBillsForAccounts($accounts); | ||||
|         $journals   = $repository->getAllJournalsInRange($bills, $start, $end); | ||||
|         $collection = new BillCollection; | ||||
|  | ||||
|         /** @var Bill $bill */ | ||||
| @@ -221,16 +464,17 @@ class ReportHelper implements ReportHelperInterface | ||||
|  | ||||
|             // is hit in period? | ||||
|             bcscale(2); | ||||
|             $set = $repository->getJournalsInRange($bill, $start, $end); | ||||
|             if ($set->count() == 0) { | ||||
|                 $billLine->setHit(false); | ||||
|             } else { | ||||
|                 $billLine->setHit(true); | ||||
|                 $amount = '0'; | ||||
|                 foreach ($set as $entry) { | ||||
|                     $amount = bcadd($amount, $entry->amount); | ||||
|  | ||||
|             $entry = $journals->filter( | ||||
|                 function (TransactionJournal $journal) use ($bill) { | ||||
|                     return $journal->bill_id == $bill->id; | ||||
|                 } | ||||
|                 $billLine->setAmount($amount); | ||||
|             ); | ||||
|             if (!is_null($entry->first())) { | ||||
|                 $billLine->setAmount($entry->first()->journalAmount); | ||||
|                 $billLine->setHit(true); | ||||
|             } else { | ||||
|                 $billLine->setHit(false); | ||||
|             } | ||||
|  | ||||
|             $collection->addBill($billLine); | ||||
| @@ -238,168 +482,33 @@ class ReportHelper implements ReportHelperInterface | ||||
|         } | ||||
|  | ||||
|         return $collection; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * Take the array as returned by SingleCategoryRepositoryInterface::spentPerDay and SingleCategoryRepositoryInterface::earnedByDay | ||||
|      * and sum up everything in the array in the given range. | ||||
|      * | ||||
|      * @return BudgetCollection | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param array  $array | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getBudgetReport(Carbon $start, Carbon $end, $shared) | ||||
|     protected function getSumOfRange(Carbon $start, Carbon $end, array $array) | ||||
|     { | ||||
|         $object = new BudgetCollection; | ||||
|         /** @var \FireflyIII\Repositories\Budget\BudgetRepositoryInterface $repository */ | ||||
|         $repository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); | ||||
|         $set        = $repository->getBudgets(); | ||||
|  | ||||
|         bcscale(2); | ||||
|         $sum          = '0'; | ||||
|         $currentStart = clone $start; // to not mess with the original one | ||||
|         $currentEnd   = clone $end; // to not mess with the original one | ||||
|  | ||||
|         foreach ($set as $budget) { | ||||
|  | ||||
|             $repetitions = $repository->getBudgetLimitRepetitions($budget, $start, $end); | ||||
|  | ||||
|             // no repetition(s) for this budget: | ||||
|             if ($repetitions->count() == 0) { | ||||
|                 $spent      = $repository->balanceInPeriod($budget, $start, $end, $shared); | ||||
|                 $budgetLine = new BudgetLine; | ||||
|                 $budgetLine->setBudget($budget); | ||||
|                 $budgetLine->setOverspent($spent); | ||||
|                 $object->addOverspent($spent); | ||||
|                 $object->addBudgetLine($budgetLine); | ||||
|                 continue; | ||||
|         while ($currentStart <= $currentEnd) { | ||||
|             $date = $currentStart->format('Y-m-d'); | ||||
|             if (isset($array[$date])) { | ||||
|                 $sum = bcadd($sum, $array[$date]); | ||||
|             } | ||||
|  | ||||
|             // one or more repetitions for budget: | ||||
|             /** @var LimitRepetition $repetition */ | ||||
|             foreach ($repetitions as $repetition) { | ||||
|                 $budgetLine = new BudgetLine; | ||||
|                 $budgetLine->setBudget($budget); | ||||
|                 $budgetLine->setRepetition($repetition); | ||||
|                 $expenses  = $repository->balanceInPeriod($budget, $repetition->startdate, $repetition->enddate, $shared); | ||||
|                 $expenses = $expenses * -1; | ||||
|                 $left      = $expenses < $repetition->amount ? bcsub($repetition->amount, $expenses) : 0; | ||||
|                 $spent     = $expenses > $repetition->amount ? 0 : $expenses; | ||||
|                 $overspent = $expenses > $repetition->amount ? bcsub($expenses, $repetition->amount) : 0; | ||||
|  | ||||
|                 $budgetLine->setLeft($left); | ||||
|                 $budgetLine->setSpent($spent); | ||||
|                 $budgetLine->setOverspent($overspent); | ||||
|                 $budgetLine->setBudgeted($repetition->amount); | ||||
|  | ||||
|                 $object->addBudgeted($repetition->amount); | ||||
|                 $object->addSpent($spent); | ||||
|                 $object->addLeft($left); | ||||
|                 $object->addOverspent($overspent); | ||||
|                 $object->addBudgetLine($budgetLine); | ||||
|  | ||||
|             } | ||||
|  | ||||
|             $currentStart->addDay(); | ||||
|         } | ||||
|  | ||||
|         // stuff outside of budgets: | ||||
|         $noBudget   = $repository->getWithoutBudgetSum($start, $end); | ||||
|         $budgetLine = new BudgetLine; | ||||
|         $budgetLine->setOverspent($noBudget); | ||||
|         $object->addOverspent($noBudget); | ||||
|         $object->addBudgetLine($budgetLine); | ||||
|  | ||||
|         return $object; | ||||
|         return $sum; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * | ||||
|      * @return CategoryCollection | ||||
|      */ | ||||
|     public function getCategoryReport(Carbon $start, Carbon $end, $shared) | ||||
|     { | ||||
|         $object = new CategoryCollection; | ||||
|  | ||||
|  | ||||
|         /** | ||||
|          * GET CATEGORIES: | ||||
|          */ | ||||
|         /** @var \FireflyIII\Repositories\Category\CategoryRepositoryInterface $repository */ | ||||
|         $repository = app('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); | ||||
|         $set        = $repository->getCategories(); | ||||
|         foreach ($set as $category) { | ||||
|             $spent = $repository->balanceInPeriod($category, $start, $end, $shared); | ||||
|             $category->spent = $spent; | ||||
|             $object->addCategory($category); | ||||
|             $object->addTotal($spent); | ||||
|         } | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get a full report on the users expenses during the period. | ||||
|      * | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * | ||||
|      * @return Expense | ||||
|      */ | ||||
|     public function getExpenseReport($start, $end, $shared) | ||||
|     { | ||||
|         $object = new Expense; | ||||
|         $set    = $this->query->expenseInPeriodCorrected($start, $end, $shared); | ||||
|         foreach ($set as $entry) { | ||||
|             $object->addToTotal($entry->amount_positive); | ||||
|             $object->addOrCreateExpense($entry); | ||||
|         } | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get a full report on the users incomes during the period. | ||||
|      * | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * | ||||
|      * @return Income | ||||
|      */ | ||||
|     public function getIncomeReport($start, $end, $shared) | ||||
|     { | ||||
|         $object = new Income; | ||||
|         $set    = $this->query->incomeInPeriodCorrected($start, $end, $shared); | ||||
|         foreach ($set as $entry) { | ||||
|             $object->addToTotal($entry->amount_positive); | ||||
|             $object->addOrCreateIncome($entry); | ||||
|         } | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function listOfMonths(Carbon $date) | ||||
|     { | ||||
|  | ||||
|         $start  = clone $date; | ||||
|         $end    = Carbon::now(); | ||||
|         $months = []; | ||||
|         while ($start <= $end) { | ||||
|             $year            = $start->year; | ||||
|             $months[$year][] = [ | ||||
|                 'formatted' => $start->formatLocalized('%B %Y'), | ||||
|                 'month'     => $start->month, | ||||
|                 'year'      => $year, | ||||
|             ]; | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|  | ||||
|         return $months; | ||||
|     } | ||||
| } | ||||
| } | ||||
| @@ -10,6 +10,7 @@ use FireflyIII\Helpers\Collection\Budget as BudgetCollection; | ||||
| use FireflyIII\Helpers\Collection\Category as CategoryCollection; | ||||
| use FireflyIII\Helpers\Collection\Expense; | ||||
| use FireflyIII\Helpers\Collection\Income; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Interface ReportHelperInterface | ||||
| @@ -21,75 +22,78 @@ interface ReportHelperInterface | ||||
|  | ||||
|     /** | ||||
|      * This method generates a full report for the given period on all | ||||
|      * the users asset and cash accounts. | ||||
|      * given accounts | ||||
|      * | ||||
|      * @param Carbon  $date | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return AccountCollection | ||||
|      */ | ||||
|     public function getAccountReport(Carbon $date, Carbon $end, $shared); | ||||
|     public function getAccountReport(Carbon $start, Carbon $end, Collection $accounts); | ||||
|  | ||||
|     /** | ||||
|      * This method generates a full report for the given period on all | ||||
|      * the users bills and their payments. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * Excludes bills which have not had a payment on the mentioned accounts. | ||||
|      * | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return BillCollection | ||||
|      */ | ||||
|     public function getBillReport(Carbon $start, Carbon $end); | ||||
|     public function getBillReport(Carbon $start, Carbon $end, Collection $accounts); | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return Balance | ||||
|      */ | ||||
|     public function getBalanceReport(Carbon $start, Carbon $end, $shared); | ||||
|     public function getBalanceReport(Carbon $start, Carbon $end, Collection $accounts); | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return BudgetCollection | ||||
|      */ | ||||
|     public function getBudgetReport(Carbon $start, Carbon $end, $shared); | ||||
|     public function getBudgetReport(Carbon $start, Carbon $end, Collection $accounts); | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return CategoryCollection | ||||
|      */ | ||||
|     public function getCategoryReport(Carbon $start, Carbon $end, $shared); | ||||
|     public function getCategoryReport(Carbon $start, Carbon $end, Collection $accounts); | ||||
|  | ||||
|     /** | ||||
|      * Get a full report on the users expenses during the period. | ||||
|      * Get a full report on the users expenses during the period for a list of accounts. | ||||
|      * | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return Expense | ||||
|      */ | ||||
|     public function getExpenseReport($start, $end, $shared); | ||||
|     public function getExpenseReport($start, $end, Collection $accounts); | ||||
|  | ||||
|     /** | ||||
|      * Get a full report on the users incomes during the period. | ||||
|      * Get a full report on the users incomes during the period for the given accounts. | ||||
|      * | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return Income | ||||
|      */ | ||||
|     public function getIncomeReport($start, $end, $shared); | ||||
|     public function getIncomeReport($start, $end, Collection $accounts); | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $date | ||||
|   | ||||
| @@ -4,14 +4,10 @@ namespace FireflyIII\Helpers\Report; | ||||
|  | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use Crypt; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Illuminate\Database\Eloquent\Builder; | ||||
| use DB; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use Illuminate\Database\Query\JoinClause; | ||||
| use Illuminate\Support\Collection; | ||||
| use Steam; | ||||
|  | ||||
| /** | ||||
|  * Class ReportQuery | ||||
| @@ -20,260 +16,163 @@ use Steam; | ||||
|  */ | ||||
| class ReportQuery implements ReportQueryInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * See ReportQueryInterface::incomeInPeriodCorrected. | ||||
|      * Returns an array of the amount of money spent in the given accounts (on withdrawals, opening balances and transfers) | ||||
|      * grouped by month like so: "2015-01" => '123.45' | ||||
|      * | ||||
|      * This method's length is caused mainly by the query build stuff. Therefor: | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $includeShared | ||||
|      * | ||||
|      * @return Collection | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function expenseInPeriodCorrected(Carbon $start, Carbon $end, $includeShared = false) | ||||
|     public function spentPerMonth(Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $query = $this->queryJournalsWithTransactions($start, $end); | ||||
|         if ($includeShared === false) { | ||||
|             $query->where( | ||||
|                 function (Builder $query) { | ||||
|                     $query->where( | ||||
|                         function (Builder $q) { // only get withdrawals not from a shared account | ||||
|                             $q->where('transaction_types.type', 'Withdrawal'); | ||||
|                             $q->where('acm_from.data', '!=', '"sharedAsset"'); | ||||
|                         } | ||||
|                     ); | ||||
|                     $query->orWhere( | ||||
|                         function (Builder $q) { // and transfers from a shared account. | ||||
|                             $q->where('transaction_types.type', 'Transfer'); | ||||
|                             $q->where('acm_to.data', '=', '"sharedAsset"'); | ||||
|                             $q->where('acm_from.data', '!=', '"sharedAsset"'); | ||||
|                         } | ||||
|                     ); | ||||
|                 } | ||||
|             ); | ||||
|         } else { | ||||
|             $query->where('transaction_types.type', 'Withdrawal'); // any withdrawal is fine. | ||||
|         $ids   = $accounts->pluck('id')->toArray(); | ||||
|         $query = Auth::user()->transactionjournals() | ||||
|                      ->leftJoin( | ||||
|                          'transactions AS t_from', function (JoinClause $join) { | ||||
|                          $join->on('transaction_journals.id', '=', 't_from.transaction_journal_id')->where('t_from.amount', '<', 0); | ||||
|                      } | ||||
|                      ) | ||||
|                      ->leftJoin( | ||||
|                          'transactions AS t_to', function (JoinClause $join) { | ||||
|                          $join->on('transaction_journals.id', '=', 't_to.transaction_journal_id')->where('t_to.amount', '>', 0); | ||||
|                      } | ||||
|                      ) | ||||
|                      ->whereIn('t_from.account_id', $ids) | ||||
|                      ->whereNotIn('t_to.account_id', $ids) | ||||
|                      ->after($start) | ||||
|                      ->before($end) | ||||
|                      ->transactionTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE]) | ||||
|                      ->groupBy('dateFormatted') | ||||
|                      ->get( | ||||
|                          [ | ||||
|                              DB::Raw('DATE_FORMAT(`transaction_journals`.`date`,"%Y-%m") AS `dateFormatted`'), | ||||
|                              DB::Raw('SUM(`t_from`.`amount`) AS `sum`') | ||||
|                          ] | ||||
|                      ); | ||||
|         $array = []; | ||||
|         foreach ($query as $result) { | ||||
|             $array[$result->dateFormatted] = $result->sum; | ||||
|         } | ||||
|         $query->orderBy('transaction_journals.date'); | ||||
|         $data = $query->get( // get everything | ||||
|             ['transaction_journals.*', 'transaction_types.type', 'ac_to.name as name', 'ac_to.id as account_id', 'ac_to.encrypted as account_encrypted'] | ||||
|         ); | ||||
|  | ||||
|         $data->each( | ||||
|             function (TransactionJournal $journal) { | ||||
|                 if (intval($journal->account_encrypted) == 1) { | ||||
|                     $journal->name = Crypt::decrypt($journal->name); | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|         return $array; | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get a users accounts combined with various meta-data related to the start and end date. | ||||
|      * Returns an array of the amount of money spent in the given accounts (on withdrawals, opening balances and transfers) | ||||
|      * grouped by month like so: "2015-01" => '123.45' | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $includeShared | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function earnedPerMonth(Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $ids   = $accounts->pluck('id')->toArray(); | ||||
|         $query = Auth::user()->transactionjournals() | ||||
|                      ->leftJoin( | ||||
|                          'transactions AS t_from', function (JoinClause $join) { | ||||
|                          $join->on('transaction_journals.id', '=', 't_from.transaction_journal_id')->where('t_from.amount', '<', 0); | ||||
|                      } | ||||
|                      ) | ||||
|                      ->leftJoin( | ||||
|                          'transactions AS t_to', function (JoinClause $join) { | ||||
|                          $join->on('transaction_journals.id', '=', 't_to.transaction_journal_id')->where('t_to.amount', '>', 0); | ||||
|                      } | ||||
|                      ) | ||||
|                      ->whereIn('t_to.account_id', $ids) | ||||
|                      ->whereNotIn('t_from.account_id', $ids) | ||||
|                      ->after($start) | ||||
|                      ->before($end) | ||||
|                      ->transactionTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE]) | ||||
|                      ->groupBy('dateFormatted') | ||||
|                      ->get( | ||||
|                          [ | ||||
|                              DB::Raw('DATE_FORMAT(`transaction_journals`.`date`,"%Y-%m") AS `dateFormatted`'), | ||||
|                              DB::Raw('SUM(`t_to`.`amount`) AS `sum`') | ||||
|                          ] | ||||
|                      ); | ||||
|         $array = []; | ||||
|         foreach ($query as $result) { | ||||
|             $array[$result->dateFormatted] = $result->sum; | ||||
|         } | ||||
|  | ||||
|         return $array; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method returns all the "in" transaction journals for the given account and given period. The amount | ||||
|      * is stored in "journalAmount". | ||||
|      * | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getAllAccounts(Carbon $start, Carbon $end, $includeShared = false) | ||||
|     public function income(Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $query = Auth::user()->accounts()->orderBy('accounts.name', 'ASC') | ||||
|                      ->accountTypeIn(['Default account', 'Asset account', 'Cash account']); | ||||
|         if ($includeShared === false) { | ||||
|             $query->leftJoin( | ||||
|                 'account_meta', function (JoinClause $join) { | ||||
|                 $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole'); | ||||
|             } | ||||
|             ) | ||||
|                   ->where( | ||||
|                       function (Builder $query) { | ||||
|  | ||||
|                           $query->where('account_meta.data', '!=', '"sharedAsset"'); | ||||
|                           $query->orWhereNull('account_meta.data'); | ||||
|  | ||||
|                       } | ||||
|                   ); | ||||
|         } | ||||
|         $set = $query->get(['accounts.*']); | ||||
|         $set->each( | ||||
|             function (Account $account) use ($start, $end) { | ||||
|                 /** | ||||
|                  * The balance for today always incorporates transactions | ||||
|                  * made on today. So to get todays "start" balance, we sub one | ||||
|                  * day. | ||||
|                  */ | ||||
|                 $yesterday = clone $start; | ||||
|                 $yesterday->subDay(); | ||||
|  | ||||
|                 /** @noinspection PhpParamsInspection */ | ||||
|                 $account->startBalance = Steam::balance($account, $yesterday); | ||||
|                 $account->endBalance   = Steam::balance($account, $end); | ||||
|             } | ||||
|         ); | ||||
|         $ids = $accounts->pluck('id')->toArray(); | ||||
|         $set = Auth::user()->transactionjournals() | ||||
|                    ->leftJoin( | ||||
|                        'transactions as t_from', function (JoinClause $join) { | ||||
|                        $join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0); | ||||
|                    } | ||||
|                    ) | ||||
|                    ->leftJoin( | ||||
|                        'transactions as t_to', function (JoinClause $join) { | ||||
|                        $join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0); | ||||
|                    } | ||||
|                    ) | ||||
|                    ->leftJoin('accounts', 't_from.account_id', '=', 'accounts.id') | ||||
|                    ->transactionTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE]) | ||||
|                    ->before($end) | ||||
|                    ->after($start) | ||||
|                    ->whereIn('t_to.account_id', $ids) | ||||
|                    ->whereNotIn('t_from.account_id', $ids) | ||||
|                    ->get(['transaction_journals.*', 't_to.amount as journalAmount', 'accounts.id as account_id', 'accounts.name as account_name']); | ||||
|  | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * This method works the same way as ReportQueryInterface::incomeInPeriod does, but instead of returning results | ||||
|      * will simply list the transaction journals only. This should allow any follow up counting to be accurate with | ||||
|      * regards to tags. | ||||
|      * This method returns all the "out" transaction journals for the given account and given period. The amount | ||||
|      * is stored in "journalAmount". | ||||
|      * | ||||
|      * This method returns all "income" journals in a certain period, which are both transfers from a shared account | ||||
|      * and "ordinary" deposits. The query used is almost equal to ReportQueryInterface::journalsByRevenueAccount but it does | ||||
|      * not group and returns different fields. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $includeShared | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function incomeInPeriodCorrected(Carbon $start, Carbon $end, $includeShared = false) | ||||
|     public function expense(Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $query = $this->queryJournalsWithTransactions($start, $end); | ||||
|         if ($includeShared === false) { | ||||
|             // only get deposits not to a shared account | ||||
|             // and transfers to a shared account. | ||||
|             $query->where( | ||||
|                 function (Builder $query) { | ||||
|                     $query->where( | ||||
|                         function (Builder $q) { | ||||
|                             $q->where('transaction_types.type', 'Deposit'); | ||||
|                             $q->where('acm_to.data', '!=', '"sharedAsset"'); | ||||
|                         } | ||||
|                     ); | ||||
|                     $query->orWhere( | ||||
|                         function (Builder $q) { | ||||
|                             $q->where('transaction_types.type', 'Transfer'); | ||||
|                             $q->where('acm_from.data', '=', '"sharedAsset"'); | ||||
|                             $q->where('acm_to.data','!=','"sharedAsset"'); | ||||
|                         } | ||||
|                     ); | ||||
|                 } | ||||
|             ); | ||||
|         } else { | ||||
|             // any deposit is fine. | ||||
|             $query->where('transaction_types.type', 'Deposit'); | ||||
|         } | ||||
|         $query->orderBy('transaction_journals.date'); | ||||
|         $ids = $accounts->pluck('id')->toArray(); | ||||
|         $set = Auth::user()->transactionjournals() | ||||
|                    ->leftJoin( | ||||
|                        'transactions as t_from', function (JoinClause $join) { | ||||
|                        $join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0); | ||||
|                    } | ||||
|                    ) | ||||
|                    ->leftJoin( | ||||
|                        'transactions as t_to', function (JoinClause $join) { | ||||
|                        $join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0); | ||||
|                    } | ||||
|                    ) | ||||
|                    ->leftJoin('accounts', 't_to.account_id', '=', 'accounts.id') | ||||
|                    ->transactionTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE]) | ||||
|                    ->before($end) | ||||
|                    ->after($start) | ||||
|                    ->whereIn('t_from.account_id', $ids) | ||||
|                    ->whereNotIn('t_to.account_id', $ids) | ||||
|                    ->get(['transaction_journals.*', 't_from.amount as journalAmount', 'accounts.id as account_id', 'accounts.name as account_name']); | ||||
|  | ||||
|         // get everything | ||||
|         $data = $query->get( | ||||
|             ['transaction_journals.*', 'transaction_types.type', 'ac_from.name as name', 'ac_from.id as account_id', 'ac_from.encrypted as account_encrypted'] | ||||
|         ); | ||||
|  | ||||
|         $data->each( | ||||
|             function (TransactionJournal $journal) { | ||||
|                 if (intval($journal->account_encrypted) == 1) { | ||||
|                     $journal->name = Crypt::decrypt($journal->name); | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|         $data = $data->filter( | ||||
|             function (TransactionJournal $journal) { | ||||
|                 if ($journal->amount != 0) { | ||||
|                     return $journal; | ||||
|                 } | ||||
|  | ||||
|                 return null; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Covers tags | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Budget  $budget | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function spentInBudgetCorrected(Account $account, Budget $budget, Carbon $start, Carbon $end) | ||||
|     { | ||||
|  | ||||
|         bcscale(2); | ||||
|  | ||||
|         return bcmul( | ||||
|             Auth::user()->transactionjournals() | ||||
|                 ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                 ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                 ->transactionTypes(['Withdrawal']) | ||||
|                 ->where('transactions.account_id', $account->id) | ||||
|                 ->before($end) | ||||
|                 ->after($start) | ||||
|                 ->where('budget_transaction_journal.budget_id', $budget->id) | ||||
|                 ->get(['transaction_journals.*'])->sum('amount'), -1 | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function spentNoBudget(Account $account, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         return | ||||
|             Auth::user()->transactionjournals() | ||||
|                 ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                 ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                 ->transactionTypes(['Withdrawal']) | ||||
|                 ->where('transactions.account_id', $account->id) | ||||
|                 ->before($end) | ||||
|                 ->after($start) | ||||
|                 ->whereNull('budget_transaction_journal.budget_id')->get(['transaction_journals.*'])->sum('amount'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Builder | ||||
|      */ | ||||
|     protected function queryJournalsWithTransactions(Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $query = TransactionJournal:: | ||||
|         leftJoin( | ||||
|             'transactions as t_from', function (JoinClause $join) { | ||||
|             $join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0); | ||||
|         } | ||||
|         ) | ||||
|                                    ->leftJoin('accounts as ac_from', 't_from.account_id', '=', 'ac_from.id') | ||||
|                                    ->leftJoin( | ||||
|                                        'account_meta as acm_from', function (JoinClause $join) { | ||||
|                                        $join->on('ac_from.id', '=', 'acm_from.account_id')->where('acm_from.name', '=', 'accountRole'); | ||||
|                                    } | ||||
|                                    ) | ||||
|                                    ->leftJoin( | ||||
|                                        'transactions as t_to', function (JoinClause $join) { | ||||
|                                        $join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0); | ||||
|                                    } | ||||
|                                    ) | ||||
|                                    ->leftJoin('accounts as ac_to', 't_to.account_id', '=', 'ac_to.id') | ||||
|                                    ->leftJoin( | ||||
|                                        'account_meta as acm_to', function (JoinClause $join) { | ||||
|                                        $join->on('ac_to.id', '=', 'acm_to.account_id')->where('acm_to.name', '=', 'accountRole'); | ||||
|                                    } | ||||
|                                    ) | ||||
|                                    ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id'); | ||||
|         $query->before($end)->after($start)->where('transaction_journals.user_id', Auth::user()->id); | ||||
|  | ||||
|         return $query; | ||||
|         return $set; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -3,8 +3,6 @@ | ||||
| namespace FireflyIII\Helpers\Report; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Budget; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
| @@ -16,65 +14,52 @@ interface ReportQueryInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * See ReportQueryInterface::incomeInPeriodCorrected | ||||
|      * Returns an array of the amount of money spent in the given accounts (on withdrawals, opening balances and transfers) | ||||
|      * grouped by month like so: "2015-01" => '123.45' | ||||
|      * | ||||
|      * This method returns all "expense" journals in a certain period, which are both transfers to a shared account | ||||
|      * and "ordinary" withdrawals. The query used is almost equal to ReportQueryInterface::journalsByRevenueAccount but it does | ||||
|      * not group and returns different fields. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $includeShared | ||||
|      * | ||||
|      * @return Collection | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function expenseInPeriodCorrected(Carbon $start, Carbon $end, $includeShared = false); | ||||
|     public function earnedPerMonth(Collection $accounts, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * Get a users accounts combined with various meta-data related to the start and end date. | ||||
|      * This method returns all the "out" transaction journals for the given account and given period. The amount | ||||
|      * is stored in "journalAmount". | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $includeShared | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getAllAccounts(Carbon $start, Carbon $end, $includeShared = false); | ||||
|     public function expense(Collection $accounts, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * This method works the same way as ReportQueryInterface::incomeInPeriod does, but instead of returning results | ||||
|      * will simply list the transaction journals only. This should allow any follow up counting to be accurate with | ||||
|      * regards to tags. | ||||
|      * This method returns all the "in" transaction journals for the given account and given period. The amount | ||||
|      * is stored in "journalAmount". | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $includeShared | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function incomeInPeriodCorrected(Carbon $start, Carbon $end, $includeShared = false); | ||||
|     public function income(Collection $accounts, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * Covers tags as well. | ||||
|      * Returns an array of the amount of money spent in the given accounts (on withdrawals, opening balances and transfers) | ||||
|      * grouped by month like so: "2015-01" => '123.45' | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Budget  $budget | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return float | ||||
|      * @return array | ||||
|      */ | ||||
|     public function spentInBudgetCorrected(Account $account, Budget $budget, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function spentNoBudget(Account $account, Carbon $start, Carbon $end); | ||||
|     public function spentPerMonth(Collection $accounts, Carbon $start, Carbon $end); | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -6,7 +6,7 @@ use Config; | ||||
| use ExpandedForm; | ||||
| use FireflyIII\Http\Requests\AccountFormRequest; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI; | ||||
| use Input; | ||||
| use Preferences; | ||||
| use Session; | ||||
| @@ -38,6 +38,8 @@ class AccountController extends Controller | ||||
|      */ | ||||
|     public function create($what = 'asset') | ||||
|     { | ||||
|  | ||||
|  | ||||
|         $subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what); | ||||
|         $subTitle     = trans('firefly.make_new_' . $what . '_account'); | ||||
|  | ||||
| @@ -54,11 +56,12 @@ class AccountController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param ARI     $repository | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function delete(AccountRepositoryInterface $repository, Account $account) | ||||
|     public function delete(ARI $repository, Account $account) | ||||
|     { | ||||
|         $typeName    = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type); | ||||
|         $subTitle    = trans('firefly.delete_' . $typeName . '_account', ['name' => $account->name]); | ||||
| @@ -74,12 +77,12 @@ class AccountController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * @param Account                    $account | ||||
|      * @param ARI     $repository | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function destroy(AccountRepositoryInterface $repository, Account $account) | ||||
|     public function destroy(ARI $repository, Account $account) | ||||
|     { | ||||
|         $type     = $account->accountType->type; | ||||
|         $typeName = Config::get('firefly.shortNamesByFullName.' . $type); | ||||
| @@ -95,12 +98,12 @@ class AccountController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * @param Account                    $account | ||||
|      * @param ARI     $repository | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function edit(AccountRepositoryInterface $repository, Account $account) | ||||
|     public function edit(ARI $repository, Account $account) | ||||
|     { | ||||
|  | ||||
|         $what           = Config::get('firefly.shortNamesByFullName')[$account->accountType->type]; | ||||
| @@ -140,40 +143,31 @@ class AccountController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * @param ARI                        $repository | ||||
|      * @param                            $what | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function index(AccountRepositoryInterface $repository, $what) | ||||
|     public function index(ARI $repository, $what) | ||||
|     { | ||||
|         $subTitle     = trans('firefly.' . $what . '_accounts'); | ||||
|         $subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what); | ||||
|         $types        = Config::get('firefly.accountTypesByIdentifier.' . $what); | ||||
|         $accounts     = $repository->getAccounts($types); | ||||
|         // last activity: | ||||
|         /** | ||||
|          * HERE WE ARE | ||||
|          */ | ||||
|         $start = clone Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end   = clone Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $start        = clone Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end          = clone Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $start->subDay(); | ||||
|  | ||||
|         // start balances: | ||||
|         $ids = []; | ||||
|         foreach ($accounts as $account) { | ||||
|             $ids[] = $account->id; | ||||
|         } | ||||
|  | ||||
|         $ids           = $accounts->pluck('id')->toArray(); | ||||
|         $startBalances = Steam::balancesById($ids, $start); | ||||
|         $endBalances   = Steam::balancesById($ids, $end); | ||||
|         $activities    = Steam::getLastActivities($ids); | ||||
|  | ||||
|         $accounts->each( | ||||
|             function (Account $account) use ($activities, $startBalances, $endBalances) { | ||||
|                 $account->lastActivityDate = isset($activities[$account->id]) ? $activities[$account->id] : null; | ||||
|                 $account->startBalance     = isset($startBalances[$account->id]) ? $startBalances[$account->id] : null; | ||||
|                 $account->endBalance       = isset($endBalances[$account->id]) ? $endBalances[$account->id] : null; | ||||
|                 $account->lastActivityDate = $this->isInArray($activities, $account->id); | ||||
|                 $account->startBalance     = $this->isInArray($startBalances, $account->id); | ||||
|                 $account->endBalance       = $this->isInArray($endBalances, $account->id); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
| @@ -181,12 +175,12 @@ class AccountController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * @param Account                    $account | ||||
|      * @param ARI     $repository | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function show(AccountRepositoryInterface $repository, Account $account) | ||||
|     public function show(ARI $repository, Account $account) | ||||
|     { | ||||
|         $page         = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page')); | ||||
|         $subTitleIcon = Config::get('firefly.subTitlesByIdentifier.' . $account->accountType->type); | ||||
| @@ -200,24 +194,25 @@ class AccountController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AccountFormRequest         $request | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * @param AccountFormRequest $request | ||||
|      * @param ARI                $repository | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function store(AccountFormRequest $request, AccountRepositoryInterface $repository) | ||||
|     public function store(AccountFormRequest $request, ARI $repository) | ||||
|     { | ||||
|         $accountData = [ | ||||
|             'name'                   => $request->input('name'), | ||||
|             'accountType'            => $request->input('what'), | ||||
|             'virtualBalance'         => round($request->input('virtualBalance'), 2), | ||||
|             'virtualBalanceCurrency' => intval($request->input('amount_currency_id_virtualBalance')), | ||||
|             'active'                 => true, | ||||
|             'user'                   => Auth::user()->id, | ||||
|             'iban'                   => $request->input('iban'), | ||||
|             'accountRole'            => $request->input('accountRole'), | ||||
|             'openingBalance'         => round($request->input('openingBalance'), 2), | ||||
|             'openingBalanceDate'     => new Carbon((string)$request->input('openingBalanceDate')), | ||||
|             'openingBalanceCurrency' => intval($request->input('balance_currency_id')), | ||||
|             'openingBalanceCurrency' => intval($request->input('amount_currency_id_openingBalance')), | ||||
|  | ||||
|         ]; | ||||
|  | ||||
| @@ -238,13 +233,13 @@ class AccountController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AccountFormRequest         $request | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * @param Account                    $account | ||||
|      * @param AccountFormRequest $request | ||||
|      * @param ARI                $repository | ||||
|      * @param Account            $account | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function update(AccountFormRequest $request, AccountRepositoryInterface $repository, Account $account) | ||||
|     public function update(AccountFormRequest $request, ARI $repository, Account $account) | ||||
|     { | ||||
|  | ||||
|         $accountData = [ | ||||
| @@ -279,4 +274,20 @@ class AccountController extends Controller | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param array $array | ||||
|      * @param       $entryId | ||||
|      * | ||||
|      * @return null|mixed | ||||
|      */ | ||||
|     protected function isInArray(array $array, $entryId) | ||||
|     { | ||||
|         if (isset($array[$entryId])) { | ||||
|             return $array[$entryId]; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -90,7 +90,8 @@ class AttachmentController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Attachment $attachment | ||||
|      * @param Attachment                $attachment | ||||
|      * @param AttachmentHelperInterface $helper | ||||
|      */ | ||||
|     public function download(Attachment $attachment, AttachmentHelperInterface $helper) | ||||
|     { | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers\Auth; | ||||
|  | ||||
| use Auth; | ||||
| use Config; | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Models\Role; | ||||
| use FireflyIII\User; | ||||
| @@ -8,6 +9,7 @@ use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers; | ||||
| use Illuminate\Foundation\Auth\ThrottlesLogins; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Mail\Message; | ||||
| use Log; | ||||
| use Mail; | ||||
| use Request as Rq; | ||||
| use Session; | ||||
| @@ -23,6 +25,18 @@ class AuthController extends Controller | ||||
| { | ||||
|     use AuthenticatesAndRegistersUsers, ThrottlesLogins; | ||||
|  | ||||
|     /** | ||||
|      * Log the user out of the application. | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function getLogout() | ||||
|     { | ||||
|         Auth::logout(); | ||||
|  | ||||
|         return redirect('/auth/login'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show the application registration form. | ||||
|      * | ||||
| @@ -44,15 +58,7 @@ class AuthController extends Controller | ||||
|      */ | ||||
|     public function postLogin(Request $request) | ||||
|     { | ||||
|         $this->validate( | ||||
|             $request, [ | ||||
|                         $this->loginUsername() => 'required', 'password' => 'required', | ||||
|                     ] | ||||
|         ); | ||||
|  | ||||
|         // If the class is using the ThrottlesLogins trait, we can automatically throttle | ||||
|         // the login attempts for this application. We'll key this by the username and | ||||
|         // the IP address of the client making these requests into this application. | ||||
|         $this->validate($request, [$this->loginUsername() => 'required', 'password' => 'required',]); | ||||
|         $throttles = $this->isUsingThrottlesLoginsTrait(); | ||||
|  | ||||
|         if ($throttles && $this->hasTooManyLoginAttempts($request)) { | ||||
| @@ -66,34 +72,25 @@ class AuthController extends Controller | ||||
|             return $this->handleUserWasAuthenticated($request, $throttles); | ||||
|         } | ||||
|  | ||||
|         // default error message: | ||||
|         $message = $this->getFailedLoginMessage(); | ||||
|  | ||||
|         // try to find a blocked user with this email address. | ||||
|         /** @var User $foundUser */ | ||||
|         $foundUser = User::where('email', $credentials['email'])->where('blocked', 1)->first(); | ||||
|         if (!is_null($foundUser)) { | ||||
|             // if it exists, show message: | ||||
|             $code    = $foundUser->blocked_code; | ||||
|             $code = $foundUser->blocked_code; | ||||
|             if (strlen($code) == 0) { | ||||
|                 $code = 'general_blocked'; | ||||
|             } | ||||
|             $message = trans('firefly.' . $code . '_error', ['email' => $credentials['email']]); | ||||
|         } | ||||
|  | ||||
|         // try | ||||
|  | ||||
|         // If the login attempt was unsuccessful we will increment the number of attempts | ||||
|         // to login and redirect the user back to the login form. Of course, when this | ||||
|         // user surpasses their maximum number of attempts they will get locked out. | ||||
|         if ($throttles) { | ||||
|             $this->incrementLoginAttempts($request); | ||||
|         } | ||||
|  | ||||
|         return redirect($this->loginPath()) | ||||
|             ->withInput($request->only($this->loginUsername(), 'remember')) | ||||
|             ->withErrors( | ||||
|                 [ | ||||
|                     $this->loginUsername() => $message, | ||||
|                 ] | ||||
|             ); | ||||
|             ->withErrors([$this->loginUsername() => $message,]); | ||||
|     } | ||||
|  | ||||
|  | ||||
| @@ -143,21 +140,35 @@ class AuthController extends Controller | ||||
|         } | ||||
|         // @codeCoverageIgnoreEnd | ||||
|  | ||||
|  | ||||
|         $data             = $request->all(); | ||||
|         $data['password'] = bcrypt($data['password']); | ||||
|  | ||||
|         // is user email domain blocked? | ||||
|         if ($this->isBlockedDomain($data['email'])) { | ||||
|             $validator->getMessageBag()->add('email', trans('validation.invalid_domain')); | ||||
|             $this->throwValidationException( | ||||
|                 $request, $validator | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         Auth::login($this->create($data)); | ||||
|  | ||||
|         // get the email address | ||||
|         if (Auth::user() instanceof User) { | ||||
|             $email   = Auth::user()->email; | ||||
|             $address = route('index'); | ||||
|             $email     = Auth::user()->email; | ||||
|             $address   = route('index'); | ||||
|             $ipAddress = $request->ip(); | ||||
|             // send email. | ||||
|             Mail::send( | ||||
|                 ['emails.registered-html', 'emails.registered'], ['address' => $address], function (Message $message) use ($email) { | ||||
|                 $message->to($email, $email)->subject('Welcome to Firefly III! '); | ||||
|             try { | ||||
|                 Mail::send( | ||||
|                     ['emails.registered-html', 'emails.registered'], ['address' => $address, 'ip' => $ipAddress], function (Message $message) use ($email) { | ||||
|                     $message->to($email, $email)->subject('Welcome to Firefly III! '); | ||||
|                 } | ||||
|                 ); | ||||
|             } catch (\Swift_TransportException $e) { | ||||
|                 Log::error($e->getMessage()); | ||||
|             } | ||||
|             ); | ||||
|  | ||||
|             // set flash message | ||||
|             Session::flash('success', 'You have registered successfully!'); | ||||
| @@ -180,6 +191,40 @@ class AuthController extends Controller | ||||
|         // @codeCoverageIgnoreEnd | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function getBlockedDomains() | ||||
|     { | ||||
|         $set     = Config::get('mail.blocked_domains'); | ||||
|         $domains = []; | ||||
|         foreach ($set as $entry) { | ||||
|             $domain = trim($entry); | ||||
|             if (strlen($domain) > 0) { | ||||
|                 $domains[] = $domain; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $domains; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $email | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     protected function isBlockedDomain($email) | ||||
|     { | ||||
|         $parts   = explode('@', $email); | ||||
|         $blocked = $this->getBlockedDomains(); | ||||
|  | ||||
|         if (isset($parts[1]) && in_array($parts[1], $blocked)) { | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get a validator for an incoming registration request. | ||||
|      * | ||||
|   | ||||
| @@ -1,7 +1,11 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers\Auth; | ||||
|  | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Foundation\Auth\ResetsPasswords; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Mail\Message; | ||||
| use Illuminate\Support\Facades\Password; | ||||
|  | ||||
| /** | ||||
|  * Class PasswordController | ||||
| @@ -41,4 +45,41 @@ class PasswordController extends Controller | ||||
|         $this->middleware('guest'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Send a reset link to the given user. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function postEmail(Request $request) | ||||
|     { | ||||
|         $this->validate($request, ['email' => 'required|email']); | ||||
|  | ||||
|         $user = User::whereEmail($request->get('email'))->first(); | ||||
|  | ||||
|         if (!is_null($user) && intval($user->blocked) === 1) { | ||||
|             $response = 'passwords.blocked'; | ||||
|         } else { | ||||
|             $response = Password::sendResetLink( | ||||
|                 $request->only('email'), function (Message $message) { | ||||
|                 $message->subject($this->getEmailSubject()); | ||||
|             } | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         switch ($response) { | ||||
|             case Password::RESET_LINK_SENT: | ||||
|                 return redirect()->back()->with('status', trans($response)); | ||||
|  | ||||
|             case Password::INVALID_USER: | ||||
|             case 'passwords.blocked': | ||||
|                 return redirect()->back()->withErrors(['email' => trans($response)]); | ||||
|  | ||||
|         } | ||||
|         abort(404); | ||||
|  | ||||
|         return ''; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -6,7 +6,9 @@ use Carbon\Carbon; | ||||
| use FireflyIII\Http\Requests\BudgetFormRequest; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\LimitRepetition; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI; | ||||
| use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| use Illuminate\Support\Collection; | ||||
| use Input; | ||||
| use Navigation; | ||||
| use Preferences; | ||||
| @@ -19,7 +21,6 @@ use View; | ||||
|  * Class BudgetController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  * @SuppressWarnings(PHPMD.TooManyMethods) | ||||
|  */ | ||||
| class BudgetController extends Controller | ||||
| { | ||||
| @@ -133,9 +134,11 @@ class BudgetController extends Controller | ||||
|     /** | ||||
|      * @param BudgetRepositoryInterface $repository | ||||
|      * | ||||
|      * @param ARI                       $accountRepository | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function index(BudgetRepositoryInterface $repository) | ||||
|     public function index(BudgetRepositoryInterface $repository, ARI $accountRepository) | ||||
|     { | ||||
|         $budgets           = $repository->getActiveBudgets(); | ||||
|         $inactive          = $repository->getInactiveBudgets(); | ||||
| @@ -147,6 +150,8 @@ class BudgetController extends Controller | ||||
|         $key               = 'budgetIncomeTotal' . $start->format('Ymd') . $end->format('Ymd'); | ||||
|         $budgetIncomeTotal = Preferences::get($key, 1000)->data; | ||||
|         $period            = Navigation::periodShow($start, $range); | ||||
|         $accounts          = $accountRepository->getAccounts(['Default account', 'Asset account', 'Cash account']); | ||||
|  | ||||
|         bcscale(2); | ||||
|         /** | ||||
|          * Do some cleanup: | ||||
| @@ -156,7 +161,7 @@ class BudgetController extends Controller | ||||
|         // loop the budgets: | ||||
|         /** @var Budget $budget */ | ||||
|         foreach ($budgets as $budget) { | ||||
|             $budget->spent      = $repository->balanceInPeriod($budget, $start, $end); | ||||
|             $budget->spent      = $repository->balanceInPeriod($budget, $start, $end, $accounts); | ||||
|             $budget->currentRep = $repository->getCurrentRepetition($budget, $start, $end); | ||||
|             if ($budget->currentRep) { | ||||
|                 $budgeted = bcadd($budgeted, $budget->currentRep->amount); | ||||
| @@ -170,7 +175,7 @@ class BudgetController extends Controller | ||||
|         $defaultCurrency = Amount::getDefaultCurrency(); | ||||
|  | ||||
|         return view( | ||||
|             'budgets.index', compact('budgetMaximum','period', 'range', 'budgetIncomeTotal', 'defaultCurrency', 'inactive', 'budgets', 'spent', 'budgeted') | ||||
|             'budgets.index', compact('budgetMaximum', 'period', 'range', 'budgetIncomeTotal', 'defaultCurrency', 'inactive', 'budgets', 'spent', 'budgeted') | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| @@ -227,13 +232,26 @@ class BudgetController extends Controller | ||||
|         $journals = $repository->getJournals($budget, $repetition); | ||||
|  | ||||
|         if (is_null($repetition->id)) { | ||||
|             $limits   = $repository->getBudgetLimits($budget); | ||||
|             $start    = $repository->firstActivity($budget); | ||||
|             $end      = new Carbon; | ||||
|             $set      = $budget->limitrepetitions()->orderBy('startdate', 'DESC')->get(); | ||||
|             $subTitle = e($budget->name); | ||||
|         } else { | ||||
|             $limits   = [$repetition->budgetLimit]; | ||||
|             $start    = $repetition->startdate; | ||||
|             $end      = $repetition->enddate; | ||||
|             $set      = new Collection([$repetition]); | ||||
|             $subTitle = trans('firefly.budget_in_month', ['name' => $budget->name, 'month' => $repetition->startdate->formatLocalized($this->monthFormat)]); | ||||
|         } | ||||
|  | ||||
|         $spentArray = $repository->spentPerDay($budget, $start, $end); | ||||
|         $limits     = new Collection(); | ||||
|  | ||||
|         /** @var LimitRepetition $entry */ | ||||
|         foreach ($set as $entry) { | ||||
|             $entry->spent = $this->getSumOfRange($entry->startdate, $entry->enddate, $spentArray); | ||||
|             $limits->push($entry); | ||||
|         } | ||||
|  | ||||
|         $journals->setPath('/budgets/show/' . $budget->id); | ||||
|  | ||||
|         return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle')); | ||||
| @@ -279,7 +297,7 @@ class BudgetController extends Controller | ||||
|     { | ||||
|         $budgetData = [ | ||||
|             'name'   => $request->input('name'), | ||||
|             'active' => intval($request->input('active')) == 1 | ||||
|             'active' => intval($request->input('active')) == 1, | ||||
|         ]; | ||||
|  | ||||
|         $repository->update($budget, $budgetData); | ||||
|   | ||||
| @@ -4,7 +4,8 @@ use Auth; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Http\Requests\CategoryFormRequest; | ||||
| use FireflyIII\Models\Category; | ||||
| use FireflyIII\Repositories\Category\CategoryRepositoryInterface; | ||||
| use FireflyIII\Repositories\Category\CategoryRepositoryInterface as CRI; | ||||
| use FireflyIII\Repositories\Category\SingleCategoryRepositoryInterface as SCRI; | ||||
| use FireflyIII\Support\CacheProperties; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use Illuminate\Support\Collection; | ||||
| @@ -68,12 +69,12 @@ class CategoryController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param Category                    $category | ||||
|      * @param SCRI     $repository | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function destroy(CategoryRepositoryInterface $repository, Category $category) | ||||
|     public function destroy(SCRI $repository, Category $category) | ||||
|     { | ||||
|  | ||||
|         $name = $category->name; | ||||
| @@ -107,17 +108,18 @@ class CategoryController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param CRI  $repository | ||||
|      * @param SCRI $singleRepository | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function index(CategoryRepositoryInterface $repository) | ||||
|     public function index(CRI $repository, SCRI $singleRepository) | ||||
|     { | ||||
|         $categories = $repository->getCategories(); | ||||
|         $categories = $repository->listCategories(); | ||||
|  | ||||
|         $categories->each( | ||||
|             function (Category $category) use ($repository) { | ||||
|                 $category->lastActivity = $repository->getLatestActivity($category); | ||||
|             function (Category $category) use ($singleRepository) { | ||||
|                 $category->lastActivity = $singleRepository->getLatestActivity($category); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
| @@ -125,15 +127,15 @@ class CategoryController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param CRI $repository | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function noCategory(CategoryRepositoryInterface $repository) | ||||
|     public function noCategory(CRI $repository) | ||||
|     { | ||||
|         $start    = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end      = Session::get('end', Carbon::now()->startOfMonth()); | ||||
|         $list     = $repository->getWithoutCategory($start, $end); | ||||
|         $list     = $repository->listNoCategory($start, $end); | ||||
|         $subTitle = trans( | ||||
|             'firefly.without_category_between', | ||||
|             ['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)] | ||||
| @@ -143,12 +145,14 @@ class CategoryController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param Category                    $category | ||||
|      * @param SCRI                              $repository | ||||
|      * @param Category                          $category | ||||
|      * | ||||
|      * @param                                   $date | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function showWithDate(CategoryRepositoryInterface $repository, Category $category, $date) | ||||
|     public function showWithDate(SCRI $repository, Category $category, $date) | ||||
|     { | ||||
|         $carbon   = new Carbon($date); | ||||
|         $range    = Preferences::get('viewRange', '1M')->data; | ||||
| @@ -168,12 +172,12 @@ class CategoryController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param Category                    $category | ||||
|      * @param SCRI     $repository | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function show(CategoryRepositoryInterface $repository, Category $category) | ||||
|     public function show(SCRI $repository, Category $category) | ||||
|     { | ||||
|         $hideCategory = true; // used in list. | ||||
|         $page         = intval(Input::get('page')); | ||||
| @@ -198,6 +202,12 @@ class CategoryController extends Controller | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty('category-show'); | ||||
|         $cache->addProperty($category->id); | ||||
|  | ||||
|         // get all spent and earned data: | ||||
|         // get amount earned in period, grouped by day. | ||||
|         $spentArray  = $repository->spentPerDay($category, $start, $end); | ||||
|         $earnedArray = $repository->earnedPerDay($category, $start, $end); | ||||
|  | ||||
|         if ($cache->has()) { | ||||
|             $entries = $cache->get(); | ||||
|         } else { | ||||
| @@ -206,9 +216,9 @@ class CategoryController extends Controller | ||||
|                 $end        = Navigation::startOfPeriod($end, $range); | ||||
|                 $currentEnd = Navigation::endOfPeriod($end, $range); | ||||
|  | ||||
|                 // here do something. | ||||
|                 $spent    = $repository->spentInPeriod($category, $end, $currentEnd); | ||||
|                 $earned   = $repository->earnedInPeriod($category, $end, $currentEnd); | ||||
|                 // get data from spentArray: | ||||
|                 $spent    = $this->getSumOfRange($end, $currentEnd, $spentArray); | ||||
|                 $earned   = $this->getSumOfRange($end, $currentEnd, $earnedArray); | ||||
|                 $dateStr  = $end->format('Y-m-d'); | ||||
|                 $dateName = Navigation::periodShow($end, $range); | ||||
|                 $entries->push([$dateStr, $dateName, $spent, $earned]); | ||||
| @@ -223,12 +233,12 @@ class CategoryController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param CategoryFormRequest         $request | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param CategoryFormRequest $request | ||||
|      * @param SCRI                $repository | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function store(CategoryFormRequest $request, CategoryRepositoryInterface $repository) | ||||
|     public function store(CategoryFormRequest $request, SCRI $repository) | ||||
|     { | ||||
|         $categoryData = [ | ||||
|             'name' => $request->input('name'), | ||||
| @@ -250,13 +260,13 @@ class CategoryController extends Controller | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param CategoryFormRequest         $request | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param Category                    $category | ||||
|      * @param CategoryFormRequest $request | ||||
|      * @param SCRI                $repository | ||||
|      * @param Category            $category | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function update(CategoryFormRequest $request, CategoryRepositoryInterface $repository, Category $category) | ||||
|     public function update(CategoryFormRequest $request, SCRI $repository, Category $category) | ||||
|     { | ||||
|         $categoryData = [ | ||||
|             'name' => $request->input('name'), | ||||
|   | ||||
| @@ -5,7 +5,7 @@ namespace FireflyIII\Http\Controllers\Chart; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI; | ||||
| use FireflyIII\Support\CacheProperties; | ||||
| use Illuminate\Support\Collection; | ||||
| use Preferences; | ||||
| @@ -35,45 +35,32 @@ class AccountController extends Controller | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Shows the balances for all the user's accounts. | ||||
|      * Shows the balances for a given set of dates and accounts. | ||||
|      * | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * @param            $reportType | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @param                            $year | ||||
|      * @param                            $month | ||||
|      * @param bool                       $shared | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function all(AccountRepositoryInterface $repository, $year, $month, $shared = false) | ||||
|     public function report($reportType, Carbon $start, Carbon $end, Collection $accounts) | ||||
|     { | ||||
|         $start = new Carbon($year . '-' . $month . '-01'); | ||||
|         $end   = clone $start; | ||||
|         $end->endOfMonth(); | ||||
|  | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties(); | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty('all'); | ||||
|         $cache->addProperty('accounts'); | ||||
|         $cache->addProperty('default'); | ||||
|         $cache->addProperty($reportType); | ||||
|         $cache->addProperty($accounts); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         /** @var Collection $accounts */ | ||||
|         $accounts = $repository->getAccounts(['Default account', 'Asset account']); | ||||
|         if ($shared === false) { | ||||
|             /** @var Account $account */ | ||||
|             foreach ($accounts as $index => $account) { | ||||
|                 if ($account->getMeta('accountRole') == 'sharedAsset') { | ||||
|                     $accounts->forget($index); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // make chart: | ||||
|         $data = $this->generator->all($accounts, $start, $end); | ||||
|         $data = $this->generator->frontpage($accounts, $start, $end); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
| @@ -82,11 +69,11 @@ class AccountController extends Controller | ||||
|     /** | ||||
|      * Shows the balances for all the user's expense accounts. | ||||
|      * | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * @param ARI $repository | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function expenseAccounts(AccountRepositoryInterface $repository) | ||||
|     public function expenseAccounts(ARI $repository) | ||||
|     { | ||||
|         $start    = clone Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end      = clone Session::get('end', Carbon::now()->endOfMonth()); | ||||
| @@ -112,11 +99,11 @@ class AccountController extends Controller | ||||
|     /** | ||||
|      * Shows the balances for all the user's frontpage accounts. | ||||
|      * | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * @param ARI $repository | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function frontpage(AccountRepositoryInterface $repository) | ||||
|     public function frontpage(ARI $repository) | ||||
|     { | ||||
|         $frontPage = Preferences::get('frontPageAccounts', []); | ||||
|         $start     = clone Session::get('start', Carbon::now()->startOfMonth()); | ||||
|   | ||||
| @@ -33,7 +33,7 @@ class BillController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Shows all bills and whether or not theyve been paid this month (pie chart). | ||||
|      * Shows all bills and whether or not they've been paid this month (pie chart). | ||||
|      * | ||||
|      * @param BillRepositoryInterface $repository | ||||
|      * | ||||
| @@ -41,28 +41,24 @@ class BillController extends Controller | ||||
|      */ | ||||
|     public function frontpage(BillRepositoryInterface $repository) | ||||
|     { | ||||
|         $start = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end   = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $cache = new CacheProperties(); // chart properties for cache: | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty('bills'); | ||||
|         $cache->addProperty('frontpage'); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         $start         = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end           = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $paid          = $repository->getBillsPaidInRange($start, $end); // will be a negative amount. | ||||
|         $unpaid        = $repository->getBillsUnpaidInRange($start, $end); // will be a positive amount. | ||||
|         $creditCardDue = $repository->getCreditCardBill($start, $end); | ||||
|  | ||||
|         if ($creditCardDue < 0) { | ||||
|             // expenses are negative (bill not yet paid), | ||||
|             $creditCardDue = bcmul($creditCardDue, '-1'); | ||||
|             $unpaid        = bcadd($unpaid, $creditCardDue); | ||||
|         } else { | ||||
|             // if more than zero, the bill has been paid: (transfer = positive). | ||||
|             // amount must be negative to be added to $paid: | ||||
|             $paid = bcadd($paid, $creditCardDue); | ||||
|         } | ||||
|  | ||||
|         $set = $repository->getBillsForChart($start, $end); | ||||
|  | ||||
|         // optionally expand this set with credit card data | ||||
|         $set    = $repository->getCreditCardInfoForChart($set, $start, $end); | ||||
|         $paid   = $set->get('paid'); | ||||
|         $unpaid = $set->get('unpaid'); | ||||
|  | ||||
|  | ||||
|         // build chart: | ||||
|         $data = $this->generator->frontpage($paid, $unpaid); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
|     } | ||||
|   | ||||
| @@ -6,6 +6,7 @@ use Carbon\Carbon; | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\LimitRepetition; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI; | ||||
| use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| use FireflyIII\Support\CacheProperties; | ||||
| use Illuminate\Support\Collection; | ||||
| @@ -35,6 +36,86 @@ class BudgetController extends Controller | ||||
|         $this->generator = app('FireflyIII\Generator\Chart\Budget\BudgetChartGenerator'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * TODO expand with no budget chart. | ||||
|      * | ||||
|      * @param BudgetRepositoryInterface $repository | ||||
|      * @param                           $reportType | ||||
|      * @param Carbon                    $start | ||||
|      * @param Carbon                    $end | ||||
|      * @param Collection                $accounts | ||||
|      * @param Collection                $budgets | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function multiYear(BudgetRepositoryInterface $repository, $reportType, Carbon $start, Carbon $end, Collection $accounts, Collection $budgets) | ||||
|     { | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties(); | ||||
|         $cache->addProperty($reportType); | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty($accounts); | ||||
|         $cache->addProperty($budgets); | ||||
|         $cache->addProperty('multiYearBudget'); | ||||
|  | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         /* | ||||
|          * Get the budgeted amounts for each budgets in each year. | ||||
|          */ | ||||
|         $budgetedSet   = $repository->getBudgetedPerYear($budgets, $start, $end); | ||||
|         $budgetedArray = []; | ||||
|         /** @var Budget $entry */ | ||||
|         foreach ($budgetedSet as $entry) { | ||||
|             $budgetedArray[$entry->id][$entry->dateFormatted] = $entry->budgeted; | ||||
|         } | ||||
|  | ||||
|         $set     = $repository->getBudgetsAndExpensesPerYear($budgets, $accounts, $start, $end); | ||||
|         $entries = new Collection; | ||||
|         // go by budget, not by year. | ||||
|         /** @var Budget $budget */ | ||||
|         foreach ($budgets as $budget) { | ||||
|             $entry        = ['name' => '', 'spent' => [], 'budgeted' => []]; | ||||
|             $id           = $budget->id; | ||||
|             $currentStart = clone $start; | ||||
|             while ($currentStart < $end) { | ||||
|                 // fix the date: | ||||
|                 $currentEnd = clone $currentStart; | ||||
|                 $currentEnd->endOfYear(); | ||||
|  | ||||
|                 // save to array: | ||||
|                 $year          = $currentStart->year; | ||||
|                 $entry['name'] = $budget->name; | ||||
|                 $spent         = 0; | ||||
|                 $budgeted      = 0; | ||||
|                 if (isset($set[$id]['entries'][$year])) { | ||||
|                     $spent = $set[$id]['entries'][$year] * -1; | ||||
|                 } | ||||
|  | ||||
|                 if (isset($budgetedArray[$id][$year])) { | ||||
|                     $budgeted = round($budgetedArray[$id][$year], 2); | ||||
|                 } | ||||
|  | ||||
|                 $entry['spent'][$year]    = $spent; | ||||
|                 $entry['budgeted'][$year] = $budgeted; | ||||
|  | ||||
|                 // jump to next year. | ||||
|                 $currentStart = clone $currentEnd; | ||||
|                 $currentStart->addDay(); | ||||
|             } | ||||
|             $entries->push($entry); | ||||
|         } | ||||
|         // generate chart with data: | ||||
|         $data = $this->generator->multiYear($entries); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BudgetRepositoryInterface $repository | ||||
|      * @param Budget                    $budget | ||||
| @@ -48,9 +129,6 @@ class BudgetController extends Controller | ||||
|         $first = $repository->getFirstBudgetLimitDate($budget); | ||||
|         $range = Preferences::get('viewRange', '1M')->data; | ||||
|         $last  = Session::get('end', new Carbon); | ||||
|         $final = clone $last; | ||||
|         $final->addYears(2); | ||||
|         $last = Navigation::endOfX($last, $range, $final); | ||||
|  | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties(); | ||||
| @@ -58,18 +136,29 @@ class BudgetController extends Controller | ||||
|         $cache->addProperty($last); | ||||
|         $cache->addProperty('budget'); | ||||
|         if ($cache->has()) { | ||||
|  | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $final = clone $last; | ||||
|         $final->addYears(2); | ||||
|         $last    = Navigation::endOfX($last, $range, $final); | ||||
|         $entries = new Collection; | ||||
|         // get all expenses: | ||||
|         $set = $repository->getExpensesPerMonth($budget, $first, $last); // TODO | ||||
|  | ||||
|         while ($first < $last) { | ||||
|             $end = Navigation::addPeriod($first, $range, 0); | ||||
|             $end->subDay(); | ||||
|             $chartDate = clone $end; | ||||
|             $chartDate->startOfMonth(); | ||||
|             $spent = $repository->balanceInPeriod($budget, $first, $end) * -1; | ||||
|             $entries->push([$chartDate, $spent]); | ||||
|             $monthFormatted = $first->format('Y-m'); | ||||
|  | ||||
|             $filtered = $set->filter( | ||||
|                 function (Budget $obj) use ($monthFormatted) { | ||||
|                     return $obj->dateFormatted == $monthFormatted; | ||||
|                 } | ||||
|             ); | ||||
|             $spent    = is_null($filtered->first()) ? '0' : $filtered->first()->monthlyAmount; | ||||
|  | ||||
|             $entries->push([$first, round(($spent * -1), 2)]); | ||||
|  | ||||
|             $first = Navigation::addPeriod($first, $range, 0); | ||||
|         } | ||||
|  | ||||
| @@ -106,15 +195,24 @@ class BudgetController extends Controller | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $set     = $repository->getExpensesPerDay($budget, $start, $end); | ||||
|         $entries = new Collection; | ||||
|         $amount  = $repetition->amount; | ||||
|  | ||||
|         // get sum (har har)! | ||||
|         while ($start <= $end) { | ||||
|             $formatted = $start->format('Y-m-d'); | ||||
|             $filtered  = $set->filter( | ||||
|                 function (Budget $obj) use ($formatted) { | ||||
|                     return $obj->date == $formatted; | ||||
|                 } | ||||
|             ); | ||||
|             $sum       = is_null($filtered->first()) ? '0' : $filtered->first()->dailyAmount; | ||||
|  | ||||
|             /* | ||||
|              * Sum of expenses on this day: | ||||
|              */ | ||||
|             $sum    = $repository->expensesOnDayCorrected($budget, $start); | ||||
|             $amount = bcadd($amount, $sum); | ||||
|             $amount = round(bcadd($amount, $sum), 2); | ||||
|             $entries->push([clone $start, $amount]); | ||||
|             $start->addDay(); | ||||
|         } | ||||
| @@ -131,14 +229,14 @@ class BudgetController extends Controller | ||||
|      * | ||||
|      * @param BudgetRepositoryInterface $repository | ||||
|      * | ||||
|      * @param ARI                       $accountRepository | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function frontpage(BudgetRepositoryInterface $repository) | ||||
|     public function frontpage(BudgetRepositoryInterface $repository, ARI $accountRepository) | ||||
|     { | ||||
|         $budgets    = $repository->getBudgets(); | ||||
|         $start      = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end        = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $allEntries = new Collection; | ||||
|         $start = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end   = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|  | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties(); | ||||
| @@ -150,98 +248,104 @@ class BudgetController extends Controller | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $budgets    = $repository->getBudgetsAndLimitsInRange($start, $end); | ||||
|         $allEntries = new Collection; | ||||
|         $accounts   = $accountRepository->getAccounts(['Default account', 'Asset account', 'Cash account']); | ||||
|  | ||||
|  | ||||
|         bcscale(2); | ||||
|  | ||||
|         /** @var Budget $budget */ | ||||
|         foreach ($budgets as $budget) { | ||||
|             $repetitions = $repository->getBudgetLimitRepetitions($budget, $start, $end); | ||||
|             if ($repetitions->count() == 0) { | ||||
|                 $expenses = $repository->balanceInPeriod($budget, $start, $end, true) * -1; | ||||
|                 $allEntries->push([$budget->name, 0, 0, $expenses, 0, 0]); | ||||
|                 continue; | ||||
|             // we already have amount, startdate and enddate. | ||||
|             // if this "is" a limit repetition (as opposed to a budget without one entirely) | ||||
|             // depends on whether startdate and enddate are null. | ||||
|             $name = $budget->name; | ||||
|             if (is_null($budget->startdate) && is_null($budget->enddate)) { | ||||
|                 $currentStart = clone $start; | ||||
|                 $currentEnd   = clone $end; | ||||
|                 $expenses     = $repository->balanceInPeriod($budget, $currentStart, $currentEnd, $accounts); | ||||
|                 $amount       = 0; | ||||
|                 $left         = 0; | ||||
|                 $spent        = $expenses; | ||||
|                 $overspent    = 0; | ||||
|             } else { | ||||
|                 $currentStart = clone $budget->startdate; | ||||
|                 $currentEnd   = clone $budget->enddate; | ||||
|                 $expenses     = $repository->balanceInPeriod($budget, $currentStart, $currentEnd, $accounts); | ||||
|                 $amount       = $budget->amount; | ||||
|                 // smaller than 1 means spent MORE than budget allows. | ||||
|                 $left      = bccomp(bcadd($budget->amount, $expenses), '0') < 1 ? 0 : bcadd($budget->amount, $expenses); | ||||
|                 $spent     = bccomp(bcadd($budget->amount, $expenses), '0') < 1 ? ($amount * -1) : $expenses; | ||||
|                 $overspent = bccomp(bcadd($budget->amount, $expenses), '0') < 1 ? bcadd($budget->amount, $expenses) : 0; | ||||
|             } | ||||
|             /** @var LimitRepetition $repetition */ | ||||
|             foreach ($repetitions as $repetition) { | ||||
|                 $expenses = $repository->balanceInPeriod($budget, $repetition->startdate, $repetition->enddate, true) * -1; | ||||
|                 // $left can be less than zero. | ||||
|                 // $overspent can be more than zero ( = overspending) | ||||
|  | ||||
|                 $left      = max(bcsub($repetition->amount, $expenses), 0); // limited at zero. | ||||
|                 $overspent = max(bcsub($expenses, $repetition->amount), 0); // limited at zero. | ||||
|                 $name      = $budget->name; | ||||
|  | ||||
|                 // $spent is maxed to the repetition amount: | ||||
|                 $spent = $expenses > $repetition->amount ? $repetition->amount : $expenses; | ||||
|  | ||||
|  | ||||
|                 $allEntries->push([$name, $left, $spent, $overspent, $repetition->amount, $expenses]); | ||||
|             } | ||||
|             $allEntries->push([$name, $left, $spent, $overspent, $amount, $expenses]); | ||||
|         } | ||||
|  | ||||
|         $noBudgetExpenses = $repository->getWithoutBudgetSum($start, $end) * -1; | ||||
|         $noBudgetExpenses = $repository->getWithoutBudgetSum($start, $end); | ||||
|         $allEntries->push([trans('firefly.noBudget'), 0, 0, $noBudgetExpenses, 0, 0]); | ||||
|  | ||||
|         $data = $this->generator->frontpage($allEntries); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show a yearly overview for a budget. | ||||
|      * TODO expand with no budget chart. | ||||
|      * | ||||
|      * @param BudgetRepositoryInterface $repository | ||||
|      * @param                           $year | ||||
|      * @param bool                      $shared | ||||
|      * @param                           $reportType | ||||
|      * @param Carbon                    $start | ||||
|      * @param Carbon                    $end | ||||
|      * @param Collection                $accounts | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function year(BudgetRepositoryInterface $repository, $year, $shared = false) | ||||
|     public function year(BudgetRepositoryInterface $repository, $reportType, Carbon $start, Carbon $end, Collection $accounts) | ||||
|     { | ||||
|         $start      = new Carbon($year . '-01-01'); | ||||
|         $end        = new Carbon($year . '-12-31'); | ||||
|         $shared     = $shared == 'shared' ? true : false; | ||||
|         $allBudgets = $repository->getBudgets(); | ||||
|         $budgets    = new Collection; | ||||
|  | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties(); | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty($reportType); | ||||
|         $cache->addProperty($accounts); | ||||
|         $cache->addProperty('budget'); | ||||
|         $cache->addProperty('year'); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         // filter empty budgets: | ||||
|         $budgetInformation = $repository->getBudgetsAndExpensesPerMonth($accounts, $start, $end); | ||||
|         $budgets           = new Collection; | ||||
|         $entries           = new Collection; | ||||
|  | ||||
|         foreach ($allBudgets as $budget) { | ||||
|             $spent = $repository->balanceInPeriod($budget, $start, $end, $shared); | ||||
|             if ($spent != 0) { | ||||
|                 $budgets->push($budget); | ||||
|             } | ||||
|         /** @var array $row */ | ||||
|         foreach ($budgetInformation as $row) { | ||||
|             $budgets->push($row['budget']); | ||||
|         } | ||||
|  | ||||
|         $entries = new Collection; | ||||
|  | ||||
|         while ($start < $end) { | ||||
|             // month is the current end of the period: | ||||
|             $month = clone $start; | ||||
|             $month->endOfMonth(); | ||||
|             $row = [clone $start]; | ||||
|             $row           = [clone $start]; | ||||
|             $dateFormatted = $start->format('Y-m'); | ||||
|  | ||||
|             // each budget, fill the row: | ||||
|             foreach ($budgets as $budget) { | ||||
|                 $spent = $repository->balanceInPeriod($budget, $start, $month, $shared); | ||||
|                 $row[] = $spent * -1; | ||||
|             // each budget, check if there is an entry for this month: | ||||
|             /** @var array $row */ | ||||
|             foreach ($budgetInformation as $budgetRow) { | ||||
|                 $spent = 0; // nothing spent. | ||||
|                 if (isset($budgetRow['entries'][$dateFormatted])) { | ||||
|                     $spent = $budgetRow['entries'][$dateFormatted] * -1; // to fit array | ||||
|                 } | ||||
|                 $row[] = $spent; | ||||
|             } | ||||
|             $entries->push($row); | ||||
|             $start->endOfMonth()->addDay(); | ||||
|         } | ||||
|  | ||||
|         $data = $this->generator->year($allBudgets, $entries); | ||||
|         $data = $this->generator->year($budgets, $entries); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
|   | ||||
| @@ -6,13 +6,15 @@ namespace FireflyIII\Http\Controllers\Chart; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Models\Category; | ||||
| use FireflyIII\Repositories\Category\CategoryRepositoryInterface; | ||||
| use FireflyIII\Repositories\Category\CategoryRepositoryInterface as CRI; | ||||
| use FireflyIII\Repositories\Category\SingleCategoryRepositoryInterface as SCRI; | ||||
| use FireflyIII\Support\CacheProperties; | ||||
| use Illuminate\Support\Collection; | ||||
| use Navigation; | ||||
| use Preferences; | ||||
| use Response; | ||||
| use Session; | ||||
| use stdClass; | ||||
|  | ||||
| /** | ||||
|  * Class CategoryController | ||||
| @@ -38,12 +40,12 @@ class CategoryController extends Controller | ||||
|     /** | ||||
|      * Show an overview for a category for all time, per month/week/year. | ||||
|      * | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param Category                    $category | ||||
|      * @param SCRI     $repository | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function all(CategoryRepositoryInterface $repository, Category $category) | ||||
|     public function all(SCRI $repository, Category $category) | ||||
|     { | ||||
|         // oldest transaction in category: | ||||
|         $start   = $repository->getFirstActivityDate($category); | ||||
| @@ -62,12 +64,18 @@ class CategoryController extends Controller | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|         $spentArray  = $repository->spentPerDay($category, $start, $end); | ||||
|         $earnedArray = $repository->earnedPerDay($category, $start, $end); | ||||
|  | ||||
|  | ||||
|         while ($start <= $end) { | ||||
|             $currentEnd = Navigation::endOfPeriod($start, $range); | ||||
|             $spent      = $repository->spentInPeriod($category, $start, $currentEnd); | ||||
|             $earned     = $repository->earnedInPeriod($category, $start, $currentEnd); | ||||
|             $date       = Navigation::periodShow($start, $range); | ||||
|  | ||||
|             // get the sum from $spentArray and $earnedArray: | ||||
|             $spent  = $this->getSumOfRange($start, $currentEnd, $spentArray); | ||||
|             $earned = $this->getSumOfRange($start, $currentEnd, $earnedArray); | ||||
|  | ||||
|             $date = Navigation::periodShow($start, $range); | ||||
|             $entries->push([clone $start, $date, $spent, $earned]); | ||||
|             $start = Navigation::addPeriod($start, $range, 0); | ||||
|         } | ||||
| @@ -84,14 +92,15 @@ class CategoryController extends Controller | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Show this month's category overview. | ||||
|      * | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param CRI $repository | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function frontpage(CategoryRepositoryInterface $repository) | ||||
|     public function frontpage(CRI $repository) | ||||
|     { | ||||
|  | ||||
|         $start = Session::get('start', Carbon::now()->startOfMonth()); | ||||
| @@ -107,32 +116,130 @@ class CategoryController extends Controller | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $array = $repository->getCategoriesAndExpensesCorrected($start, $end); | ||||
|         // sort by callback: | ||||
|         uasort( | ||||
|             $array, | ||||
|             function ($left, $right) { | ||||
|                 if ($left['sum'] == $right['sum']) { | ||||
|                     return 0; | ||||
|                 } | ||||
|         // get data for categories (and "no category"): | ||||
|         $set     = $repository->spentForAccountsPerMonth(new Collection, $start, $end); | ||||
|         $outside = $repository->sumSpentNoCategory(new Collection, $start, $end); | ||||
|  | ||||
|                 return ($left['sum'] < $right['sum']) ? -1 : 1; | ||||
|             } | ||||
|         ); | ||||
|         $set  = new Collection($array); | ||||
|         // this is a "fake" entry for the "no category" entry. | ||||
|         $entry = new stdClass(); | ||||
|         $entry->name = trans('firefly.no_category'); | ||||
|         $entry->spent = $outside; | ||||
|         $set->push($entry); | ||||
|  | ||||
|         $set = $set->sortBy('spent'); | ||||
|         $data = $this->generator->frontpage($set); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param Category                    $category | ||||
|      * @param                             $reportType | ||||
|      * @param Carbon                      $start | ||||
|      * @param Carbon                      $end | ||||
|      * @param Collection                  $accounts | ||||
|      * @param Collection                  $categories | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function multiYear($reportType, Carbon $start, Carbon $end, Collection $accounts, Collection $categories) | ||||
|     { | ||||
|         /** @var CRI $repository */ | ||||
|         $repository = app('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); | ||||
|  | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties(); | ||||
|         $cache->addProperty($reportType); | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty($accounts); | ||||
|         $cache->addProperty($categories); | ||||
|         $cache->addProperty('multiYearCategory'); | ||||
|  | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          *  category | ||||
|          *   year: | ||||
|          *    spent: x | ||||
|          *    earned: x | ||||
|          *   year | ||||
|          *    spent: x | ||||
|          *    earned: x | ||||
|          */ | ||||
|         $entries = new Collection; | ||||
|         // go by category, not by year. | ||||
|  | ||||
|         // given a set of categories and accounts, it should not be difficult to get | ||||
|         // the exact array of data we need. | ||||
|  | ||||
|         // then get the data for "no category". | ||||
|         $set = $repository->listMultiYear($categories, $accounts, $start, $end); | ||||
|  | ||||
|         /** @var Category $category */ | ||||
|         foreach ($categories as $category) { | ||||
|             $entry = ['name' => '', 'spent' => [], 'earned' => []]; | ||||
|  | ||||
|             $currentStart = clone $start; | ||||
|             while ($currentStart < $end) { | ||||
|                 // fix the date: | ||||
|                 $year       = $currentStart->year; | ||||
|                 $currentEnd = clone $currentStart; | ||||
|                 $currentEnd->endOfYear(); | ||||
|  | ||||
|  | ||||
|                 // get data: | ||||
|                 if (is_null($category->id)) { | ||||
|                     $name   = trans('firefly.noCategory'); | ||||
|                     $spent  = $repository->sumSpentNoCategory($accounts, $currentStart, $currentEnd); | ||||
|                     $earned = $repository->sumEarnedNoCategory($accounts, $currentStart, $currentEnd); | ||||
|                 } else { | ||||
|                     // get from set: | ||||
|                     $entrySpent  = $set->filter( | ||||
|                         function (Category $cat) use ($year, $category) { | ||||
|                             return ($cat->type == 'Withdrawal' && $cat->dateFormatted == $year && $cat->id == $category->id); | ||||
|                         } | ||||
|                     )->first(); | ||||
|                     $entryEarned = $set->filter( | ||||
|                         function (Category $cat) use ($year, $category) { | ||||
|                             return ($cat->type == 'Deposit' && $cat->dateFormatted == $year && $cat->id == $category->id); | ||||
|                         } | ||||
|                     )->first(); | ||||
|  | ||||
|                     $name   = $category->name; | ||||
|                     $spent  = !is_null($entrySpent) ? $entrySpent->sum : 0; | ||||
|                     $earned = !is_null($entryEarned) ? $entryEarned->sum : 0; | ||||
|                 } | ||||
|  | ||||
|                 // save to array: | ||||
|                 $entry['name']          = $name; | ||||
|                 $entry['spent'][$year]  = ($spent * -1); | ||||
|                 $entry['earned'][$year] = $earned; | ||||
|  | ||||
|                 // jump to next year. | ||||
|                 $currentStart = clone $currentEnd; | ||||
|                 $currentStart->addDay(); | ||||
|             } | ||||
|             $entries->push($entry); | ||||
|         } | ||||
|         // generate chart with data: | ||||
|         $data = $this->generator->multiYear($entries); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param SCRI     $repository | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function currentPeriod(CategoryRepositoryInterface $repository, Category $category) | ||||
|     public function currentPeriod(SCRI $repository, Category $category) | ||||
|     { | ||||
|         $start = clone Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end   = Session::get('end', Carbon::now()->endOfMonth()); | ||||
| @@ -143,16 +250,21 @@ class CategoryController extends Controller | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty($category->id); | ||||
|         $cache->addProperty('category'); | ||||
|         $cache->addProperty('currentPeriod'); | ||||
|         $cache->addProperty('current-period'); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|         $entries = new Collection; | ||||
|  | ||||
|         // get amount earned in period, grouped by day. | ||||
|         // get amount spent in period, grouped by day. | ||||
|         $spentArray  = $repository->spentPerDay($category, $start, $end); | ||||
|         $earnedArray = $repository->earnedPerDay($category, $start, $end); | ||||
|  | ||||
|         while ($start <= $end) { | ||||
|             $spent  = $repository->spentOnDaySumCorrected($category, $start); | ||||
|             $earned = $repository->earnedOnDaySumCorrected($category, $start); | ||||
|             $str    = $start->format('Y-m-d'); | ||||
|             $spent  = isset($spentArray[$str]) ? $spentArray[$str] : 0; | ||||
|             $earned = isset($earnedArray[$str]) ? $earnedArray[$str] : 0; | ||||
|             $date   = Navigation::periodShow($start, '1D'); | ||||
|             $entries->push([clone $start, $date, $spent, $earned]); | ||||
|             $start->addDay(); | ||||
| @@ -162,17 +274,17 @@ class CategoryController extends Controller | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param SCRI                        $repository | ||||
|      * @param Category                    $category | ||||
|      * | ||||
|      * @param                             $date | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function specificPeriod(CategoryRepositoryInterface $repository, Category $category, $date) | ||||
|     public function specificPeriod(SCRI $repository, Category $category, $date) | ||||
|     { | ||||
|         $carbon = new Carbon($date); | ||||
|         $range  = Preferences::get('viewRange', '1M')->data; | ||||
| @@ -192,12 +304,17 @@ class CategoryController extends Controller | ||||
|         } | ||||
|         $entries = new Collection; | ||||
|  | ||||
|         // get amount earned in period, grouped by day. | ||||
|         $spentArray  = $repository->spentPerDay($category, $start, $end); | ||||
|         $earnedArray = $repository->earnedPerDay($category, $start, $end); | ||||
|         // get amount spent in period, grouped by day. | ||||
|  | ||||
|         while ($start <= $end) { | ||||
|             $spent   = $repository->spentOnDaySumCorrected($category, $start); | ||||
|             $earned  = $repository->earnedOnDaySumCorrected($category, $start); | ||||
|             $theDate = Navigation::periodShow($start, '1D'); | ||||
|             $entries->push([clone $start, $theDate, $spent, $earned]); | ||||
|             $str    = $start->format('Y-m-d'); | ||||
|             $spent  = isset($spentArray[$str]) ? $spentArray[$str] : 0; | ||||
|             $earned = isset($earnedArray[$str]) ? $earnedArray[$str] : 0; | ||||
|             $date   = Navigation::periodShow($start, '1D'); | ||||
|             $entries->push([clone $start, $date, $spent, $earned]); | ||||
|             $start->addDay(); | ||||
|         } | ||||
|  | ||||
| @@ -210,120 +327,137 @@ class CategoryController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This chart will only show expenses. | ||||
|      * Returns a chart of what has been earned in this period in each category | ||||
|      * grouped by month. | ||||
|      * | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param                             $year | ||||
|      * @param bool                        $shared | ||||
|      * @param CRI                         $repository | ||||
|      * @param                             $reportType | ||||
|      * @param Carbon                      $start | ||||
|      * @param Carbon                      $end | ||||
|      * @param Collection                  $accounts | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function spentInYear(CategoryRepositoryInterface $repository, $year, $shared = false) | ||||
|     public function earnedInPeriod(CRI $repository, $reportType, Carbon $start, Carbon $end, Collection $accounts) | ||||
|     { | ||||
|         $start = new Carbon($year . '-01-01'); | ||||
|         $end   = new Carbon($year . '-12-31'); | ||||
|  | ||||
|         $cache = new CacheProperties; // chart properties for cache: | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty($reportType); | ||||
|         $cache->addProperty($accounts); | ||||
|         $cache->addProperty('category'); | ||||
|         $cache->addProperty('spent-in-year'); | ||||
|         $cache->addProperty('earned-in-period'); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $shared        = $shared == 'shared' ? true : false; | ||||
|         $allCategories = $repository->getCategories(); | ||||
|         $entries       = new Collection; | ||||
|         $categories    = $allCategories->filter( | ||||
|             function (Category $category) use ($repository, $start, $end, $shared) { | ||||
|                 $spent = $repository->balanceInPeriod($category, $start, $end, $shared); | ||||
|                 if ($spent < 0) { | ||||
|                     return $category; | ||||
|                 } | ||||
|  | ||||
|                 return null; | ||||
|         $set        = $repository->earnedForAccountsPerMonth($accounts, $start, $end); | ||||
|         $categories = $set->unique('id')->sortBy( | ||||
|             function (Category $category) { | ||||
|                 return $category->name; | ||||
|             } | ||||
|         ); | ||||
|         $entries    = new Collection; | ||||
|  | ||||
|         while ($start < $end) { | ||||
|             $month = clone $start; // month is the current end of the period | ||||
|             $month->endOfMonth(); | ||||
|             $row = [clone $start]; // make a row: | ||||
|  | ||||
|             foreach ($categories as $category) { // each budget, fill the row | ||||
|                 $spent = $repository->balanceInPeriod($category, $start, $month, $shared); | ||||
|                 if ($spent < 0) { | ||||
|                     $row[] = $spent * -1; | ||||
|         while ($start < $end) { // filter the set: | ||||
|             $row = [clone $start]; | ||||
|             // get possibly relevant entries from the big $set | ||||
|             $currentSet = $set->filter( | ||||
|                 function (Category $category) use ($start) { | ||||
|                     return $category->dateFormatted == $start->format("Y-m"); | ||||
|                 } | ||||
|             ); | ||||
|             // check for each category if its in the current set. | ||||
|             /** @var Category $category */ | ||||
|             foreach ($categories as $category) { | ||||
|                 // if its in there, use the value. | ||||
|                 $entry = $currentSet->filter( | ||||
|                     function (Category $cat) use ($category) { | ||||
|                         return ($cat->id == $category->id); | ||||
|                     } | ||||
|                 )->first(); | ||||
|                 if (!is_null($entry)) { | ||||
|                     $row[] = round($entry->earned, 2); | ||||
|                 } else { | ||||
|                     $row[] = 0; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             $entries->push($row); | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|         $data = $this->generator->spentInYear($categories, $entries); | ||||
|         $data = $this->generator->earnedInPeriod($categories, $entries); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
|         return $data; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This chart will only show income. | ||||
|      * Returns a chart of what has been spent in this period in each category | ||||
|      * grouped by month. | ||||
|      * | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param                             $year | ||||
|      * @param bool                        $shared | ||||
|      * @param CRI                         $repository | ||||
|      * @param                             $reportType | ||||
|      * @param Carbon                      $start | ||||
|      * @param Carbon                      $end | ||||
|      * @param Collection                  $accounts | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function earnedInYear(CategoryRepositoryInterface $repository, $year, $shared = false) | ||||
|     public function spentInPeriod(CRI $repository, $reportType, Carbon $start, Carbon $end, Collection $accounts) | ||||
|     { | ||||
|         $start = new Carbon($year . '-01-01'); | ||||
|         $end   = new Carbon($year . '-12-31'); | ||||
|  | ||||
|         $cache = new CacheProperties; // chart properties for cache: | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty($reportType); | ||||
|         $cache->addProperty($accounts); | ||||
|         $cache->addProperty('category'); | ||||
|         $cache->addProperty('earned-in-year'); | ||||
|         $cache->addProperty('spent-in-period'); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $shared        = $shared == 'shared' ? true : false; | ||||
|         $allCategories = $repository->getCategories(); | ||||
|         $allEntries    = new Collection; | ||||
|         $categories    = $allCategories->filter( | ||||
|             function (Category $category) use ($repository, $start, $end, $shared) { | ||||
|                 $spent = $repository->balanceInPeriod($category, $start, $end, $shared); | ||||
|                 if ($spent > 0) { | ||||
|                     return $category; | ||||
|                 } | ||||
|  | ||||
|                 return null; | ||||
|         $set        = $repository->spentForAccountsPerMonth($accounts, $start, $end); | ||||
|         $categories = $set->unique('id')->sortBy( | ||||
|             function (Category $category) { | ||||
|                 return $category->name; | ||||
|             } | ||||
|         ); | ||||
|         $entries    = new Collection; | ||||
|  | ||||
|         while ($start < $end) { | ||||
|             $month = clone $start; // month is the current end of the period | ||||
|             $month->endOfMonth(); | ||||
|             $row = [clone $start]; // make a row: | ||||
|  | ||||
|             foreach ($categories as $category) { // each budget, fill the row | ||||
|                 $spent = $repository->balanceInPeriod($category, $start, $month, $shared); | ||||
|                 if ($spent > 0) { | ||||
|                     $row[] = $spent; | ||||
|         while ($start < $end) { // filter the set: | ||||
|             $row = [clone $start]; | ||||
|             // get possibly relevant entries from the big $set | ||||
|             $currentSet = $set->filter( | ||||
|                 function (Category $category) use ($start) { | ||||
|                     return $category->dateFormatted == $start->format("Y-m"); | ||||
|                 } | ||||
|             ); | ||||
|             // check for each category if its in the current set. | ||||
|             /** @var Category $category */ | ||||
|             foreach ($categories as $category) { | ||||
|                 // if its in there, use the value. | ||||
|                 $entry = $currentSet->filter( | ||||
|                     function (Category $cat) use ($category) { | ||||
|                         return ($cat->id == $category->id); | ||||
|                     } | ||||
|                 )->first(); | ||||
|                 if (!is_null($entry)) { | ||||
|                     $row[] = round(($entry->spent * -1), 2); | ||||
|                 } else { | ||||
|                     $row[] = 0; | ||||
|                 } | ||||
|             } | ||||
|             $allEntries->push($row); | ||||
|  | ||||
|             $entries->push($row); | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|         $data = $this->generator->earnedInYear($categories, $allEntries); | ||||
|         $data = $this->generator->spentInPeriod($categories, $entries); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -9,7 +9,6 @@ use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Support\CacheProperties; | ||||
| use Illuminate\Support\Collection; | ||||
| use Response; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class ReportController | ||||
| @@ -37,40 +36,39 @@ class ReportController extends Controller | ||||
|      * Summarizes all income and expenses, per month, for a given year. | ||||
|      * | ||||
|      * @param ReportQueryInterface $query | ||||
|      * @param                      $year | ||||
|      * @param bool                 $shared | ||||
|      * @param                      $reportType | ||||
|      * @param Carbon               $start | ||||
|      * @param Carbon               $end | ||||
|      * @param Collection           $accounts | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function yearInOut(ReportQueryInterface $query, $year, $shared = false) | ||||
|     public function yearInOut(ReportQueryInterface $query, $reportType, Carbon $start, Carbon $end, Collection $accounts) | ||||
|     { | ||||
|         // get start and end of year | ||||
|         $start  = new Carbon($year . '-01-01'); | ||||
|         $end    = new Carbon($year . '-12-31'); | ||||
|         $shared = $shared == 'shared' ? true : false; | ||||
|  | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties; | ||||
|         $cache->addProperty('yearInOut'); | ||||
|         $cache->addProperty($year); | ||||
|         $cache->addProperty($shared); | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($reportType); | ||||
|         $cache->addProperty($accounts); | ||||
|         $cache->addProperty($end); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $entries = new Collection; | ||||
|         while ($start < $end) { | ||||
|             $month = clone $start; | ||||
|             $month->endOfMonth(); | ||||
|             // total income and total expenses: | ||||
|             $incomeSum  = $query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount_positive'); | ||||
|             $expenseSum = $query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount_positive'); | ||||
|         // spent per month, and earned per month. For a specific set of accounts | ||||
|         // grouped by month | ||||
|         $spentArray  = $query->spentPerMonth($accounts, $start, $end); | ||||
|         $earnedArray = $query->earnedPerMonth($accounts, $start, $end); | ||||
|  | ||||
|             $entries->push([clone $start, $incomeSum, $expenseSum]); | ||||
|             $start->addMonth(); | ||||
|         if ($start->diffInMonths($end) > 12) { | ||||
|             // data = method X | ||||
|             $data = $this->multiYearInOut($earnedArray, $spentArray, $start, $end); | ||||
|         } else { | ||||
|             // data = method Y | ||||
|             $data = $this->singleYearInOut($earnedArray, $spentArray, $start, $end); | ||||
|         } | ||||
|  | ||||
|         $data = $this->generator->yearInOut($entries); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
| @@ -81,56 +79,170 @@ class ReportController extends Controller | ||||
|      * Summarizes all income and expenses for a given year. Gives a total and an average. | ||||
|      * | ||||
|      * @param ReportQueryInterface $query | ||||
|      * @param                      $year | ||||
|      * @param bool                 $shared | ||||
|      * @param                      $reportType | ||||
|      * @param Carbon               $start | ||||
|      * @param Carbon               $end | ||||
|      * @param Collection           $accounts | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function yearInOutSummarized(ReportQueryInterface $query, $year, $shared = false) | ||||
|     public function yearInOutSummarized(ReportQueryInterface $query, $reportType, Carbon $start, Carbon $end, Collection $accounts) | ||||
|     { | ||||
|  | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties; | ||||
|         $cache->addProperty('yearInOutSummarized'); | ||||
|         $cache->addProperty($year); | ||||
|         $cache->addProperty($shared); | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty($reportType); | ||||
|         $cache->addProperty($accounts); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|         // spent per month, and earned per month. For a specific set of accounts | ||||
|         // grouped by month | ||||
|         $spentArray  = $query->spentPerMonth($accounts, $start, $end); | ||||
|         $earnedArray = $query->earnedPerMonth($accounts, $start, $end); | ||||
|         if ($start->diffInMonths($end) > 12) { | ||||
|             // per year | ||||
|             $data = $this->multiYearInOutSummarized($earnedArray, $spentArray, $start, $end); | ||||
|         } else { | ||||
|             // per month! | ||||
|             $data = $this->singleYearInOutSummarized($earnedArray, $spentArray, $start, $end); | ||||
|         } | ||||
|         $cache->store($data); | ||||
|  | ||||
|         $start   = new Carbon($year . '-01-01'); | ||||
|         $end     = new Carbon($year . '-12-31'); | ||||
|         $shared  = $shared == 'shared' ? true : false; | ||||
|         return Response::json($data); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array  $earned | ||||
|      * @param array  $spent | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function singleYearInOutSummarized(array $earned, array $spent, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $income  = '0'; | ||||
|         $expense = '0'; | ||||
|         $count   = 0; | ||||
|  | ||||
|         bcscale(2); | ||||
|  | ||||
|         while ($start < $end) { | ||||
|             $month = clone $start; | ||||
|             $month->endOfMonth(); | ||||
|             // total income and total expenses: | ||||
|             $currentIncome = $query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount_positive'); | ||||
|             $currentExpense = $query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount_positive'); | ||||
|              | ||||
|             Log::debug('Date ['.$month->format('M Y').']: income = ['.$income.' + '.$currentIncome.'], out = ['.$expense.' + '.$currentExpense.']'); | ||||
|              | ||||
|             $income  = bcadd($income, $currentIncome); | ||||
|             $expense = bcadd($expense, $currentExpense); | ||||
|              | ||||
|              | ||||
|              | ||||
|              | ||||
|              | ||||
|             $date           = $start->format('Y-m'); | ||||
|             $currentIncome  = isset($earned[$date]) ? $earned[$date] : 0; | ||||
|             $currentExpense = isset($spent[$date]) ? ($spent[$date] * -1) : 0; | ||||
|             $income         = bcadd($income, $currentIncome); | ||||
|             $expense        = bcadd($expense, $currentExpense); | ||||
|  | ||||
|             $count++; | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|  | ||||
|         $data = $this->generator->yearInOutSummarized($income, $expense, $count); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array  $earned | ||||
|      * @param array  $spent | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function multiYearInOutSummarized(array $earned, array $spent, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $income  = '0'; | ||||
|         $expense = '0'; | ||||
|         $count   = 0; | ||||
|         while ($start < $end) { | ||||
|  | ||||
|             $currentIncome  = $this->pluckFromArray($start->year, $earned); | ||||
|             $currentExpense = $this->pluckFromArray($start->year, $spent) * -1; | ||||
|             $income         = bcadd($income, $currentIncome); | ||||
|             $expense        = bcadd($expense, $currentExpense); | ||||
|  | ||||
|             $count++; | ||||
|             $start->addYear(); | ||||
|         } | ||||
|  | ||||
|         $data = $this->generator->multiYearInOutSummarized($income, $expense, $count); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array  $earned | ||||
|      * @param array  $spent | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function multiYearInOut(array $earned, array $spent, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $entries = new Collection; | ||||
|         while ($start < $end) { | ||||
|  | ||||
|             $incomeSum  = $this->pluckFromArray($start->year, $earned); | ||||
|             $expenseSum = $this->pluckFromArray($start->year, $spent) * -1; | ||||
|  | ||||
|             $entries->push([clone $start, $incomeSum, $expenseSum]); | ||||
|             $start->addYear(); | ||||
|         } | ||||
|  | ||||
|         $data = $this->generator->multiYearInOut($entries); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array  $earned | ||||
|      * @param array  $spent | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function singleYearInOut(array $earned, array $spent, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         // per month? simply use each month. | ||||
|  | ||||
|         $entries = new Collection; | ||||
|         while ($start < $end) { | ||||
|             // total income and total expenses: | ||||
|             $date       = $start->format('Y-m'); | ||||
|             $incomeSum  = isset($earned[$date]) ? $earned[$date] : 0; | ||||
|             $expenseSum = isset($spent[$date]) ? ($spent[$date] * -1) : 0; | ||||
|  | ||||
|             $entries->push([clone $start, $incomeSum, $expenseSum]); | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|  | ||||
|         $data = $this->generator->yearInOut($entries); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param int   $year | ||||
|      * @param array $set | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function pluckFromArray($year, array $set) | ||||
|     { | ||||
|         bcscale(2); | ||||
|         $sum = '0'; | ||||
|         foreach ($set as $date => $amount) { | ||||
|             if (substr($date, 0, 4) == $year) { | ||||
|                 $sum = bcadd($sum, $amount); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $sum; | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Auth; | ||||
| use Config; | ||||
| use Carbon\Carbon; | ||||
| use Illuminate\Foundation\Bus\DispatchesJobs; | ||||
| use Illuminate\Foundation\Validation\ValidatesRequests; | ||||
| use Illuminate\Routing\Controller as BaseController; | ||||
| @@ -34,14 +34,43 @@ abstract class Controller extends BaseController | ||||
|         View::share('hideTags', false); | ||||
|  | ||||
|         if (Auth::check()) { | ||||
|             $pref                    = Preferences::get('language', 'en'); | ||||
|             $pref                    = Preferences::get('language', env('DEFAULT_LANGUAGE', 'en_US')); | ||||
|             $lang                    = $pref->data; | ||||
|             $this->monthFormat       = Config::get('firefly.month.' . $lang); | ||||
|             $this->monthAndDayFormat = Config::get('firefly.monthAndDay.' . $lang); | ||||
|             $this->monthFormat       = trans('config.month'); | ||||
|             $this->monthAndDayFormat = trans('config.month_and_day'); | ||||
|  | ||||
|             View::share('monthFormat', $this->monthFormat); | ||||
|             View::share('monthAndDayFormat', $this->monthAndDayFormat); | ||||
|             View::share('language', $lang); | ||||
|             View::share('localeconv', localeconv()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Take the array as returned by SingleCategoryRepositoryInterface::spentPerDay and SingleCategoryRepositoryInterface::earnedByDay | ||||
|      * and sum up everything in the array in the given range. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param array  $array | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function getSumOfRange(Carbon $start, Carbon $end, array $array) | ||||
|     { | ||||
|         bcscale(2); | ||||
|         $sum          = '0'; | ||||
|         $currentStart = clone $start; // to not mess with the original one | ||||
|         $currentEnd   = clone $end; // to not mess with the original one | ||||
|  | ||||
|         while ($currentStart <= $currentEnd) { | ||||
|             $date = $currentStart->format('Y-m-d'); | ||||
|             if (isset($array[$date])) { | ||||
|                 $sum = bcadd($sum, $array[$date]); | ||||
|             } | ||||
|             $currentStart->addDay(); | ||||
|         } | ||||
|  | ||||
|         return $sum; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,74 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use FireflyIII\User; | ||||
|  | ||||
| /** | ||||
|  * Class WebhookController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| class CronController extends Controller | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Firefly doesn't have anything that should be in the a cron job, except maybe this one, and it's fairly exceptional. | ||||
|      * | ||||
|      * If you use SendGrid like I do, you can detect bounces and thereby check if users gave an invalid address. If they did, | ||||
|      * it's easy to block them and change their password. Optionally, you could notify yourself about it and send them a message. | ||||
|      * | ||||
|      * But thats something not supported right now. | ||||
|      */ | ||||
|     public function sendgrid() | ||||
|     { | ||||
|  | ||||
|         if (strlen(env('SENDGRID_USERNAME')) > 0 && strlen(env('SENDGRID_PASSWORD')) > 0) { | ||||
|  | ||||
|             $set = [ | ||||
|                 'blocks'   => 'https://api.sendgrid.com/api/blocks.get.json', | ||||
|                 'bounces'  => 'https://api.sendgrid.com/api/bounces.get.json', | ||||
|                 'invalids' => 'https://api.sendgrid.com/api/invalidemails.get.json', | ||||
|  | ||||
|             ]; | ||||
|             echo '<pre>'; | ||||
|             foreach ($set as $name => $URL) { | ||||
|  | ||||
|  | ||||
|                 $parameters = [ | ||||
|                     'api_user' => env('SENDGRID_USERNAME'), | ||||
|                     'api_key'  => env('SENDGRID_PASSWORD'), | ||||
|                     'date'     => 1, | ||||
|                     'days'     => 7 | ||||
|                 ]; | ||||
|                 $fullURL    = $URL . '?' . http_build_query($parameters); | ||||
|                 $data       = json_decode(file_get_contents($fullURL)); | ||||
|  | ||||
|                 /* | ||||
|                  * Loop the result, if any. | ||||
|                  */ | ||||
|                 if (is_array($data)) { | ||||
|                     echo 'Found ' . count($data) . ' entries in the SendGrid ' . $name . ' list.' . "\n"; | ||||
|                     foreach ($data as $entry) { | ||||
|                         $address = $entry->email; | ||||
|                         $user    = User::where('email', $address)->where('blocked', 0)->first(); | ||||
|                         if (!is_null($user)) { | ||||
|                             echo 'Found a user: ' . $address . ', who is now blocked.' . "\n"; | ||||
|                             $user->blocked      = 1; | ||||
|                             $user->blocked_code = 'bounced'; | ||||
|                             $user->password     = 'bounced'; | ||||
|                             $user->save(); | ||||
|                         } else { | ||||
|                             echo 'Found no user: ' . $address . ', did nothing.' . "\n"; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             echo 'Done!' . "\n"; | ||||
|         } else { | ||||
|             echo 'Please fill in SendGrid details.'; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -8,7 +8,7 @@ use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Csv\Data; | ||||
| use FireflyIII\Helpers\Csv\Importer; | ||||
| use FireflyIII\Helpers\Csv\WizardInterface; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI; | ||||
| use Illuminate\Http\Request; | ||||
| use Input; | ||||
| use Log; | ||||
| @@ -146,9 +146,11 @@ class CsvController extends Controller | ||||
|      * | ||||
|      * STEP ONE | ||||
|      * | ||||
|      * @param ARI $repository | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function index(AccountRepositoryInterface $repository) | ||||
|     public function index(ARI $repository) | ||||
|     { | ||||
|         $subTitle = trans('firefly.csv_import'); | ||||
|  | ||||
|   | ||||
| @@ -147,7 +147,7 @@ class CurrencyController extends Controller | ||||
|     public function index(CurrencyRepositoryInterface $repository) | ||||
|     { | ||||
|         $currencies      = $repository->get(); | ||||
|         $defaultCurrency = $repository->getCurrencyByPreference(Preferences::get('currencyPreference', 'EUR')); | ||||
|         $defaultCurrency = $repository->getCurrencyByPreference(Preferences::get('currencyPreference', env('DEFAULT_CURRENCY', 'EUR'))); | ||||
|  | ||||
|  | ||||
|         if (!Auth::user()->hasRole('owner')) { | ||||
|   | ||||
| @@ -1,15 +1,12 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Artisan; | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use Config; | ||||
| use FireflyIII\Models\Tag; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI; | ||||
| use Input; | ||||
| use Log; | ||||
| use Preferences; | ||||
| use Route; | ||||
| use Session; | ||||
| use Steam; | ||||
|  | ||||
| @@ -65,11 +62,11 @@ class HomeController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * @param ARI $repository | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View | ||||
|      */ | ||||
|     public function index(AccountRepositoryInterface $repository) | ||||
|     public function index(ARI $repository) | ||||
|     { | ||||
|         $types = Config::get('firefly.accountTypesByIdentifier.asset'); | ||||
|         $count = $repository->countAccounts($types); | ||||
| @@ -120,33 +117,4 @@ class HomeController extends Controller | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * @return \Illuminate\Http\RedirectResponse|string | ||||
|      */ | ||||
|     public function routes() | ||||
|     { | ||||
|         if (!Auth::user()->hasRole('owner')) { | ||||
|             Session::flash('warning', 'This page is broken.'); | ||||
|  | ||||
|             return redirect(route('index')); | ||||
|         } | ||||
|         Log::debug('Make log.'); | ||||
|  | ||||
|         // get all routes: | ||||
|         $routeCollection = Route::getRoutes(); | ||||
|         /** @var \Illuminate\Routing\Route $value */ | ||||
|         foreach ($routeCollection as $value) { | ||||
|             $name    = $value->getName(); | ||||
|             $methods = $value->getMethods(); | ||||
|             $isPost  = in_array('POST', $methods); | ||||
|             $index   = str_replace('.', '-', $name); | ||||
|  | ||||
|             if (strlen($name) > 0 && !$isPost) { | ||||
|                 echo "'" . $index . "' => '" . $name . "',<br />"; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return ' '; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -3,19 +3,15 @@ | ||||
| use Amount; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Helpers\Report\ReportQueryInterface; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI; | ||||
| use FireflyIII\Repositories\Bill\BillRepositoryInterface; | ||||
| use FireflyIII\Repositories\Category\CategoryRepositoryInterface; | ||||
| use FireflyIII\Repositories\Category\CategoryRepositoryInterface as CRI; | ||||
| use FireflyIII\Repositories\Journal\JournalRepositoryInterface; | ||||
| use FireflyIII\Repositories\Tag\TagRepositoryInterface; | ||||
| use FireflyIII\Support\CacheProperties; | ||||
| use Illuminate\Support\Collection; | ||||
| use Preferences; | ||||
| use Response; | ||||
| use Session; | ||||
| use Steam; | ||||
|  | ||||
| /** | ||||
|  * Class JsonController | ||||
| @@ -64,111 +60,52 @@ class JsonController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BillRepositoryInterface    $repository | ||||
|      * | ||||
|      * @param AccountRepositoryInterface $accountRepository | ||||
|      * @param BillRepositoryInterface $repository | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function boxBillsPaid(BillRepositoryInterface $repository, AccountRepositoryInterface $accountRepository) | ||||
|     public function boxBillsPaid(BillRepositoryInterface $repository) | ||||
|     { | ||||
|         $start  = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end    = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $amount = 0; | ||||
|         $start = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end   = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         bcscale(2); | ||||
|  | ||||
|         // works for json too! | ||||
|         $cache = new CacheProperties; | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty('box-bills-paid'); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         /* | ||||
|          * Since both this method and the chart use the exact same data, we can suffice | ||||
|          * with calling the one method in the bill repository that will get this amount. | ||||
|          */ | ||||
|         $amount        = $repository->getBillsPaidInRange($start, $end); // will be a negative amount. | ||||
|         $creditCardDue = $repository->getCreditCardBill($start, $end); | ||||
|         if ($creditCardDue >= 0) { | ||||
|             $amount = bcadd($amount, $creditCardDue); | ||||
|         } | ||||
|         $bills = $repository->getActiveBills(); // these two functions are the same as the chart | ||||
|         $amount = $amount * -1; | ||||
|  | ||||
|         /** @var Bill $bill */ | ||||
|         foreach ($bills as $bill) { | ||||
|             $amount = bcadd($amount, $repository->billPaymentsInRange($bill, $start, $end)); | ||||
|         } | ||||
|         unset($bill, $bills); | ||||
|  | ||||
|         $amount = $amount * -1; // make the amount positive again. | ||||
|  | ||||
|         $creditCards = $accountRepository->getCreditCards(); // Find credit card accounts and possibly unpaid credit card bills. | ||||
|         /** @var Account $creditCard */ | ||||
|         foreach ($creditCards as $creditCard) { | ||||
|             $balance = Steam::balance($creditCard, $end, true); // if the balance is not zero, the monthly payment is still underway. | ||||
|             if ($balance == 0) { | ||||
|                 // find a transfer TO the credit card which should account for | ||||
|                 // anything paid. If not, the CC is not yet used. | ||||
|                 $amount = bcadd($amount, $accountRepository->getTransfersInRange($creditCard, $start, $end)->sum('amount')); | ||||
|             } | ||||
|         } | ||||
|         $data = ['box' => 'bills-paid', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]; | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BillRepositoryInterface    $repository | ||||
|      * @param AccountRepositoryInterface $accountRepository | ||||
|      * @param BillRepositoryInterface $repository | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function boxBillsUnpaid(BillRepositoryInterface $repository, AccountRepositoryInterface $accountRepository) | ||||
|     public function boxBillsUnpaid(BillRepositoryInterface $repository) | ||||
|     { | ||||
|         $amount = 0; | ||||
|         $start  = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end    = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         bcscale(2); | ||||
|         $start         = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end           = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $amount        = $repository->getBillsUnpaidInRange($start, $end); // will be a positive amount. | ||||
|         $creditCardDue = $repository->getCreditCardBill($start, $end); | ||||
|  | ||||
|         // works for json too! | ||||
|         $cache = new CacheProperties; | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty('box-bills-unpaid'); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $bills  = $repository->getActiveBills(); | ||||
|         $unpaid = new Collection; // bills | ||||
|  | ||||
|         /** @var Bill $bill */ | ||||
|         foreach ($bills as $bill) { | ||||
|             $ranges = $repository->getRanges($bill, $start, $end); | ||||
|  | ||||
|             foreach ($ranges as $range) { | ||||
|                 $journals = $repository->getJournalsInRange($bill, $range['start'], $range['end']); | ||||
|                 if ($journals->count() == 0) { | ||||
|                     $unpaid->push([$bill, $range['start']]); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         unset($bill, $bills, $range, $ranges); | ||||
|  | ||||
|         $creditCards = $accountRepository->getCreditCards(); | ||||
|         foreach ($creditCards as $creditCard) { | ||||
|             $balance = Steam::balance($creditCard, $end, true); | ||||
|             $date    = new Carbon($creditCard->getMeta('ccMonthlyPaymentDate')); | ||||
|             if ($balance < 0) { | ||||
|                 // unpaid! create a fake bill that matches the amount. | ||||
|                 $description = $creditCard->name; | ||||
|                 $fakeAmount  = $balance * -1; | ||||
|                 $fakeBill    = $repository->createFakeBill($description, $date, $fakeAmount); | ||||
|                 $unpaid->push([$fakeBill, $date]); | ||||
|             } | ||||
|         } | ||||
|         /** @var Bill $entry */ | ||||
|         foreach ($unpaid as $entry) { | ||||
|             $current = bcdiv(bcadd($entry[0]->amount_max, $entry[0]->amount_min), 2); | ||||
|             $amount  = bcadd($amount, $current); | ||||
|         if ($creditCardDue < 0) { | ||||
|             // expenses are negative (bill not yet paid), | ||||
|             $creditCardDue = bcmul($creditCardDue, '-1'); | ||||
|             $amount        = bcadd($amount, $creditCardDue); | ||||
|         } | ||||
|  | ||||
|         $data = ['box' => 'bills-unpaid', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]; | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
|     } | ||||
| @@ -176,9 +113,11 @@ class JsonController extends Controller | ||||
|     /** | ||||
|      * @param ReportQueryInterface $reportQuery | ||||
|      * | ||||
|      * @param ARI                  $accountRepository | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function boxIn(ReportQueryInterface $reportQuery) | ||||
|     public function boxIn(ReportQueryInterface $reportQuery, ARI $accountRepository) | ||||
|     { | ||||
|         $start = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end   = Session::get('end', Carbon::now()->endOfMonth()); | ||||
| @@ -191,8 +130,8 @@ class JsonController extends Controller | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $amount = $reportQuery->incomeInPeriodCorrected($start, $end, true)->sum('amount'); | ||||
|         $accounts = $accountRepository->getAccounts(['Default account', 'Asset account', 'Cash account']); | ||||
|         $amount   = $reportQuery->income($accounts, $start, $end)->sum('journalAmount'); | ||||
|  | ||||
|         $data = ['box' => 'in', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]; | ||||
|         $cache->store($data); | ||||
| @@ -203,13 +142,16 @@ class JsonController extends Controller | ||||
|     /** | ||||
|      * @param ReportQueryInterface $reportQuery | ||||
|      * | ||||
|      * @param ARI                  $accountRepository | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function boxOut(ReportQueryInterface $reportQuery) | ||||
|     public function boxOut(ReportQueryInterface $reportQuery, ARI $accountRepository) | ||||
|     { | ||||
|         $start = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end   = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|  | ||||
|         $accounts = $accountRepository->getAccounts(['Default account', 'Asset account', 'Cash account']); | ||||
|  | ||||
|         // works for json too! | ||||
|         $cache = new CacheProperties; | ||||
| @@ -220,8 +162,7 @@ class JsonController extends Controller | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $amount = $reportQuery->expenseInPeriodCorrected($start, $end, true)->sum('amount'); | ||||
|         $amount = $amount * -1; | ||||
|         $amount = $reportQuery->expense($accounts, $start, $end)->sum('journalAmount'); | ||||
|  | ||||
|         $data = ['box' => 'out', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]; | ||||
|         $cache->store($data); | ||||
| @@ -232,18 +173,17 @@ class JsonController extends Controller | ||||
|     /** | ||||
|      * Returns a list of categories. | ||||
|      * | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param CRI $repository | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function categories(CategoryRepositoryInterface $repository) | ||||
|     public function categories(CRI $repository) | ||||
|     { | ||||
|         $list   = $repository->getCategories(); | ||||
|         $list   = $repository->listCategories(); | ||||
|         $return = []; | ||||
|         foreach ($list as $entry) { | ||||
|             $return[] = $entry->name; | ||||
|         } | ||||
|         sort($return); | ||||
|  | ||||
|         return Response::json($return); | ||||
|     } | ||||
| @@ -251,11 +191,11 @@ class JsonController extends Controller | ||||
|     /** | ||||
|      * Returns a JSON list of all beneficiaries. | ||||
|      * | ||||
|      * @param AccountRepositoryInterface $accountRepository | ||||
|      * @param ARI $accountRepository | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function expenseAccounts(AccountRepositoryInterface $accountRepository) | ||||
|     public function expenseAccounts(ARI $accountRepository) | ||||
|     { | ||||
|         $list   = $accountRepository->getAccounts(['Expense account', 'Beneficiary account']); | ||||
|         $return = []; | ||||
| @@ -268,11 +208,11 @@ class JsonController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AccountRepositoryInterface $accountRepository | ||||
|      * @param ARI $accountRepository | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function revenueAccounts(AccountRepositoryInterface $accountRepository) | ||||
|     public function revenueAccounts(ARI $accountRepository) | ||||
|     { | ||||
|         $list   = $accountRepository->getAccounts(['Revenue account']); | ||||
|         $return = []; | ||||
|   | ||||
| @@ -5,7 +5,7 @@ use Carbon\Carbon; | ||||
| use Config; | ||||
| use FireflyIII\Http\Requests\NewUserFormRequest; | ||||
| use FireflyIII\Models\AccountMeta; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI; | ||||
| use Preferences; | ||||
| use Session; | ||||
| use View; | ||||
| @@ -20,11 +20,11 @@ class NewUserController extends Controller | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * @param ARI $repository | ||||
|      * | ||||
|      * @@return \Illuminate\Http\RedirectResponse|\Illuminate\View\View | ||||
|      */ | ||||
|     public function index(AccountRepositoryInterface $repository) | ||||
|     public function index(ARI $repository) | ||||
|     { | ||||
|         View::share('title', 'Welcome to Firefly!'); | ||||
|         View::share('mainTitleIcon', 'fa-fire'); | ||||
| @@ -42,14 +42,13 @@ class NewUserController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param NewUserFormRequest         $request | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * @param NewUserFormRequest $request | ||||
|      * @param ARI                $repository | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function submit(NewUserFormRequest $request, AccountRepositoryInterface $repository) | ||||
|     public function submit(NewUserFormRequest $request, ARI $repository) | ||||
|     { | ||||
|  | ||||
|         // create normal asset account: | ||||
|         $assetAccount = [ | ||||
|             'name'                   => $request->get('bank_name'), | ||||
| @@ -61,7 +60,7 @@ class NewUserController extends Controller | ||||
|             'accountRole'            => 'defaultAsset', | ||||
|             'openingBalance'         => round($request->input('bank_balance'), 2), | ||||
|             'openingBalanceDate'     => new Carbon, | ||||
|             'openingBalanceCurrency' => intval($request->input('balance_currency_id')), | ||||
|             'openingBalanceCurrency' => intval($request->input('amount_currency_id_bank_balance')), | ||||
|         ]; | ||||
|  | ||||
|         $repository->store($assetAccount); | ||||
| @@ -78,7 +77,7 @@ class NewUserController extends Controller | ||||
|                 'accountRole'            => 'savingAsset', | ||||
|                 'openingBalance'         => round($request->input('savings_balance'), 2), | ||||
|                 'openingBalanceDate'     => new Carbon, | ||||
|                 'openingBalanceCurrency' => intval($request->input('balance_currency_id')), | ||||
|                 'openingBalanceCurrency' => intval($request->input('amount_currency_id_savings_balance')), | ||||
|             ]; | ||||
|             $repository->store($savingsAccount); | ||||
|         } | ||||
| @@ -96,7 +95,7 @@ class NewUserController extends Controller | ||||
|                 'accountRole'            => 'ccAsset', | ||||
|                 'openingBalance'         => null, | ||||
|                 'openingBalanceDate'     => null, | ||||
|                 'openingBalanceCurrency' => intval($request->input('balance_currency_id')), | ||||
|                 'openingBalanceCurrency' => intval($request->input('amount_currency_id_credit_card_limit')), | ||||
|             ]; | ||||
|             $creditCard    = $repository->store($creditAccount); | ||||
|  | ||||
|   | ||||
| @@ -6,7 +6,7 @@ use Config; | ||||
| use ExpandedForm; | ||||
| use FireflyIII\Http\Requests\PiggyBankFormRequest; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI; | ||||
| use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; | ||||
| use Illuminate\Support\Collection; | ||||
| use Input; | ||||
| @@ -18,7 +18,6 @@ use View; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.TooManyMethods) | ||||
|  * | ||||
|  * Class PiggyBankController | ||||
|  * | ||||
| @@ -40,12 +39,12 @@ class PiggyBankController extends Controller | ||||
|     /** | ||||
|      * Add money to piggy bank | ||||
|      * | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * @param PiggyBank                  $piggyBank | ||||
|      * @param ARI       $repository | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function add(AccountRepositoryInterface $repository, PiggyBank $piggyBank) | ||||
|     public function add(ARI $repository, PiggyBank $piggyBank) | ||||
|     { | ||||
|         bcscale(2); | ||||
|         $date          = Session::get('end', Carbon::now()->endOfMonth()); | ||||
| @@ -58,11 +57,11 @@ class PiggyBankController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * @param ARI $repository | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function create(AccountRepositoryInterface $repository) | ||||
|     public function create(ARI $repository) | ||||
|     { | ||||
|  | ||||
|         $periods      = Config::get('firefly.piggy_bank_periods'); | ||||
| @@ -116,12 +115,12 @@ class PiggyBankController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * @param PiggyBank                  $piggyBank | ||||
|      * @param ARI       $repository | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return View | ||||
|      */ | ||||
|     public function edit(AccountRepositoryInterface $repository, PiggyBank $piggyBank) | ||||
|     public function edit(ARI $repository, PiggyBank $piggyBank) | ||||
|     { | ||||
|  | ||||
|         $periods      = Config::get('firefly.piggy_bank_periods'); | ||||
| @@ -157,12 +156,12 @@ class PiggyBankController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AccountRepositoryInterface   $repository | ||||
|      * @param ARI   $repository | ||||
|      * @param PiggyBankRepositoryInterface $piggyRepository | ||||
|      * | ||||
|      * @return View | ||||
|      */ | ||||
|     public function index(AccountRepositoryInterface $repository, PiggyBankRepositoryInterface $piggyRepository) | ||||
|     public function index(ARI $repository, PiggyBankRepositoryInterface $piggyRepository) | ||||
|     { | ||||
|         /** @var Collection $piggyBanks */ | ||||
|         $piggyBanks = $piggyRepository->getPiggyBanks(); | ||||
| @@ -219,12 +218,12 @@ class PiggyBankController extends Controller | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBankRepositoryInterface $repository | ||||
|      * @param AccountRepositoryInterface   $accounts | ||||
|      * @param ARI                          $accounts | ||||
|      * @param PiggyBank                    $piggyBank | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function postAdd(PiggyBankRepositoryInterface $repository, AccountRepositoryInterface $accounts, PiggyBank $piggyBank) | ||||
|     public function postAdd(PiggyBankRepositoryInterface $repository, ARI $accounts, PiggyBank $piggyBank) | ||||
|     { | ||||
|         bcscale(2); | ||||
|         $amount        = round(Input::get('amount'), 2); | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Config; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI; | ||||
| use Input; | ||||
| use Preferences; | ||||
| use Session; | ||||
| @@ -26,21 +26,23 @@ class PreferencesController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * @param ARI $repository | ||||
|      * | ||||
|      * @return $this|\Illuminate\View\View | ||||
|      */ | ||||
|     public function index(AccountRepositoryInterface $repository) | ||||
|     public function index(ARI $repository) | ||||
|     { | ||||
|         $accounts          = $repository->getAccounts(['Default account', 'Asset account']); | ||||
|         $viewRangePref     = Preferences::get('viewRange', '1M'); | ||||
|         $viewRange         = $viewRangePref->data; | ||||
|         $frontPageAccounts = Preferences::get('frontPageAccounts', []); | ||||
|         $budgetMax         = Preferences::get('budgetMaximum', 1000); | ||||
|         $language          = Preferences::get('language', 'en')->data; | ||||
|         $language          = Preferences::get('language', env('DEFAULT_LANGUAGE', 'en_US'))->data; | ||||
|         $budgetMaximum     = $budgetMax->data; | ||||
|  | ||||
|         return view('preferences.index', compact('budgetMaximum', 'language', 'accounts', 'frontPageAccounts', 'viewRange')); | ||||
|         $showIncomplete = env('SHOW_INCOMPLETE_TRANSLATIONS', 'false') == 'true'; | ||||
|  | ||||
|         return view('preferences.index', compact('budgetMaximum', 'language', 'accounts', 'frontPageAccounts', 'viewRange', 'showIncomplete')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -70,7 +72,7 @@ class PreferencesController extends Controller | ||||
|  | ||||
|         // language: | ||||
|         $lang = Input::get('language'); | ||||
|         if (in_array($lang, array_keys(Config::get('firefly.lang')))) { | ||||
|         if (in_array($lang, array_keys(Config::get('firefly.languages')))) { | ||||
|             Preferences::set('language', $lang); | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -66,7 +66,7 @@ class ProfileController extends Controller | ||||
|         } | ||||
|  | ||||
|         // update the user with the new password. | ||||
|         Auth::user()->password = $request->get('new_password'); | ||||
|         Auth::user()->password = bcrypt($request->get('new_password')); | ||||
|         Auth::user()->save(); | ||||
|  | ||||
|         Session::flash('success', trans('firefly.password_changed')); | ||||
|   | ||||
| @@ -3,7 +3,8 @@ | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Helpers\Report\ReportHelperInterface; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI; | ||||
| use Illuminate\Support\Collection; | ||||
| use Session; | ||||
| use View; | ||||
|  | ||||
| @@ -34,118 +35,209 @@ class ReportController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * @param ARI $repository | ||||
|      * | ||||
|      * @return View | ||||
|      * @internal param ReportHelperInterface $helper | ||||
|      */ | ||||
|     public function index(AccountRepositoryInterface $repository) | ||||
|     public function index(ARI $repository) | ||||
|     { | ||||
|         $start  = Session::get('first'); | ||||
|         $months = $this->helper->listOfMonths($start); | ||||
|         $start        = Session::get('first'); | ||||
|         $months       = $this->helper->listOfMonths($start); | ||||
|         $startOfMonth = clone Session::get('start'); | ||||
|         $endOfMonth   = clone Session::get('start'); | ||||
|         $startOfYear  = clone Session::get('start'); | ||||
|         $endOfYear    = clone Session::get('start'); | ||||
|         $startOfMonth->startOfMonth(); | ||||
|         $endOfMonth->endOfMonth(); | ||||
|         $startOfYear->startOfYear(); | ||||
|         $endOfYear->endOfYear(); | ||||
|  | ||||
|         // does the user have shared accounts? | ||||
|         $accounts  = $repository->getAccounts(['Default account', 'Asset account']); | ||||
|         $hasShared = false; | ||||
|  | ||||
|         $accounts = $repository->getAccounts(['Default account', 'Asset account']); | ||||
|         // get id's for quick links: | ||||
|         $accountIds = []; | ||||
|         /** @var Account $account */ | ||||
|         foreach ($accounts as $account) { | ||||
|             if ($account->getMeta('accountRole') == 'sharedAsset') { | ||||
|                 $hasShared = true; | ||||
|             } | ||||
|             $accountIds [] = $account->id; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         return view('reports.index', compact('months', 'hasShared')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $year | ||||
|      * @param string $month | ||||
|      * | ||||
|      * @param bool   $shared | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function month($year = '2014', $month = '1', $shared = false) | ||||
|     { | ||||
|         $start            = new Carbon($year . '-' . $month . '-01'); | ||||
|         $subTitle         = trans('firefly.reportForMonth', ['month' => $start->formatLocalized($this->monthFormat)]); | ||||
|         $subTitleIcon     = 'fa-calendar'; | ||||
|         $end              = clone $start; | ||||
|         $incomeTopLength  = 8; | ||||
|         $expenseTopLength = 8; | ||||
|         if ($shared == 'shared') { | ||||
|             $shared   = true; | ||||
|             $subTitle = trans('firefly.reportForMonthShared', ['month' => $start->formatLocalized($this->monthFormat)]); | ||||
|         } | ||||
|  | ||||
|         $end->endOfMonth(); | ||||
|  | ||||
|         $accounts   = $this->helper->getAccountReport($start, $end, $shared); | ||||
|         $incomes    = $this->helper->getIncomeReport($start, $end, $shared); | ||||
|         $expenses   = $this->helper->getExpenseReport($start, $end, $shared); | ||||
|         $budgets    = $this->helper->getBudgetReport($start, $end, $shared); | ||||
|         $categories = $this->helper->getCategoryReport($start, $end, $shared); | ||||
|         $balance    = $this->helper->getBalanceReport($start, $end, $shared); | ||||
|         $bills      = $this->helper->getBillReport($start, $end); | ||||
|  | ||||
|         Session::flash('gaEventCategory', 'report'); | ||||
|         Session::flash('gaEventAction', 'month'); | ||||
|         Session::flash('gaEventLabel', $start->format('F Y')); | ||||
|         $accountList = join(',', $accountIds); | ||||
|  | ||||
|  | ||||
|         return view( | ||||
|             'reports.month', | ||||
|             compact( | ||||
|                 'start', 'shared', | ||||
|                 'subTitle', 'subTitleIcon', | ||||
|                 'accounts', | ||||
|                 'incomes', 'incomeTopLength', | ||||
|                 'expenses', 'expenseTopLength', | ||||
|                 'budgets', 'balance', | ||||
|                 'categories', | ||||
|                 'bills' | ||||
|             ) | ||||
|             'reports.index', compact( | ||||
|                                'months', 'accounts', 'start', 'accountList', | ||||
|                                'startOfMonth', 'endOfMonth', 'startOfYear', 'endOfYear' | ||||
|                            ) | ||||
|         ); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param      $year | ||||
|      * @param            $reportType | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @param bool $shared | ||||
|      * | ||||
|      * @return $this | ||||
|      * @return View | ||||
|      */ | ||||
|     public function year($year, $shared = false) | ||||
|     public function defaultYear($reportType, Carbon $start, Carbon $end, Collection $accounts) | ||||
|     { | ||||
|         $start            = new Carbon('01-01-' . $year); | ||||
|         $end              = clone $start; | ||||
|         $subTitle         = trans('firefly.reportForYear', ['year' => $year]); | ||||
|         $subTitleIcon     = 'fa-bar-chart'; | ||||
|         $incomeTopLength  = 8; | ||||
|         $expenseTopLength = 8; | ||||
|  | ||||
|         if ($shared == 'shared') { | ||||
|             $shared   = true; | ||||
|             $subTitle = trans('firefly.reportForYearShared', ['year' => $year]); | ||||
|         } | ||||
|         $end->endOfYear(); | ||||
|  | ||||
|         $accounts = $this->helper->getAccountReport($start, $end, $shared); | ||||
|         $incomes  = $this->helper->getIncomeReport($start, $end, $shared); | ||||
|         $expenses = $this->helper->getExpenseReport($start, $end, $shared); | ||||
|         $accountReport = $this->helper->getAccountReport($start, $end, $accounts); | ||||
|         $incomes       = $this->helper->getIncomeReport($start, $end, $accounts); | ||||
|         $expenses      = $this->helper->getExpenseReport($start, $end, $accounts); | ||||
|  | ||||
|         Session::flash('gaEventCategory', 'report'); | ||||
|         Session::flash('gaEventAction', 'year'); | ||||
|         Session::flash('gaEventLabel', $start->format('Y')); | ||||
|  | ||||
|         // and some id's, joined: | ||||
|         $accountIds = []; | ||||
|         /** @var Account $account */ | ||||
|         foreach ($accounts as $account) { | ||||
|             $accountIds[] = $account->id; | ||||
|         } | ||||
|         $accountIds = join(',', $accountIds); | ||||
|  | ||||
|         return view( | ||||
|             'reports.year', | ||||
|             compact('start', 'shared', 'accounts', 'incomes', 'expenses', 'subTitle', 'subTitleIcon', 'incomeTopLength', 'expenseTopLength') | ||||
|             'reports.default.year', | ||||
|             compact( | ||||
|                 'start', 'accountReport', 'incomes', 'reportType', 'accountIds', 'end', | ||||
|                 'expenses', 'incomeTopLength', 'expenseTopLength' | ||||
|             ) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param            $reportType | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return View | ||||
|      */ | ||||
|     public function defaultMonth($reportType, Carbon $start, Carbon $end, Collection $accounts) | ||||
|     { | ||||
|         $incomeTopLength  = 8; | ||||
|         $expenseTopLength = 8; | ||||
|  | ||||
|         // get report stuff! | ||||
|         $accountReport = $this->helper->getAccountReport($start, $end, $accounts); // done (+2) | ||||
|         $incomes       = $this->helper->getIncomeReport($start, $end, $accounts); // done (+3) | ||||
|         $expenses      = $this->helper->getExpenseReport($start, $end, $accounts); // done (+1) | ||||
|         $budgets       = $this->helper->getBudgetReport($start, $end, $accounts); // done (+5) | ||||
|         $categories    = $this->helper->getCategoryReport($start, $end, $accounts); // done (+1) (20) | ||||
|         $balance       = $this->helper->getBalanceReport($start, $end, $accounts); // +566 | ||||
|         $bills         = $this->helper->getBillReport($start, $end, $accounts); | ||||
|  | ||||
|         // and some id's, joined: | ||||
|         $accountIds = join(',', $accounts->pluck('id')->toArray()); | ||||
|  | ||||
|         // continue! | ||||
|         return view( | ||||
|             'reports.default.month', | ||||
|             compact( | ||||
|                 'start', 'end', 'reportType', | ||||
|                 'accountReport', | ||||
|                 'incomes', 'incomeTopLength', | ||||
|                 'expenses', 'expenseTopLength', | ||||
|                 'budgets', 'balance', | ||||
|                 'categories', | ||||
|                 'bills', | ||||
|                 'accountIds', 'reportType' | ||||
|             ) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $reportType | ||||
|      * @param $start | ||||
|      * @param $end | ||||
|      * @param $accounts | ||||
|      * | ||||
|      * @return View | ||||
|      */ | ||||
|     public function defaultMultiYear($reportType, $start, $end, $accounts) | ||||
|     { | ||||
|  | ||||
|         $incomeTopLength  = 8; | ||||
|         $expenseTopLength = 8; | ||||
|         // list of users stuff: | ||||
|         $budgets       = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface')->getActiveBudgets(); | ||||
|         $categories    = app('FireflyIII\Repositories\Category\CategoryRepositoryInterface')->listCategories(); | ||||
|         $accountReport = $this->helper->getAccountReport($start, $end, $accounts); // done (+2) | ||||
|         $incomes       = $this->helper->getIncomeReport($start, $end, $accounts); // done (+3) | ||||
|         $expenses      = $this->helper->getExpenseReport($start, $end, $accounts); // done (+1) | ||||
|  | ||||
|         // and some id's, joined: | ||||
|         $accountIds = []; | ||||
|         /** @var Account $account */ | ||||
|         foreach ($accounts as $account) { | ||||
|             $accountIds[] = $account->id; | ||||
|         } | ||||
|         $accountIds = join(',', $accountIds); | ||||
|  | ||||
|         return view( | ||||
|             'reports.default.multi-year', | ||||
|             compact( | ||||
|                 'budgets', 'accounts', 'categories', 'start', 'end', 'accountIds', 'reportType', 'accountReport', 'incomes', 'expenses', | ||||
|                 'incomeTopLength', 'expenseTopLength' | ||||
|             ) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param            $reportType | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return View | ||||
|      */ | ||||
|     public function report($reportType, Carbon $start, Carbon $end, Collection $accounts) | ||||
|     { | ||||
|         // throw an error if necessary. | ||||
|         if ($end < $start) { | ||||
|             return view('error')->with('message', 'End date cannot be before start date, silly!'); | ||||
|         } | ||||
|  | ||||
|         // lower threshold | ||||
|         if ($start < Session::get('first')) { | ||||
|             $start = Session::get('first'); | ||||
|         } | ||||
|  | ||||
|         switch ($reportType) { | ||||
|             default: | ||||
|             case 'default': | ||||
|  | ||||
|                 View::share( | ||||
|                     'subTitle', trans( | ||||
|                                   'firefly.report_default', | ||||
|                                   [ | ||||
|                                       'start' => $start->formatLocalized($this->monthFormat), | ||||
|                                       'end'   => $end->formatLocalized($this->monthFormat), | ||||
|                                   ] | ||||
|                               ) | ||||
|                 ); | ||||
|                 View::share('subTitleIcon', 'fa-calendar'); | ||||
|  | ||||
|                 // more than one year date difference means year report. | ||||
|                 if ($start->diffInMonths($end) > 12) { | ||||
|                     return $this->defaultMultiYear($reportType, $start, $end, $accounts); | ||||
|                 } | ||||
|                 // more than two months date difference means year report. | ||||
|                 if ($start->diffInMonths($end) > 1) { | ||||
|                     return $this->defaultYear($reportType, $start, $end, $accounts); | ||||
|                 } | ||||
|  | ||||
|                 return $this->defaultMonth($reportType, $start, $end, $accounts); | ||||
|         } | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -10,10 +10,13 @@ use FireflyIII\Events\JournalSaved; | ||||
| use FireflyIII\Helpers\Attachments\AttachmentHelperInterface; | ||||
| use FireflyIII\Http\Requests\JournalFormRequest; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\PiggyBankEvent; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI; | ||||
| use FireflyIII\Repositories\Journal\JournalRepositoryInterface; | ||||
| use Illuminate\Support\Collection; | ||||
| use Input; | ||||
| use Preferences; | ||||
| use Response; | ||||
| @@ -40,13 +43,14 @@ class TransactionController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * @param string                     $what | ||||
|      * @param ARI    $repository | ||||
|      * @param string $what | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function create(AccountRepositoryInterface $repository, $what = 'deposit') | ||||
|     public function create(ARI $repository, $what = TransactionType::DEPOSIT) | ||||
|     { | ||||
|         $what        = strtolower($what); | ||||
|         $maxFileSize = Steam::phpBytes(ini_get('upload_max_filesize')); | ||||
|         $maxPostSize = Steam::phpBytes(ini_get('post_max_size')); | ||||
|         $uploadSize  = min($maxFileSize, $maxPostSize); | ||||
| @@ -95,7 +99,7 @@ class TransactionController extends Controller | ||||
|      */ | ||||
|     public function delete(TransactionJournal $journal) | ||||
|     { | ||||
|         $what     = strtolower($journal->transactionType->type); | ||||
|         $what     = strtolower($journal->getTransactionType()); | ||||
|         $subTitle = trans('firefly.delete_' . $what, ['description' => $journal->description]); | ||||
|  | ||||
|         // put previous url in session | ||||
| @@ -129,15 +133,15 @@ class TransactionController extends Controller | ||||
|     /** | ||||
|      * Shows the view to edit a transaction. | ||||
|      * | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * @param TransactionJournal         $journal | ||||
|      * @param ARI                $repository | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function edit(AccountRepositoryInterface $repository, TransactionJournal $journal) | ||||
|     public function edit(ARI $repository, TransactionJournal $journal) | ||||
|     { | ||||
|         // cannot edit opening balance | ||||
|         if ($journal->transactionType->type == 'Opening balance') { | ||||
|         if ($journal->isOpeningBalance()) { | ||||
|             return view('error')->with('message', 'Cannot edit this transaction. Edit the account instead!'); | ||||
|         } | ||||
|  | ||||
| @@ -145,7 +149,7 @@ class TransactionController extends Controller | ||||
|         $maxFileSize = Steam::phpBytes(ini_get('upload_max_filesize')); | ||||
|         $maxPostSize = Steam::phpBytes(ini_get('post_max_size')); | ||||
|         $uploadSize  = min($maxFileSize, $maxPostSize); | ||||
|         $what        = strtolower($journal->transactionType->type); | ||||
|         $what        = strtolower($journal->getTransactionType()); | ||||
|         $accounts    = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account'])); | ||||
|         $budgets     = ExpandedForm::makeSelectList(Auth::user()->budgets()->get()); | ||||
|         $budgets[0]  = trans('form.noBudget'); | ||||
| @@ -159,11 +163,7 @@ class TransactionController extends Controller | ||||
|             'piggy_bank_id' => 0 | ||||
|         ]; | ||||
|         // get tags: | ||||
|         $tags = []; | ||||
|         foreach ($journal->tags as $tag) { | ||||
|             $tags[] = $tag->tag; | ||||
|         } | ||||
|         $preFilled['tags'] = join(',', $tags); | ||||
|         $preFilled['tags'] = join(',', $journal->tags->pluck('tag')->toArray()); | ||||
|  | ||||
|         $category = $journal->categories()->first(); | ||||
|         if (!is_null($category)) { | ||||
| @@ -181,7 +181,7 @@ class TransactionController extends Controller | ||||
|  | ||||
|         $preFilled['amount'] = $journal->amount_positive; | ||||
|  | ||||
|         if ($journal->transactionType->type == 'Withdrawal') { | ||||
|         if ($journal->isWithdrawal()) { | ||||
|             $preFilled['account_id']      = $journal->source_account->id; | ||||
|             $preFilled['expense_account'] = $journal->destination_account->name_for_editform; | ||||
|         } else { | ||||
| @@ -262,6 +262,15 @@ class TransactionController extends Controller | ||||
|      */ | ||||
|     public function show(JournalRepositoryInterface $repository, TransactionJournal $journal) | ||||
|     { | ||||
|  | ||||
|         /** @var Collection $set */ | ||||
|         $events = $journal->piggyBankEvents()->get(); | ||||
|         $events->each( | ||||
|             function (PiggyBankEvent $event) { | ||||
|                 $event->piggyBank = $event->piggyBank()->withTrashed()->first(); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         bcscale(2); | ||||
|         $journal->transactions->each( | ||||
|             function (Transaction $t) use ($journal, $repository) { | ||||
| @@ -269,16 +278,18 @@ class TransactionController extends Controller | ||||
|                 $t->after  = bcadd($t->before, $t->amount); | ||||
|             } | ||||
|         ); | ||||
|         $what     = strtolower($journal->transactionType->type); | ||||
|         $subTitle = trans('firefly.' . $journal->transactionType->type) . ' "' . e($journal->description) . '"'; | ||||
|         $what     = strtolower($journal->getTransactionType()); | ||||
|         $subTitle = trans('firefly.' . $journal->getTransactionType()) . ' "' . e($journal->description) . '"'; | ||||
|  | ||||
|         return view('transactions.show', compact('journal', 'subTitle', 'what')); | ||||
|         return view('transactions.show', compact('journal', 'events', 'subTitle', 'what')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param JournalFormRequest         $request | ||||
|      * @param JournalRepositoryInterface $repository | ||||
|      * | ||||
|      * @param AttachmentHelperInterface  $att | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function store(JournalFormRequest $request, JournalRepositoryInterface $repository, AttachmentHelperInterface $att) | ||||
| @@ -287,7 +298,7 @@ class TransactionController extends Controller | ||||
|         $journalData = $request->getJournalData(); | ||||
|  | ||||
|         // if not withdrawal, unset budgetid. | ||||
|         if ($journalData['what'] != 'withdrawal') { | ||||
|         if ($journalData['what'] != strtolower(TransactionType::WITHDRAWAL)) { | ||||
|             $journalData['budget_id'] = 0; | ||||
|         } | ||||
|  | ||||
| @@ -308,7 +319,7 @@ class TransactionController extends Controller | ||||
|         // rescan journal, UpdateJournalConnection | ||||
|         event(new JournalSaved($journal)); | ||||
|  | ||||
|         if ($journal->transactionType->type == 'Transfer' && intval($request->get('piggy_bank_id')) > 0) { | ||||
|         if ($journal->isTransfer() && intval($request->get('piggy_bank_id')) > 0) { | ||||
|             event(new JournalCreated($journal, intval($request->get('piggy_bank_id')))); | ||||
|         } | ||||
|  | ||||
| @@ -339,8 +350,7 @@ class TransactionController extends Controller | ||||
|     public function update(JournalFormRequest $request, JournalRepositoryInterface $repository, AttachmentHelperInterface $att, TransactionJournal $journal) | ||||
|     { | ||||
|  | ||||
|         // cannot edit opening balance | ||||
|         if ($journal->transactionType->type == 'Opening balance') { | ||||
|         if ($journal->isOpeningBalance()) { | ||||
|             return view('error')->with('message', 'Cannot edit this transaction. Edit the account instead!'); | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -1,9 +1,10 @@ | ||||
| <?php namespace FireflyIII\Http\Middleware; | ||||
|  | ||||
| use App; | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use Closure; | ||||
| use Config; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Contracts\Auth\Guard; | ||||
| use Illuminate\Http\Request; | ||||
| use Preferences; | ||||
| @@ -45,6 +46,7 @@ class Authenticate | ||||
|      */ | ||||
|     public function handle(Request $request, Closure $next) | ||||
|     { | ||||
|  | ||||
|         if ($this->auth->guest()) { | ||||
|             if ($request->ajax()) { | ||||
|                 return response('Unauthorized.', 401); | ||||
| @@ -52,17 +54,23 @@ class Authenticate | ||||
|                 return redirect()->guest('auth/login'); | ||||
|             } | ||||
|         } | ||||
|         /** @var User $user */ | ||||
|         $user = $this->auth->user(); | ||||
|         if ($user instanceof User && intval($user->blocked) == 1) { | ||||
|             Auth::logout(); | ||||
|  | ||||
|         if (intval($this->auth->user()->blocked) == 1) { | ||||
|             return redirect()->route('logout'); | ||||
|             return redirect()->route('index'); | ||||
|         } | ||||
|  | ||||
|         // if logged in, set user language: | ||||
|         $pref = Preferences::get('language', 'en'); | ||||
|         $pref = Preferences::get('language', env('DEFAULT_LANGUAGE', 'en_US')); | ||||
|         App::setLocale($pref->data); | ||||
|         Carbon::setLocale($pref->data); | ||||
|         Carbon::setLocale(substr($pref->data, 0, 2)); | ||||
|         $locale = explode(',', trans('config.locale')); | ||||
|         $locale = array_map('trim', $locale); | ||||
|  | ||||
|         setlocale(LC_TIME, Config::get('firefly.locales.' . $pref->data)); | ||||
|         setlocale(LC_TIME, $locale); | ||||
|         setlocale(LC_MONETARY, $locale); | ||||
|  | ||||
|         return $next($request); | ||||
|     } | ||||
|   | ||||
| @@ -42,7 +42,6 @@ class Range | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @param  \Closure                 $theNext | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|   | ||||
| @@ -41,18 +41,19 @@ class AccountFormRequest extends Request | ||||
|         } | ||||
|  | ||||
|         return [ | ||||
|             'id'                   => $idRule, | ||||
|             'name'                 => $nameRule, | ||||
|             'openingBalance'       => 'numeric', | ||||
|             'iban'                 => 'iban', | ||||
|             'virtualBalance'       => 'numeric', | ||||
|             'openingBalanceDate'   => 'date', | ||||
|             'accountRole'          => 'in:' . $accountRoles, | ||||
|             'active'               => 'boolean', | ||||
|             'ccType'               => 'in:' . $ccPaymentTypes, | ||||
|             'ccMonthlyPaymentDate' => 'date', | ||||
|             'balance_currency_id'  => 'exists:transaction_currencies,id', | ||||
|             'what'                 => 'in:' . $types | ||||
|             'id'                                => $idRule, | ||||
|             'name'                              => $nameRule, | ||||
|             'openingBalance'                    => 'numeric', | ||||
|             'iban'                              => 'iban', | ||||
|             'virtualBalance'                    => 'numeric', | ||||
|             'openingBalanceDate'                => 'date', | ||||
|             'accountRole'                       => 'in:' . $accountRoles, | ||||
|             'active'                            => 'boolean', | ||||
|             'ccType'                            => 'in:' . $ccPaymentTypes, | ||||
|             'ccMonthlyPaymentDate'              => 'date', | ||||
|             'amount_currency_id_openingBalance' => 'exists:transaction_currencies,id', | ||||
|             'amount_currency_id_virtualBalance' => 'exists:transaction_currencies,id', | ||||
|             'what'                              => 'in:' . $types | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -29,17 +29,18 @@ class BillFormRequest extends Request | ||||
|     public function getBillData() | ||||
|     { | ||||
|         return [ | ||||
|             'name'               => $this->get('name'), | ||||
|             'match'              => $this->get('match'), | ||||
|             'amount_min'         => round($this->get('amount_min'), 2), | ||||
|             'amount_currency_id' => round($this->get('amount_currency_id'), 2), | ||||
|             'amount_max'         => round($this->get('amount_max'), 2), | ||||
|             'date'               => new Carbon($this->get('date')), | ||||
|             'user'               => Auth::user()->id, | ||||
|             'repeat_freq'        => $this->get('repeat_freq'), | ||||
|             'skip'               => intval($this->get('skip')), | ||||
|             'automatch'          => intval($this->get('automatch')) === 1, | ||||
|             'active'             => intval($this->get('active')) === 1, | ||||
|             'name'                          => $this->get('name'), | ||||
|             'match'                         => $this->get('match'), | ||||
|             'amount_min'                    => round($this->get('amount_min'), 2), | ||||
|             'amount_currency_id_amount_min' => intval($this->get('amount_currency_id_amount_min')), | ||||
|             'amount_currency_id_amount_max' => intval($this->get('amount_currency_id_amount_max')), | ||||
|             'amount_max'                    => round($this->get('amount_max'), 2), | ||||
|             'date'                          => new Carbon($this->get('date')), | ||||
|             'user'                          => Auth::user()->id, | ||||
|             'repeat_freq'                   => $this->get('repeat_freq'), | ||||
|             'skip'                          => intval($this->get('skip')), | ||||
|             'automatch'                     => intval($this->get('automatch')) === 1, | ||||
|             'active'                        => intval($this->get('active')) === 1, | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
| @@ -56,16 +57,17 @@ class BillFormRequest extends Request | ||||
|         } | ||||
|  | ||||
|         $rules = [ | ||||
|             'name'               => $nameRule, | ||||
|             'match'              => $matchRule, | ||||
|             'amount_min'         => 'required|numeric|min:0.01', | ||||
|             'amount_max'         => 'required|numeric|min:0.01', | ||||
|             'amount_currency_id' => 'required|exists:transaction_currencies,id', | ||||
|             'date'               => 'required|date', | ||||
|             'repeat_freq'        => 'required|in:weekly,monthly,quarterly,half-year,yearly', | ||||
|             'skip'               => 'required|between:0,31', | ||||
|             'automatch'          => 'in:1', | ||||
|             'active'             => 'in:1', | ||||
|             'name'                          => $nameRule, | ||||
|             'match'                         => $matchRule, | ||||
|             'amount_min'                    => 'required|numeric|min:0.01', | ||||
|             'amount_max'                    => 'required|numeric|min:0.01', | ||||
|             'amount_currency_id_amount_min' => 'required|exists:transaction_currencies,id', | ||||
|             'amount_currency_id_amount_max' => 'required|exists:transaction_currencies,id', | ||||
|             'date'                          => 'required|date', | ||||
|             'repeat_freq'                   => 'required|in:weekly,monthly,quarterly,half-year,yearly', | ||||
|             'skip'                          => 'required|between:0,31', | ||||
|             'automatch'                     => 'in:1', | ||||
|             'active'                        => 'in:1', | ||||
|         ]; | ||||
|  | ||||
|         return $rules; | ||||
|   | ||||
| @@ -5,6 +5,7 @@ namespace FireflyIII\Http\Requests; | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use Exception; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use Input; | ||||
|  | ||||
| /** | ||||
| @@ -30,42 +31,41 @@ class JournalFormRequest extends Request | ||||
|     public function getJournalData() | ||||
|     { | ||||
|         return [ | ||||
|             'what'               => $this->get('what'), | ||||
|             'description'        => $this->get('description'), | ||||
|             'account_id'         => intval($this->get('account_id')), | ||||
|             'account_from_id'    => intval($this->get('account_from_id')), | ||||
|             'account_to_id'      => intval($this->get('account_to_id')), | ||||
|             'expense_account'    => $this->get('expense_account'), | ||||
|             'revenue_account'    => $this->get('revenue_account'), | ||||
|             'amount'             => round($this->get('amount'), 2), | ||||
|             'user'               => Auth::user()->id, | ||||
|             'amount_currency_id' => intval($this->get('amount_currency_id')), | ||||
|             'date'               => new Carbon($this->get('date')), | ||||
|             'budget_id'          => intval($this->get('budget_id')), | ||||
|             'category'           => $this->get('category'), | ||||
|             'tags'               => explode(',', $this->get('tags')), | ||||
|             'what'                      => $this->get('what'), | ||||
|             'description'               => $this->get('description'), | ||||
|             'account_id'                => intval($this->get('account_id')), | ||||
|             'account_from_id'           => intval($this->get('account_from_id')), | ||||
|             'account_to_id'             => intval($this->get('account_to_id')), | ||||
|             'expense_account'           => $this->get('expense_account'), | ||||
|             'revenue_account'           => $this->get('revenue_account'), | ||||
|             'amount'                    => round($this->get('amount'), 2), | ||||
|             'user'                      => Auth::user()->id, | ||||
|             'amount_currency_id_amount' => intval($this->get('amount_currency_id_amount')), | ||||
|             'date'                      => new Carbon($this->get('date')), | ||||
|             'budget_id'                 => intval($this->get('budget_id')), | ||||
|             'category'                  => $this->get('category'), | ||||
|             'tags'                      => explode(',', $this->get('tags')), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      * @throws Exception | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      */ | ||||
|     public function rules() | ||||
|     { | ||||
|         $what  = Input::get('what'); | ||||
|         $rules = [ | ||||
|             'description'        => 'required|min:1,max:255', | ||||
|             'what'               => 'required|in:withdrawal,deposit,transfer', | ||||
|             'amount'             => 'numeric|required|min:0.01', | ||||
|             'date'               => 'required|date', | ||||
|             'amount_currency_id' => 'required|exists:transaction_currencies,id', | ||||
|             'description'               => 'required|min:1,max:255', | ||||
|             'what'                      => 'required|in:withdrawal,deposit,transfer', | ||||
|             'amount'                    => 'numeric|required|min:0.01', | ||||
|             'date'                      => 'required|date', | ||||
|             'amount_currency_id_amount' => 'required|exists:transaction_currencies,id', | ||||
|  | ||||
|         ]; | ||||
|  | ||||
|         switch ($what) { | ||||
|             case 'withdrawal': | ||||
|             case strtolower(TransactionType::WITHDRAWAL): | ||||
|                 $rules['account_id']      = 'required|exists:accounts,id|belongsToUser:accounts'; | ||||
|                 $rules['expense_account'] = 'between:1,255'; | ||||
|                 $rules['category']        = 'between:1,255'; | ||||
| @@ -73,12 +73,12 @@ class JournalFormRequest extends Request | ||||
|                     $rules['budget_id'] = 'exists:budgets,id|belongsToUser:budgets'; | ||||
|                 } | ||||
|                 break; | ||||
|             case 'deposit': | ||||
|             case strtolower(TransactionType::DEPOSIT): | ||||
|                 $rules['category']        = 'between:1,255'; | ||||
|                 $rules['account_id']      = 'required|exists:accounts,id|belongsToUser:accounts'; | ||||
|                 $rules['revenue_account'] = 'between:1,255'; | ||||
|                 break; | ||||
|             case 'transfer': | ||||
|             case strtolower(TransactionType::TRANSFER): | ||||
|                 $rules['account_from_id'] = 'required|exists:accounts,id|belongsToUser:accounts|different:account_to_id'; | ||||
|                 $rules['account_to_id']   = 'required|exists:accounts,id|belongsToUser:accounts|different:account_from_id'; | ||||
|                 $rules['category']        = 'between:1,255'; | ||||
|   | ||||
| @@ -27,11 +27,13 @@ class NewUserFormRequest extends Request | ||||
|     public function rules() | ||||
|     { | ||||
|         return [ | ||||
|             'bank_name'           => 'required|between:1,200', | ||||
|             'bank_balance'        => 'required|numeric', | ||||
|             'savings_balance'     => 'numeric', | ||||
|             'credit_card_limit'   => 'numeric', | ||||
|             'balance_currency_id' => 'exists:transaction_currencies,id', | ||||
|             'bank_name'                            => 'required|between:1,200', | ||||
|             'bank_balance'                         => 'required|numeric', | ||||
|             'savings_balance'                      => 'numeric', | ||||
|             'credit_card_limit'                    => 'numeric', | ||||
|             'amount_currency_id_bank_balance'      => 'exists:transaction_currencies,id', | ||||
|             'amount_currency_id_savings_balance'   => 'exists:transaction_currencies,id', | ||||
|             'amount_currency_id_credit_card_limit' => 'exists:transaction_currencies,id', | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -36,13 +36,13 @@ class PiggyBankFormRequest extends Request | ||||
|  | ||||
|  | ||||
|         $rules = [ | ||||
|             'name'               => $nameRule, | ||||
|             'account_id'         => 'required|belongsToUser:accounts', | ||||
|             'targetamount'       => 'required|min:0.01', | ||||
|             'amount_currency_id' => 'exists:transaction_currencies,id', | ||||
|             'startdate'          => 'date', | ||||
|             'targetdate'         => $targetDateRule, | ||||
|             'order'              => 'integer|min:1', | ||||
|             'name'                            => $nameRule, | ||||
|             'account_id'                      => 'required|belongsToUser:accounts', | ||||
|             'targetamount'                    => 'required|min:0.01', | ||||
|             'amount_currency_id_targetamount' => 'exists:transaction_currencies,id', | ||||
|             'startdate'                       => 'date', | ||||
|             'targetdate'                      => $targetDateRule, | ||||
|             'order'                           => 'integer|min:1', | ||||
|  | ||||
|         ]; | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| <?php | ||||
| use Carbon\Carbon; | ||||
| use DaveJamesMiller\Breadcrumbs\Generator; | ||||
| use DaveJamesMiller\Breadcrumbs\Generator as BreadCrumbGenerator; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\Budget; | ||||
| @@ -16,7 +16,7 @@ use FireflyIII\Models\TransactionJournal; | ||||
|  */ | ||||
| Breadcrumbs::register( | ||||
|     'home', | ||||
|     function (Generator $breadcrumbs) { | ||||
|     function (BreadCrumbGenerator $breadcrumbs) { | ||||
|  | ||||
|         $breadcrumbs->push(trans('breadcrumbs.home'), route('index')); | ||||
|     } | ||||
| @@ -24,7 +24,7 @@ Breadcrumbs::register( | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'index', | ||||
|     function (Generator $breadcrumbs) { | ||||
|     function (BreadCrumbGenerator $breadcrumbs) { | ||||
|  | ||||
|         $breadcrumbs->push(trans('breadcrumbs.home'), route('index')); | ||||
|     } | ||||
| @@ -33,21 +33,21 @@ Breadcrumbs::register( | ||||
|  | ||||
| // accounts | ||||
| Breadcrumbs::register( | ||||
|     'accounts.index', function (Generator $breadcrumbs, $what) { | ||||
|     'accounts.index', function (BreadCrumbGenerator $breadcrumbs, $what) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push(trans('firefly.' . strtolower(e($what)) . '_accounts'), route('accounts.index', [$what])); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'accounts.create', function (Generator $breadcrumbs, $what) { | ||||
|     'accounts.create', function (BreadCrumbGenerator $breadcrumbs, $what) { | ||||
|     $breadcrumbs->parent('accounts.index', $what); | ||||
|     $breadcrumbs->push(trans('firefly.new_' . strtolower(e($what)) . '_account'), route('accounts.create', [$what])); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'accounts.show', function (Generator $breadcrumbs, Account $account) { | ||||
|     'accounts.show', function (BreadCrumbGenerator $breadcrumbs, Account $account) { | ||||
|  | ||||
|     $what = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type); | ||||
|  | ||||
| @@ -57,7 +57,7 @@ Breadcrumbs::register( | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'accounts.delete', function (Generator $breadcrumbs, Account $account) { | ||||
|     'accounts.delete', function (BreadCrumbGenerator $breadcrumbs, Account $account) { | ||||
|     $breadcrumbs->parent('accounts.show', $account); | ||||
|     $breadcrumbs->push(trans('firefly.delete_account', ['name' => e($account->name)]), route('accounts.delete', [$account->id])); | ||||
| } | ||||
| @@ -65,7 +65,7 @@ Breadcrumbs::register( | ||||
|  | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'accounts.edit', function (Generator $breadcrumbs, Account $account) { | ||||
|     'accounts.edit', function (BreadCrumbGenerator $breadcrumbs, Account $account) { | ||||
|     $breadcrumbs->parent('accounts.show', $account); | ||||
|     $what = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type); | ||||
|  | ||||
| @@ -75,40 +75,40 @@ Breadcrumbs::register( | ||||
|  | ||||
| // budgets. | ||||
| Breadcrumbs::register( | ||||
|     'budgets.index', function (Generator $breadcrumbs) { | ||||
|     'budgets.index', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push(trans('firefly.budgets'), route('budgets.index')); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'budgets.create', function (Generator $breadcrumbs) { | ||||
|     'budgets.create', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('budgets.index'); | ||||
|     $breadcrumbs->push(trans('firefly.create_new_budget'), route('budgets.create')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'budgets.edit', function (Generator $breadcrumbs, Budget $budget) { | ||||
|     'budgets.edit', function (BreadCrumbGenerator $breadcrumbs, Budget $budget) { | ||||
|     $breadcrumbs->parent('budgets.show', $budget); | ||||
|     $breadcrumbs->push(trans('firefly.edit_budget', ['name' => e($budget->name)]), route('budgets.edit', [$budget->id])); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'budgets.delete', function (Generator $breadcrumbs, Budget $budget) { | ||||
|     'budgets.delete', function (BreadCrumbGenerator $breadcrumbs, Budget $budget) { | ||||
|     $breadcrumbs->parent('budgets.show', $budget); | ||||
|     $breadcrumbs->push(trans('firefly.delete_budget', ['name' => e($budget->name)]), route('budgets.delete', [$budget->id])); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'budgets.noBudget', function (Generator $breadcrumbs, $subTitle) { | ||||
|     'budgets.noBudget', function (BreadCrumbGenerator $breadcrumbs, $subTitle) { | ||||
|     $breadcrumbs->parent('budgets.index'); | ||||
|     $breadcrumbs->push($subTitle, route('budgets.noBudget')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'budgets.show', function (Generator $breadcrumbs, Budget $budget, LimitRepetition $repetition = null) { | ||||
|     'budgets.show', function (BreadCrumbGenerator $breadcrumbs, Budget $budget, LimitRepetition $repetition = null) { | ||||
|     $breadcrumbs->parent('budgets.index'); | ||||
|     $breadcrumbs->push(e($budget->name), route('budgets.show', [$budget->id])); | ||||
|     if (!is_null($repetition) && !is_null($repetition->id)) { | ||||
| @@ -121,33 +121,33 @@ Breadcrumbs::register( | ||||
|  | ||||
| // categories | ||||
| Breadcrumbs::register( | ||||
|     'categories.index', function (Generator $breadcrumbs) { | ||||
|     'categories.index', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push(trans('firefly.categories'), route('categories.index')); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'categories.create', function (Generator $breadcrumbs) { | ||||
|     'categories.create', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('categories.index'); | ||||
|     $breadcrumbs->push(trans('firefly.new_category'), route('categories.create')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'categories.edit', function (Generator $breadcrumbs, Category $category) { | ||||
|     'categories.edit', function (BreadCrumbGenerator $breadcrumbs, Category $category) { | ||||
|     $breadcrumbs->parent('categories.show', $category); | ||||
|     $breadcrumbs->push(trans('firefly.edit_category', ['name' => e($category->name)]), route('categories.edit', [$category->id])); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'categories.delete', function (Generator $breadcrumbs, Category $category) { | ||||
|     'categories.delete', function (BreadCrumbGenerator $breadcrumbs, Category $category) { | ||||
|     $breadcrumbs->parent('categories.show', $category); | ||||
|     $breadcrumbs->push(trans('firefly.delete_category', ['name' => e($category->name)]), route('categories.delete', [$category->id])); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'categories.show', function (Generator $breadcrumbs, Category $category) { | ||||
|     'categories.show', function (BreadCrumbGenerator $breadcrumbs, Category $category) { | ||||
|     $breadcrumbs->parent('categories.index'); | ||||
|     $breadcrumbs->push(e($category->name), route('categories.show', [$category->id])); | ||||
|  | ||||
| @@ -155,7 +155,7 @@ Breadcrumbs::register( | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'categories.show.date', function (Generator $breadcrumbs, Category $category, Carbon $date) { | ||||
|     'categories.show.date', function (BreadCrumbGenerator $breadcrumbs, Category $category, Carbon $date) { | ||||
|  | ||||
|     // get current period preference. | ||||
|     $range = Preferences::get('viewRange', '1M')->data; | ||||
| @@ -168,7 +168,7 @@ Breadcrumbs::register( | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'categories.noCategory', function (Generator $breadcrumbs, $subTitle) { | ||||
|     'categories.noCategory', function (BreadCrumbGenerator $breadcrumbs, $subTitle) { | ||||
|     $breadcrumbs->parent('categories.index'); | ||||
|     $breadcrumbs->push($subTitle, route('categories.noCategory')); | ||||
| } | ||||
| @@ -176,35 +176,35 @@ Breadcrumbs::register( | ||||
|  | ||||
| // CSV: | ||||
| Breadcrumbs::register( | ||||
|     'csv.index', function (Generator $breadcrumbs) { | ||||
|     'csv.index', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push(trans('firefly.csv_index_title'), route('csv.index')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'csv.column-roles', function (Generator $breadcrumbs) { | ||||
|     'csv.column-roles', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('csv.index'); | ||||
|     $breadcrumbs->push(trans('firefly.csv_define_column_roles'), route('csv.column-roles')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'csv.map', function (Generator $breadcrumbs) { | ||||
|     'csv.map', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('csv.index'); | ||||
|     $breadcrumbs->push(trans('firefly.csv_map_values'), route('csv.map')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'csv.download-config-page', function (Generator $breadcrumbs) { | ||||
|     'csv.download-config-page', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('csv.index'); | ||||
|     $breadcrumbs->push(trans('firefly.csv_download_config'), route('csv.download-config-page')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'csv.process', function (Generator $breadcrumbs) { | ||||
|     'csv.process', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('csv.index'); | ||||
|     $breadcrumbs->push(trans('firefly.csv_process_title'), route('csv.process')); | ||||
| } | ||||
| @@ -213,27 +213,27 @@ Breadcrumbs::register( | ||||
|  | ||||
| // currencies. | ||||
| Breadcrumbs::register( | ||||
|     'currency.index', function (Generator $breadcrumbs) { | ||||
|     'currency.index', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push(trans('firefly.currencies'), route('currency.index')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'currency.create', function (Generator $breadcrumbs) { | ||||
|     'currency.create', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('currency.index'); | ||||
|     $breadcrumbs->push(trans('firefly.create_currency'), route('currency.create')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'currency.edit', function (Generator $breadcrumbs, TransactionCurrency $currency) { | ||||
|     'currency.edit', function (BreadCrumbGenerator $breadcrumbs, TransactionCurrency $currency) { | ||||
|     $breadcrumbs->parent('currency.index'); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.edit_currency', ['name' => e($currency->name)]), route('currency.edit', [$currency->id])); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'currency.delete', function (Generator $breadcrumbs, TransactionCurrency $currency) { | ||||
|     'currency.delete', function (BreadCrumbGenerator $breadcrumbs, TransactionCurrency $currency) { | ||||
|     $breadcrumbs->parent('currency.index'); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.delete_currency', ['name' => e($currency->name)]), route('currency.delete', [$currency->id])); | ||||
| } | ||||
| @@ -242,33 +242,33 @@ Breadcrumbs::register( | ||||
|  | ||||
| // piggy banks | ||||
| Breadcrumbs::register( | ||||
|     'piggy-banks.index', function (Generator $breadcrumbs) { | ||||
|     'piggy-banks.index', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push(trans('firefly.piggyBanks'), route('piggy-banks.index')); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'piggy-banks.create', function (Generator $breadcrumbs) { | ||||
|     'piggy-banks.create', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('piggy-banks.index'); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.newPiggyBank'), route('piggy-banks.create')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'piggy-banks.edit', function (Generator $breadcrumbs, PiggyBank $piggyBank) { | ||||
|     'piggy-banks.edit', function (BreadCrumbGenerator $breadcrumbs, PiggyBank $piggyBank) { | ||||
|     $breadcrumbs->parent('piggy-banks.show', $piggyBank); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.edit_piggyBank', ['name' => e($piggyBank->name)]), route('piggy-banks.edit', [$piggyBank->id])); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'piggy-banks.delete', function (Generator $breadcrumbs, PiggyBank $piggyBank) { | ||||
|     'piggy-banks.delete', function (BreadCrumbGenerator $breadcrumbs, PiggyBank $piggyBank) { | ||||
|     $breadcrumbs->parent('piggy-banks.show', $piggyBank); | ||||
|     $breadcrumbs->push(trans('firefly.delete_piggy_bank', ['name' => e($piggyBank->name)]), route('piggy-banks.delete', [$piggyBank->id])); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'piggy-banks.show', function (Generator $breadcrumbs, PiggyBank $piggyBank) { | ||||
|     'piggy-banks.show', function (BreadCrumbGenerator $breadcrumbs, PiggyBank $piggyBank) { | ||||
|     $breadcrumbs->parent('piggy-banks.index'); | ||||
|     $breadcrumbs->push(e($piggyBank->name), route('piggy-banks.show', [$piggyBank->id])); | ||||
|  | ||||
| @@ -277,7 +277,7 @@ Breadcrumbs::register( | ||||
|  | ||||
| // preferences | ||||
| Breadcrumbs::register( | ||||
|     'preferences', function (Generator $breadcrumbs) { | ||||
|     'preferences', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.preferences'), route('preferences')); | ||||
|  | ||||
| @@ -286,21 +286,21 @@ Breadcrumbs::register( | ||||
|  | ||||
| // profile | ||||
| Breadcrumbs::register( | ||||
|     'profile', function (Generator $breadcrumbs) { | ||||
|     'profile', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.profile'), route('profile')); | ||||
|  | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'profile.change-password', function (Generator $breadcrumbs) { | ||||
|     'profile.change-password', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('profile'); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.changePassword'), route('profile.change-password')); | ||||
|  | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'profile.delete-account', function (Generator $breadcrumbs) { | ||||
|     'profile.delete-account', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('profile'); | ||||
|     $breadcrumbs->push(trans('firefly.delete_account'), route('profile.delete-account')); | ||||
|  | ||||
| @@ -309,33 +309,33 @@ Breadcrumbs::register( | ||||
|  | ||||
| // bills | ||||
| Breadcrumbs::register( | ||||
|     'bills.index', function (Generator $breadcrumbs) { | ||||
|     'bills.index', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.bills'), route('bills.index')); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'bills.create', function (Generator $breadcrumbs) { | ||||
|     'bills.create', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('bills.index'); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.newBill'), route('bills.create')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'bills.edit', function (Generator $breadcrumbs, Bill $bill) { | ||||
|     'bills.edit', function (BreadCrumbGenerator $breadcrumbs, Bill $bill) { | ||||
|     $breadcrumbs->parent('bills.show', $bill); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.edit_bill', ['name' => e($bill->name)]), route('bills.edit', [$bill->id])); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'bills.delete', function (Generator $breadcrumbs, Bill $bill) { | ||||
|     'bills.delete', function (BreadCrumbGenerator $breadcrumbs, Bill $bill) { | ||||
|     $breadcrumbs->parent('bills.show', $bill); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.delete_bill', ['name' => e($bill->name)]), route('bills.delete', [$bill->id])); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'bills.show', function (Generator $breadcrumbs, Bill $bill) { | ||||
|     'bills.show', function (BreadCrumbGenerator $breadcrumbs, Bill $bill) { | ||||
|     $breadcrumbs->parent('bills.index'); | ||||
|     $breadcrumbs->push(e($bill->name), route('bills.show', [$bill->id])); | ||||
|  | ||||
| @@ -344,43 +344,26 @@ Breadcrumbs::register( | ||||
|  | ||||
| // reports | ||||
| Breadcrumbs::register( | ||||
|     'reports.index', function (Generator $breadcrumbs) { | ||||
|     'reports.index', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.reports'), route('reports.index')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'reports.year', function (Generator $breadcrumbs, Carbon $date, $shared) { | ||||
|     'reports.report', function (BreadCrumbGenerator $breadcrumbs, Carbon $start, Carbon $end, $reportType, $accountIds) { | ||||
|     $breadcrumbs->parent('reports.index'); | ||||
|     if ($shared) { | ||||
|         $title = trans('breadcrumbs.yearly_report_shared', ['date' => $date->year]); | ||||
|     } else { | ||||
|         $title = trans('breadcrumbs.yearly_report', ['date' => $date->year]); | ||||
|     } | ||||
|     $breadcrumbs->push($title, route('reports.year', [$date->year])); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'reports.month', function (Generator $breadcrumbs, Carbon $date, $shared) { | ||||
|     $breadcrumbs->parent('reports.year', $date, $shared); | ||||
|     $language = Preferences::get('language', 'en')->data; | ||||
|     $format   = Config::get('firefly.month.' . $language); | ||||
|     $monthFormat = trans('config.month_and_day'); | ||||
|     $title       = trans('firefly.report_' . $reportType, ['start' => $start->formatLocalized($monthFormat), 'end' => $end->formatLocalized($monthFormat)]); | ||||
|  | ||||
|     if ($shared) { | ||||
|         $title = trans('breadcrumbs.monthly_report_shared', ['date' => $date->formatLocalized($format)]); | ||||
|     } else { | ||||
|         $title = trans('breadcrumbs.monthly_report', ['date' => $date->formatLocalized($format)]); | ||||
|     } | ||||
|  | ||||
|     $breadcrumbs->push($title, route('reports.month', [$date->year, $date->month])); | ||||
|     $breadcrumbs->push($title, route('reports.report', [$reportType, $start->format('Ymd'), $end->format('Ymd'), $accountIds])); | ||||
| } | ||||
| ); | ||||
|  | ||||
| // search | ||||
| Breadcrumbs::register( | ||||
|     'search', function (Generator $breadcrumbs, $query) { | ||||
|     'search', function (BreadCrumbGenerator $breadcrumbs, $query) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.searchResult', ['query' => e($query)]), route('search')); | ||||
| } | ||||
| @@ -388,35 +371,35 @@ Breadcrumbs::register( | ||||
|  | ||||
| // transactions | ||||
| Breadcrumbs::register( | ||||
|     'transactions.index', function (Generator $breadcrumbs, $what) { | ||||
|     'transactions.index', function (BreadCrumbGenerator $breadcrumbs, $what) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.' . $what . '_list'), route('transactions.index', [$what])); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'transactions.create', function (Generator $breadcrumbs, $what) { | ||||
|     'transactions.create', function (BreadCrumbGenerator $breadcrumbs, $what) { | ||||
|     $breadcrumbs->parent('transactions.index', $what); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.create_' . e($what)), route('transactions.create', [$what])); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'transactions.edit', function (Generator $breadcrumbs, TransactionJournal $journal) { | ||||
|     'transactions.edit', function (BreadCrumbGenerator $breadcrumbs, TransactionJournal $journal) { | ||||
|     $breadcrumbs->parent('transactions.show', $journal); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.edit_journal', ['description' => $journal->description]), route('transactions.edit', [$journal->id])); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'transactions.delete', function (Generator $breadcrumbs, TransactionJournal $journal) { | ||||
|     'transactions.delete', function (BreadCrumbGenerator $breadcrumbs, TransactionJournal $journal) { | ||||
|     $breadcrumbs->parent('transactions.show', $journal); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.delete_journal', ['description' => e($journal->description)]), route('transactions.delete', [$journal->id])); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'transactions.show', function (Generator $breadcrumbs, TransactionJournal $journal) { | ||||
|     'transactions.show', function (BreadCrumbGenerator $breadcrumbs, TransactionJournal $journal) { | ||||
|  | ||||
|     $breadcrumbs->parent('transactions.index', strtolower($journal->transactionType->type)); | ||||
|     $breadcrumbs->parent('transactions.index', strtolower($journal->getTransactionType())); | ||||
|     $breadcrumbs->push($journal->description, route('transactions.show', [$journal->id])); | ||||
|  | ||||
| } | ||||
| @@ -424,28 +407,28 @@ Breadcrumbs::register( | ||||
|  | ||||
| // tags | ||||
| Breadcrumbs::register( | ||||
|     'tags.index', function (Generator $breadcrumbs) { | ||||
|     'tags.index', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.tags'), route('tags.index')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'tags.create', function (Generator $breadcrumbs) { | ||||
|     'tags.create', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('tags.index'); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.createTag'), route('tags.create')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'tags.edit', function (Generator $breadcrumbs, Tag $tag) { | ||||
|     'tags.edit', function (BreadCrumbGenerator $breadcrumbs, Tag $tag) { | ||||
|     $breadcrumbs->parent('tags.show', $tag); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.edit_tag', ['tag' => e($tag->tag)]), route('tags.edit', [$tag->id])); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'tags.delete', function (Generator $breadcrumbs, Tag $tag) { | ||||
|     'tags.delete', function (BreadCrumbGenerator $breadcrumbs, Tag $tag) { | ||||
|     $breadcrumbs->parent('tags.show', $tag); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.delete_tag', ['tag' => e($tag->tag)]), route('tags.delete', [$tag->id])); | ||||
| } | ||||
| @@ -453,7 +436,7 @@ Breadcrumbs::register( | ||||
|  | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'tags.show', function (Generator $breadcrumbs, Tag $tag) { | ||||
|     'tags.show', function (BreadCrumbGenerator $breadcrumbs, Tag $tag) { | ||||
|     $breadcrumbs->parent('tags.index'); | ||||
|     $breadcrumbs->push(e($tag->tag), route('tags.show', [$tag->id])); | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| <?php | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Attachment; | ||||
| use FireflyIII\Models\Bill; | ||||
| @@ -29,6 +30,111 @@ Route::bind( | ||||
|         throw new NotFoundHttpException; | ||||
|     } | ||||
| ); | ||||
| // accounts | ||||
| Route::bind( | ||||
|     'accountList', | ||||
|     function ($value) { | ||||
|         if (Auth::check()) { | ||||
|             $ids = explode(',', $value); | ||||
|             /** @var \Illuminate\Support\Collection $object */ | ||||
|             $object = Account::leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id') | ||||
|                              ->where('account_types.editable', 1) | ||||
|                              ->whereIn('accounts.id', $ids) | ||||
|                              ->where('user_id', Auth::user()->id) | ||||
|                              ->get(['accounts.*']); | ||||
|             if ($object->count() > 0) { | ||||
|                 return $object; | ||||
|             } | ||||
|         } | ||||
|         throw new NotFoundHttpException; | ||||
|     } | ||||
| ); | ||||
| // budget list | ||||
| Route::bind( | ||||
|     'budgetList', | ||||
|     function ($value) { | ||||
|         if (Auth::check()) { | ||||
|             $ids = explode(',', $value); | ||||
|             /** @var \Illuminate\Support\Collection $object */ | ||||
|             $object = Budget::where('active', 1) | ||||
|                             ->whereIn('id', $ids) | ||||
|                             ->where('user_id', Auth::user()->id) | ||||
|                             ->get(); | ||||
|  | ||||
|             // add empty budget if applicable. | ||||
|             if (in_array('0', $ids)) { | ||||
|                 $object->push(new Budget); | ||||
|             } | ||||
|  | ||||
|             if ($object->count() > 0) { | ||||
|                 return $object; | ||||
|             } | ||||
|         } | ||||
|         throw new NotFoundHttpException; | ||||
|     } | ||||
| ); | ||||
|  | ||||
| // category list | ||||
| Route::bind( | ||||
|     'categoryList', | ||||
|     function ($value) { | ||||
|         if (Auth::check()) { | ||||
|             $ids = explode(',', $value); | ||||
|             /** @var \Illuminate\Support\Collection $object */ | ||||
|             $object = Category::whereIn('id', $ids) | ||||
|                               ->where('user_id', Auth::user()->id) | ||||
|                               ->get(); | ||||
|  | ||||
|             // add empty budget if applicable. | ||||
|             if (in_array('0', $ids)) { | ||||
|                 $object->push(new Category); | ||||
|             } | ||||
|  | ||||
|             if ($object->count() > 0) { | ||||
|                 return $object; | ||||
|             } | ||||
|         } | ||||
|         throw new NotFoundHttpException; | ||||
|     } | ||||
| ); | ||||
|  | ||||
| // Date | ||||
| Route::bind( | ||||
|     'start_date', | ||||
|     function ($value) { | ||||
|         if (Auth::check()) { | ||||
|  | ||||
|             try { | ||||
|                 $date = new Carbon($value); | ||||
|             } catch (Exception $e) { | ||||
|                 Log::error('Could not parse date "' . $value . '" for user #' . Auth::user()->id); | ||||
|                 throw new NotFoundHttpException; | ||||
|             } | ||||
|  | ||||
|             return $date; | ||||
|         } | ||||
|         throw new NotFoundHttpException; | ||||
|     } | ||||
| ); | ||||
|  | ||||
| // Date | ||||
| Route::bind( | ||||
|     'end_date', | ||||
|     function ($value) { | ||||
|         if (Auth::check()) { | ||||
|  | ||||
|             try { | ||||
|                 $date = new Carbon($value); | ||||
|             } catch (Exception $e) { | ||||
|                 Log::error('Could not parse date "' . $value . '" for user #' . Auth::user()->id); | ||||
|                 throw new NotFoundHttpException; | ||||
|             } | ||||
|  | ||||
|             return $date; | ||||
|         } | ||||
|         throw new NotFoundHttpException; | ||||
|     } | ||||
| ); | ||||
|  | ||||
| Route::bind( | ||||
|     'tj', function ($value) { | ||||
| @@ -158,11 +264,10 @@ Route::bind( | ||||
|  * Auth\AuthController | ||||
|  */ | ||||
| Route::get('/register', ['uses' => 'Auth\AuthController@getRegister', 'as' => 'register']); | ||||
| Route::get('/cron/sendgrid', ['uses' => 'CronController@sendgrid']); | ||||
|  | ||||
| Route::controllers( | ||||
|     [ | ||||
|         'auth' => 'Auth\AuthController', | ||||
|         'auth'     => 'Auth\AuthController', | ||||
|         'password' => 'Auth\PasswordController', | ||||
|     ] | ||||
| ); | ||||
| @@ -178,7 +283,6 @@ Route::group( | ||||
|     Route::get('/home', ['uses' => 'HomeController@index', 'as' => 'home']); | ||||
|     Route::post('/daterange', ['uses' => 'HomeController@dateRange', 'as' => 'daterange']); | ||||
|     Route::get('/flush', ['uses' => 'HomeController@flush', 'as' => 'flush']); | ||||
|     Route::get('/routes', ['uses' => 'HomeController@routes']); | ||||
|     /** | ||||
|      * Account Controller | ||||
|      */ | ||||
| @@ -284,9 +388,7 @@ Route::group( | ||||
|     // accounts: | ||||
|     Route::get('/chart/account/frontpage', ['uses' => 'Chart\AccountController@frontpage']); | ||||
|     Route::get('/chart/account/expense', ['uses' => 'Chart\AccountController@expenseAccounts']); | ||||
|     Route::get('/chart/account/month/{year}/{month}/{shared?}', ['uses' => 'Chart\AccountController@all'])->where( | ||||
|         ['year' => '[0-9]{4}', 'month' => '[0-9]{1,2}', 'shared' => 'shared'] | ||||
|     ); | ||||
|     Route::get('/chart/account/report/{reportType}/{start_date}/{end_date}/{accountList}', ['uses' => 'Chart\AccountController@report']); | ||||
|     Route::get('/chart/account/{account}', ['uses' => 'Chart\AccountController@single']); | ||||
|  | ||||
|  | ||||
| @@ -296,30 +398,34 @@ Route::group( | ||||
|  | ||||
|     // budgets: | ||||
|     Route::get('/chart/budget/frontpage', ['uses' => 'Chart\BudgetController@frontpage']); | ||||
|     Route::get('/chart/budget/year/{year}/{shared?}', ['uses' => 'Chart\BudgetController@year'])->where(['year' => '[0-9]{4}', 'shared' => 'shared']); | ||||
|  | ||||
|     // this chart is used in reports: | ||||
|     Route::get('/chart/budget/year/{reportType}/{start_date}/{end_date}/{accountList}', ['uses' => 'Chart\BudgetController@year']); | ||||
|     Route::get('/chart/budget/multi-year/{reportType}/{start_date}/{end_date}/{accountList}/{budgetList}', ['uses' => 'Chart\BudgetController@multiYear']); | ||||
|  | ||||
|     Route::get('/chart/budget/{budget}/{limitrepetition}', ['uses' => 'Chart\BudgetController@budgetLimit']); | ||||
|     Route::get('/chart/budget/{budget}', ['uses' => 'Chart\BudgetController@budget']); | ||||
|  | ||||
|     // categories: | ||||
|     Route::get('/chart/category/frontpage', ['uses' => 'Chart\CategoryController@frontpage']); | ||||
|     Route::get('/chart/category/spent-in-year/{year}/{shared?}', ['uses' => 'Chart\CategoryController@spentInYear'])->where( | ||||
| ['year' => '[0-9]{4}', 'shared' => 'shared'] | ||||
|     ); | ||||
|     Route::get('/chart/category/earned-in-year/{year}/{shared?}', ['uses' => 'Chart\CategoryController@earnedInYear'])->where( | ||||
|         ['year' => '[0-9]{4}', 'shared' => 'shared'] | ||||
|  | ||||
|     // these three charts are for reports: | ||||
|     Route::get('/chart/category/earned-in-period/{reportType}/{start_date}/{end_date}/{accountList}', ['uses' => 'Chart\CategoryController@earnedInPeriod']); | ||||
|     Route::get('/chart/category/spent-in-period/{reportType}/{start_date}/{end_date}/{accountList}', ['uses' => 'Chart\CategoryController@spentInPeriod']); | ||||
|     Route::get( | ||||
|         '/chart/category/multi-year/{reportType}/{start_date}/{end_date}/{accountList}/{categoryList}', ['uses' => 'Chart\CategoryController@multiYear'] | ||||
|     ); | ||||
|  | ||||
|     Route::get('/chart/category/{category}/period', ['uses' => 'Chart\CategoryController@currentPeriod']); | ||||
|     Route::get('/chart/category/{category}/period/{date}', ['uses' => 'Chart\CategoryController@specificPeriod']); | ||||
|     Route::get('/chart/category/{category}/all', ['uses' => 'Chart\CategoryController@all']); | ||||
|  | ||||
|     // piggy banks: | ||||
|     Route::get('/chart/piggyBank/{piggyBank}', ['uses' => 'Chart\PiggyBankController@history']); | ||||
|     Route::get('/chart/piggy-bank/{piggyBank}', ['uses' => 'Chart\PiggyBankController@history']); | ||||
|  | ||||
|     // reports: | ||||
|     Route::get('/chart/report/in-out/{year}/{shared?}', ['uses' => 'Chart\ReportController@yearInOut'])->where(['year' => '[0-9]{4}', 'shared' => 'shared']); | ||||
|     Route::get('/chart/report/in-out-sum/{year}/{shared?}', ['uses' => 'Chart\ReportController@yearInOutSummarized'])->where( | ||||
|         ['year' => '[0-9]{4}', 'shared' => 'shared'] | ||||
|     ); | ||||
|     Route::get('/chart/report/in-out/{reportType}/{start_date}/{end_date}/{accountList}', ['uses' => 'Chart\ReportController@yearInOut']); | ||||
|     Route::get('/chart/report/in-out-sum/{reportType}/{start_date}/{end_date}/{accountList}', ['uses' => 'Chart\ReportController@yearInOutSummarized']); | ||||
|  | ||||
|  | ||||
|     /** | ||||
| @@ -385,12 +491,7 @@ Route::group( | ||||
|      * Report Controller | ||||
|      */ | ||||
|     Route::get('/reports', ['uses' => 'ReportController@index', 'as' => 'reports.index']); | ||||
|     Route::get('/reports/{year}/{shared?}', ['uses' => 'ReportController@year', 'as' => 'reports.year'])->where(['year' => '[0-9]{4}', 'shared' => 'shared']); | ||||
|     Route::get('/reports/{year}/{month}/{shared?}', ['uses' => 'ReportController@month', 'as' => 'reports.month'])->where( | ||||
|         ['year' => '[0-9]{4}', 'month' => '[0-9]{1,2}', 'shared' => 'shared'] | ||||
|     ); | ||||
|  | ||||
|     // pop ups for budget report: | ||||
|     Route::get('/reports/report/{reportType}/{start_date}/{end_date}/{accountList}', ['uses' => 'ReportController@report', 'as' => 'reports.report']); | ||||
|  | ||||
|     /** | ||||
|      * Search Controller | ||||
|   | ||||
| @@ -1,53 +1,38 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Crypt; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Database\Eloquent\Builder as EloquentBuilder; | ||||
| use Illuminate\Database\Eloquent\Collection; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
| use Illuminate\Database\Query\Builder; | ||||
| use Illuminate\Database\Query\JoinClause; | ||||
| use Watson\Validating\ValidatingTrait; | ||||
|  | ||||
| /** | ||||
|  * Class Account | ||||
|  * FireflyIII\Models\Account | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  * @property integer                                                                        $id | ||||
|  * @property \Carbon\Carbon                                                                 $created_at | ||||
|  * @property \Carbon\Carbon                                                                 $updated_at | ||||
|  * @property \Carbon\Carbon                                                                 $deleted_at | ||||
|  * @property integer                                                                        $user_id | ||||
|  * @property integer                                                                        $account_type_id | ||||
|  * @property string                                                                         $name | ||||
|  * @property boolean                                                                        $active | ||||
|  * @property boolean                                                                        $encrypted | ||||
|  * @property float                                                                          $virtual_balance | ||||
|  * @property string                                                                         $iban | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\AccountMeta[] $accountMeta | ||||
|  * @property-read \FireflyIII\Models\AccountType                                            $accountType | ||||
|  * @property-read mixed                                                                     $name_for_editform | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBank[]   $piggyBanks | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Transaction[] $transactions | ||||
|  * @property-read \FireflyIII\User                                                          $user | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereCreatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereUpdatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereDeletedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereUserId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereAccountTypeId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereName($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereActive($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereEncrypted($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereVirtualBalance($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account whereIban($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account accountTypeIn($types) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Account hasMetaValue($name, $value) | ||||
|  * @property-read bool                                                                      $joinedAccountTypes | ||||
|  * @property float                                                                          $startBalance | ||||
|  * @property float                                                                          $endBalance | ||||
|  * @property float                                                                          $piggyBalance | ||||
|  * @property float                                                                          $percentage | ||||
|  * @property float                                                                          $difference | ||||
|  * @property \Carbon\Carbon                                                                 $lastActivityDate | ||||
|  * @property integer                       $id | ||||
|  * @property Carbon                        $created_at | ||||
|  * @property Carbon                        $updated_at | ||||
|  * @property Carbon                        $deleted_at | ||||
|  * @property integer                       $user_id | ||||
|  * @property integer                       $account_type_id | ||||
|  * @property string                        $name | ||||
|  * @property boolean                       $active | ||||
|  * @property boolean                       $encrypted | ||||
|  * @property float                         $virtual_balance | ||||
|  * @property string                        $iban | ||||
|  * @property-read Collection|AccountMeta[] $accountMeta | ||||
|  * @property-read AccountType              $accountType | ||||
|  * @property-read mixed                    $name_for_editform | ||||
|  * @property-read Collection|PiggyBank[]   $piggyBanks | ||||
|  * @property-read Collection|Transaction[] $transactions | ||||
|  * @property-read User                     $user | ||||
|  * @method static Builder|Account accountTypeIn($types) | ||||
|  * @method static Builder|Account hasMetaValue($name, $value) | ||||
|  */ | ||||
| class Account extends Model | ||||
| { | ||||
| @@ -65,7 +50,6 @@ class Account extends Model | ||||
|  | ||||
|     /** | ||||
|      * @param array $fields | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * | ||||
|      * @return Account|null | ||||
|      */ | ||||
|   | ||||
| @@ -1,25 +1,19 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Watson\Validating\ValidatingTrait; | ||||
|  | ||||
| /** | ||||
|  * Class AccountMeta | ||||
|  * FireflyIII\Models\AccountMeta | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  * @property integer                         $id | ||||
|  * @property \Carbon\Carbon                  $created_at | ||||
|  * @property \Carbon\Carbon                  $updated_at | ||||
|  * @property integer                         $account_id | ||||
|  * @property string                          $name | ||||
|  * @property string                          $data | ||||
|  * @property-read \FireflyIII\Models\Account $account | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountMeta whereId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountMeta whereCreatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountMeta whereUpdatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountMeta whereAccountId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountMeta whereName($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountMeta whereData($value) | ||||
|  * @property integer      $id | ||||
|  * @property Carbon       $created_at | ||||
|  * @property Carbon       $updated_at | ||||
|  * @property integer      $account_id | ||||
|  * @property string       $name | ||||
|  * @property string       $data | ||||
|  * @property-read Account $account | ||||
|  */ | ||||
| class AccountMeta extends Model | ||||
| { | ||||
|   | ||||
| @@ -1,22 +1,18 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Illuminate\Database\Eloquent\Collection; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
|  | ||||
| /** | ||||
|  * Class AccountType | ||||
|  * FireflyIII\Models\AccountType | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  * @property integer                                                                    $id | ||||
|  * @property \Carbon\Carbon                                                             $created_at | ||||
|  * @property \Carbon\Carbon                                                             $updated_at | ||||
|  * @property string                                                                     $type | ||||
|  * @property boolean                                                                    $editable | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Account[] $accounts | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountType whereId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountType whereCreatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountType whereUpdatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountType whereType($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\AccountType whereEditable($value) | ||||
|  * @property integer                   $id | ||||
|  * @property Carbon                    $created_at | ||||
|  * @property Carbon                    $updated_at | ||||
|  * @property string                    $type | ||||
|  * @property boolean                   $editable | ||||
|  * @property-read Collection|Account[] $accounts | ||||
|  */ | ||||
| class AccountType extends Model | ||||
| { | ||||
| @@ -33,6 +29,7 @@ class AccountType extends Model | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     /** @noinspection PhpMissingParentCallCommonInspection */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at']; | ||||
|   | ||||
| @@ -2,46 +2,32 @@ | ||||
|  | ||||
| namespace FireflyIII\Models; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Crypt; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
|  | ||||
| /** | ||||
|  * Class Attachment | ||||
|  * FireflyIII\Models\Attachment | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  * @property integer               $id | ||||
|  * @property \Carbon\Carbon        $created_at | ||||
|  * @property \Carbon\Carbon        $updated_at | ||||
|  * @property string                $deleted_at | ||||
|  * @property integer               $attachable_id | ||||
|  * @property string                $attachable_type | ||||
|  * @property integer               $user_id | ||||
|  * @property string                $md5 | ||||
|  * @property string                $filename | ||||
|  * @property string                $mime | ||||
|  * @property integer               $size | ||||
|  * @property boolean               $uploaded | ||||
|  * @property-read \                $attachable | ||||
|  * @property-read \FireflyIII\User $user | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereCreatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereUpdatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereDeletedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereAttachableId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereAttachableType($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereUserId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereMd5($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereFilename($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereMime($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereSize($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereUploaded($value) | ||||
|  * @property string                $title | ||||
|  * @property string                $description | ||||
|  * @property string                $notes | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereTitle($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereDescription($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Attachment whereNotes($value) | ||||
|  * @property integer         $id | ||||
|  * @property Carbon          $created_at | ||||
|  * @property Carbon          $updated_at | ||||
|  * @property string          $deleted_at | ||||
|  * @property integer         $attachable_id | ||||
|  * @property string          $attachable_type | ||||
|  * @property integer         $user_id | ||||
|  * @property string          $md5 | ||||
|  * @property string          $filename | ||||
|  * @property string          $title | ||||
|  * @property string          $description | ||||
|  * @property string          $notes | ||||
|  * @property string          $mime | ||||
|  * @property integer         $size | ||||
|  * @property boolean         $uploaded | ||||
|  * @property-read Attachment $attachable | ||||
|  * @property-read User       $user | ||||
|  */ | ||||
| class Attachment extends Model | ||||
| { | ||||
|   | ||||
| @@ -1,46 +1,31 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Crypt; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Database\Eloquent\Collection; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
|  | ||||
| /** | ||||
|  * Class Bill | ||||
|  * FireflyIII\Models\Bill | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  * @property integer                                                                               $id | ||||
|  * @property \Carbon\Carbon                                                                        $created_at | ||||
|  * @property \Carbon\Carbon                                                                        $updated_at | ||||
|  * @property integer                                                                               $user_id | ||||
|  * @property string                                                                                $name | ||||
|  * @property string                                                                                $match | ||||
|  * @property float                                                                                 $amount_min | ||||
|  * @property float                                                                                 $amount_max | ||||
|  * @property \Carbon\Carbon                                                                        $date | ||||
|  * @property boolean                                                                               $active | ||||
|  * @property boolean                                                                               $automatch | ||||
|  * @property string                                                                                $repeat_freq | ||||
|  * @property integer                                                                               $skip | ||||
|  * @property boolean                                                                               $name_encrypted | ||||
|  * @property boolean                                                                               $match_encrypted | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionjournals | ||||
|  * @property-read \FireflyIII\User                                                                 $user | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereCreatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereUpdatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereUserId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereName($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereMatch($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereAmountMin($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereAmountMax($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereDate($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereActive($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereAutomatch($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereRepeatFreq($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereSkip($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereNameEncrypted($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereMatchEncrypted($value) | ||||
|  * @property \Carbon\Carbon                                                                   $nextExpectedMatch | ||||
|  * @property \Carbon\Carbon                                                                   $lastFoundMatch | ||||
|  * @property integer                              $id | ||||
|  * @property Carbon                               $created_at | ||||
|  * @property Carbon                               $updated_at | ||||
|  * @property integer                              $user_id | ||||
|  * @property string                               $name | ||||
|  * @property string                               $match | ||||
|  * @property float                                $amount_min | ||||
|  * @property float                                $amount_max | ||||
|  * @property Carbon                               $date | ||||
|  * @property boolean                              $active | ||||
|  * @property boolean                              $automatch | ||||
|  * @property string                               $repeat_freq | ||||
|  * @property integer                              $skip | ||||
|  * @property boolean                              $name_encrypted | ||||
|  * @property boolean                              $match_encrypted | ||||
|  * @property-read Collection|TransactionJournal[] $transactionjournals | ||||
|  * @property-read User                            $user | ||||
|  */ | ||||
| class Bill extends Model | ||||
| { | ||||
|   | ||||
| @@ -1,32 +1,26 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Crypt; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Database\Eloquent\Collection; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
|  | ||||
| /** | ||||
|  * Class Budget | ||||
|  * FireflyIII\Models\Budget | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  * @property integer                                                                               $id | ||||
|  * @property \Carbon\Carbon                                                                        $created_at | ||||
|  * @property \Carbon\Carbon                                                                        $updated_at | ||||
|  * @property \Carbon\Carbon                                                                        $deleted_at | ||||
|  * @property string                                                                                $name | ||||
|  * @property integer                                                                               $user_id | ||||
|  * @property boolean                                                                               $active | ||||
|  * @property boolean                                                                               $encrypted | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\BudgetLimit[]        $budgetlimits | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionjournals | ||||
|  * @property-read \FireflyIII\User                                                                 $user | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereCreatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereUpdatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereDeletedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereName($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereUserId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereActive($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Budget whereEncrypted($value) | ||||
|  * @property integer                              $id | ||||
|  * @property Carbon                               $created_at | ||||
|  * @property Carbon                               $updated_at | ||||
|  * @property Carbon                               $deleted_at | ||||
|  * @property string                               $name | ||||
|  * @property integer                              $user_id | ||||
|  * @property boolean                              $active | ||||
|  * @property boolean                              $encrypted | ||||
|  * @property-read Collection|BudgetLimit[]        $budgetlimits | ||||
|  * @property-read Collection|TransactionJournal[] $transactionjournals | ||||
|  * @property-read User                            $user | ||||
|  */ | ||||
| class Budget extends Model | ||||
| { | ||||
| @@ -78,7 +72,7 @@ class Budget extends Model | ||||
|      */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at', 'deleted_at']; | ||||
|         return ['created_at', 'updated_at', 'deleted_at', 'startdate', 'enddate']; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -1,29 +1,22 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Illuminate\Database\Eloquent\Collection; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
|  | ||||
| /** | ||||
|  * Class BudgetLimit | ||||
|  * FireflyIII\Models\BudgetLimit | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  * @property integer                                                                            $id | ||||
|  * @property \Carbon\Carbon                                                                     $created_at | ||||
|  * @property \Carbon\Carbon                                                                     $updated_at | ||||
|  * @property integer                                                                            $budget_id | ||||
|  * @property \Carbon\Carbon                                                                     $startdate | ||||
|  * @property float                                                                              $amount | ||||
|  * @property boolean                                                                            $repeats | ||||
|  * @property string                                                                             $repeat_freq | ||||
|  * @property-read \FireflyIII\Models\Budget                                                     $budget | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\LimitRepetition[] $limitrepetitions | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereCreatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereUpdatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereBudgetId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereStartdate($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereAmount($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereRepeats($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\BudgetLimit whereRepeatFreq($value) | ||||
|  * @property integer                           $id | ||||
|  * @property Carbon                            $created_at | ||||
|  * @property Carbon                            $updated_at | ||||
|  * @property integer                           $budget_id | ||||
|  * @property Carbon                            $startdate | ||||
|  * @property float                             $amount | ||||
|  * @property boolean                           $repeats | ||||
|  * @property string                            $repeat_freq | ||||
|  * @property-read Budget                       $budget | ||||
|  * @property-read Collection|LimitRepetition[] $limitrepetitions | ||||
|  */ | ||||
| class BudgetLimit extends Model | ||||
| { | ||||
|   | ||||
| @@ -1,31 +1,24 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Crypt; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Database\Eloquent\Collection; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
|  | ||||
| /** | ||||
|  * Class Category | ||||
|  * FireflyIII\Models\Category | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  * @property integer                                                                               $id | ||||
|  * @property \Carbon\Carbon                                                                        $created_at | ||||
|  * @property \Carbon\Carbon                                                                        $updated_at | ||||
|  * @property \Carbon\Carbon                                                                        $deleted_at | ||||
|  * @property string                                                                                $name | ||||
|  * @property integer                                                                               $user_id | ||||
|  * @property boolean                                                                               $encrypted | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionjournals | ||||
|  * @property-read \FireflyIII\User                                                                 $user | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereCreatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereUpdatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereDeletedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereName($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereUserId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereEncrypted($value) | ||||
|  * @property-read float                                                                            $spent | ||||
|  * @property \Carbon\Carbon                                                                   $lastActivity | ||||
|  * @property integer                              $id | ||||
|  * @property Carbon                               $created_at | ||||
|  * @property Carbon                               $updated_at | ||||
|  * @property Carbon                               $deleted_at | ||||
|  * @property string                               $name | ||||
|  * @property integer                              $user_id | ||||
|  * @property boolean                              $encrypted | ||||
|  * @property-read Collection|TransactionJournal[] $transactionjournals | ||||
|  * @property-read User                            $user | ||||
|  */ | ||||
| class Category extends Model | ||||
| { | ||||
| @@ -36,7 +29,6 @@ class Category extends Model | ||||
|  | ||||
|     /** | ||||
|      * @param array $fields | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * | ||||
|      * @return Category | ||||
|      */ | ||||
|   | ||||
| @@ -1,26 +1,19 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
|  | ||||
| /** | ||||
|  * Class Component | ||||
|  * FireflyIII\Models\Component | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  * @property integer        $id | ||||
|  * @property \Carbon\Carbon $created_at | ||||
|  * @property \Carbon\Carbon $updated_at | ||||
|  * @property \Carbon\Carbon $deleted_at | ||||
|  * @property string         $name | ||||
|  * @property integer        $user_id | ||||
|  * @property string         $class | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Component whereId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Component whereCreatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Component whereUpdatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Component whereDeletedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Component whereName($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Component whereUserId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Component whereClass($value) | ||||
|  * @property integer $id | ||||
|  * @property Carbon  $created_at | ||||
|  * @property Carbon  $updated_at | ||||
|  * @property Carbon  $deleted_at | ||||
|  * @property string  $name | ||||
|  * @property integer $user_id | ||||
|  * @property string  $class | ||||
|  */ | ||||
| class Component extends Model | ||||
| { | ||||
|   | ||||
| @@ -1,26 +1,19 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
|  | ||||
| /** | ||||
|  * Class LimitRepetition | ||||
|  * FireflyIII\Models\LimitRepetition | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  * @property integer                             $id | ||||
|  * @property \Carbon\Carbon                      $created_at | ||||
|  * @property \Carbon\Carbon                      $updated_at | ||||
|  * @property integer                             $budget_limit_id | ||||
|  * @property \Carbon\Carbon                      $startdate | ||||
|  * @property \Carbon\Carbon                      $enddate | ||||
|  * @property float                               $amount | ||||
|  * @property-read \FireflyIII\Models\BudgetLimit $budgetLimit | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereCreatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereUpdatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereBudgetLimitId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereStartdate($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereEnddate($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\LimitRepetition whereAmount($value) | ||||
|  * @property integer          $id | ||||
|  * @property Carbon           $created_at | ||||
|  * @property Carbon           $updated_at | ||||
|  * @property integer          $budget_limit_id | ||||
|  * @property Carbon           $startdate | ||||
|  * @property Carbon           $enddate | ||||
|  * @property float            $amount | ||||
|  * @property-read BudgetLimit $budgetLimit | ||||
|  */ | ||||
| class LimitRepetition extends Model | ||||
| { | ||||
|   | ||||
| @@ -2,25 +2,20 @@ | ||||
|  | ||||
| namespace FireflyIII\Models; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Illuminate\Database\Eloquent\Collection; | ||||
| use Zizaco\Entrust\EntrustPermission; | ||||
|  | ||||
| /** | ||||
|  * Class Permission | ||||
|  * FireflyIII\Models\Permission | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  * @property integer        $id | ||||
|  * @property string         $name | ||||
|  * @property string         $display_name | ||||
|  * @property string         $description | ||||
|  * @property \Carbon\Carbon $created_at | ||||
|  * @property \Carbon\Carbon $updated_at | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\Config::get('entrust.role[] $roles | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Permission whereId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Permission whereName($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Permission whereDisplayName($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Permission whereDescription($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Permission whereCreatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Permission whereUpdatedAt($value) | ||||
|  * @property integer                $id | ||||
|  * @property string                 $name | ||||
|  * @property string                 $display_name | ||||
|  * @property string                 $description | ||||
|  * @property Carbon                 $created_at | ||||
|  * @property Carbon                 $updated_at | ||||
|  * @property-read Collection|Role[] $roles | ||||
|  */ | ||||
| class Permission extends EntrustPermission | ||||
| { | ||||
|   | ||||
| @@ -1,45 +1,30 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Crypt; | ||||
| use Illuminate\Database\Eloquent\Collection; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
|  | ||||
| /** | ||||
|  * Class PiggyBank | ||||
|  * FireflyIII\Models\PiggyBank | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  * @property integer                                                                                $id | ||||
|  * @property \Carbon\Carbon                                                                         $created_at | ||||
|  * @property \Carbon\Carbon                                                                         $updated_at | ||||
|  * @property \Carbon\Carbon                                                                         $deleted_at | ||||
|  * @property integer                                                                                $account_id | ||||
|  * @property string                                                                                 $name | ||||
|  * @property float                                                                                  $targetamount | ||||
|  * @property \Carbon\Carbon                                                                         $startdate | ||||
|  * @property \Carbon\Carbon                                                                         $targetdate | ||||
|  * @property integer                                                                                $order | ||||
|  * @property boolean                                                                                $encrypted | ||||
|  * @property boolean                                                                                $remind_me | ||||
|  * @property integer                                                                                $reminder_skip | ||||
|  * @property-read \FireflyIII\Models\Account                                                        $account | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBankRepetition[] $piggyBankRepetitions | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBankEvent[]      $piggyBankEvents | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereCreatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereUpdatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereDeletedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereAccountId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereName($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereTargetamount($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereStartdate($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereTargetdate($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereOrder($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereEncrypted($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereRemindMe($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereReminderSkip($value) | ||||
|  * @property-read \FireflyIII\Models\PiggyBankRepetition                                            $currentRep | ||||
|  * @property string                                                                                 $reminder | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereReminder($value) | ||||
|  * @property integer                               $id | ||||
|  * @property Carbon                                $created_at | ||||
|  * @property Carbon                                $updated_at | ||||
|  * @property Carbon                                $deleted_at | ||||
|  * @property integer                               $account_id | ||||
|  * @property string                                $name | ||||
|  * @property float                                 $targetamount | ||||
|  * @property Carbon                                $startdate | ||||
|  * @property Carbon                                $targetdate | ||||
|  * @property integer                               $order | ||||
|  * @property boolean                               $encrypted | ||||
|  * @property boolean                               $remind_me | ||||
|  * @property integer                               $reminder_skip | ||||
|  * @property-read Account                          $account | ||||
|  * @property-read Collection|PiggyBankRepetition[] $piggyBankRepetitions | ||||
|  * @property-read Collection|PiggyBankEvent[]      $piggyBankEvents | ||||
|  */ | ||||
| class PiggyBank extends Model | ||||
| { | ||||
|   | ||||
| @@ -1,27 +1,20 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
|  | ||||
| /** | ||||
|  * Class PiggyBankEvent | ||||
|  * FireflyIII\Models\PiggyBankEvent | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  * @property integer                                    $id | ||||
|  * @property \Carbon\Carbon                             $created_at | ||||
|  * @property \Carbon\Carbon                             $updated_at | ||||
|  * @property integer                                    $piggy_bank_id | ||||
|  * @property integer                                    $transaction_journal_id | ||||
|  * @property \Carbon\Carbon                             $date | ||||
|  * @property float                                      $amount | ||||
|  * @property-read \FireflyIII\Models\PiggyBank          $piggyBank | ||||
|  * @property-read \FireflyIII\Models\TransactionJournal $transactionJournal | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereCreatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereUpdatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent wherePiggyBankId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereTransactionJournalId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereDate($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankEvent whereAmount($value) | ||||
|  * @property integer                 $id | ||||
|  * @property Carbon                  $created_at | ||||
|  * @property Carbon                  $updated_at | ||||
|  * @property integer                 $piggy_bank_id | ||||
|  * @property integer                 $transaction_journal_id | ||||
|  * @property Carbon                  $date | ||||
|  * @property float                   $amount | ||||
|  * @property PiggyBank               $piggyBank | ||||
|  * @property-read TransactionJournal $transactionJournal | ||||
|  */ | ||||
| class PiggyBankEvent extends Model | ||||
| { | ||||
| @@ -32,6 +25,7 @@ class PiggyBankEvent extends Model | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     /** @noinspection PhpMissingParentCallCommonInspection */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at', 'date']; | ||||
|   | ||||
| @@ -3,28 +3,21 @@ | ||||
| use Carbon\Carbon; | ||||
| use Illuminate\Database\Eloquent\Builder as EloquentBuilder; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Query\Builder; | ||||
|  | ||||
| /** | ||||
|  * Class PiggyBankRepetition | ||||
|  * FireflyIII\Models\PiggyBankRepetition | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  * @property integer                           $id | ||||
|  * @property \Carbon\Carbon                    $created_at | ||||
|  * @property \Carbon\Carbon                    $updated_at | ||||
|  * @property integer                           $piggy_bank_id | ||||
|  * @property \Carbon\Carbon                    $startdate | ||||
|  * @property \Carbon\Carbon                    $targetdate | ||||
|  * @property float                             $currentamount | ||||
|  * @property-read \FireflyIII\Models\PiggyBank $piggyBank | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereCreatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereUpdatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition wherePiggyBankId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereStartdate($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereTargetdate($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition whereCurrentamount($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition onDates($start, $target) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBankRepetition relevantOnDate($date) | ||||
|  * @property integer        $id | ||||
|  * @property Carbon         $created_at | ||||
|  * @property Carbon         $updated_at | ||||
|  * @property integer        $piggy_bank_id | ||||
|  * @property Carbon         $startdate | ||||
|  * @property Carbon         $targetdate | ||||
|  * @property float          $currentamount | ||||
|  * @property-read PiggyBank $piggyBank | ||||
|  * @method static Builder|PiggyBankRepetition onDates($start, $target) | ||||
|  * @method static Builder|PiggyBankRepetition relevantOnDate($date) | ||||
|  */ | ||||
| class PiggyBankRepetition extends Model | ||||
| { | ||||
|   | ||||
| @@ -1,29 +1,22 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Crypt; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
|  | ||||
| /** | ||||
|  * Class Preference | ||||
|  * FireflyIII\Models\Preference | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  * @property integer               $id | ||||
|  * @property \Carbon\Carbon        $created_at | ||||
|  * @property \Carbon\Carbon        $updated_at | ||||
|  * @property integer               $user_id | ||||
|  * @property string                $name | ||||
|  * @property string                $name_encrypted | ||||
|  * @property string                $data | ||||
|  * @property string                $data_encrypted | ||||
|  * @property-read \FireflyIII\User $user | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereCreatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereUpdatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereUserId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereName($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereNameEncrypted($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereData($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Preference whereDataEncrypted($value) | ||||
|  * @property integer   $id | ||||
|  * @property Carbon    $created_at | ||||
|  * @property Carbon    $updated_at | ||||
|  * @property integer   $user_id | ||||
|  * @property string    $name | ||||
|  * @property string    $name_encrypted | ||||
|  * @property string    $data | ||||
|  * @property string    $data_encrypted | ||||
|  * @property-read User $user | ||||
|  */ | ||||
| class Preference extends Model | ||||
| { | ||||
|   | ||||
| @@ -2,26 +2,21 @@ | ||||
| namespace FireflyIII\Models; | ||||
|  | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Illuminate\Database\Eloquent\Collection; | ||||
| use Zizaco\Entrust\EntrustRole; | ||||
|  | ||||
| /** | ||||
|  * Class Role | ||||
|  * FireflyIII\Models\Role | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  * @property integer        $id | ||||
|  * @property string         $name | ||||
|  * @property string         $display_name | ||||
|  * @property string         $description | ||||
|  * @property \Carbon\Carbon $created_at | ||||
|  * @property \Carbon\Carbon $updated_at | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\Config::get('auth.model[] $users | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\Config::get('entrust.permission[] $perms | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Role whereId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Role whereName($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Role whereDisplayName($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Role whereDescription($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Role whereCreatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Role whereUpdatedAt($value) | ||||
|  * @property integer                            $id | ||||
|  * @property string                             $name | ||||
|  * @property string                             $display_name | ||||
|  * @property string                             $description | ||||
|  * @property Carbon                             $created_at | ||||
|  * @property Carbon                             $updated_at | ||||
|  * @property-read Collection|\FireflyIII\User[] $users | ||||
|  * @property-read Collection|Permission[]       $perms | ||||
|  */ | ||||
| class Role extends EntrustRole | ||||
| { | ||||
|   | ||||
| @@ -2,40 +2,30 @@ | ||||
|  | ||||
| namespace FireflyIII\Models; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Crypt; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Database\Eloquent\Collection; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Watson\Validating\ValidatingTrait; | ||||
|  | ||||
| /** | ||||
|  * Class Tag | ||||
|  * FireflyIII\Models\Tag | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  * @property integer                                                                               $id | ||||
|  * @property \Carbon\Carbon                                                                        $created_at | ||||
|  * @property \Carbon\Carbon                                                                        $updated_at | ||||
|  * @property string                                                                                $deleted_at | ||||
|  * @property integer                                                                               $user_id | ||||
|  * @property string                                                                                $tag | ||||
|  * @property string                                                                                $tagMode | ||||
|  * @property \Carbon\Carbon                                                                        $date | ||||
|  * @property string                                                                                $description | ||||
|  * @property float                                                                                 $latitude | ||||
|  * @property float                                                                                 $longitude | ||||
|  * @property integer                                                                               $zoomLevel | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionjournals | ||||
|  * @property-read \FireflyIII\User                                                                 $user | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereCreatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereUpdatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereDeletedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereUserId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereTag($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereTagMode($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereDate($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereDescription($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereLatitude($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereLongitude($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Tag whereZoomLevel($value) | ||||
|  * @property integer                              $id | ||||
|  * @property Carbon                               $created_at | ||||
|  * @property Carbon                               $updated_at | ||||
|  * @property string                               $deleted_at | ||||
|  * @property integer                              $user_id | ||||
|  * @property string                               $tag | ||||
|  * @property string                               $tagMode | ||||
|  * @property Carbon                               $date | ||||
|  * @property string                               $description | ||||
|  * @property float                                $latitude | ||||
|  * @property float                                $longitude | ||||
|  * @property integer                              $zoomLevel | ||||
|  * @property-read Collection|TransactionJournal[] $transactionjournals | ||||
|  * @property-read User                            $user | ||||
|  */ | ||||
| class Tag extends Model | ||||
| { | ||||
| @@ -54,8 +44,6 @@ class Tag extends Model | ||||
|  | ||||
|     /** | ||||
|      * @param array $fields | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * @SuppressWarnings(PHPMD.NPathComplexity) | ||||
|      * | ||||
|      * @return Tag|null | ||||
|      */ | ||||
|   | ||||
| @@ -4,34 +4,24 @@ use Carbon\Carbon; | ||||
| use Illuminate\Database\Eloquent\Builder as EloquentBuilder; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
| use Illuminate\Database\Query\Builder; | ||||
| use Watson\Validating\ValidatingTrait; | ||||
|  | ||||
| /** | ||||
|  * Class Transaction | ||||
|  * FireflyIII\Models\Transaction | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  * @property integer                                    $id | ||||
|  * @property \Carbon\Carbon                             $created_at | ||||
|  * @property \Carbon\Carbon                             $updated_at | ||||
|  * @property \Carbon\Carbon                             $deleted_at | ||||
|  * @property integer                                    $account_id | ||||
|  * @property integer                                    $transaction_journal_id | ||||
|  * @property string                                     $description | ||||
|  * @property float                                      $amount | ||||
|  * @property-read \FireflyIII\Models\Account            $account | ||||
|  * @property-read \FireflyIII\Models\TransactionJournal $transactionJournal | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereCreatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereUpdatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereDeletedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereAccountId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereTransactionJournalId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereDescription($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction whereAmount($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction after($date) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Transaction before($date) | ||||
|  * @property float                                      $before | ||||
|  * @property float                                      $after | ||||
|  * @property integer                 $id | ||||
|  * @property Carbon                  $created_at | ||||
|  * @property Carbon                  $updated_at | ||||
|  * @property Carbon                  $deleted_at | ||||
|  * @property integer                 $account_id | ||||
|  * @property integer                 $transaction_journal_id | ||||
|  * @property string                  $description | ||||
|  * @property float                   $amount | ||||
|  * @property-read Account            $account | ||||
|  * @property-read TransactionJournal $transactionJournal | ||||
|  * @method static Builder|Transaction after($date) | ||||
|  * @method static Builder|Transaction before($date) | ||||
|  */ | ||||
| class Transaction extends Model | ||||
| { | ||||
|   | ||||
| @@ -1,27 +1,21 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Illuminate\Database\Eloquent\Collection; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
|  | ||||
| /** | ||||
|  * Class TransactionCurrency | ||||
|  * FireflyIII\Models\TransactionCurrency | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  * @property integer                                                                               $id | ||||
|  * @property \Carbon\Carbon                                                                        $created_at | ||||
|  * @property \Carbon\Carbon                                                                        $updated_at | ||||
|  * @property \Carbon\Carbon                                                                        $deleted_at | ||||
|  * @property string                                                                                $code | ||||
|  * @property string                                                                                $name | ||||
|  * @property string                                                                                $symbol | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionJournals | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionCurrency whereId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionCurrency whereCreatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionCurrency whereUpdatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionCurrency whereDeletedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionCurrency whereCode($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionCurrency whereName($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionCurrency whereSymbol($value) | ||||
|  * @property integer                              $id | ||||
|  * @property Carbon                               $created_at | ||||
|  * @property Carbon                               $updated_at | ||||
|  * @property Carbon                               $deleted_at | ||||
|  * @property string                               $code | ||||
|  * @property string                               $name | ||||
|  * @property string                               $symbol | ||||
|  * @property-read Collection|TransactionJournal[] $transactionJournals | ||||
|  */ | ||||
| class TransactionCurrency extends Model | ||||
| { | ||||
|   | ||||
| @@ -1,26 +1,22 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Database\Eloquent\Collection; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
|  | ||||
| /** | ||||
|  * Class TransactionGroup | ||||
|  * FireflyIII\Models\TransactionGroup | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  * @property integer                                                                               $id | ||||
|  * @property \Carbon\Carbon                                                                        $created_at | ||||
|  * @property \Carbon\Carbon                                                                        $updated_at | ||||
|  * @property \Carbon\Carbon                                                                        $deleted_at | ||||
|  * @property integer                                                                               $user_id | ||||
|  * @property string                                                                                $relation | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionjournals | ||||
|  * @property-read \FireflyIII\User                                                                 $user | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionGroup whereId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionGroup whereCreatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionGroup whereUpdatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionGroup whereDeletedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionGroup whereUserId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionGroup whereRelation($value) | ||||
|  * @property integer                              $id | ||||
|  * @property Carbon                               $created_at | ||||
|  * @property Carbon                               $updated_at | ||||
|  * @property Carbon                               $deleted_at | ||||
|  * @property integer                              $user_id | ||||
|  * @property string                               $relation | ||||
|  * @property-read Collection|TransactionJournal[] $transactionjournals | ||||
|  * @property-read User                            $user | ||||
|  */ | ||||
| class TransactionGroup extends Model | ||||
| { | ||||
|   | ||||
| @@ -3,73 +3,53 @@ | ||||
| use Carbon\Carbon; | ||||
| use Crypt; | ||||
| use FireflyIII\Support\CacheProperties; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Database\Eloquent\Builder as EloquentBuilder; | ||||
| use Illuminate\Database\Eloquent\Collection; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\Relations\HasMany; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
| use Illuminate\Database\Query\Builder; | ||||
| use Watson\Validating\ValidatingTrait; | ||||
|  | ||||
| /** | ||||
|  * Class TransactionJournal | ||||
|  * FireflyIII\Models\TransactionJournal | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  * @property integer                                                                             $id | ||||
|  * @property \Carbon\Carbon                                                                      $created_at | ||||
|  * @property \Carbon\Carbon                                                                      $updated_at | ||||
|  * @property \Carbon\Carbon                                                                      $deleted_at | ||||
|  * @property integer                                                                             $user_id | ||||
|  * @property integer                                                                             $transaction_type_id | ||||
|  * @property integer                                                                             $bill_id | ||||
|  * @property integer                                                                             $transaction_currency_id | ||||
|  * @property string                                                                              $description | ||||
|  * @property boolean                                                                             $completed | ||||
|  * @property \Carbon\Carbon                                                                      $date | ||||
|  * @property boolean                                                                             $encrypted | ||||
|  * @property integer                                                                             $order | ||||
|  * @property integer                                                                             $tag_count | ||||
|  * @property-read \FireflyIII\Models\Bill                                                        $bill | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Budget[]           $budgets | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Category[]         $categories | ||||
|  * @property-read mixed                                                                          $actual_amount | ||||
|  * @property-read mixed                                                                          $amount | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Tag[]              $tags | ||||
|  * @property-read mixed                                                                          $correct_amount | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Transaction[]      $transactions | ||||
|  * @property-read mixed                                                                          $destination_account | ||||
|  * @property-read mixed                                                                          $source_account | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBankEvent[]   $piggyBankEvents | ||||
|  * @property-read \FireflyIII\Models\TransactionCurrency                                         $transactionCurrency | ||||
|  * @property-read \FireflyIII\Models\TransactionType                                             $transactionType | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionGroup[] $transactiongroups | ||||
|  * @property-read \FireflyIII\User                                                               $user | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereCreatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereUpdatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereDeletedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereUserId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereTransactionTypeId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereBillId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereTransactionCurrencyId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereDescription($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereCompleted($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereDate($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereEncrypted($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereOrder($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal whereTagCount($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal accountIs($account) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal after($date) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal before($date) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal onDate($date) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal transactionTypes($types) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionJournal withRelevantData() | ||||
|  * @property-read bool                                                                           $account_encrypted | ||||
|  * @property-read bool                                                                           $joinedTransactions | ||||
|  * @property-read bool                                                                           $joinedTransactionTypes | ||||
|  * @property-read int                                                                            $account_id | ||||
|  * @property string                                                                              $name | ||||
|  * @property-read string                                                                         $symbol | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Attachment[]       $attachments | ||||
|  * @property-read mixed                                                                          $amount_positive | ||||
|  * @property integer                            $id | ||||
|  * @property Carbon                             $created_at | ||||
|  * @property Carbon                             $updated_at | ||||
|  * @property Carbon                             $deleted_at | ||||
|  * @property integer                            $user_id | ||||
|  * @property integer                            $transaction_type_id | ||||
|  * @property integer                            $bill_id | ||||
|  * @property integer                            $transaction_currency_id | ||||
|  * @property string                             $description | ||||
|  * @property boolean                            $completed | ||||
|  * @property Carbon                             $date | ||||
|  * @property boolean                            $encrypted | ||||
|  * @property integer                            $order | ||||
|  * @property integer                            $tag_count | ||||
|  * @property-read Bill                          $bill | ||||
|  * @property-read Collection|Budget[]           $budgets | ||||
|  * @property-read Collection|Category[]         $categories | ||||
|  * @property-read mixed                         $amount_positive | ||||
|  * @property-read mixed                         $amount | ||||
|  * @property-read Collection|Tag[]              $tags | ||||
|  * @property-read Collection|Transaction[]      $transactions | ||||
|  * @property-read mixed                         $destination_account | ||||
|  * @property-read mixed                         $source_account | ||||
|  * @property-read Collection|PiggyBankEvent[]   $piggyBankEvents | ||||
|  * @property-read Collection|Attachment[]       $attachments | ||||
|  * @property-read TransactionCurrency           $transactionCurrency | ||||
|  * @property-read TransactionType               $transactionType | ||||
|  * @property-read Collection|TransactionGroup[] $transactiongroups | ||||
|  * @property-read User                          $user | ||||
|  * @method static Builder|TransactionJournal accountIs($account) | ||||
|  * @method static Builder|TransactionJournal after($date) | ||||
|  * @method static Builder|TransactionJournal before($date) | ||||
|  * @method static Builder|TransactionJournal onDate($date) | ||||
|  * @method static Builder|TransactionJournal transactionTypes($types) | ||||
|  * @method static Builder|TransactionJournal withRelevantData() | ||||
|  */ | ||||
| class TransactionJournal extends Model | ||||
| { | ||||
| @@ -147,10 +127,9 @@ class TransactionJournal extends Model | ||||
|         } | ||||
|  | ||||
|         bcscale(2); | ||||
|         $type        = $this->transactionType->type; | ||||
|         $transaction = $this->transactions->sortByDesc('amount')->first(); | ||||
|         $amount      = $transaction->amount; | ||||
|         if ($type == 'Withdrawal') { | ||||
|         if ($this->isWithdrawal()) { | ||||
|             $amount = $amount * -1; | ||||
|         } | ||||
|         $cache->store($amount); | ||||
| @@ -167,15 +146,15 @@ class TransactionJournal extends Model | ||||
|      */ | ||||
|     protected function amountByTagAdvancePayment(Tag $tag, $amount) | ||||
|     { | ||||
|         if ($this->transactionType->type == 'Withdrawal') { | ||||
|             $others = $tag->transactionJournals()->transactionTypes(['Deposit'])->get(); | ||||
|         if ($this->isWithdrawal()) { | ||||
|             $others = $tag->transactionJournals()->transactionTypes([TransactionType::DEPOSIT])->get(); | ||||
|             foreach ($others as $other) { | ||||
|                 $amount = bcsub($amount, $other->amount_positive); | ||||
|             } | ||||
|  | ||||
|             return $amount; | ||||
|         } | ||||
|         if ($this->transactionType->type == 'Deposit') { | ||||
|         if ($this->isDeposit()) { | ||||
|             return '0'; | ||||
|         } | ||||
|  | ||||
| @@ -190,8 +169,8 @@ class TransactionJournal extends Model | ||||
|      */ | ||||
|     protected function amountByTagBalancingAct($tag, $amount) | ||||
|     { | ||||
|         if ($this->transactionType->type == 'Withdrawal') { | ||||
|             $transfer = $tag->transactionJournals()->transactionTypes(['Transfer'])->first(); | ||||
|         if ($this->isWithdrawal()) { | ||||
|             $transfer = $tag->transactionJournals()->transactionTypes([TransactionType::TRANSFER])->first(); | ||||
|             if ($transfer) { | ||||
|                 $amount = bcsub($amount, $transfer->amount_positive); | ||||
|  | ||||
| @@ -491,4 +470,59 @@ class TransactionJournal extends Model | ||||
|         return $this->belongsTo('FireflyIII\User'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getTransactionType() | ||||
|     { | ||||
|         return $this->transactionType->type; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function isWithdrawal() | ||||
|     { | ||||
|         if (!is_null($this->type)) { | ||||
|             return $this->type == TransactionType::WITHDRAWAL; | ||||
|         } | ||||
|  | ||||
|         return $this->transactionType->isWithdrawal(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function isDeposit() | ||||
|     { | ||||
|         if (!is_null($this->type)) { | ||||
|             return $this->type == TransactionType::DEPOSIT; | ||||
|         } | ||||
|  | ||||
|         return $this->transactionType->isDeposit(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function isTransfer() | ||||
|     { | ||||
|         if (!is_null($this->type)) { | ||||
|             return $this->type == TransactionType::TRANSFER; | ||||
|         } | ||||
|  | ||||
|         return $this->transactionType->isTransfer(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function isOpeningBalance() | ||||
|     { | ||||
|         if (!is_null($this->type)) { | ||||
|             return $this->type == TransactionType::OPENING_BALANCE; | ||||
|         } | ||||
|  | ||||
|         return $this->transactionType->isOpeningBalance(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,21 +0,0 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
|  | ||||
| /** | ||||
|  * Class TransactionRelation | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  */ | ||||
| class TransactionRelation extends Model | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at']; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -1,28 +1,29 @@ | ||||
| <?php namespace FireflyIII\Models; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Illuminate\Database\Eloquent\Collection; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
|  | ||||
| /** | ||||
|  * Class TransactionType | ||||
|  * FireflyIII\Models\TransactionType | ||||
|  * | ||||
|  * @package FireflyIII\Models | ||||
|  * @property integer                                                                               $id | ||||
|  * @property \Carbon\Carbon                                                                        $created_at | ||||
|  * @property \Carbon\Carbon                                                                        $updated_at | ||||
|  * @property \Carbon\Carbon                                                                        $deleted_at | ||||
|  * @property string                                                                                $type | ||||
|  * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionJournals | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionType whereId($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionType whereCreatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionType whereUpdatedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionType whereDeletedAt($value) | ||||
|  * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\TransactionType whereType($value) | ||||
|  * @property integer                              $id | ||||
|  * @property Carbon                               $created_at | ||||
|  * @property Carbon                               $updated_at | ||||
|  * @property Carbon                               $deleted_at | ||||
|  * @property string                               $type | ||||
|  * @property-read Collection|TransactionJournal[] $transactionJournals | ||||
|  */ | ||||
| class TransactionType extends Model | ||||
| { | ||||
|     use SoftDeletes; | ||||
|  | ||||
|     const WITHDRAWAL      = 'Withdrawal'; | ||||
|     const DEPOSIT         = 'Deposit'; | ||||
|     const TRANSFER        = 'Transfer'; | ||||
|     const OPENING_BALANCE = 'Opening balance'; | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
| @@ -31,6 +32,38 @@ class TransactionType extends Model | ||||
|         return ['created_at', 'updated_at', 'deleted_at']; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function isDeposit() | ||||
|     { | ||||
|         return $this->type === TransactionType::DEPOSIT; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function isOpeningBalance() | ||||
|     { | ||||
|         return $this->type === TransactionType::OPENING_BALANCE; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function isTransfer() | ||||
|     { | ||||
|         return $this->type === TransactionType::TRANSFER; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function isWithdrawal() | ||||
|     { | ||||
|         return $this->type === TransactionType::WITHDRAWAL; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\HasMany | ||||
|      */ | ||||
|   | ||||
| @@ -19,7 +19,6 @@ class ConfigServiceProvider extends ServiceProvider | ||||
|      * to overwrite any "vendor" or package configuration that you may want to | ||||
|      * modify before the application handles the incoming request / command. | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|   | ||||
| @@ -47,7 +47,7 @@ class FireflyServiceProvider extends ServiceProvider | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|      * | ||||
|      */ | ||||
|     public function register() | ||||
|     { | ||||
| @@ -83,6 +83,7 @@ class FireflyServiceProvider extends ServiceProvider | ||||
|         $this->app->bind('FireflyIII\Repositories\Account\AccountRepositoryInterface', 'FireflyIII\Repositories\Account\AccountRepository'); | ||||
|         $this->app->bind('FireflyIII\Repositories\Budget\BudgetRepositoryInterface', 'FireflyIII\Repositories\Budget\BudgetRepository'); | ||||
|         $this->app->bind('FireflyIII\Repositories\Category\CategoryRepositoryInterface', 'FireflyIII\Repositories\Category\CategoryRepository'); | ||||
|         $this->app->bind('FireflyIII\Repositories\Category\SingleCategoryRepositoryInterface', 'FireflyIII\Repositories\Category\SingleCategoryRepository'); | ||||
|         $this->app->bind('FireflyIII\Repositories\Journal\JournalRepositoryInterface', 'FireflyIII\Repositories\Journal\JournalRepository'); | ||||
|         $this->app->bind('FireflyIII\Repositories\Bill\BillRepositoryInterface', 'FireflyIII\Repositories\Bill\BillRepository'); | ||||
|         $this->app->bind('FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface', 'FireflyIII\Repositories\PiggyBank\PiggyBankRepository'); | ||||
|   | ||||
| @@ -39,6 +39,8 @@ class RouteServiceProvider extends ServiceProvider | ||||
|      * | ||||
|      * @param  \Illuminate\Routing\Router $router | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.UnusedFormalParameter) | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function map(Router $router) | ||||
|   | ||||
| @@ -14,9 +14,7 @@ use FireflyIII\Models\Preference; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Support\CacheProperties; | ||||
| use Illuminate\Database\Eloquent\Relations\HasMany; | ||||
| use Illuminate\Database\Query\Builder; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
| @@ -25,7 +23,6 @@ use Steam; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @SuppressWarnings(PHPMD.TooManyMethods) | ||||
|  * | ||||
|  * Class AccountRepository | ||||
|  * | ||||
| @@ -41,7 +38,9 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|      */ | ||||
|     public function countAccounts(array $types) | ||||
|     { | ||||
|         return Auth::user()->accounts()->accountTypeIn($types)->count(); | ||||
|         $count = Auth::user()->accounts()->accountTypeIn($types)->count(); | ||||
|  | ||||
|         return $count; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -81,26 +80,40 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|                 return strtolower($account->name); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * This method returns the users credit cards, along with some basic information about the | ||||
|      * balance they have on their CC. To be used in the JSON boxes on the front page that say | ||||
|      * how many bills there are still left to pay. The balance will be saved in field "balance". | ||||
|      * | ||||
|      * To get the balance, the field "date" is necessary. | ||||
|      * | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getCreditCards() | ||||
|     public function getCreditCards(Carbon $date) | ||||
|     { | ||||
|         return Auth::user()->accounts() | ||||
|         $set = Auth::user()->accounts() | ||||
|                    ->hasMetaValue('accountRole', 'ccAsset') | ||||
|                    ->hasMetaValue('ccType', 'monthlyFull') | ||||
|                    ->leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id') | ||||
|                    ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') | ||||
|                    ->whereNull('transactions.deleted_at') | ||||
|                    ->where('transaction_journals.date', '<=', $date->format('Y-m-d')) | ||||
|                    ->groupBy('accounts.id') | ||||
|                    ->get( | ||||
|                        [ | ||||
|                            'accounts.*', | ||||
|                            'ccType.data as ccType', | ||||
|                            'accountRole.data as accountRole' | ||||
|                            'accountRole.data as accountRole', | ||||
|                            DB::Raw('SUM(`transactions`.`amount`) AS `balance`') | ||||
|                        ] | ||||
|                    ); | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -111,8 +124,9 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|      */ | ||||
|     public function getFirstTransaction(TransactionJournal $journal, Account $account) | ||||
|     { | ||||
|         $transaction = $journal->transactions()->where('account_id', $account->id)->first(); | ||||
|  | ||||
|         return $journal->transactions()->where('account_id', $account->id)->first(); | ||||
|         return $transaction; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -122,12 +136,6 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|      */ | ||||
|     public function getFrontpageAccounts(Preference $preference) | ||||
|     { | ||||
|         $cache = new CacheProperties(); | ||||
|         $cache->addProperty($preference->data); | ||||
|         $cache->addProperty('frontPageaccounts'); | ||||
|         if ($cache->has()) { | ||||
|             return $cache->get(); // @codeCoverageIgnore | ||||
|         } | ||||
|         $query = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account']); | ||||
|  | ||||
|         if (count($preference->data) > 0) { | ||||
| @@ -135,9 +143,6 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|         } | ||||
|  | ||||
|         $result = $query->get(['accounts.*']); | ||||
|  | ||||
|         $cache->store($result); | ||||
|  | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
| @@ -154,14 +159,6 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|      */ | ||||
|     public function getFrontpageTransactions(Account $account, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $cache = new CacheProperties(); | ||||
|         $cache->addProperty($account->id); | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         if ($cache->has()) { | ||||
|             return $cache->get(); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $set = Auth::user() | ||||
|                    ->transactionjournals() | ||||
|                    ->with(['transactions']) | ||||
| @@ -172,11 +169,10 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|                    ->before($end) | ||||
|                    ->after($start) | ||||
|                    ->orderBy('transaction_journals.date', 'DESC') | ||||
|                    ->orderBy('transaction_journals.order', 'ASC') | ||||
|                    ->orderBy('transaction_journals.id', 'DESC') | ||||
|                    ->take(10) | ||||
|                    ->get(['transaction_journals.*', 'transaction_currencies.symbol', 'transaction_types.type']); | ||||
|         $cache->store($set); | ||||
|  | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
| @@ -214,27 +210,15 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|      */ | ||||
|     public function getPiggyBankAccounts() | ||||
|     { | ||||
|         $ids        = []; | ||||
|         $start      = clone Session::get('start', new Carbon); | ||||
|         $end        = clone Session::get('end', new Carbon); | ||||
|         $accountIds = DB::table('piggy_banks')->distinct()->get(['piggy_banks.account_id']); | ||||
|         $collection = new Collection(DB::table('piggy_banks')->distinct()->get(['piggy_banks.account_id'])); | ||||
|         $ids        = $collection->pluck('account_id')->toArray(); | ||||
|         $accounts   = new Collection; | ||||
|  | ||||
|         /** @var PiggyBank $id */ | ||||
|         foreach ($accountIds as $id) { | ||||
|             $ids[] = intval($id->account_id); | ||||
|         } | ||||
|  | ||||
|         $cache = new CacheProperties; | ||||
|         $cache->addProperty($ids); | ||||
|         $cache->addProperty('piggyAccounts'); | ||||
|         if ($cache->has()) { | ||||
|             return $cache->get(); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $ids = array_unique($ids); | ||||
|         if (count($ids) > 0) { | ||||
|             $accounts = Auth::user()->accounts()->whereIn('id', $ids)->get(); | ||||
|             $accounts = Auth::user()->accounts()->whereIn('id', $ids)->where('accounts.active', 1)->get(); | ||||
|         } | ||||
|         bcscale(2); | ||||
|  | ||||
| @@ -257,8 +241,6 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         $cache->store($accounts); | ||||
|  | ||||
|         return $accounts; | ||||
|  | ||||
|     } | ||||
| @@ -273,6 +255,7 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|         $accounts = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC') | ||||
|                         ->leftJoin('account_meta', 'account_meta.account_id', '=', 'accounts.id') | ||||
|                         ->where('account_meta.name', 'accountRole') | ||||
|                         ->where('accounts.active', 1) | ||||
|                         ->where('account_meta.data', '"savingAsset"') | ||||
|                         ->get(['accounts.*']); | ||||
|         $start    = clone Session::get('start', new Carbon); | ||||
| @@ -308,44 +291,6 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|         return $accounts; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all transfers TO this account in this range. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getTransfersInRange(Account $account, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $set      = TransactionJournal::whereIn( | ||||
|             'id', function (Builder $q) use ($account, $start, $end) { | ||||
|             $q->select('transaction_journals.id') | ||||
|               ->from('transactions') | ||||
|               ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') | ||||
|               ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') | ||||
|               ->where('transactions.account_id', $account->id) | ||||
|               ->where('transaction_journals.user_id', Auth::user()->id) | ||||
|               ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) | ||||
|               ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) | ||||
|               ->where('transaction_types.type', 'Transfer'); | ||||
|  | ||||
|         } | ||||
|         )->get(); | ||||
|         $filtered = $set->filter( | ||||
|             function (TransactionJournal $journal) use ($account) { | ||||
|                 if ($journal->destination_account->id == $account->id) { | ||||
|                     return $journal; | ||||
|                 } | ||||
|  | ||||
|                 return null; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return $filtered; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $date | ||||
| @@ -372,12 +317,14 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|      */ | ||||
|     public function openingBalanceTransaction(Account $account) | ||||
|     { | ||||
|         return TransactionJournal | ||||
|         $journal = TransactionJournal | ||||
|             ::orderBy('transaction_journals.date', 'ASC') | ||||
|             ->accountIs($account) | ||||
|             ->transactionTypes(['Opening balance']) | ||||
|             ->transactionTypes([TransactionType::OPENING_BALANCE]) | ||||
|             ->orderBy('created_at', 'ASC') | ||||
|             ->first(['transaction_journals.*']); | ||||
|  | ||||
|         return $journal; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -548,7 +495,7 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|      */ | ||||
|     protected function storeInitialBalance(Account $account, Account $opposing, array $data) | ||||
|     { | ||||
|         $transactionType = TransactionType::whereType('Opening balance')->first(); | ||||
|         $transactionType = TransactionType::whereType(TransactionType::OPENING_BALANCE)->first(); | ||||
|         $journal         = TransactionJournal::create( | ||||
|             [ | ||||
|                 'user_id'                 => $data['user'], | ||||
| @@ -588,7 +535,6 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|      * @param Account $account | ||||
|      * @param array   $data | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      */ | ||||
|     protected function updateMetadata(Account $account, array $data) | ||||
|     { | ||||
| @@ -642,4 +588,16 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|  | ||||
|         return $journal; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @deprecated | ||||
|      * | ||||
|      * @param $accountId | ||||
|      * | ||||
|      * @return Account | ||||
|      */ | ||||
|     public function find($accountId) | ||||
|     { | ||||
|         return Auth::user()->accounts()->findOrNew($accountId); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -24,6 +24,15 @@ interface AccountRepositoryInterface | ||||
|      */ | ||||
|     public function countAccounts(array $types); | ||||
|  | ||||
|     /** | ||||
|      * @param $accountId | ||||
|      * | ||||
|      * @deprecated | ||||
|      * | ||||
|      * @return Account | ||||
|      */ | ||||
|     public function find($accountId); | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param Account $moveTo | ||||
| @@ -35,7 +44,7 @@ interface AccountRepositoryInterface | ||||
|     /** | ||||
|      * @param array $types | ||||
|      * | ||||
|      * @return mixed | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getAccounts(array $types); | ||||
|  | ||||
| @@ -48,9 +57,17 @@ interface AccountRepositoryInterface | ||||
|     public function getFirstTransaction(TransactionJournal $journal, Account $account); | ||||
|  | ||||
|     /** | ||||
|      * This method returns the users credit cards, along with some basic information about the | ||||
|      * balance they have on their CC. To be used in the JSON boxes on the front page that say | ||||
|      * how many bills there are still left to pay. The balance will be saved in field "balance". | ||||
|      * | ||||
|      * To get the balance, the field "date" is necessary. | ||||
|      * | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getCreditCards(); | ||||
|     public function getCreditCards(Carbon $date); | ||||
|  | ||||
|     /** | ||||
|      * Get the accounts of a user that have piggy banks connected to them. | ||||
| @@ -59,18 +76,6 @@ interface AccountRepositoryInterface | ||||
|      */ | ||||
|     public function getPiggyBankAccounts(); | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Get all transfers TO this account in this range. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getTransfersInRange(Account $account, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Preference $preference | ||||
|      * | ||||
|   | ||||
| @@ -5,13 +5,16 @@ namespace FireflyIII\Repositories\Bill; | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use DB; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use Illuminate\Database\Query\Builder; | ||||
| use Illuminate\Database\Query\JoinClause; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
| use Navigation; | ||||
| use Steam; | ||||
|  | ||||
| /** | ||||
|  * Class BillRepository | ||||
| @@ -20,52 +23,6 @@ use Steam; | ||||
|  */ | ||||
| class BillRepository implements BillRepositoryInterface | ||||
| { | ||||
|     /** | ||||
|      * Returns the sum of all payments connected to this bill between the dates. | ||||
|      * | ||||
|      * @param Bill   $bill | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return integer | ||||
|      */ | ||||
|     public function billPaymentsInRange(Bill $bill, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $amount   = 0; | ||||
|         $journals = $bill->transactionjournals()->before($end)->after($start)->get(); | ||||
|         /** @var TransactionJournal $journal */ | ||||
|         foreach ($journals as $journal) { | ||||
|             $amount += $journal->amount; | ||||
|         } | ||||
|  | ||||
|         return $amount; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Create a fake bill to help the chart controller. | ||||
|      * | ||||
|      * @param string $description | ||||
|      * @param Carbon $date | ||||
|      * @param float  $amount | ||||
|      * | ||||
|      * @return Bill | ||||
|      */ | ||||
|     public function createFakeBill($description, Carbon $date, $amount) | ||||
|     { | ||||
|         $bill              = new Bill; | ||||
|         $bill->name        = $description; | ||||
|         $bill->match       = $description; | ||||
|         $bill->amount_min  = $amount; | ||||
|         $bill->amount_max  = $amount; | ||||
|         $bill->date        = $date; | ||||
|         $bill->repeat_freq = 'monthly'; | ||||
|         $bill->skip        = 0; | ||||
|         $bill->automatch   = false; | ||||
|         $bill->active      = false; | ||||
|  | ||||
|         return $bill; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
| @@ -78,16 +35,40 @@ class BillRepository implements BillRepositoryInterface | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns all journals connected to these bills in the given range. Amount paid | ||||
|      * is stored in "journalAmount" as a negative number. | ||||
|      * | ||||
|      * @param Collection $bills | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getActiveBills() | ||||
|     public function getAllJournalsInRange(Collection $bills, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         /** @var Collection $set */ | ||||
|         $set = Auth::user()->bills()->orderBy('name', 'ASC')->where('active', 1)->get()->sortBy('name'); | ||||
|         $ids = $bills->pluck('id')->toArray(); | ||||
|  | ||||
|         $set = Auth::user()->transactionjournals() | ||||
|                    ->leftJoin( | ||||
|                        'transactions', function (JoinClause $join) { | ||||
|                        $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0); | ||||
|                    } | ||||
|                    ) | ||||
|                    ->whereIn('bill_id', $ids) | ||||
|                    ->before($end) | ||||
|                    ->after($start) | ||||
|                    ->groupBy('transaction_journals.bill_id') | ||||
|                    ->get( | ||||
|                        [ | ||||
|                            'transaction_journals.bill_id', | ||||
|                            DB::Raw('SUM(`transactions`.`amount`) as `journalAmount`') | ||||
|                        ] | ||||
|                    ); | ||||
|  | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
| @@ -109,22 +90,70 @@ class BillRepository implements BillRepositoryInterface | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getBillsForAccounts(Collection $accounts) | ||||
|     { | ||||
|         $ids = $accounts->pluck('id')->toArray(); | ||||
|         $set = Auth::user()->bills() | ||||
|                    ->leftJoin( | ||||
|                        'transaction_journals', function (JoinClause $join) { | ||||
|                        $join->on('transaction_journals.bill_id', '=', 'bills.id')->whereNull('transaction_journals.deleted_at'); | ||||
|                    } | ||||
|                    ) | ||||
|                    ->leftJoin( | ||||
|                        'transactions', function (JoinClause $join) { | ||||
|                        $join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0); | ||||
|                    } | ||||
|                    ) | ||||
|                    ->whereIn('transactions.account_id', $ids) | ||||
|                    ->whereNull('transaction_journals.deleted_at') | ||||
|                    ->groupBy('bills.id') | ||||
|                    ->get(['bills.*']); | ||||
|  | ||||
|         $set = $set->sortBy( | ||||
|             function (Bill $bill) { | ||||
|  | ||||
|                 $int = $bill->active == 1 ? 0 : 1; | ||||
|  | ||||
|                 return $int . strtolower($bill->name); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method also returns the amount of the journal in "journalAmount" | ||||
|      * for easy access. | ||||
|      * | ||||
|      * @param Bill $bill | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getJournals(Bill $bill) | ||||
|     { | ||||
|         return $bill->transactionjournals()->withRelevantData() | ||||
|         $set = $bill->transactionjournals() | ||||
|                     ->leftJoin( | ||||
|                         'transactions', function (JoinClause $join) { | ||||
|                         $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                              ->where('amount', '<', 0); | ||||
|                     } | ||||
|                     ) | ||||
|                     ->orderBy('transaction_journals.date', 'DESC') | ||||
|                     ->orderBy('transaction_journals.order', 'ASC') | ||||
|                     ->orderBy('transaction_journals.id', 'DESC') | ||||
|                     ->get(['transaction_journals.*']); | ||||
|                     ->get(['transaction_journals.*', 'transactions.amount as journalAmount']); | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all journals that were recorded on this bill between these dates. | ||||
|      * | ||||
|      * @deprecated | ||||
|      * | ||||
|      * @param Bill   $bill | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
| @@ -146,15 +175,11 @@ class BillRepository implements BillRepositoryInterface | ||||
|         $set = DB::table('transactions')->where('amount', '>', 0)->where('amount', '>=', $bill->amount_min)->where('amount', '<=', $bill->amount_max)->get( | ||||
|             ['transaction_journal_id'] | ||||
|         ); | ||||
|         $ids = []; | ||||
|         $ids = $set->pluck('transaction_journal_id')->toArray(); | ||||
|  | ||||
|         /** @var Transaction $entry */ | ||||
|         foreach ($set as $entry) { | ||||
|             $ids[] = intval($entry->transaction_journal_id); | ||||
|         } | ||||
|         $journals = new Collection; | ||||
|         if (count($ids) > 0) { | ||||
|             $journals = Auth::user()->transactionjournals()->transactionTypes(['Withdrawal'])->whereIn('transaction_journals.id', $ids)->get( | ||||
|             $journals = Auth::user()->transactionjournals()->transactionTypes([TransactionType::WITHDRAWAL])->whereIn('transaction_journals.id', $ids)->get( | ||||
|                 ['transaction_journals.*'] | ||||
|             ); | ||||
|         } | ||||
| @@ -276,12 +301,21 @@ class BillRepository implements BillRepositoryInterface | ||||
|      */ | ||||
|     public function scan(Bill $bill, TransactionJournal $journal) | ||||
|     { | ||||
|  | ||||
|         /* | ||||
|          * Can only support withdrawals. | ||||
|          */ | ||||
|         if (false === $journal->isWithdrawal()) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         $matches     = explode(',', $bill->match); | ||||
|         $description = strtolower($journal->description) . ' ' . strtolower($journal->destination_account->name); | ||||
|         $wordMatch   = $this->doWordMatch($matches, $description); | ||||
|         $amountMatch = $this->doAmountMatch($journal->amount_positive, $bill->amount_min, $bill->amount_max); | ||||
|         Log::debug('Journal #' . $journal->id . ' has description "' . $description . '"'); | ||||
|  | ||||
|  | ||||
|         /* | ||||
|          * If both, update! | ||||
|          */ | ||||
| @@ -396,82 +430,141 @@ class BillRepository implements BillRepositoryInterface | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Gets a collection of paid bills and a collection of unpaid bills to be used | ||||
|      * in the pie chart on the front page. | ||||
|      * Get the total amount of money paid for the users active bills in the date range given. | ||||
|      * This amount will be negative (they're expenses). | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getBillsForChart(Carbon $start, Carbon $end) | ||||
|     public function getBillsPaidInRange(Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $paid   = new Collection; | ||||
|         $unpaid = new Collection; | ||||
|         $amount = '0'; | ||||
|         $bills  = $this->getActiveBills(); | ||||
|  | ||||
|         $bills = $this->getActiveBills(); | ||||
|         /** @var Bill $bill */ | ||||
|         foreach ($bills as $bill) { | ||||
|             $ranges = $this->getRanges($bill, $start, $end); | ||||
|  | ||||
|             foreach ($ranges as $range) { | ||||
|                 // paid a bill in this range? | ||||
|                 $journals = $this->getJournalsInRange($bill, $range['start'], $range['end']); | ||||
|                 if ($journals->count() == 0) { | ||||
|                     $unpaid->push([$bill, $range['start']]); | ||||
|                 } else { | ||||
|                     $paid = $paid->merge($journals); | ||||
|                 } | ||||
|  | ||||
|                 $paid   = $bill->transactionjournals() | ||||
|                                ->before($range['end']) | ||||
|                                ->after($range['start']) | ||||
|                                ->leftJoin( | ||||
|                                    'transactions', function (JoinClause $join) { | ||||
|                                    $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0); | ||||
|                                } | ||||
|                                ) | ||||
|                                ->first([DB::Raw('SUM(`transactions`.`amount`) as `sum_amount`')]); | ||||
|                 $amount = bcadd($amount, $paid->sum_amount); | ||||
|             } | ||||
|         } | ||||
|         $set = new Collection; | ||||
|         $set->put('paid', $paid); | ||||
|         $set->put('unpaid', $unpaid); | ||||
|  | ||||
|         return $set; | ||||
|         return $amount; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Takes the paid/unpaid bills collection set up before and expands it using | ||||
|      * credit cards the user might have. | ||||
|      * | ||||
|      * @param Collection $set | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getCreditCardInfoForChart(Collection $set, Carbon $start, Carbon $end) | ||||
|     public function getActiveBills() | ||||
|     { | ||||
|  | ||||
|         $accounts    = app('FireflyIII\Repositories\Account\AccountRepositoryInterface'); | ||||
|         $creditCards = $accounts->getCreditCards(); | ||||
|         $paid        = $set->get('paid'); | ||||
|         $unpaid      = $set->get('unpaid'); | ||||
|  | ||||
|         foreach ($creditCards as $creditCard) { | ||||
|             $balance = Steam::balance($creditCard, $end, true); | ||||
|             $date    = new Carbon($creditCard->getMeta('ccMonthlyPaymentDate')); | ||||
|             if ($balance < 0) { | ||||
|                 // unpaid! create a fake bill that matches the amount. | ||||
|                 $description = $creditCard->name; | ||||
|                 $amount      = $balance * -1; | ||||
|                 $fakeBill    = $this->createFakeBill($description, $date, $amount); | ||||
|                 unset($description, $amount); | ||||
|                 $unpaid->push([$fakeBill, $date]); | ||||
|             } | ||||
|             if ($balance == 0) { | ||||
|                 // find transfer(s) TO the credit card which should account for | ||||
|                 // anything paid. If not, the CC is not yet used. | ||||
|                 $journals = $accounts->getTransfersInRange($creditCard, $start, $end); | ||||
|                 $paid     = $paid->merge($journals); | ||||
|             } | ||||
|         } | ||||
|         $set = new Collection; | ||||
|         $set->put('paid', $paid); | ||||
|         $set->put('unpaid', $unpaid); | ||||
|         /** @var Collection $set */ | ||||
|         $set = Auth::user()->bills() | ||||
|                    ->where('active', 1) | ||||
|                    ->get( | ||||
|                        [ | ||||
|                            'bills.*', | ||||
|                            DB::Raw('(`bills`.`amount_min` + `bills`.`amount_max` / 2) as `expectedAmount`') | ||||
|                        ] | ||||
|                    )->sortBy('name'); | ||||
|  | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Get the total amount of money due for the users active bills in the date range given. This amount will be positive. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getBillsUnpaidInRange(Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $amount = '0'; | ||||
|         $bills  = $this->getActiveBills(); | ||||
|  | ||||
|         /** @var Bill $bill */ | ||||
|         foreach ($bills as $bill) { | ||||
|             $ranges   = $this->getRanges($bill, $start, $end); | ||||
|             $paidBill = '0'; | ||||
|             foreach ($ranges as $range) { | ||||
|                 $paid     = $bill->transactionjournals() | ||||
|                                  ->before($range['end']) | ||||
|                                  ->after($range['start']) | ||||
|                                  ->leftJoin( | ||||
|                                      'transactions', function (JoinClause $join) { | ||||
|                                      $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '>', 0); | ||||
|                                  } | ||||
|                                  ) | ||||
|                                  ->first([DB::Raw('SUM(`transactions`.`amount`) as `sum_amount`')]); | ||||
|                 $paidBill = bcadd($paid->sum_amount, $paidBill); | ||||
|             } | ||||
|             if ($paidBill == 0) { | ||||
|                 $amount = bcadd($amount, $bill->expectedAmount); | ||||
|             } | ||||
|         } | ||||
|         return $amount; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method will tell you if you still have a CC bill to pay. Amount will be positive if the amount | ||||
|      * has been paid, otherwise it will be negative. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getCreditCardBill(Carbon $start, Carbon $end) | ||||
|     { | ||||
|  | ||||
|         /** @var AccountRepositoryInterface $accountRepository */ | ||||
|         $accountRepository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface'); | ||||
|         $amount            = '0'; | ||||
|         $creditCards       = $accountRepository->getCreditCards($end); // Find credit card accounts and possibly unpaid credit card bills. | ||||
|         /** @var Account $creditCard */ | ||||
|         foreach ($creditCards as $creditCard) { | ||||
|             if ($creditCard->balance == 0) { | ||||
|                 // find a transfer TO the credit card which should account for | ||||
|                 // anything paid. If not, the CC is not yet used. | ||||
|                 $set = TransactionJournal::whereIn( | ||||
|                     'transaction_journals.id', function (Builder $q) use ($creditCard, $start, $end) { | ||||
|                     $q->select('transaction_journals.id') | ||||
|                       ->from('transactions') | ||||
|                       ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') | ||||
|                       ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') | ||||
|                       ->where('transactions.account_id', $creditCard->id) | ||||
|                       ->where('transactions.amount', '>', 0)// this makes the filter unnecessary. | ||||
|                       ->where('transaction_journals.user_id', Auth::user()->id) | ||||
|                       ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) | ||||
|                       ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) | ||||
|                       ->where('transaction_types.type', TransactionType::TRANSFER); | ||||
|                 } | ||||
|                 )->leftJoin( | ||||
|                     'transactions', function (JoinClause $join) { | ||||
|                     $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '>', 0); | ||||
|                 } | ||||
|                 )->first([DB::Raw('SUM(`transactions`.`amount`) as `sum_amount`')]); | ||||
|  | ||||
|                 $amount = bcadd($amount, $set->sum_amount); | ||||
|             } else { | ||||
|                 $amount = bcadd($amount, $creditCard->balance); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $amount; | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -16,49 +16,41 @@ interface BillRepositoryInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Takes the paid/unpaid bills collection set up before and expands it using | ||||
|      * credit cards the user might have. | ||||
|      * | ||||
|      * @param Collection $set | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getCreditCardInfoForChart(Collection $set, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * Gets a collection of paid bills and a collection of unpaid bills to be used | ||||
|      * in the pie chart on the front page. | ||||
|      * This method will tell you if you still have a CC bill to pay. Amount will be negative if the amount | ||||
|      * has been paid | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getBillsForChart(Carbon $start, Carbon $end); | ||||
|     public function getCreditCardBill(Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * Returns the sum of all payments connected to this bill between the dates. | ||||
|      * Get the total amount of money paid for the users active bills in the date range given. | ||||
|      * | ||||
|      * @param Bill   $bill | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return float | ||||
|      * @return string | ||||
|      */ | ||||
|     public function billPaymentsInRange(Bill $bill, Carbon $start, Carbon $end); | ||||
|     public function getBillsPaidInRange(Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * Create a fake bill to help the chart controller. | ||||
|      * Get the total amount of money due for the users active bills in the date range given. | ||||
|      * | ||||
|      * @param string $description | ||||
|      * @param Carbon $date | ||||
|      * @param float  $amount | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Bill | ||||
|      * @return string | ||||
|      */ | ||||
|     public function createFakeBill($description, Carbon $date, $amount); | ||||
|     public function getBillsUnpaidInRange(Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getActiveBills(); | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
| @@ -68,15 +60,32 @@ interface BillRepositoryInterface | ||||
|     public function destroy(Bill $bill); | ||||
|  | ||||
|     /** | ||||
|      * Returns all journals connected to these bills in the given range. Amount paid | ||||
|      * is stored in "journalAmount" as a negative number. | ||||
|      * | ||||
|      * @param Collection $bills | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getActiveBills(); | ||||
|     public function getAllJournalsInRange(Collection $bills, Carbon $start, Carbon $end); | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getBills(); | ||||
|  | ||||
|     /** | ||||
|      * Gets the bills which have some kind of relevance to the accounts mentioned. | ||||
|      * | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getBillsForAccounts(Collection $accounts); | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      * | ||||
| @@ -105,7 +114,7 @@ interface BillRepositoryInterface | ||||
|     /** | ||||
|      * Every bill repeats itself weekly, monthly or yearly (or whatever). This method takes a date-range (usually the view-range of Firefly itself) | ||||
|      * and returns date ranges that fall within the given range; those ranges are the bills expected. When a bill is due on the 14th of the month and | ||||
|      * you give 1st and the 31st of that month as argument, you'll get one response, matching the range of your bill. | ||||
|      * you give 1st and the 31st of that month as argument, you'll get one response, matching the range of your bill (from the 14th to the 31th). | ||||
|      * | ||||
|      * @param Bill   $bill | ||||
|      * @param Carbon $start | ||||
|   | ||||
| @@ -4,12 +4,15 @@ namespace FireflyIII\Repositories\Budget; | ||||
|  | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use DB; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\BudgetLimit; | ||||
| use FireflyIII\Models\LimitRepetition; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Repositories\Shared\ComponentRepository; | ||||
| use FireflyIII\Support\CacheProperties; | ||||
| use Illuminate\Database\Eloquent\Builder; | ||||
| use Illuminate\Database\Query\Builder as QueryBuilder; | ||||
| use Illuminate\Database\Query\JoinClause; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use Illuminate\Support\Collection; | ||||
| use Input; | ||||
| @@ -32,6 +35,67 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the expenses for this budget grouped per day, with the date | ||||
|      * in "date" (a string, not a Carbon) and the amount in "dailyAmount". | ||||
|      * | ||||
|      * @param Budget $budget | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getExpensesPerDay(Budget $budget, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $set = Auth::user()->budgets() | ||||
|                    ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.budget_id', '=', 'budgets.id') | ||||
|                    ->leftJoin('transaction_journals', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                    ->leftJoin('transactions', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') | ||||
|                    ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) | ||||
|                    ->whereNull('transaction_journals.deleted_at') | ||||
|                    ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) | ||||
|                    ->where('budgets.id', $budget->id) | ||||
|                    ->where('transactions.amount', '<', 0) | ||||
|                    ->groupBy('transaction_journals.date') | ||||
|                    ->orderBy('transaction_journals.date') | ||||
|                    ->get(['transaction_journals.date', DB::Raw('SUM(`transactions`.`amount`) as `dailyAmount`')]); | ||||
|  | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the expenses for this budget grouped per month, with the date | ||||
|      * in "dateFormatted" (a string, not a Carbon) and the amount in "dailyAmount". | ||||
|      * | ||||
|      * @param Budget $budget | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getExpensesPerMonth(Budget $budget, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $set = Auth::user()->budgets() | ||||
|                    ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.budget_id', '=', 'budgets.id') | ||||
|                    ->leftJoin('transaction_journals', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                    ->leftJoin('transactions', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') | ||||
|                    ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) | ||||
|                    ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) | ||||
|                    ->whereNull('transaction_journals.deleted_at') | ||||
|                    ->where('budgets.id', $budget->id) | ||||
|                    ->where('transactions.amount', '<', 0) | ||||
|                    ->groupBy('dateFormatted') | ||||
|                    ->orderBy('transaction_journals.date') | ||||
|                    ->get( | ||||
|                        [ | ||||
|                            DB::Raw('DATE_FORMAT(`transaction_journals`.`date`, "%Y-%m") AS `dateFormatted`'), | ||||
|                            DB::Raw('SUM(`transactions`.`amount`) as `monthlyAmount`') | ||||
|                        ] | ||||
|                    ); | ||||
|  | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * | ||||
| @@ -44,20 +108,6 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function expensesOnDayCorrected(Budget $budget, Carbon $date) | ||||
|     { | ||||
|         bcscale(2); | ||||
|         $sum = $budget->transactionjournals()->transactionTypes(['Withdrawal'])->onDate($date)->get(['transaction_journals.*'])->sum('amount'); | ||||
|  | ||||
|         return $sum; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
| @@ -76,31 +126,113 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * Returns a list of budgets, budget limits and limit repetitions | ||||
|      * (doubling any of them in a left join) | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getBudgetLimitRepetitions(Budget $budget, Carbon $start, Carbon $end) | ||||
|     public function getBudgetsAndLimitsInRange(Carbon $start, Carbon $end) | ||||
|     { | ||||
|         /** @var Collection $repetitions */ | ||||
|         return LimitRepetition:: | ||||
|         leftJoin('budget_limits', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id') | ||||
|                               ->where('limit_repetitions.startdate', '<=', $end->format('Y-m-d 00:00:00')) | ||||
|                               ->where('limit_repetitions.startdate', '>=', $start->format('Y-m-d 00:00:00')) | ||||
|                               ->where('budget_limits.budget_id', $budget->id) | ||||
|                               ->get(['limit_repetitions.*']); | ||||
|         /** @var Collection $set */ | ||||
|         $set = Auth::user() | ||||
|                    ->budgets() | ||||
|                    ->leftJoin('budget_limits', 'budget_limits.budget_id', '=', 'budgets.id') | ||||
|                    ->leftJoin('limit_repetitions', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id') | ||||
|                    ->where( | ||||
|                        function (Builder $query) use ($start, $end) { | ||||
|                            $query->where( | ||||
|                                function (Builder $query) use ($start, $end) { | ||||
|                                    $query->where('limit_repetitions.startdate', '>=', $start->format('Y-m-d')); | ||||
|                                    $query->where('limit_repetitions.startdate', '<=', $end->format('Y-m-d')); | ||||
|                                } | ||||
|                            ); | ||||
|                            $query->orWhere( | ||||
|                                function (Builder $query) { | ||||
|                                    $query->whereNull('limit_repetitions.startdate'); | ||||
|                                    $query->whereNull('limit_repetitions.enddate'); | ||||
|                                } | ||||
|                            ); | ||||
|                        } | ||||
|                    ) | ||||
|                    ->get(['budgets.*', 'limit_repetitions.startdate', 'limit_repetitions.enddate', 'limit_repetitions.amount']); | ||||
|  | ||||
|         $set = $set->sortBy( | ||||
|             function (Budget $budget) { | ||||
|                 return strtolower($budget->name); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return $set; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return Carbon | ||||
|      */ | ||||
|     public function firstActivity(Budget $budget) | ||||
|     { | ||||
|         $first = $budget->transactionjournals()->orderBy('date', 'ASC')->first(); | ||||
|         if ($first) { | ||||
|             return $first->date; | ||||
|         } | ||||
|  | ||||
|         return new Carbon; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getBudgetLimits(Budget $budget) | ||||
|     public function getAllBudgetLimitRepetitions(Carbon $start, Carbon $end) | ||||
|     { | ||||
|         return $budget->budgetLimits()->orderBy('startdate', 'DESC')->get(); | ||||
|         /** @var Collection $repetitions */ | ||||
|         return LimitRepetition:: | ||||
|         leftJoin('budget_limits', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id') | ||||
|                               ->leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id') | ||||
|                               ->where('limit_repetitions.startdate', '<=', $end->format('Y-m-d 00:00:00')) | ||||
|                               ->where('limit_repetitions.startdate', '>=', $start->format('Y-m-d 00:00:00')) | ||||
|                               ->where('budgets.user_id', Auth::user()->id) | ||||
|                               ->get(['limit_repetitions.*', 'budget_limits.budget_id']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns an array with the following key:value pairs: | ||||
|      * | ||||
|      * yyyy-mm-dd:<amount> | ||||
|      * | ||||
|      * Where yyyy-mm-dd is the date and <amount> is the money spent using DEPOSITS in the $budget | ||||
|      * from all the users accounts. | ||||
|      * | ||||
|      * @param Budget $budget | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function spentPerDay(Budget $budget, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         /** @var Collection $query */ | ||||
|         $query = $budget->transactionJournals() | ||||
|                         ->transactionTypes([TransactionType::WITHDRAWAL]) | ||||
|                         ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                         ->where('transactions.amount', '<', 0) | ||||
|                         ->before($end) | ||||
|                         ->after($start) | ||||
|                         ->groupBy('dateFormatted')->get(['transaction_journals.date as dateFormatted', DB::Raw('SUM(`transactions`.`amount`) AS `sum`')]); | ||||
|  | ||||
|         $return = []; | ||||
|         foreach ($query->toArray() as $entry) { | ||||
|             $return[$entry['dateFormatted']] = $entry['sum']; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -129,21 +261,10 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn | ||||
|      */ | ||||
|     public function getCurrentRepetition(Budget $budget, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $cache = new CacheProperties; | ||||
|         $cache->addProperty($budget->id); | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|  | ||||
|         $cache->addProperty('getCurrentRepetition'); | ||||
|         if ($cache->has()) { | ||||
|             return $cache->get(); // @codeCoverageIgnore | ||||
|         } | ||||
|         $data = $budget->limitrepetitions() | ||||
|                        ->where('limit_repetitions.startdate', $start) | ||||
|                        ->where('limit_repetitions.enddate', $end) | ||||
|                        ->where('limit_repetitions.startdate', $start->format('Y-m-d 00:00:00')) | ||||
|                        ->where('limit_repetitions.enddate', $end->format('Y-m-d 00:00:00')) | ||||
|                        ->first(['limit_repetitions.*']); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
| @@ -162,6 +283,64 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn | ||||
|         return Carbon::now()->startOfYear(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns an array with every budget in it and the expenses for each budget | ||||
|      * per month. | ||||
|      * | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getBudgetsAndExpensesPerMonth(Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $ids = $accounts->pluck('id')->toArray(); | ||||
|  | ||||
|         /** @var Collection $set */ | ||||
|         $set = Auth::user()->budgets() | ||||
|                    ->leftJoin('budget_transaction_journal', 'budgets.id', '=', 'budget_transaction_journal.budget_id') | ||||
|                    ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'budget_transaction_journal.transaction_journal_id') | ||||
|                    ->leftJoin( | ||||
|                        'transactions', function (JoinClause $join) { | ||||
|                        $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0); | ||||
|                    } | ||||
|                    ) | ||||
|                    ->groupBy('budgets.id') | ||||
|                    ->groupBy('dateFormatted') | ||||
|                    ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) | ||||
|                    ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) | ||||
|                    ->whereIn('transactions.account_id', $ids) | ||||
|                    ->get( | ||||
|                        [ | ||||
|                            'budgets.*', | ||||
|                            DB::Raw('DATE_FORMAT(`transaction_journals`.`date`, "%Y-%m") AS `dateFormatted`'), | ||||
|                            DB::Raw('SUM(`transactions`.`amount`) AS `sumAmount`') | ||||
|                        ] | ||||
|                    ); | ||||
|  | ||||
|         $set = $set->sortBy( | ||||
|             function (Budget $budget) { | ||||
|                 return strtolower($budget->name); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         $return = []; | ||||
|         foreach ($set as $budget) { | ||||
|             $id = $budget->id; | ||||
|             if (!isset($return[$id])) { | ||||
|                 $return[$id] = [ | ||||
|                     'budget'  => $budget, | ||||
|                     'entries' => [], | ||||
|                 ]; | ||||
|             } | ||||
|             // store each entry: | ||||
|             $return[$id]['entries'][$budget->dateFormatted] = $budget->sumAmount; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
| @@ -190,17 +369,6 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn | ||||
|      */ | ||||
|     public function getJournals(Budget $budget, LimitRepetition $repetition = null, $take = 50) | ||||
|     { | ||||
|         $cache = new CacheProperties; | ||||
|         $cache->addProperty($budget->id); | ||||
|         if ($repetition) { | ||||
|             $cache->addProperty($repetition->id); | ||||
|         } | ||||
|         $cache->addProperty($take); | ||||
|         $cache->addProperty('getJournals'); | ||||
|         if ($cache->has()) { | ||||
|             return $cache->get(); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $offset     = intval(Input::get('page')) > 0 ? intval(Input::get('page')) * $take : 0; | ||||
|         $setQuery   = $budget->transactionJournals()->withRelevantData()->take($take)->offset($offset) | ||||
|                              ->orderBy('transaction_journals.date', 'DESC') | ||||
| @@ -220,46 +388,10 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn | ||||
|  | ||||
|  | ||||
|         $paginator = new LengthAwarePaginator($set, $count, $take, $offset); | ||||
|         $cache->store($paginator); | ||||
|  | ||||
|         return $paginator; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return Carbon | ||||
|      */ | ||||
|     public function getLastBudgetLimitDate(Budget $budget) | ||||
|     { | ||||
|         $limit = $budget->budgetlimits()->orderBy('startdate', 'DESC')->first(); | ||||
|         if ($limit) { | ||||
|             return $limit->startdate; | ||||
|         } | ||||
|  | ||||
|         return Carbon::now()->startOfYear(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return float|null | ||||
|      */ | ||||
|     public function getLimitAmountOnDate(Budget $budget, Carbon $date) | ||||
|     { | ||||
|         $repetition = LimitRepetition::leftJoin('budget_limits', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id') | ||||
|                                      ->where('limit_repetitions.startdate', $date->format('Y-m-d 00:00:00')) | ||||
|                                      ->where('budget_limits.budget_id', $budget->id) | ||||
|                                      ->first(['limit_repetitions.*']); | ||||
|  | ||||
|         if ($repetition) { | ||||
|             return $repetition->amount; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
| @@ -288,40 +420,43 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn | ||||
|      */ | ||||
|     public function getWithoutBudgetSum(Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $noBudgetSet = Auth::user() | ||||
|                            ->transactionjournals() | ||||
|                            ->whereNotIn( | ||||
|                                'transaction_journals.id', function (QueryBuilder $query) use ($start, $end) { | ||||
|                                $query | ||||
|                                    ->select('transaction_journals.id') | ||||
|                                    ->from('transaction_journals') | ||||
|                                    ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                                    ->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00')) | ||||
|                                    ->where('transaction_journals.date', '<=', $end->format('Y-m-d 00:00:00')) | ||||
|                                    ->whereNotNull('budget_transaction_journal.budget_id'); | ||||
|                            } | ||||
|                            ) | ||||
|                            ->after($start) | ||||
|                            ->before($end) | ||||
|                            ->transactionTypes(['Withdrawal']) | ||||
|                            ->get(['transaction_journals.*'])->sum('amount'); | ||||
|         $entry = Auth::user() | ||||
|                      ->transactionjournals() | ||||
|                      ->whereNotIn( | ||||
|                          'transaction_journals.id', function (QueryBuilder $query) use ($start, $end) { | ||||
|                          $query | ||||
|                              ->select('transaction_journals.id') | ||||
|                              ->from('transaction_journals') | ||||
|                              ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                              ->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00')) | ||||
|                              ->where('transaction_journals.date', '<=', $end->format('Y-m-d 00:00:00')) | ||||
|                              ->whereNotNull('budget_transaction_journal.budget_id'); | ||||
|                      } | ||||
|                      ) | ||||
|                      ->after($start) | ||||
|                      ->before($end) | ||||
|                      ->leftJoin( | ||||
|                          'transactions', function (JoinClause $join) { | ||||
|                          $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0); | ||||
|                      } | ||||
|                      ) | ||||
|                      ->transactionTypes([TransactionType::WITHDRAWAL]) | ||||
|                      ->first([DB::Raw('SUM(`transactions`.`amount`) as `journalAmount`')]); | ||||
|  | ||||
|         bcscale(2); | ||||
|  | ||||
|         return bcmul($noBudgetSet, -1); | ||||
|         return $entry->journalAmount; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $shared | ||||
|      * @param Budget     $budget | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function balanceInPeriod(Budget $budget, Carbon $start, Carbon $end, $shared = true) | ||||
|     public function balanceInPeriod(Budget $budget, Carbon $start, Carbon $end, Collection $accounts) | ||||
|     { | ||||
|         return $this->commonBalanceInPeriod($budget, $start, $end, $shared); | ||||
|         return $this->commonBalanceInPeriod($budget, $start, $end, $accounts); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -395,7 +530,197 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn | ||||
|         } | ||||
|  | ||||
|         return $limit; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the budgeted amounts for each budgets in each year. | ||||
|      * | ||||
|      * @param Collection $budgets | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getBudgetedPerYear(Collection $budgets, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $budgetIds = $budgets->pluck('id')->toArray(); | ||||
|  | ||||
|         $set = Auth::user()->budgets() | ||||
|                    ->leftJoin('budget_limits', 'budgets.id', '=', 'budget_limits.budget_id') | ||||
|                    ->leftJoin('limit_repetitions', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id') | ||||
|                    ->where('limit_repetitions.startdate', '>=', $start->format('Y-m-d')) | ||||
|                    ->where('limit_repetitions.enddate', '<=', $end->format('Y-m-d')) | ||||
|                    ->groupBy('budgets.id') | ||||
|                    ->groupBy('dateFormatted') | ||||
|                    ->whereIn('budgets.id', $budgetIds) | ||||
|                    ->get( | ||||
|                        [ | ||||
|                            'budgets.*', | ||||
|                            DB::Raw('DATE_FORMAT(`limit_repetitions`.`startdate`,"%Y") as `dateFormatted`'), | ||||
|                            DB::Raw('SUM(`limit_repetitions`.`amount`) as `budgeted`') | ||||
|                        ] | ||||
|                    ); | ||||
|  | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns an array with every budget in it and the expenses for each budget | ||||
|      * per year for. | ||||
|      * | ||||
|      * @param Collection $budgets | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getBudgetsAndExpensesPerYear(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $ids       = $accounts->pluck('id')->toArray(); | ||||
|         $budgetIds = $budgets->pluck('id')->toArray(); | ||||
|  | ||||
|         /** @var Collection $set */ | ||||
|         $set = Auth::user()->budgets() | ||||
|                    ->leftJoin('budget_transaction_journal', 'budgets.id', '=', 'budget_transaction_journal.budget_id') | ||||
|                    ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'budget_transaction_journal.transaction_journal_id') | ||||
|                    ->leftJoin( | ||||
|                        'transactions', function (JoinClause $join) { | ||||
|                        $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0); | ||||
|                    } | ||||
|                    ) | ||||
|                    ->groupBy('budgets.id') | ||||
|                    ->groupBy('dateFormatted') | ||||
|                    ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) | ||||
|                    ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) | ||||
|                    ->whereIn('transactions.account_id', $ids) | ||||
|                    ->whereIn('budgets.id', $budgetIds) | ||||
|                    ->get( | ||||
|                        [ | ||||
|                            'budgets.*', | ||||
|                            DB::Raw('DATE_FORMAT(`transaction_journals`.`date`, "%Y") AS `dateFormatted`'), | ||||
|                            DB::Raw('SUM(`transactions`.`amount`) AS `sumAmount`') | ||||
|                        ] | ||||
|                    ); | ||||
|  | ||||
|         $set = $set->sortBy( | ||||
|             function (Budget $budget) { | ||||
|                 return strtolower($budget->name); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         $return = []; | ||||
|         foreach ($set as $budget) { | ||||
|             $id = $budget->id; | ||||
|             if (!isset($return[$id])) { | ||||
|                 $return[$id] = [ | ||||
|                     'budget'  => $budget, | ||||
|                     'entries' => [], | ||||
|                 ]; | ||||
|             } | ||||
|             // store each entry: | ||||
|             $return[$id]['entries'][$budget->dateFormatted] = $budget->sumAmount; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns an array with the following key:value pairs: | ||||
|      * | ||||
|      * yyyy-mm-dd:<array> | ||||
|      * | ||||
|      * That array contains: | ||||
|      * | ||||
|      * budgetid:<amount> | ||||
|      * | ||||
|      * Where yyyy-mm-dd is the date and <amount> is the money spent using WITHDRAWALS in the $budget | ||||
|      * from the given users accounts.. | ||||
|      * | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function spentAllPerDayForAccounts(Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $ids = $accounts->pluck('id')->toArray(); | ||||
|         /** @var Collection $query */ | ||||
|         $query = Auth::user()->transactionJournals() | ||||
|                      ->transactionTypes([TransactionType::WITHDRAWAL]) | ||||
|                      ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                      ->leftJoin('budget_transaction_journal', 'transaction_journals.id', '=', 'budget_transaction_journal.transaction_journal_id') | ||||
|                      ->whereIn('transactions.account_id', $ids) | ||||
|                      ->where('transactions.amount', '<', 0) | ||||
|                      ->before($end) | ||||
|                      ->after($start) | ||||
|                      ->groupBy('budget_id') | ||||
|                      ->groupBy('dateFormatted') | ||||
|                      ->get( | ||||
|                          ['transaction_journals.date as dateFormatted', 'budget_transaction_journal.budget_id', | ||||
|                           DB::Raw('SUM(`transactions`.`amount`) AS `sum`')] | ||||
|                      ); | ||||
|  | ||||
|         $return = []; | ||||
|         foreach ($query->toArray() as $entry) { | ||||
|             $budgetId = $entry['budget_id']; | ||||
|             if (!isset($return[$budgetId])) { | ||||
|                 $return[$budgetId] = []; | ||||
|             } | ||||
|             $return[$budgetId][$entry['dateFormatted']] = $entry['sum']; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a list of expenses (in the field "spent", grouped per budget per account. | ||||
|      * | ||||
|      * @param Collection $budgets | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function spentPerBudgetPerAccount(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $accountIds = $accounts->pluck('id')->toArray(); | ||||
|         $budgetIds  = $budgets->pluck('id')->toArray(); | ||||
|         $set        = Auth::user()->transactionjournals() | ||||
|                           ->leftJoin( | ||||
|                               'transactions AS t_from', function (JoinClause $join) { | ||||
|                               $join->on('transaction_journals.id', '=', 't_from.transaction_journal_id')->where('t_from.amount', '<', 0); | ||||
|                           } | ||||
|                           ) | ||||
|                           ->leftJoin( | ||||
|                               'transactions AS t_to', function (JoinClause $join) { | ||||
|                               $join->on('transaction_journals.id', '=', 't_to.transaction_journal_id')->where('t_to.amount', '>', 0); | ||||
|                           } | ||||
|                           ) | ||||
|                           ->leftJoin('budget_transaction_journal', 'transaction_journals.id', '=', 'budget_transaction_journal.transaction_journal_id') | ||||
|                           ->whereIn('t_from.account_id', $accountIds) | ||||
|                           ->whereNotIn('t_to.account_id', $accountIds) | ||||
|                           ->where( | ||||
|                               function (Builder $q) use ($budgetIds) { | ||||
|                                   $q->whereIn('budget_transaction_journal.budget_id', $budgetIds); | ||||
|                                   $q->orWhereNull('budget_transaction_journal.budget_id'); | ||||
|                               } | ||||
|                           ) | ||||
|                           ->after($start) | ||||
|                           ->before($end) | ||||
|                           ->groupBy('t_from.account_id') | ||||
|                           ->groupBy('budget_transaction_journal.budget_id') | ||||
|                           ->transactionTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE]) | ||||
|                           ->get( | ||||
|                               [ | ||||
|                                   't_from.account_id', 'budget_transaction_journal.budget_id', | ||||
|                                   DB::Raw('SUM(`t_from`.`amount`) AS `spent`') | ||||
|                               ] | ||||
|                           ); | ||||
|  | ||||
|         return $set; | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -15,11 +15,93 @@ use Illuminate\Support\Collection; | ||||
|  */ | ||||
| interface BudgetRepositoryInterface | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @return void | ||||
|      */ | ||||
|     public function cleanupBudgets(); | ||||
|  | ||||
|     /** | ||||
|      * Returns the expenses for this budget grouped per day, with the date | ||||
|      * in "date" (a string, not a Carbon) and the amount in "dailyAmount". | ||||
|      * | ||||
|      * @param Budget $budget | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getExpensesPerDay(Budget $budget, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return Carbon | ||||
|      */ | ||||
|     public function firstActivity(Budget $budget); | ||||
|  | ||||
|     /** | ||||
|      * Returns the expenses for this budget grouped per month, with the date | ||||
|      * in "date" (a string, not a Carbon) and the amount in "dailyAmount". | ||||
|      * | ||||
|      * @param Budget $budget | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getExpensesPerMonth(Budget $budget, Carbon $start, Carbon $end); | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Returns a list of expenses (in the field "spent", grouped per budget per account. | ||||
|      * | ||||
|      * @param Collection $budgets | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function spentPerBudgetPerAccount(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * Returns an array with the following key:value pairs: | ||||
|      * | ||||
|      * yyyy-mm-dd:<amount> | ||||
|      * | ||||
|      * Where yyyy-mm-dd is the date and <amount> is the money spent using WITHDRAWALS in the $budget | ||||
|      * from all the users accounts. | ||||
|      * | ||||
|      * @param Budget $budget | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function spentPerDay(Budget $budget, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * Returns an array with the following key:value pairs: | ||||
|      * | ||||
|      * yyyy-mm-dd:<array> | ||||
|      * | ||||
|      * That array contains: | ||||
|      * | ||||
|      * budgetid:<amount> | ||||
|      * | ||||
|      * Where yyyy-mm-dd is the date and <amount> is the money spent using WITHDRAWALS in the $budget | ||||
|      * from the given users accounts.. | ||||
|      * | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function spentAllPerDayForAccounts(Collection $accounts, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * | ||||
| @@ -28,14 +110,29 @@ interface BudgetRepositoryInterface | ||||
|     public function destroy(Budget $budget); | ||||
|  | ||||
|     /** | ||||
|      * Takes tags into account. | ||||
|      * Returns an array with every budget in it and the expenses for each budget | ||||
|      * per month. | ||||
|      * | ||||
|      * @param Budget $budget | ||||
|      * @param Carbon $date | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return float | ||||
|      * @return array | ||||
|      */ | ||||
|     public function expensesOnDayCorrected(Budget $budget, Carbon $date); | ||||
|     public function getBudgetsAndExpensesPerMonth(Collection $accounts, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * Returns an array with every budget in it and the expenses for each budget | ||||
|      * per year for. | ||||
|      * | ||||
|      * @param Collection $budgets | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getBudgetsAndExpensesPerYear(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
| @@ -43,26 +140,40 @@ interface BudgetRepositoryInterface | ||||
|     public function getActiveBudgets(); | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * Get the budgeted amounts for each budgets in each year. | ||||
|      * | ||||
|      * @param Collection $budgets | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getBudgetedPerYear(Collection $budgets, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getBudgetLimitRepetitions(Budget $budget, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getBudgetLimits(Budget $budget); | ||||
|     public function getAllBudgetLimitRepetitions(Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getBudgets(); | ||||
|  | ||||
|     /** | ||||
|      * Returns a list of budgets, budget limits and limit repetitions | ||||
|      * (doubling any of them in a left join) | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getBudgetsAndLimitsInRange(Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * @param Carbon $start | ||||
| @@ -95,21 +206,6 @@ interface BudgetRepositoryInterface | ||||
|      */ | ||||
|     public function getJournals(Budget $budget, LimitRepetition $repetition = null, $take = 50); | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return Carbon | ||||
|      */ | ||||
|     public function getLastBudgetLimitDate(Budget $budget); | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getLimitAmountOnDate(Budget $budget, Carbon $date); | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
| @@ -128,16 +224,16 @@ interface BudgetRepositoryInterface | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * Same as ::spentInPeriod but corrects journals for their amount (tags). | ||||
|      * Same as ::spentInPeriod but corrects journals for a set of accounts | ||||
|      * | ||||
|      * @param Budget  $budget | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * @param Budget     $budget | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function balanceInPeriod(Budget $budget, Carbon $start, Carbon $end, $shared = true); | ||||
|     public function balanceInPeriod(Budget $budget, Carbon $start, Carbon $end, Collection $accounts); | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|   | ||||
| @@ -4,11 +4,11 @@ namespace FireflyIII\Repositories\Category; | ||||
|  | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use Crypt; | ||||
| use DB; | ||||
| use FireflyIII\Models\Category; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Repositories\Shared\ComponentRepository; | ||||
| use FireflyIII\Support\CacheProperties; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Sql\Query; | ||||
| use Illuminate\Database\Query\JoinClause; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
| @@ -16,36 +16,15 @@ use Illuminate\Support\Collection; | ||||
|  * | ||||
|  * @package FireflyIII\Repositories\Category | ||||
|  */ | ||||
| class CategoryRepository extends ComponentRepository implements CategoryRepositoryInterface | ||||
| class CategoryRepository implements CategoryRepositoryInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * Returns a list of all the categories belonging to a user. | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function countJournals(Category $category) | ||||
|     { | ||||
|         return $category->transactionJournals()->count(); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return boolean | ||||
|      */ | ||||
|     public function destroy(Category $category) | ||||
|     { | ||||
|         $category->delete(); | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getCategories() | ||||
|     public function listCategories() | ||||
|     { | ||||
|         /** @var Collection $set */ | ||||
|         $set = Auth::user()->categories()->orderBy('name', 'ASC')->get(); | ||||
| @@ -58,111 +37,16 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Returns a list of transaction journals in the range (all types, all accounts) that have no category | ||||
|      * associated to them. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getCategoriesAndExpensesCorrected(Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $set = Auth::user()->transactionjournals() | ||||
|                    ->leftJoin( | ||||
|                        'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id' | ||||
|                    ) | ||||
|                    ->leftJoin('categories', 'categories.id', '=', 'category_transaction_journal.category_id') | ||||
|                    ->before($end) | ||||
|                    ->where('categories.user_id', Auth::user()->id) | ||||
|                    ->after($start) | ||||
|                    ->transactionTypes(['Withdrawal']) | ||||
|                    ->get(['categories.id as category_id', 'categories.encrypted as category_encrypted', 'categories.name', 'transaction_journals.*']); | ||||
|  | ||||
|         bcscale(2); | ||||
|         $result = []; | ||||
|         foreach ($set as $entry) { | ||||
|             $categoryId = intval($entry->category_id); | ||||
|             if (isset($result[$categoryId])) { | ||||
|                 $result[$categoryId]['sum'] = bcadd($result[$categoryId]['sum'], $entry->amount); | ||||
|             } else { | ||||
|                 $isEncrypted         = intval($entry->category_encrypted) === 1 ? true : false; | ||||
|                 $name                = strlen($entry->name) === 0 ? trans('firefly.no_category') : $entry->name; | ||||
|                 $name                = $isEncrypted ? Crypt::decrypt($name) : $name; | ||||
|                 $result[$categoryId] = [ | ||||
|                     'name' => $name, | ||||
|                     'sum'  => $entry->amount, | ||||
|                 ]; | ||||
|  | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return Carbon | ||||
|      */ | ||||
|     public function getFirstActivityDate(Category $category) | ||||
|     { | ||||
|         /** @var TransactionJournal $first */ | ||||
|         $first = $category->transactionjournals()->orderBy('date', 'ASC')->first(); | ||||
|         if ($first) { | ||||
|             return $first->date; | ||||
|         } | ||||
|  | ||||
|         return new Carbon; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * @param int      $page | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getJournals(Category $category, $page) | ||||
|     { | ||||
|         $offset = $page > 0 ? $page * 50 : 0; | ||||
|  | ||||
|         return $category->transactionJournals()->withRelevantData()->take(50)->offset($offset) | ||||
|                         ->orderBy('transaction_journals.date', 'DESC') | ||||
|                         ->orderBy('transaction_journals.order', 'ASC') | ||||
|                         ->orderBy('transaction_journals.id', 'DESC') | ||||
|                         ->get( | ||||
|                             ['transaction_journals.*'] | ||||
|                         ); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return Carbon|null | ||||
|      */ | ||||
|     public function getLatestActivity(Category $category) | ||||
|     { | ||||
|         $latest = $category->transactionjournals() | ||||
|                            ->orderBy('transaction_journals.date', 'DESC') | ||||
|                            ->orderBy('transaction_journals.order', 'ASC') | ||||
|                            ->orderBy('transaction_journals.id', 'DESC') | ||||
|                            ->first(); | ||||
|         if ($latest) { | ||||
|             return $latest->date; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getWithoutCategory(Carbon $start, Carbon $end) | ||||
|     public function listNoCategory(Carbon $start, Carbon $end) | ||||
|     { | ||||
|         return Auth::user() | ||||
|                    ->transactionjournals() | ||||
| @@ -177,196 +61,239 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * @param Carbon   $start | ||||
|      * @param Carbon   $end | ||||
|      * This method returns a very special collection for each category: | ||||
|      * | ||||
|      * @param bool     $shared | ||||
|      * category, year, expense/earned, amount | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function balanceInPeriod(Category $category, Carbon $start, Carbon $end, $shared = false) | ||||
|     { | ||||
|         return $this->commonBalanceInPeriod($category, $start, $end, $shared); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Corrected for tags | ||||
|      * categories can be duplicated. | ||||
|      * | ||||
|      * @param Category $category | ||||
|      * @param Carbon   $date | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function spentOnDaySumCorrected(Category $category, Carbon $date) | ||||
|     { | ||||
|         return $category->transactionjournals()->transactionTypes(['Withdrawal'])->onDate($date)->get(['transaction_journals.*'])->sum('amount'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return Category | ||||
|      */ | ||||
|     public function store(array $data) | ||||
|     { | ||||
|         $newCategory = new Category( | ||||
|             [ | ||||
|                 'user_id' => $data['user'], | ||||
|                 'name'    => $data['name'], | ||||
|             ] | ||||
|         ); | ||||
|         $newCategory->save(); | ||||
|  | ||||
|         return $newCategory; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * @param array    $data | ||||
|      * | ||||
|      * @return Category | ||||
|      */ | ||||
|     public function update(Category $category, array $data) | ||||
|     { | ||||
|         // update the account: | ||||
|         $category->name = $data['name']; | ||||
|         $category->save(); | ||||
|  | ||||
|         return $category; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method returns the sum of the journals in the category, optionally | ||||
|      * limited by a start or end date. | ||||
|      * | ||||
|      * @param Category $category | ||||
|      * @param Carbon   $start | ||||
|      * @param Carbon   $end | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function journalsSum(Category $category, Carbon $start = null, Carbon $end = null) | ||||
|     { | ||||
|         $query = $category->transactionJournals() | ||||
|                           ->orderBy('transaction_journals.date', 'DESC') | ||||
|                           ->orderBy('transaction_journals.order', 'ASC') | ||||
|                           ->orderBy('transaction_journals.id', 'DESC'); | ||||
|         if (!is_null($start)) { | ||||
|             $query->after($start); | ||||
|         } | ||||
|  | ||||
|         if (!is_null($end)) { | ||||
|             $query->before($end); | ||||
|         } | ||||
|  | ||||
|         return $query->get(['transaction_journals.*'])->sum('amount'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category       $category | ||||
|      * @param \Carbon\Carbon $start | ||||
|      * @param \Carbon\Carbon $end | ||||
|      * | ||||
|      * @param bool           $shared | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function spentInPeriod(Category $category, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $cache = new CacheProperties; // we must cache this. | ||||
|         $cache->addProperty($category->id); | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty('spentInPeriod'); | ||||
|  | ||||
|         if ($cache->has()) { | ||||
|             return $cache->get(); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $sum = $category->transactionjournals()->transactionTypes(['Withdrawal'])->before($end)->after($start)->get(['transaction_journals.*'])->sum( | ||||
|             'amount' | ||||
|         ); | ||||
|  | ||||
|         $cache->store($sum); | ||||
|  | ||||
|         return $sum; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category       $category | ||||
|      * @param \Carbon\Carbon $start | ||||
|      * @param \Carbon\Carbon $end | ||||
|      * | ||||
|      * @param bool           $shared | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function earnedInPeriod(Category $category, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $cache = new CacheProperties; // we must cache this. | ||||
|         $cache->addProperty($category->id); | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty('earnedInPeriod'); | ||||
|  | ||||
|         if ($cache->has()) { | ||||
|             return $cache->get(); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $sum = $category->transactionjournals()->transactionTypes(['Deposit'])->before($end)->after($start)->get(['transaction_journals.*'])->sum( | ||||
|             'amount' | ||||
|         ); | ||||
|  | ||||
|         $cache->store($sum); | ||||
|  | ||||
|         return $sum; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * @param int      $page | ||||
|      * @param Collection $categories | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getJournalsInRange(Category $category, $page, Carbon $start, Carbon $end) | ||||
|     public function listMultiYear(Collection $categories, Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $offset = $page > 0 ? $page * 50 : 0; | ||||
|         /* | ||||
|          * select categories.id, DATE_FORMAT(transaction_journals.date,"%Y") as dateFormatted, transaction_types.type, SUM(amount) as sum from categories | ||||
|  | ||||
| left join category_transaction_journal ON category_transaction_journal.category_id = categories.id | ||||
| left join transaction_journals ON transaction_journals.id = category_transaction_journal.transaction_journal_id | ||||
| left join transaction_types ON transaction_types.id = transaction_journals.transaction_type_id | ||||
| left join transactions ON transactions.transaction_journal_id = transaction_journals.id | ||||
|  | ||||
|  | ||||
| where | ||||
| categories.user_id =1 | ||||
| and transaction_types.type in ("Withdrawal","Deposit") | ||||
| and transactions.account_id IN (2,4,6,10,11,610,725,879,1248) | ||||
|  | ||||
| group by categories.id, transaction_types.type, dateFormatted | ||||
|          */ | ||||
|         $set = Auth::user()->categories() | ||||
|                    ->leftJoin('category_transaction_journal', 'category_transaction_journal.category_id', '=', 'categories.id') | ||||
|                    ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'category_transaction_journal.transaction_journal_id') | ||||
|                    ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') | ||||
|                    ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                    ->whereIn('transaction_types.type', [TransactionType::DEPOSIT, TransactionType::WITHDRAWAL]) | ||||
|                    ->whereIn('transactions.account_id', $accounts->pluck('id')->toArray()) | ||||
|                    ->whereIn('categories.id', $categories->pluck('id')->toArray()) | ||||
|                    ->groupBy('categories.id') | ||||
|                    ->groupBy('transaction_types.type') | ||||
|                    ->groupBy('dateFormatted') | ||||
|                    ->get( | ||||
|                        [ | ||||
|                            'categories.*', | ||||
|                            DB::Raw('DATE_FORMAT(`transaction_journals`.`date`,"%Y") as `dateFormatted`'), | ||||
|                            'transaction_types.type', | ||||
|                            DB::Raw('SUM(`amount`) as `sum`') | ||||
|                        ] | ||||
|                    ); | ||||
|  | ||||
|         return $set; | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Returns a collection of Categories appended with the amount of money that has been earned | ||||
|      * in these categories, based on the $accounts involved, in period X, grouped per month. | ||||
|      * The amount earned in category X in period X is saved in field "earned". | ||||
|      * | ||||
|      * @param $accounts | ||||
|      * @param $start | ||||
|      * @param $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function earnedForAccountsPerMonth(Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|  | ||||
|         $collection = Auth::user()->categories() | ||||
|                           ->leftJoin('category_transaction_journal', 'category_transaction_journal.category_id', '=', 'categories.id') | ||||
|                           ->leftJoin('transaction_journals', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                           ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') | ||||
|                           ->leftJoin( | ||||
|                               'transactions AS t_src', function (JoinClause $join) { | ||||
|                               $join->on('t_src.transaction_journal_id', '=', 'transaction_journals.id')->where('t_src.amount', '<', 0); | ||||
|                           } | ||||
|                           ) | ||||
|                           ->leftJoin( | ||||
|                               'transactions AS t_dest', function (JoinClause $join) { | ||||
|                               $join->on('t_dest.transaction_journal_id', '=', 'transaction_journals.id')->where('t_dest.amount', '>', 0); | ||||
|                           } | ||||
|                           ) | ||||
|                           ->whereIn('t_dest.account_id', $accounts->pluck('id')->toArray())// to these accounts (earned) | ||||
|                           ->whereNotIn('t_src.account_id', $accounts->pluck('id')->toArray())//-- but not from these accounts | ||||
|                           ->whereIn( | ||||
|                 'transaction_types.type', [TransactionType::DEPOSIT, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE] | ||||
|             ) | ||||
|                           ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) | ||||
|                           ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) | ||||
|                           ->groupBy('categories.id') | ||||
|                           ->groupBy('dateFormatted') | ||||
|                           ->get( | ||||
|                               [ | ||||
|                                   'categories.*', | ||||
|                                   DB::Raw('DATE_FORMAT(`transaction_journals`.`date`,"%Y-%m") as `dateFormatted`'), | ||||
|                                   DB::Raw('SUM(`t_dest`.`amount`) AS `earned`') | ||||
|                               ] | ||||
|                           ); | ||||
|  | ||||
|         return $collection; | ||||
|  | ||||
|  | ||||
|         return $category->transactionJournals() | ||||
|                         ->after($start) | ||||
|                         ->before($end) | ||||
|                         ->withRelevantData()->take(50)->offset($offset) | ||||
|                         ->orderBy('transaction_journals.date', 'DESC') | ||||
|                         ->orderBy('transaction_journals.order', 'ASC') | ||||
|                         ->orderBy('transaction_journals.id', 'DESC') | ||||
|                         ->get( | ||||
|                             ['transaction_journals.*'] | ||||
|                         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * Returns a collection of Categories appended with the amount of money that has been spent | ||||
|      * in these categories, based on the $accounts involved, in period X, grouped per month. | ||||
|      * The amount spent in category X in period X is saved in field "spent". | ||||
|      * | ||||
|      * @return int | ||||
|      * @param $accounts | ||||
|      * @param $start | ||||
|      * @param $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function countJournalsInRange(Category $category, Carbon $start, Carbon $end) | ||||
|     public function spentForAccountsPerMonth(Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         return $category->transactionJournals()->before($end)->after($start)->count(); | ||||
|         $accountIds = $accounts->pluck('id')->toArray(); | ||||
|         $query      = Auth::user()->categories() | ||||
|                           ->leftJoin('category_transaction_journal', 'category_transaction_journal.category_id', '=', 'categories.id') | ||||
|                           ->leftJoin('transaction_journals', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                           ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') | ||||
|                           ->leftJoin( | ||||
|                               'transactions AS t_src', function (JoinClause $join) { | ||||
|                               $join->on('t_src.transaction_journal_id', '=', 'transaction_journals.id')->where('t_src.amount', '<', 0); | ||||
|                           } | ||||
|                           ) | ||||
|                           ->leftJoin( | ||||
|                               'transactions AS t_dest', function (JoinClause $join) { | ||||
|                               $join->on('t_dest.transaction_journal_id', '=', 'transaction_journals.id')->where('t_dest.amount', '>', 0); | ||||
|                           } | ||||
|                           ) | ||||
|                           ->whereIn( | ||||
|                               'transaction_types.type', [TransactionType::WITHDRAWAL, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE] | ||||
|                           )// spent on these things. | ||||
|                           ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) | ||||
|                           ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) | ||||
|                           ->groupBy('categories.id') | ||||
|                           ->groupBy('dateFormatted'); | ||||
|  | ||||
|         if (count($accountIds) > 0) { | ||||
|             $query->whereIn('t_src.account_id', $accountIds)// from these accounts (spent) | ||||
|                   ->whereNotIn('t_dest.account_id', $accountIds);//-- but not from these accounts (spent internally) | ||||
|         } | ||||
|  | ||||
|         $collection = $query->get( | ||||
|             [ | ||||
|                 'categories.*', | ||||
|                 DB::Raw('DATE_FORMAT(`transaction_journals`.`date`,"%Y-%m") as `dateFormatted`'), | ||||
|                 DB::Raw('SUM(`t_src`.`amount`) AS `spent`') | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|         return $collection; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Returns the total amount of money related to transactions without any category connected to | ||||
|      * it. Returns either the spent amount. | ||||
|      * | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function sumSpentNoCategory(Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         return $this->sumNoCategory($accounts, $start, $end, Query::SPENT); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the total amount of money related to transactions without any category connected to | ||||
|      * it. Returns either the earned amount. | ||||
|      * | ||||
|      * Corrected for tags. | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @param Category $category | ||||
|      * @param Carbon   $date | ||||
|      * | ||||
|      * @return float | ||||
|      * @return string | ||||
|      */ | ||||
|     public function earnedOnDaySumCorrected(Category $category, Carbon $date) | ||||
|     public function sumEarnedNoCategory(Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         return $category->transactionjournals()->transactionTypes(['Deposit'])->onDate($date)->get(['transaction_journals.*'])->sum('amount'); | ||||
|         return $this->sumNoCategory($accounts, $start, $end, Query::EARNED); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the total amount of money related to transactions without any category connected to | ||||
|      * it. Returns either the earned or the spent amount. | ||||
|      * | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * @param int        $group | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function sumNoCategory(Collection $accounts, Carbon $start, Carbon $end, $group = Query::EARNED) | ||||
|     { | ||||
|         $accountIds = $accounts->pluck('id')->toArray(); | ||||
|         if ($group == Query::EARNED) { | ||||
|             $types = [TransactionType::DEPOSIT]; | ||||
|         } else { | ||||
|             $types = [TransactionType::WITHDRAWAL]; | ||||
|         } | ||||
|  | ||||
|         // is withdrawal or transfer AND account_from is in the list of $accounts | ||||
|         $query = Auth::user() | ||||
|                      ->transactionjournals() | ||||
|                      ->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                      ->whereNull('category_transaction_journal.id') | ||||
|                      ->before($end) | ||||
|                      ->after($start) | ||||
|                      ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                      ->transactionTypes($types); | ||||
|         if (count($accountIds) > 0) { | ||||
|             $query->whereIn('transactions.account_id', $accountIds); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $single = $query->first( | ||||
|             [ | ||||
|                 DB::Raw('SUM(`transactions`.`amount`) as `sum`') | ||||
|             ] | ||||
|         ); | ||||
|         if (!is_null($single)) { | ||||
|             return $single->sum; | ||||
|         } | ||||
|  | ||||
|         return '0'; | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -3,7 +3,6 @@ | ||||
| namespace FireflyIII\Repositories\Category; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\Category; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
| @@ -13,162 +12,90 @@ use Illuminate\Support\Collection; | ||||
|  */ | ||||
| interface CategoryRepositoryInterface | ||||
| { | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function countJournals(Category $category); | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * Returns a collection of Categories appended with the amount of money that has been earned | ||||
|      * in these categories, based on the $accounts involved, in period X, grouped per month. | ||||
|      * The amount earned in category X in period X is saved in field "earned". | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function countJournalsInRange(Category $category, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return boolean | ||||
|      */ | ||||
|     public function destroy(Category $category); | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getCategories(); | ||||
|  | ||||
|     /** | ||||
|      * Corrected for tags. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getCategoriesAndExpensesCorrected(Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return Carbon | ||||
|      */ | ||||
|     public function getFirstActivityDate(Category $category); | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * @param int      $page | ||||
|      * @param $accounts | ||||
|      * @param $start | ||||
|      * @param $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getJournals(Category $category, $page); | ||||
|     public function earnedForAccountsPerMonth(Collection $accounts, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * @param int      $page | ||||
|      * Returns a list of all the categories belonging to a user. | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getJournalsInRange(Category $category, $page, Carbon $start, Carbon $end); | ||||
|     public function listCategories(); | ||||
|  | ||||
|     /** | ||||
|      * This method returns the sum of the journals in the category, optionally | ||||
|      * limited by a start or end date. | ||||
|      * This method returns a very special collection for each category: | ||||
|      * | ||||
|      * @param Category $category | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * category, year, expense/earned, amount | ||||
|      * | ||||
|      * @return string | ||||
|      * categories can be duplicated. | ||||
|      * | ||||
|      * @param Collection $categories | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function journalsSum(Category $category, Carbon $start = null, Carbon $end = null); | ||||
|     public function listMultiYear(Collection $categories, Collection $accounts, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * Returns a list of transaction journals in the range (all types, all accounts) that have no category | ||||
|      * associated to them. | ||||
|      * | ||||
|      * @return Carbon|null | ||||
|      */ | ||||
|     public function getLatestActivity(Category $category); | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getWithoutCategory(Carbon $start, Carbon $end); | ||||
|     public function listNoCategory(Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * Corrected for tags. | ||||
|      * Returns a collection of Categories appended with the amount of money that has been spent | ||||
|      * in these categories, based on the $accounts involved, in period X, grouped per month. | ||||
|      * The amount earned in category X in period X is saved in field "spent". | ||||
|      * | ||||
|      * @param Category       $category | ||||
|      * @param \Carbon\Carbon $start | ||||
|      * @param \Carbon\Carbon $end | ||||
|      * @param $accounts | ||||
|      * @param $start | ||||
|      * @param $end | ||||
|      * | ||||
|      * @param bool           $shared | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function spentForAccountsPerMonth(Collection $accounts, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * Returns the total amount of money related to transactions without any category connected to | ||||
|      * it. Returns either the earned amount. | ||||
|      * | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function balanceInPeriod(Category $category, Carbon $start, Carbon $end, $shared = false); | ||||
|     public function sumEarnedNoCategory(Collection $accounts, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Category       $category | ||||
|      * @param \Carbon\Carbon $start | ||||
|      * @param \Carbon\Carbon $end | ||||
|      * Returns the total amount of money related to transactions without any category connected to | ||||
|      * it. Returns either the spent amount. | ||||
|      * | ||||
|      * @param bool           $shared | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function spentInPeriod(Category $category, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Category       $category | ||||
|      * @param \Carbon\Carbon $start | ||||
|      * @param \Carbon\Carbon $end | ||||
|      * | ||||
|      * @param bool           $shared | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function earnedInPeriod(Category $category, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * Corrected for tags. | ||||
|      * | ||||
|      * @param Category $category | ||||
|      * @param Carbon   $date | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function spentOnDaySumCorrected(Category $category, Carbon $date); | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * Corrected for tags. | ||||
|      * | ||||
|      * @param Category $category | ||||
|      * @param Carbon   $date | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function earnedOnDaySumCorrected(Category $category, Carbon $date); | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return Category | ||||
|      */ | ||||
|     public function store(array $data); | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * @param array    $data | ||||
|      * | ||||
|      * @return Category | ||||
|      */ | ||||
|     public function update(Category $category, array $data); | ||||
|     public function sumSpentNoCategory(Collection $accounts, Carbon $start, Carbon $end); | ||||
|  | ||||
| } | ||||
|   | ||||
							
								
								
									
										238
									
								
								app/Repositories/Category/SingleCategoryRepository.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										238
									
								
								app/Repositories/Category/SingleCategoryRepository.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,238 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Repositories\Category; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use DB; | ||||
| use FireflyIII\Models\Category; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Repositories\Shared\ComponentRepository; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class SingleCategoryRepository | ||||
|  * | ||||
|  * @package FireflyIII\Repositories\Category | ||||
|  */ | ||||
| class SingleCategoryRepository extends ComponentRepository implements SingleCategoryRepositoryInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function countJournals(Category $category) | ||||
|     { | ||||
|         return $category->transactionJournals()->count(); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @param Carbon   $start | ||||
|      * @param Carbon   $end | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function countJournalsInRange(Category $category, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         return $category->transactionJournals()->before($end)->after($start)->count(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return boolean | ||||
|      */ | ||||
|     public function destroy(Category $category) | ||||
|     { | ||||
|         $category->delete(); | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns an array with the following key:value pairs: | ||||
|      * | ||||
|      * yyyy-mm-dd:<amount> | ||||
|      * | ||||
|      * Where yyyy-mm-dd is the date and <amount> is the money earned using DEPOSITS in the $category | ||||
|      * from all the users $accounts. | ||||
|      * | ||||
|      * @param Category $category | ||||
|      * @param Carbon   $start | ||||
|      * @param Carbon   $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function earnedPerDay(Category $category, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         /** @var Collection $query */ | ||||
|         $query = $category->transactionJournals() | ||||
|                           ->transactionTypes([TransactionType::DEPOSIT]) | ||||
|                           ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                           ->where('transactions.amount', '>', 0) | ||||
|                           ->before($end) | ||||
|                           ->after($start) | ||||
|                           ->groupBy('date')->get(['transaction_journals.date as dateFormatted', DB::Raw('SUM(`transactions`.`amount`) AS `sum`')]); | ||||
|  | ||||
|         $return = []; | ||||
|         foreach ($query->toArray() as $entry) { | ||||
|             $return[$entry['dateFormatted']] = $entry['sum']; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return Carbon | ||||
|      */ | ||||
|     public function getFirstActivityDate(Category $category) | ||||
|     { | ||||
|         /** @var TransactionJournal $first */ | ||||
|         $first = $category->transactionjournals()->orderBy('date', 'ASC')->first(); | ||||
|         if ($first) { | ||||
|             return $first->date; | ||||
|         } | ||||
|  | ||||
|         return new Carbon; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * @param int      $page | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getJournals(Category $category, $page) | ||||
|     { | ||||
|         $offset = $page > 0 ? $page * 50 : 0; | ||||
|  | ||||
|         return $category->transactionJournals()->withRelevantData()->take(50)->offset($offset) | ||||
|                         ->orderBy('transaction_journals.date', 'DESC') | ||||
|                         ->orderBy('transaction_journals.order', 'ASC') | ||||
|                         ->orderBy('transaction_journals.id', 'DESC') | ||||
|                         ->get( | ||||
|                             ['transaction_journals.*'] | ||||
|                         ); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * @param int      $page | ||||
|      * @param Carbon   $start | ||||
|      * @param Carbon   $end | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function getJournalsInRange(Category $category, $page, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $offset = $page > 0 ? $page * 50 : 0; | ||||
|  | ||||
|         return $category->transactionJournals() | ||||
|                         ->after($start) | ||||
|                         ->before($end) | ||||
|                         ->withRelevantData()->take(50)->offset($offset) | ||||
|                         ->orderBy('transaction_journals.date', 'DESC') | ||||
|                         ->orderBy('transaction_journals.order', 'ASC') | ||||
|                         ->orderBy('transaction_journals.id', 'DESC') | ||||
|                         ->get( | ||||
|                             ['transaction_journals.*'] | ||||
|                         ); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return Carbon|null | ||||
|      */ | ||||
|     public function getLatestActivity(Category $category) | ||||
|     { | ||||
|         $latest = $category->transactionjournals() | ||||
|                            ->orderBy('transaction_journals.date', 'DESC') | ||||
|                            ->orderBy('transaction_journals.order', 'ASC') | ||||
|                            ->orderBy('transaction_journals.id', 'DESC') | ||||
|                            ->first(); | ||||
|         if ($latest) { | ||||
|             return $latest->date; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns an array with the following key:value pairs: | ||||
|      * | ||||
|      * yyyy-mm-dd:<amount> | ||||
|      * | ||||
|      * Where yyyy-mm-dd is the date and <amount> is the money spent using DEPOSITS in the $category | ||||
|      * from all the users accounts. | ||||
|      * | ||||
|      * @param Category $category | ||||
|      * @param Carbon   $start | ||||
|      * @param Carbon   $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function spentPerDay(Category $category, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         /** @var Collection $query */ | ||||
|         $query = $category->transactionJournals() | ||||
|                           ->transactionTypes([TransactionType::WITHDRAWAL]) | ||||
|                           ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                           ->where('transactions.amount', '<', 0) | ||||
|                           ->before($end) | ||||
|                           ->after($start) | ||||
|                           ->groupBy('date')->get(['transaction_journals.date as dateFormatted', DB::Raw('SUM(`transactions`.`amount`) AS `sum`')]); | ||||
|  | ||||
|         $return = []; | ||||
|         foreach ($query->toArray() as $entry) { | ||||
|             $return[$entry['dateFormatted']] = $entry['sum']; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return Category | ||||
|      */ | ||||
|     public function store(array $data) | ||||
|     { | ||||
|         $newCategory = new Category( | ||||
|             [ | ||||
|                 'user_id' => $data['user'], | ||||
|                 'name'    => $data['name'], | ||||
|             ] | ||||
|         ); | ||||
|         $newCategory->save(); | ||||
|  | ||||
|         return $newCategory; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * @param array    $data | ||||
|      * | ||||
|      * @return Category | ||||
|      */ | ||||
|     public function update(Category $category, array $data) | ||||
|     { | ||||
|         // update the account: | ||||
|         $category->name = $data['name']; | ||||
|         $category->save(); | ||||
|  | ||||
|         return $category; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										122
									
								
								app/Repositories/Category/SingleCategoryRepositoryInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								app/Repositories/Category/SingleCategoryRepositoryInterface.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,122 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Repositories\Category; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\Category; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Interface SingleCategoryRepositoryInterface | ||||
|  * | ||||
|  * @package FireflyIII\Repositories\Category | ||||
|  */ | ||||
| interface SingleCategoryRepositoryInterface | ||||
| { | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function countJournals(Category $category); | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @param Carbon   $start | ||||
|      * @param Carbon   $end | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function countJournalsInRange(Category $category, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return boolean | ||||
|      */ | ||||
|     public function destroy(Category $category); | ||||
|  | ||||
|     /** | ||||
|      * Returns an array with the following key:value pairs: | ||||
|      * | ||||
|      * yyyy-mm-dd:<amount> | ||||
|      * | ||||
|      * Where yyyy-mm-dd is the date and <amount> is the money earned using DEPOSITS in the $category | ||||
|      * from all the users accounts. | ||||
|      * | ||||
|      * @param Category $category | ||||
|      * @param Carbon   $start | ||||
|      * @param Carbon   $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function earnedPerDay(Category $category, Carbon $start, Carbon $end); | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return Carbon | ||||
|      */ | ||||
|     public function getFirstActivityDate(Category $category); | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * @param int      $page | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getJournals(Category $category, $page); | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * @param int      $page | ||||
|      * | ||||
|      * @param Carbon   $start | ||||
|      * @param Carbon   $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getJournalsInRange(Category $category, $page, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return Carbon|null | ||||
|      */ | ||||
|     public function getLatestActivity(Category $category); | ||||
|  | ||||
|     /** | ||||
|      * Returns an array with the following key:value pairs: | ||||
|      * | ||||
|      * yyyy-mm-dd:<amount> | ||||
|      * | ||||
|      * Where yyyy-mm-dd is the date and <amount> is the money spent using WITHDRAWALS in the $category | ||||
|      * from all the users accounts. | ||||
|      * | ||||
|      * @param Category $category | ||||
|      * @param Carbon   $start | ||||
|      * @param Carbon   $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function spentPerDay(Category $category, Carbon $start, Carbon $end); | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return Category | ||||
|      */ | ||||
|     public function store(array $data); | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * @param array    $data | ||||
|      * | ||||
|      * @return Category | ||||
|      */ | ||||
|     public function update(Category $category, array $data); | ||||
| } | ||||
| @@ -44,7 +44,9 @@ class JournalRepository implements JournalRepositoryInterface | ||||
|      */ | ||||
|     public function first() | ||||
|     { | ||||
|         return Auth::user()->transactionjournals()->orderBy('date', 'ASC')->first(['transaction_journals.*']); | ||||
|         $entry = Auth::user()->transactionjournals()->orderBy('date', 'ASC')->first(['transaction_journals.*']); | ||||
|  | ||||
|         return $entry; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -164,7 +166,7 @@ class JournalRepository implements JournalRepositoryInterface | ||||
|             [ | ||||
|                 'user_id'                 => $data['user'], | ||||
|                 'transaction_type_id'     => $transactionType->id, | ||||
|                 'transaction_currency_id' => $data['amount_currency_id'], | ||||
|                 'transaction_currency_id' => $data['amount_currency_id_amount'], | ||||
|                 'description'             => $data['description'], | ||||
|                 'completed'               => 0, | ||||
|                 'date'                    => $data['date'], | ||||
| @@ -226,7 +228,7 @@ class JournalRepository implements JournalRepositoryInterface | ||||
|     public function update(TransactionJournal $journal, array $data) | ||||
|     { | ||||
|         // update actual journal. | ||||
|         $journal->transaction_currency_id = $data['amount_currency_id']; | ||||
|         $journal->transaction_currency_id = $data['amount_currency_id_amount']; | ||||
|         $journal->description             = $data['description']; | ||||
|         $journal->date                    = $data['date']; | ||||
|  | ||||
| @@ -327,15 +329,15 @@ class JournalRepository implements JournalRepositoryInterface | ||||
|         $fromAccount = null; | ||||
|         $toAccount   = null; | ||||
|         switch ($type->type) { | ||||
|             case 'Withdrawal': | ||||
|             case TransactionType::WITHDRAWAL: | ||||
|                 list($fromAccount, $toAccount) = $this->storeWithdrawalAccounts($data); | ||||
|                 break; | ||||
|  | ||||
|             case 'Deposit': | ||||
|             case TransactionType::DEPOSIT: | ||||
|                 list($fromAccount, $toAccount) = $this->storeDepositAccounts($data); | ||||
|  | ||||
|                 break; | ||||
|             case 'Transfer': | ||||
|             case TransactionType::TRANSFER: | ||||
|                 $fromAccount = Account::find($data['account_from_id']); | ||||
|                 $toAccount   = Account::find($data['account_to_id']); | ||||
|                 break; | ||||
|   | ||||
| @@ -1,149 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Repositories\PiggyBank; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\PiggyBankRepetition; | ||||
|  | ||||
| /** | ||||
|  * Class PiggyBankPart | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @package FireflyIII\Collection | ||||
|  */ | ||||
| class PiggyBankPart | ||||
| { | ||||
|     /** @var  float */ | ||||
|     public $amountPerBar; | ||||
|     /** @var  float */ | ||||
|     public $cumulativeAmount; | ||||
|     /** @var  float */ | ||||
|     public $currentamount; | ||||
|  | ||||
|     /** @var  PiggyBankRepetition */ | ||||
|     public $repetition; | ||||
|  | ||||
|     /** @var  Carbon */ | ||||
|     public $startdate; | ||||
|  | ||||
|     /** @var  Carbon */ | ||||
|     public $targetdate; | ||||
|  | ||||
|     /** | ||||
|      * @return PiggyBankRepetition | ||||
|      */ | ||||
|     public function getRepetition() | ||||
|     { | ||||
|         return $this->repetition; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBankRepetition $repetition | ||||
|      */ | ||||
|     public function setRepetition($repetition) | ||||
|     { | ||||
|         $this->repetition = $repetition; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Carbon | ||||
|      */ | ||||
|     public function getStartdate() | ||||
|     { | ||||
|         return $this->startdate; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $startdate | ||||
|      */ | ||||
|     public function setStartdate($startdate) | ||||
|     { | ||||
|         $this->startdate = $startdate; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Carbon | ||||
|      */ | ||||
|     public function getTargetdate() | ||||
|     { | ||||
|         return $this->targetdate; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $targetdate | ||||
|      */ | ||||
|     public function setTargetdate($targetdate) | ||||
|     { | ||||
|         $this->targetdate = $targetdate; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float|int | ||||
|      */ | ||||
|     public function percentage() | ||||
|     { | ||||
|         bcscale(2); | ||||
|         if ($this->getCurrentamount() < $this->getCumulativeAmount()) { | ||||
|             $pct = 0; | ||||
|             // calculate halfway point? | ||||
|             if (bcsub($this->getCumulativeAmount(), $this->getCurrentamount()) < $this->getAmountPerBar()) { | ||||
|                 $left = $this->getCurrentamount() % $this->getAmountPerBar(); | ||||
|                 $pct  = round($left / $this->getAmountPerBar() * 100); | ||||
|             } | ||||
|  | ||||
|             return $pct; | ||||
|         } else { | ||||
|             return 100; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getCurrentamount() | ||||
|     { | ||||
|         return $this->currentamount; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $currentamount | ||||
|      */ | ||||
|     public function setCurrentamount($currentamount) | ||||
|     { | ||||
|         $this->currentamount = $currentamount; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getCumulativeAmount() | ||||
|     { | ||||
|         return $this->cumulativeAmount; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $cumulativeAmount | ||||
|      */ | ||||
|     public function setCumulativeAmount($cumulativeAmount) | ||||
|     { | ||||
|         $this->cumulativeAmount = $cumulativeAmount; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getAmountPerBar() | ||||
|     { | ||||
|         return $this->amountPerBar; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $amountPerBar | ||||
|      */ | ||||
|     public function setAmountPerBar($amountPerBar) | ||||
|     { | ||||
|         $this->amountPerBar = $amountPerBar; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user