mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-31 02:36:28 +00:00 
			
		
		
		
	Compare commits
	
		
			532 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 | ||
|  | 8b9607f9b5 | ||
|  | af107ad5e8 | ||
|  | 8926d62165 | ||
|  | 45344ee347 | ||
|  | baf9ebab15 | ||
|  | b7dab817f2 | ||
|  | fb2fa54480 | ||
|  | 2c966a1234 | ||
|  | 143ea69c0d | ||
|  | 8a02ead013 | ||
|  | 930d5ab941 | ||
|  | e54a56d3a8 | ||
|  | f5216c0d85 | ||
|  | ebc77540b9 | ||
|  | 28d2583c10 | ||
|  | b0988a7b00 | ||
|  | 2c4920db2d | ||
|  | 8321663815 | ||
|  | ac0280d460 | ||
|  | ba6f4268f0 | ||
|  | 0bd18f94ac | ||
|  | 66fb63661f | ||
|  | d9b16beb0a | ||
|  | 6a01a9bdfd | ||
|  | b81b34a706 | ||
|  | 3750a00b5f | ||
|  | 05ddcc169d | ||
|  | f571a5f1bd | ||
|  | 48b786adea | ||
|  | d691fa9b4d | ||
|  | da50f9e419 | ||
|  | 103de5e18a | ||
|  | dac6efd98b | ||
|  | 46aa7f81b2 | ||
|  | 0683c7cd67 | ||
|  | 50d7aa7b6a | ||
|  | b781215d0a | ||
|  | 866bc2f3bd | ||
|  | 49d4705014 | ||
|  | 9163fcfccb | ||
|  | 7e10641461 | ||
|  | cdc0e3cfd8 | ||
|  | 466e81d56a | ||
|  | 5953f691d1 | ||
|  | e2790ca6c1 | ||
|  | 66dbd48b76 | ||
|  | 73cfbbd2ba | ||
|  | 38bc38bf26 | ||
|  | e12d13c838 | ||
|  | fcc3af6136 | ||
|  | 491298e1cb | ||
|  | 72b5895217 | ||
|  | 0a8f4017bd | ||
|  | cb985f5897 | ||
|  | 968ec0853f | ||
|  | 0bde72d3df | ||
|  | 45293fbd42 | ||
|  | 72997065f0 | ||
|  | a838dc163d | ||
|  | 3d15a4ca6d | ||
|  | 51c7d4fb1b | ||
|  | fa586dba7e | ||
|  | 8ad40389f2 | ||
|  | b3333cc2d3 | ||
|  | 3699a7ba9a | ||
|  | 204e521ba4 | ||
|  | c9bab3e5c3 | ||
|  | 3d00e20238 | ||
|  | c3958ed3c4 | ||
|  | e5b88be5fa | ||
|  | 425552988a | ||
|  | a81dd8abe5 | ||
|  | bac8154a5b | ||
|  | 737d15fa0e | ||
|  | 5f2317af7f | ||
|  | 2bd1f783e5 | ||
|  | d6c0c9f963 | ||
|  | 21b6ad7a41 | ||
|  | a65d609fdc | ||
|  | 04e676b936 | ||
|  | be8eaaffdf | ||
|  | 28c753523f | ||
|  | 7fbd0b2ffc | ||
|  | 7ffb48a87a | ||
|  | d485270e1f | ||
|  | 5fd688b266 | ||
|  | 3716668e0c | ||
|  | ae7fd18c34 | ||
|  | 4f59b1d32f | ||
|  | 90cb3279df | ||
|  | cf0c7ef6b2 | ||
|  | 47c23781d9 | ||
|  | e258c050f7 | ||
|  | 57801b2f34 | ||
|  | 710e9c9423 | ||
|  | deefef83bd | ||
|  | 51e30aed66 | ||
|  | 8d109a3cfe | ||
|  | 3424e019b5 | ||
|  | c6b4bceb67 | ||
|  | afb4155015 | ||
|  | 8d99baf38a | ||
|  | b91cb60328 | ||
|  | c0d62237fc | ||
|  | 223ea80860 | ||
|  | 5a77bef494 | ||
|  | 80c0efe821 | ||
|  | 8044d89557 | ||
|  | 4f0ed97410 | ||
|  | af7952f204 | ||
|  | d8dcae856b | ||
|  | 7296796ed9 | ||
|  | a2c2bb4948 | ||
|  | 72ebfdc20e | ||
|  | 16b95ea78a | ||
|  | c04f08dfd8 | ||
|  | a30793e818 | ||
|  | e39e1eaf21 | ||
|  | ab22d2cbaa | ||
|  | 96ddbe7227 | ||
|  | 4d09235aef | ||
|  | 136b8975e3 | ||
|  | e21b1eca17 | ||
|  | 244b90b1d4 | ||
|  | b318f3f940 | ||
|  | e211c9812e | ||
|  | eef28d96f4 | ||
|  | c8227e09ee | ||
|  | 3e05fd91d9 | ||
|  | 450baba56a | ||
|  | 17a8c4918c | ||
|  | 0e2419d61a | ||
|  | 79b1a2ca6d | ||
|  | 2213c68155 | ||
|  | 2492b1fa96 | ||
|  | 6c6598dac5 | ||
|  | a137112e66 | ||
|  | 8642ae8180 | ||
|  | 894c4dc5a7 | ||
|  | d96063ea6e | ||
|  | c3dc193f3e | ||
|  | 3c2952009e | ||
|  | f4ade470df | ||
|  | 2e33b43389 | ||
|  | 92799699bc | ||
|  | 7ab0508167 | ||
|  | 3c65c28936 | ||
|  | 43892da07e | ||
|  | 7c436920a4 | ||
|  | 89d565e63b | ||
|  | 150b6fe5b6 | ||
|  | 0e77574c26 | ||
|  | df23863443 | ||
|  | 581bf11b21 | ||
|  | d602d4b429 | ||
|  | d1d4a52934 | ||
|  | 375d113769 | ||
|  | 9b83974bff | ||
|  | 3c68c99bd5 | ||
|  | ec4b37c596 | ||
|  | ba9601d21c | ||
|  | 50c13fd469 | ||
|  | 7af072b8fc | ||
|  | faa128d41e | ||
|  | 868fe46932 | ||
|  | e9e4307ce5 | ||
|  | 774d4844a9 | ||
|  | 586c53e670 | ||
|  | 68e073fbff | ||
|  | 8101dc37b1 | ||
|  | 63f16c458d | ||
|  | 821e007e95 | ||
|  | 1656a2f11a | ||
|  | 4dbc135dce | ||
|  | fc886f6bc1 | ||
|  | f93e480466 | ||
|  | fe807e23f8 | ||
|  | ecf61c31f1 | ||
|  | 4feff18af5 | ||
|  | a07c52e0d8 | ||
|  | 7bb07d7f55 | ||
|  | f12dfc8a14 | ||
|  | be030f15c4 | ||
|  | f5fb6c063b | ||
|  | fb722f06b9 | ||
|  | c0ea19e15e | ||
|  | cdeb1ad87c | ||
|  | 0dbe4e94fa | ||
|  | b5e2e8aa1d | ||
|  | 9502010248 | ||
|  | fea0557b47 | ||
|  | ed4fcc9011 | ||
|  | ed12ea7cfb | ||
|  | 73e526645e | ||
|  | 72aeafb2b5 | ||
|  | cc1af60cb4 | ||
|  | 359fab315f | ||
|  | 6a9574bab9 | ||
|  | 83d6158483 | ||
|  | 63ef89b6cc | ||
|  | b0beab4cd3 | ||
|  | a34782575f | ||
|  | 142bdc9430 | ||
|  | 14b79cb0a4 | ||
|  | ce5beeaf2c | ||
|  | 31114a2ca5 | ||
|  | 32528094ad | ||
|  | 0a2a01c44c | ||
|  | c1888dc3ac | ||
|  | 4d76afbe01 | ||
|  | 76d7a97f93 | ||
|  | 8b1366b20a | ||
|  | e0f9685578 | ||
|  | 5235657954 | ||
|  | a15fbc8094 | ||
|  | 546f1d9c50 | ||
|  | 74231f552a | 
							
								
								
									
										15
									
								
								.env.example
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								.env.example
									
									
									
									
									
								
							| @@ -1,6 +1,7 @@ | ||||
| APP_ENV=production | ||||
| APP_DEBUG=false | ||||
| APP_KEY=SomeRandomString | ||||
| APP_KEY=SomeRandomStringOf32CharsExactly | ||||
|  | ||||
|  | ||||
| DB_CONNECTION=mysql | ||||
| DB_HOST=localhost | ||||
| @@ -11,11 +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 | ||||
| SITE_OWNER=mail@example.com | ||||
|  | ||||
| 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 | ||||
|   | ||||
							
								
								
									
										37
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								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. | ||||
| 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 | ||||
|  | ||||
| @@ -90,6 +104,7 @@ Firefly III uses the following libraries and tools: | ||||
|  | ||||
| * The AdminLTE template by [Almsaseed Studio](https://almsaeedstudio.com/) | ||||
| * The [Google charts](https://developers.google.com/chart/) library. | ||||
| * [Chart.js](http://www.chartjs.org/) | ||||
| * [Bootstrap](http://getbootstrap.com/) | ||||
| * [Laravel](http://laravel.com/) | ||||
| * [Twig](http://twig.sensiolabs.org/) | ||||
|   | ||||
| @@ -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 | ||||
| @@ -40,4 +31,13 @@ interface AccountChartGenerator | ||||
|      * @return array | ||||
|      */ | ||||
|     public function single(Account $account, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function expenseAccounts(Collection $accounts, Carbon $start, Carbon $end); | ||||
| } | ||||
|   | ||||
| @@ -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,69 @@ 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) | ||||
|     public function expenseAccounts(Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         return $this->frontpage($accounts, $start, $end); | ||||
|         $data = [ | ||||
|             'count'  => 1, | ||||
|             'labels' => [], 'datasets' => [[ | ||||
|                                                'label' => trans('firefly.spent'), | ||||
|                                                'data'  => []]]]; | ||||
|  | ||||
|         bcscale(2); | ||||
|         $start->subDay(); | ||||
|         $ids           = $this->getIdsFromCollection($accounts); | ||||
|         $startBalances = Steam::balancesById($ids, $start); | ||||
|         $endBalances   = Steam::balancesById($ids, $end); | ||||
|  | ||||
|         $accounts->each( | ||||
|             function (Account $account) use ($startBalances, $endBalances) { | ||||
|                 $id                  = $account->id; | ||||
|                 $startBalance        = $this->isInArray($startBalances, $id); | ||||
|                 $endBalance          = $this->isInArray($endBalances, $id); | ||||
|                 $diff                = bcsub($endBalance, $startBalance); | ||||
|                 $account->difference = round($diff, 2); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         $accounts = $accounts->sortByDesc( | ||||
|             function (Account $account) { | ||||
|                 return $account->difference; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         foreach ($accounts as $account) { | ||||
|             if ($account->difference > 0) { | ||||
|                 $data['labels'][]              = $account->name; | ||||
|                 $data['datasets'][0]['data'][] = $account->difference; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $array | ||||
|      * @param $entryId | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     protected function isInArray($array, $entryId) | ||||
|     { | ||||
|         if (isset($array[$entryId])) { | ||||
|             return $array[$entryId]; | ||||
|         } | ||||
|  | ||||
|         return '0'; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
| @@ -42,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)', | ||||
| @@ -66,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; | ||||
| @@ -88,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' => [ | ||||
| @@ -101,15 +152,36 @@ 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(); | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $collection | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function getIdsFromCollection(Collection $collection) | ||||
|     { | ||||
|         $ids = []; | ||||
|         foreach ($collection as $entry) { | ||||
|             $ids[] = $entry->id; | ||||
|         } | ||||
|  | ||||
|         return array_unique($ids); | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,97 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Account; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\Account; | ||||
| use Grumpydictator\Gchart\GChart; | ||||
| use Illuminate\Support\Collection; | ||||
| use Steam; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class GoogleAccountChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Account | ||||
|  */ | ||||
| class GoogleAccountChartGenerator implements AccountChartGenerator | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function all(Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         // make chart (original code): | ||||
|         $chart = new GChart; | ||||
|         $chart->addColumn(trans('firefly.dayOfMonth'), 'date'); | ||||
|         $index = 1; | ||||
|         /** @var Account $account */ | ||||
|         foreach ($accounts as $account) { | ||||
|             $chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number'); | ||||
|             $chart->addCertainty($index); | ||||
|             $index++; | ||||
|         } | ||||
|         $current = clone $start; | ||||
|         $current->subDay(); | ||||
|         $today = Carbon::now(); | ||||
|         while ($end >= $current) { | ||||
|             $row     = [clone $current]; | ||||
|             $certain = $current < $today; | ||||
|             foreach ($accounts as $account) { | ||||
|                 $row[] = Steam::balance($account, $current); | ||||
|                 $row[] = $certain; | ||||
|             } | ||||
|             $chart->addRowArray($row); | ||||
|             $current->addDay(); | ||||
|         } | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return $chart->getData(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage(Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         return $this->all($accounts, $start, $end); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function single(Account $account, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $current = clone $start; | ||||
|         $today   = new Carbon; | ||||
|         $chart   = new GChart; | ||||
|         $chart->addColumn(trans('firefly.dayOfMonth'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number'); | ||||
|         $chart->addCertainty(1); | ||||
|  | ||||
|         while ($end >= $current) { | ||||
|             $certain = $current < $today; | ||||
|             $chart->addRow(clone $current, Steam::balance($account, $current), $certain); | ||||
|             $current->addDay(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return $chart->getData(); | ||||
|     } | ||||
| } | ||||
| @@ -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); | ||||
|         } | ||||
|         /** @var Bill $entry */ | ||||
|         foreach ($unpaid as $entry) { // loop unpaid: | ||||
|             $description          = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')'; | ||||
|             $amount               = ($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, 2); | ||||
|             /* | ||||
|              * journalAmount has been collected in BillRepository::getJournals | ||||
|              */ | ||||
|             $actualAmount[] = round(($entry->journalAmount * -1), 2); | ||||
|         } | ||||
|  | ||||
|         $data['datasets'][] = [ | ||||
|   | ||||
| @@ -1,94 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Bill; | ||||
|  | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Grumpydictator\Gchart\GChart; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class GoogleBillChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Bill | ||||
|  */ | ||||
| class GoogleBillChartGenerator implements BillChartGenerator | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $paid | ||||
|      * @param Collection $unpaid | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage(Collection $paid, Collection $unpaid) | ||||
|     { | ||||
|         // loop paid and create single entry: | ||||
|         $paidDescriptions   = []; | ||||
|         $paidAmount         = 0; | ||||
|         $unpaidDescriptions = []; | ||||
|         $unpaidAmount       = 0; | ||||
|  | ||||
|         bcscale(2); | ||||
|  | ||||
|  | ||||
|         /** @var TransactionJournal $entry */ | ||||
|         foreach ($paid as $entry) { | ||||
|  | ||||
|             $paidDescriptions[] = $entry->description; | ||||
|             $paidAmount         = bcadd($paidAmount, $entry->amount); | ||||
|         } | ||||
|  | ||||
|         // loop unpaid: | ||||
|         /** @var Bill $entry */ | ||||
|         foreach ($unpaid as $entry) { | ||||
|             $description          = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')'; | ||||
|             $amount               = ($entry[0]->amount_max + $entry[0]->amount_min) / 2; | ||||
|             $unpaidDescriptions[] = $description; | ||||
|             $unpaidAmount         = bcadd($unpaidAmount, $amount); | ||||
|             unset($amount, $description); | ||||
|         } | ||||
|  | ||||
|         $chart = new GChart; | ||||
|         $chart->addColumn(trans('firefly.name'), 'string'); | ||||
|         $chart->addColumn(trans('firefly.amount'), 'number'); | ||||
|  | ||||
|         $chart->addRow(trans('firefly.unpaid') . ': ' . join(', ', $unpaidDescriptions), $unpaidAmount); | ||||
|         $chart->addRow(trans('firefly.paid') . ': ' . join(', ', $paidDescriptions), $paidAmount); | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return $chart->getData(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill       $bill | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function single(Bill $bill, Collection $entries) | ||||
|     { | ||||
|         // make chart: | ||||
|         $chart = new GChart; | ||||
|         $chart->addColumn(trans('firefly.date'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.maxAmount'), 'number'); | ||||
|         $chart->addColumn(trans('firefly.minAmount'), 'number'); | ||||
|         $chart->addColumn(trans('firefly.billEntry'), 'number'); | ||||
|  | ||||
|         /** @var TransactionJournal $result */ | ||||
|         foreach ($entries as $result) { | ||||
|             $chart->addRow( | ||||
|                 clone $result->date, | ||||
|                 floatval($bill->amount_max), | ||||
|                 floatval($bill->amount_min), | ||||
|                 floatval($result->amount) | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return $chart->getData(); | ||||
|     } | ||||
| } | ||||
| @@ -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; | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,102 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Budget; | ||||
|  | ||||
| use Grumpydictator\Gchart\GChart; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class GoogleBudgetChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Budget | ||||
|  */ | ||||
| class GoogleBudgetChartGenerator implements BudgetChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function budget(Collection $entries) | ||||
|     { | ||||
|  | ||||
|         $chart = new GChart; | ||||
|         $chart->addColumn(trans('firefly.period'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.spent'), 'number'); | ||||
|  | ||||
|         /** @var array $entry */ | ||||
|         foreach ($entries as $entry) { | ||||
|             $chart->addRow($entry[0], $entry[1]); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return $chart->getData(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function budgetLimit(Collection $entries) | ||||
|     { | ||||
|         return $this->budget($entries); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage(Collection $entries) | ||||
|     { | ||||
|         $chart = new GChart; | ||||
|         $chart->addColumn(trans('firefly.budget'), 'string'); | ||||
|         $chart->addColumn(trans('firefly.left'), 'number'); | ||||
|         $chart->addColumn(trans('firefly.spent'), 'number'); | ||||
|         $chart->addColumn(trans('firefly.overspent'), 'number'); | ||||
|  | ||||
|         /** @var array $entry */ | ||||
|         foreach ($entries as $entry) { | ||||
|             if ($entry[1] != 0 || $entry[2] != 0 || $entry[3] != 0) { | ||||
|                 $chart->addRow($entry[0], $entry[1], $entry[2], $entry[3]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return $chart->getData(); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $budgets | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function year(Collection $budgets, Collection $entries) | ||||
|     { | ||||
|         $chart = new GChart; | ||||
|         // add columns: | ||||
|         $chart->addColumn(trans('firefly.month'), 'date'); | ||||
|         foreach ($budgets as $budget) { | ||||
|             $chart->addColumn($budget->name, 'number'); | ||||
|         } | ||||
|  | ||||
|         /** @var array $entry */ | ||||
|         foreach ($entries as $entry) { | ||||
|  | ||||
|             $chart->addRowArray($entry); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return $chart->getData(); | ||||
|     } | ||||
| } | ||||
| @@ -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 | ||||
|      * | ||||
| @@ -31,8 +39,14 @@ interface CategoryChartGenerator | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function month(Collection $entries); | ||||
|     public function multiYear(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function period(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $categories | ||||
| @@ -40,5 +54,5 @@ interface CategoryChartGenerator | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function year(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; | ||||
|  | ||||
|  | ||||
| /** | ||||
| @@ -17,36 +15,73 @@ class ChartJsCategoryChartGenerator implements CategoryChartGenerator | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * @param string     $dateFormat | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function all(Collection $entries, $dateFormat = 'month') | ||||
|     public function all(Collection $entries) | ||||
|     { | ||||
|  | ||||
|         // language: | ||||
|         $language = Preferences::get('language', 'en')->data; | ||||
|         $format   = Config::get('firefly.' . $dateFormat . '.' . $language); | ||||
|  | ||||
|         $data = [ | ||||
|             'count'    => 1, | ||||
|             'count'    => 2, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [ | ||||
|                 [ | ||||
|                     'label' => trans('firefly.spent'), | ||||
|                     'data'  => [] | ||||
|                 ], | ||||
|                 [ | ||||
|                     'label' => trans('firefly.earned'), | ||||
|                     'data'  => [] | ||||
|                 ] | ||||
|             ], | ||||
|         ]; | ||||
|  | ||||
|         foreach ($entries as $entry) { | ||||
|             $data['labels'][]              = $entry[0]->formatLocalized($format); | ||||
|             $data['datasets'][0]['data'][] = round($entry[1], 2); | ||||
|             $data['labels'][] = $entry[1]; | ||||
|             $spent            = round($entry[2], 2); | ||||
|             $earned           = round($entry[3], 2); | ||||
|  | ||||
|             $data['datasets'][0]['data'][] = $spent == 0 ? null : $spent * -1; | ||||
|             $data['datasets'][1]['data'][] = $earned == 0 ? null : $earned; | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $categories | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function earnedInPeriod(Collection $categories, Collection $entries) | ||||
|     { | ||||
|  | ||||
|         // language: | ||||
|         $format = trans('config.month'); | ||||
|  | ||||
|         $data = [ | ||||
|             'count'    => 0, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [], | ||||
|         ]; | ||||
|  | ||||
|         foreach ($categories as $category) { | ||||
|             $data['labels'][] = $category->name; | ||||
|         } | ||||
|  | ||||
|         foreach ($entries as $entry) { | ||||
|             $date = $entry[0]->formatLocalized($format); | ||||
|             array_shift($entry); | ||||
|             $data['count']++; | ||||
|             $data['datasets'][] = ['label' => $date, 'data' => $entry]; | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
| @@ -65,15 +100,52 @@ class ChartJsCategoryChartGenerator implements CategoryChartGenerator | ||||
|             ], | ||||
|         ]; | ||||
|         foreach ($entries as $entry) { | ||||
|             if ($entry['sum'] != 0) { | ||||
|                 $data['labels'][]              = $entry['name']; | ||||
|                 $data['datasets'][0]['data'][] = round($entry['sum'], 2); | ||||
|             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 | ||||
|      * | ||||
| @@ -81,9 +153,9 @@ class ChartJsCategoryChartGenerator implements CategoryChartGenerator | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function month(Collection $entries) | ||||
|     public function period(Collection $entries) | ||||
|     { | ||||
|         return $this->all($entries, 'monthAndDay'); | ||||
|         return $this->all($entries); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -93,12 +165,11 @@ class ChartJsCategoryChartGenerator implements CategoryChartGenerator | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function year(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, | ||||
|   | ||||
| @@ -1,106 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Category; | ||||
|  | ||||
| use Grumpydictator\Gchart\GChart; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class GoogleCategoryChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Category | ||||
|  */ | ||||
| class GoogleCategoryChartGenerator implements CategoryChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function all(Collection $entries) | ||||
|     { | ||||
|         $chart = new GChart; | ||||
|         $chart->addColumn(trans('firefly.period'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.spent'), 'number'); | ||||
|  | ||||
|         /** @var array $entry */ | ||||
|         foreach ($entries as $entry) { | ||||
|             $chart->addRow($entry[0], $entry[1]); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return $chart->getData(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage(Collection $entries) | ||||
|     { | ||||
|         $chart = new GChart; | ||||
|         $chart->addColumn(trans('firefly.category'), 'string'); | ||||
|         $chart->addColumn(trans('firefly.spent'), 'number'); | ||||
|  | ||||
|  | ||||
|         /** @var array $entry */ | ||||
|         foreach ($entries as $entry) { | ||||
|             $sum = $entry['sum']; | ||||
|             if ($sum != 0) { | ||||
|                 $chart->addRow($entry['name'], $sum); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return $chart->getData(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function month(Collection $entries) | ||||
|     { | ||||
|         $chart = new GChart; | ||||
|  | ||||
|         $chart->addColumn(trans('firefly.period'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.spent'), 'number'); | ||||
|  | ||||
|         /** @var array $entry */ | ||||
|         foreach ($entries as $entry) { | ||||
|             $chart->addRow($entry[0], $entry[1]); | ||||
|         } | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return $chart->getData(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $categories | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function year(Collection $categories, Collection $entries) | ||||
|     { | ||||
|         $chart = new GChart; | ||||
|  | ||||
|         $chart->addColumn(trans('firefly.month'), 'date'); | ||||
|         foreach ($categories as $category) { | ||||
|             $chart->addColumn($category->name, 'number'); | ||||
|         } | ||||
|         /** @var array $entry */ | ||||
|         foreach ($entries as $entry) { | ||||
|             $chart->addRowArray($entry); | ||||
|         } | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return $chart->getData(); | ||||
|  | ||||
|     } | ||||
| } | ||||
| @@ -3,13 +3,11 @@ | ||||
| namespace FireflyIII\Generator\Chart\PiggyBank; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Config; | ||||
| use Illuminate\Support\Collection; | ||||
| use Preferences; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class GooglePiggyBankChartGenerator | ||||
|  * Class ChartJsPiggyBankChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\PiggyBank | ||||
|  */ | ||||
| @@ -25,8 +23,7 @@ class ChartJsPiggyBankChartGenerator implements PiggyBankChartGenerator | ||||
|     { | ||||
|  | ||||
|         // language: | ||||
|         $language = Preferences::get('language', 'en')->data; | ||||
|         $format   = Config::get('firefly.month.' . $language); | ||||
|         $format = trans('config.month_and_day'); | ||||
|  | ||||
|         $data = [ | ||||
|             'count'    => 1, | ||||
|   | ||||
| @@ -1,41 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\PiggyBank; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Grumpydictator\Gchart\GChart; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class GooglePiggyBankChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\PiggyBank | ||||
|  */ | ||||
| class GooglePiggyBankChartGenerator implements PiggyBankChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $set | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function history(Collection $set) | ||||
|     { | ||||
|         $chart = new GChart; | ||||
|         $chart->addColumn(trans('firefly.date'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.balance'), 'number'); | ||||
|  | ||||
|         $sum = '0'; | ||||
|         bcscale(2); | ||||
|  | ||||
|         foreach ($set as $entry) { | ||||
|             $sum = bcadd($sum, $entry->sum); | ||||
|             $chart->addRow(new Carbon($entry->date), $sum); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return $chart->getData(); | ||||
|     } | ||||
| } | ||||
| @@ -2,18 +2,80 @@ | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Report; | ||||
|  | ||||
| use Config; | ||||
| use Illuminate\Support\Collection; | ||||
| use Preferences; | ||||
|  | ||||
| /** | ||||
|  * Class GoogleReportChartGenerator | ||||
|  * Class ChartJsReportChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Report | ||||
|  */ | ||||
| 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, | ||||
|   | ||||
| @@ -1,58 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Report; | ||||
|  | ||||
| use Grumpydictator\Gchart\GChart; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class GoogleReportChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Report | ||||
|  */ | ||||
| class GoogleReportChartGenerator implements ReportChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function yearInOut(Collection $entries) | ||||
|     { | ||||
|         $chart = new GChart; | ||||
|         $chart->addColumn(trans('firefly.month'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.income'), 'number'); | ||||
|         $chart->addColumn(trans('firefly.expenses'), 'number'); | ||||
|  | ||||
|         /** @var array $entry */ | ||||
|         foreach ($entries as $entry) { | ||||
|             $chart->addRowArray($entry); | ||||
|         } | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return $chart->getData(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $income | ||||
|      * @param string $expense | ||||
|      * @param int    $count | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function yearInOutSummarized($income, $expense, $count) | ||||
|     { | ||||
|         $chart = new GChart; | ||||
|  | ||||
|         $chart->addColumn(trans('firefly.summary'), 'string'); | ||||
|         $chart->addColumn(trans('firefly.income'), 'number'); | ||||
|         $chart->addColumn(trans('firefly.expenses'), 'number'); | ||||
|         $chart->addRow(trans('firefly.sum'), $income, $expense); | ||||
|         $chart->addRow(trans('firefly.average'), ($income / $count), ($expense / $count)); | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return $chart->getData(); | ||||
|     } | ||||
| } | ||||
| @@ -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 | ||||
| @@ -53,7 +51,7 @@ class ConnectJournalToPiggyBank | ||||
|         } | ||||
|         bcscale(2); | ||||
|  | ||||
|         $amount = $journal->actual_amount; | ||||
|         $amount = $journal->amount_positive; | ||||
|         // if piggy account matches source account, the amount is positive | ||||
|         if ($piggyBank->account_id == $journal->source_account->id) { | ||||
|             $amount = $amount * -1; | ||||
|   | ||||
| @@ -49,10 +49,12 @@ class UpdateJournalConnection | ||||
|         if (is_null($repetition)) { | ||||
|             return; | ||||
|         } | ||||
|         $amount = $journal->amount; | ||||
|         $diff   = $amount - $event->amount; // update current repetition | ||||
|         bcscale(2); | ||||
|  | ||||
|         $repetition->currentamount += $diff; | ||||
|         $amount = $journal->amount; | ||||
|         $diff   = bcsub($amount, $event->amount); // update current repetition | ||||
|  | ||||
|         $repetition->currentamount = bcadd($repetition->currentamount, $diff); | ||||
|         $repetition->save(); | ||||
|  | ||||
|  | ||||
|   | ||||
							
								
								
									
										224
									
								
								app/Helpers/Attachments/AttachmentHelper.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										224
									
								
								app/Helpers/Attachments/AttachmentHelper.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,224 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Attachments; | ||||
|  | ||||
| use Auth; | ||||
| use Config; | ||||
| use Crypt; | ||||
| use FireflyIII\Models\Attachment; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Support\MessageBag; | ||||
| use Input; | ||||
| use Symfony\Component\HttpFoundation\File\UploadedFile; | ||||
|  | ||||
| /** | ||||
|  * Class AttachmentHelper | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Attachments | ||||
|  */ | ||||
| class AttachmentHelper implements AttachmentHelperInterface | ||||
| { | ||||
|  | ||||
|     /** @var int */ | ||||
|     protected $maxUploadSize; | ||||
|     /** @var array */ | ||||
|     protected $allowedMimes; | ||||
|     /** @var MessageBag */ | ||||
|     public $errors; | ||||
|     /** @var MessageBag */ | ||||
|     public $messages; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->maxUploadSize = Config::get('firefly.maxUploadSize'); | ||||
|         $this->allowedMimes  = Config::get('firefly.allowedMimes'); | ||||
|         $this->errors        = new MessageBag; | ||||
|         $this->messages      = new MessageBag; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Attachment $attachment | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getAttachmentLocation(Attachment $attachment) | ||||
|     { | ||||
|         $path = storage_path('upload') . DIRECTORY_SEPARATOR . 'at-' . $attachment->id . '.data'; | ||||
|  | ||||
|         return $path; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Model $model | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function saveAttachmentsForModel(Model $model) | ||||
|     { | ||||
|         $files = Input::file('attachments'); | ||||
|  | ||||
|         if (is_array($files)) { | ||||
|             foreach ($files as $entry) { | ||||
|                 if (!is_null($entry)) { | ||||
|                     $this->processFile($entry, $model); | ||||
|                 } | ||||
|             } | ||||
|         } else { | ||||
|             if (!is_null($files)) { | ||||
|                 $this->processFile($files, $model); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param UploadedFile $file | ||||
|      * @param Model        $model | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     protected function hasFile(UploadedFile $file, Model $model) | ||||
|     { | ||||
|         $md5   = md5_file($file->getRealPath()); | ||||
|         $name  = $file->getClientOriginalName(); | ||||
|         $class = get_class($model); | ||||
|         $count = Auth::user()->attachments()->where('md5', $md5)->where('attachable_id', $model->id)->where('attachable_type', $class)->count(); | ||||
|  | ||||
|         if ($count > 0) { | ||||
|             $msg = trans('validation.file_already_attached', ['name' => $name]); | ||||
|             $this->errors->add('attachments', $msg); | ||||
|  | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param UploadedFile $file | ||||
|      * @param Model        $model | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     protected function validateUpload(UploadedFile $file, Model $model) | ||||
|     { | ||||
|         if (!$this->validMime($file)) { | ||||
|             return false; | ||||
|         } | ||||
|         if (!$this->validSize($file)) { | ||||
|             return false; | ||||
|         } | ||||
|         if ($this->hasFile($file, $model)) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param UploadedFile $file | ||||
|      * @param Model        $model | ||||
|      * | ||||
|      * @return bool|Attachment | ||||
|      */ | ||||
|     protected function processFile(UploadedFile $file, Model $model) | ||||
|     { | ||||
|         $validation = $this->validateUpload($file, $model); | ||||
|         if ($validation === false) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         $attachment = new Attachment; // create Attachment object. | ||||
|         $attachment->user()->associate(Auth::user()); | ||||
|         $attachment->attachable()->associate($model); | ||||
|         $attachment->md5      = md5_file($file->getRealPath()); | ||||
|         $attachment->filename = $file->getClientOriginalName(); | ||||
|         $attachment->mime     = $file->getMimeType(); | ||||
|         $attachment->size     = $file->getSize(); | ||||
|         $attachment->uploaded = 0; | ||||
|         $attachment->save(); | ||||
|  | ||||
|         $path      = $file->getRealPath(); // encrypt and move file to storage. | ||||
|         $content   = file_get_contents($path); | ||||
|         $encrypted = Crypt::encrypt($content); | ||||
|  | ||||
|         // store it: | ||||
|         $upload = $this->getAttachmentLocation($attachment); | ||||
|         if (is_writable(dirname($upload))) { | ||||
|             file_put_contents($upload, $encrypted); | ||||
|         } | ||||
|  | ||||
|         $attachment->uploaded = 1; // update attachment | ||||
|         $attachment->save(); | ||||
|  | ||||
|         $name = e($file->getClientOriginalName()); // add message: | ||||
|         $msg  = trans('validation.file_attached', ['name' => $name]); | ||||
|         $this->messages->add('attachments', $msg); | ||||
|  | ||||
|         // return it. | ||||
|         return $attachment; | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param UploadedFile $file | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     protected function validMime(UploadedFile $file) | ||||
|     { | ||||
|         $mime = e($file->getMimeType()); | ||||
|         $name = e($file->getClientOriginalName()); | ||||
|  | ||||
|         if (!in_array($mime, $this->allowedMimes)) { | ||||
|             $msg = trans('validation.file_invalid_mime', ['name' => $name, 'mime' => $mime]); | ||||
|             $this->errors->add('attachments', $msg); | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param UploadedFile $file | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     protected function validSize(UploadedFile $file) | ||||
|     { | ||||
|         $size = $file->getSize(); | ||||
|         $name = e($file->getClientOriginalName()); | ||||
|         if ($size > $this->maxUploadSize) { | ||||
|             $msg = trans('validation.file_too_large', ['name' => $name]); | ||||
|             $this->errors->add('attachments', $msg); | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return MessageBag | ||||
|      */ | ||||
|     public function getErrors() | ||||
|     { | ||||
|         return $this->errors; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return MessageBag | ||||
|      */ | ||||
|     public function getMessages() | ||||
|     { | ||||
|         return $this->messages; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										41
									
								
								app/Helpers/Attachments/AttachmentHelperInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								app/Helpers/Attachments/AttachmentHelperInterface.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Attachments; | ||||
|  | ||||
| use FireflyIII\Models\Attachment; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Support\MessageBag; | ||||
|  | ||||
| /** | ||||
|  * Interface AttachmentHelperInterface | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Attachments | ||||
|  */ | ||||
| interface AttachmentHelperInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Model $model | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function saveAttachmentsForModel(Model $model); | ||||
|  | ||||
|     /** | ||||
|      * @return MessageBag | ||||
|      */ | ||||
|     public function getErrors(); | ||||
|  | ||||
|     /** | ||||
|      * @return MessageBag | ||||
|      */ | ||||
|     public function getMessages(); | ||||
|  | ||||
|     /** | ||||
|      * @param Attachment $attachment | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function getAttachmentLocation(Attachment $attachment); | ||||
|  | ||||
| } | ||||
| @@ -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; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -34,8 +34,10 @@ class Category | ||||
|      */ | ||||
|     public function addCategory(CategoryModel $category) | ||||
|     { | ||||
|         if ($category->spent > 0) { | ||||
|         // spent is minus zero for an expense report: | ||||
|         if ($category->spent < 0) { | ||||
|             $this->categories->push($category); | ||||
|             $this->addTotal($category->spent); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -54,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,19 +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, 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); | ||||
|             $existing->amount = bcadd($existing->amount, $amount); | ||||
|             $existing->count++; | ||||
|             $this->expenses->put($accountId, $existing); | ||||
|         } | ||||
| @@ -56,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); | ||||
|     } | ||||
|  | ||||
| @@ -66,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, 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); | ||||
|             $existing->amount = bcadd($existing->amount, $entry->journalAmount); | ||||
|             $existing->count++; | ||||
|             $this->incomes->put($accountId, $existing); | ||||
|         } | ||||
|   | ||||
| @@ -29,7 +29,7 @@ class AccountId extends BasicConverter implements ConverterInterface | ||||
|             $account = Auth::user()->accounts()->find($this->value); | ||||
|  | ||||
|             if (!is_null($account)) { | ||||
|                 Log::debug('Found ' . $account->accountType->type . ' named "******" with ID: ' . $this->value.' (not mapped) '); | ||||
|                 Log::debug('Found ' . $account->accountType->type . ' named "******" with ID: ' . $this->value . ' (not mapped) '); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -3,6 +3,9 @@ | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use InvalidArgumentException; | ||||
| use Log; | ||||
| use Session; | ||||
|  | ||||
| /** | ||||
| @@ -14,13 +17,22 @@ class Date extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Carbon | ||||
|      * @return static | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         $format = Session::get('csv-date-format'); | ||||
|         try { | ||||
|             $date = Carbon::createFromFormat($format, $this->value); | ||||
|         } catch (InvalidArgumentException $e) { | ||||
|             Log::error('Date conversion error: ' . $e->getMessage() . '. Value was "' . $this->value . '", format was "' . $format . '".'); | ||||
|  | ||||
|             $message = trans('firefly.csv_date_parse_error', ['format' => $format, 'value' => $this->value]); | ||||
|  | ||||
|             throw new FireflyException($message); | ||||
|         } | ||||
|  | ||||
|         $date = Carbon::createFromFormat($format, $this->value); | ||||
|  | ||||
|         return $date; | ||||
|     } | ||||
|   | ||||
| @@ -124,7 +124,7 @@ class Importer | ||||
|      */ | ||||
|     protected function parseRow($index) | ||||
|     { | ||||
|         return (($this->data->hasHeaders() && $index > 1) || !$this->data->hasHeaders()); | ||||
|         return (($this->data->hasHeaders() && $index >= 1) || !$this->data->hasHeaders()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -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; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -7,9 +7,10 @@ use Crypt; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Csv\Mapper\MapperInterface; | ||||
| use League\Csv\Reader; | ||||
| use Log; | ||||
| use ReflectionException; | ||||
| use Session; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class Wizard | ||||
|  * | ||||
| @@ -110,6 +111,7 @@ class Wizard implements WizardInterface | ||||
|         foreach ($fields as $field) { | ||||
|             if (!Session::has($field)) { | ||||
|                 Log::error('Session is missing field: ' . $field); | ||||
|  | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -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, ($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); | ||||
|             $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,165 +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->spentInPeriodCorrected($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->spentInPeriodCorrected($budget, $repetition->startdate, $repetition->enddate, $shared); | ||||
|                 $left      = $expenses < floatval($repetition->amount) ? floatval($repetition->amount) - $expenses : 0; | ||||
|                 $spent     = $expenses > floatval($repetition->amount) ? 0 : $expenses; | ||||
|                 $overspent = $expenses > floatval($repetition->amount) ? $expenses - floatval($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->spentInPeriodCorrected($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); | ||||
|             $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); | ||||
|             $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,265 +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"'); | ||||
|                         } | ||||
|                     ); | ||||
|                 } | ||||
|             ); | ||||
|         } 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); | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|         $data = $data->filter( | ||||
|             function (TransactionJournal $journal) { | ||||
|                 if ($journal->amount != 0) { | ||||
|                     return $journal; | ||||
|                 } | ||||
|         return $array; | ||||
|  | ||||
|                 return null; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         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"'); | ||||
|                         } | ||||
|                     ); | ||||
|                 } | ||||
|             ); | ||||
|         } 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) | ||||
|     { | ||||
|  | ||||
|         return floatval( | ||||
|                    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]; | ||||
| @@ -130,7 +133,7 @@ class AccountController extends Controller | ||||
|             'ccMonthlyPaymentDate' => $account->getMeta('ccMonthlyPaymentDate'), | ||||
|             'openingBalanceDate'   => $openingBalance ? $openingBalance->date->format('Y-m-d') : null, | ||||
|             'openingBalance'       => $openingBalanceAmount, | ||||
|             'virtualBalance'       => floatval($account->virtual_balance) | ||||
|             'virtualBalance'       => round($account->virtual_balance, 2) | ||||
|         ]; | ||||
|         Session::flash('preFilled', $preFilled); | ||||
|         Session::flash('gaEventCategory', 'accounts'); | ||||
| @@ -140,39 +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 ($startBalances, $endBalances) { | ||||
|                 $account->lastActivityDate = null;//$repository->getLastActivity($account); | ||||
|                 $account->startBalance     = isset($startBalances[$account->id]) ? $startBalances[$account->id] : null; | ||||
|                 $account->endBalance       = isset($endBalances[$account->id]) ? $endBalances[$account->id] : null; | ||||
|             function (Account $account) use ($activities, $startBalances, $endBalances) { | ||||
|                 $account->lastActivityDate = $this->isInArray($activities, $account->id); | ||||
|                 $account->startBalance     = $this->isInArray($startBalances, $account->id); | ||||
|                 $account->endBalance       = $this->isInArray($endBalances, $account->id); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
| @@ -180,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); | ||||
| @@ -199,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'         => floatval($request->input('virtualBalance')), | ||||
|             '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'         => floatval($request->input('openingBalance')), | ||||
|             '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')), | ||||
|  | ||||
|         ]; | ||||
|  | ||||
| @@ -237,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 = [ | ||||
| @@ -252,8 +248,8 @@ class AccountController extends Controller | ||||
|             'user'                   => Auth::user()->id, | ||||
|             'iban'                   => $request->input('iban'), | ||||
|             'accountRole'            => $request->input('accountRole'), | ||||
|             'virtualBalance'         => floatval($request->input('virtualBalance')), | ||||
|             'openingBalance'         => floatval($request->input('openingBalance')), | ||||
|             'virtualBalance'         => round($request->input('virtualBalance'), 2), | ||||
|             'openingBalance'         => round($request->input('openingBalance'), 2), | ||||
|             'openingBalanceDate'     => new Carbon((string)$request->input('openingBalanceDate')), | ||||
|             'openingBalanceCurrency' => intval($request->input('balance_currency_id')), | ||||
|             'ccType'                 => $request->input('ccType'), | ||||
| @@ -278,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; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
							
								
								
									
										174
									
								
								app/Http/Controllers/AttachmentController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								app/Http/Controllers/AttachmentController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,174 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
|  | ||||
| use Crypt; | ||||
| use File; | ||||
| use FireflyIII\Helpers\Attachments\AttachmentHelperInterface; | ||||
| use FireflyIII\Http\Requests\AttachmentFormRequest; | ||||
| use FireflyIII\Models\Attachment; | ||||
| use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface; | ||||
| use Input; | ||||
| use Preferences; | ||||
| use Response; | ||||
| use Session; | ||||
| use URL; | ||||
| use View; | ||||
|  | ||||
| /** | ||||
|  * Class AttachmentController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| class AttachmentController extends Controller | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         View::share('mainTitleIcon', 'fa-paperclip'); | ||||
|         View::share('title', trans('firefly.attachments')); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param Attachment $attachment | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function edit(Attachment $attachment) | ||||
|     { | ||||
|         $subTitleIcon = 'fa-pencil'; | ||||
|         $subTitle     = trans('firefly.edit_attachment', ['name' => $attachment->filename]); | ||||
|  | ||||
|         // put previous url in session if not redirect from store (not "return_to_edit"). | ||||
|         if (Session::get('attachments.edit.fromUpdate') !== true) { | ||||
|             Session::put('attachments.edit.url', URL::previous()); | ||||
|         } | ||||
|         Session::forget('attachments.edit.fromUpdate'); | ||||
|  | ||||
|         return view('attachments.edit', compact('attachment', 'subTitleIcon', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Attachment $attachment | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function delete(Attachment $attachment) | ||||
|     { | ||||
|         $subTitle = trans('firefly.delete_attachment', ['name' => $attachment->filename]); | ||||
|  | ||||
|         // put previous url in session | ||||
|         Session::put('attachments.delete.url', URL::previous()); | ||||
|         Session::flash('gaEventCategory', 'attachments'); | ||||
|         Session::flash('gaEventAction', 'delete-attachment'); | ||||
|  | ||||
|         return view('attachments.delete', compact('attachment', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AttachmentRepositoryInterface $repository | ||||
|      * @param Attachment                    $attachment | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function destroy(AttachmentRepositoryInterface $repository, Attachment $attachment) | ||||
|     { | ||||
|         $name = $attachment->filename; | ||||
|  | ||||
|         $repository->destroy($attachment); | ||||
|  | ||||
|         Session::flash('success', trans('firefly.attachment_deleted', ['name' => $name])); | ||||
|         Preferences::mark(); | ||||
|  | ||||
|         return redirect(Session::get('attachments.delete.url')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Attachment                $attachment | ||||
|      * @param AttachmentHelperInterface $helper | ||||
|      */ | ||||
|     public function download(Attachment $attachment, AttachmentHelperInterface $helper) | ||||
|     { | ||||
|  | ||||
|         $file = $helper->getAttachmentLocation($attachment); | ||||
|         if (file_exists($file)) { | ||||
|  | ||||
|             $quoted = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\')); | ||||
|  | ||||
|             header('Content-Description: File Transfer'); | ||||
|             header('Content-Type: application/octet-stream'); | ||||
|             header('Content-Disposition: attachment; filename=' . $quoted); | ||||
|             header('Content-Transfer-Encoding: binary'); | ||||
|             header('Connection: Keep-Alive'); | ||||
|             header('Expires: 0'); | ||||
|             header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); | ||||
|             header('Pragma: public'); | ||||
|             header('Content-Length: ' . $attachment->size); | ||||
|  | ||||
|             echo Crypt::decrypt(file_get_contents($file)); | ||||
|  | ||||
|         } else { | ||||
|             abort(404); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Attachment $attachment | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function preview(Attachment $attachment) | ||||
|     { | ||||
|         if ($attachment->mime == 'application/pdf') { | ||||
|             $file = public_path('images/page_white_acrobat.png'); | ||||
|         } else { | ||||
|             $file = public_path('images/page_green.png'); | ||||
|         } | ||||
|  | ||||
|         $response = Response::make(File::get($file)); | ||||
|         $response->header('Content-Type', 'image/png'); | ||||
|  | ||||
|         return $response; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param AttachmentFormRequest         $request | ||||
|      * @param AttachmentRepositoryInterface $repository | ||||
|      * @param Attachment                    $attachment | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function update(AttachmentFormRequest $request, AttachmentRepositoryInterface $repository, Attachment $attachment) | ||||
|     { | ||||
|  | ||||
|         $attachmentData = [ | ||||
|             'title'       => $request->input('title'), | ||||
|             'description' => $request->input('description'), | ||||
|             'notes'       => $request->input('notes'), | ||||
|         ]; | ||||
|  | ||||
|         $repository->update($attachment, $attachmentData); | ||||
|  | ||||
|         Session::flash('success', 'Attachment "' . $attachment->filename . '" updated.'); | ||||
|         Preferences::mark(); | ||||
|  | ||||
|         if (intval(Input::get('return_to_edit')) === 1) { | ||||
|             // set value so edit routine will not overwrite URL: | ||||
|             Session::put('attachments.edit.fromUpdate', true); | ||||
|  | ||||
|             return redirect(route('attachments.edit', [$attachment->id]))->withInput(['return_to_edit' => 1]); | ||||
|         } | ||||
|  | ||||
|         // redirect to previous URL. | ||||
|         return redirect(Session::get('attachments.edit.url')); | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -1,13 +1,17 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers\Auth; | ||||
|  | ||||
| use Auth; | ||||
| use Config; | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Models\Role; | ||||
| use FireflyIII\User; | ||||
| 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; | ||||
| use Twig; | ||||
| use Validator; | ||||
| @@ -19,19 +23,76 @@ use Validator; | ||||
|  */ | ||||
| class AuthController extends Controller | ||||
| { | ||||
|     use AuthenticatesAndRegistersUsers, ThrottlesLogins; | ||||
|  | ||||
|     /* | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | Registration & Login Controller | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | | ||||
|     | This controller handles the registration of new users, as well as the | ||||
|     | authentication of existing users. By default, this controller uses | ||||
|     | a simple trait to add these behaviors. Why don't you explore it? | ||||
|     | | ||||
|     */ | ||||
|     /** | ||||
|      * 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. | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function getRegister() | ||||
|     { | ||||
|         $host = Rq::getHttpHost(); | ||||
|  | ||||
|         return view('auth.register', compact('host')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Handle a login request to the application. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function postLogin(Request $request) | ||||
|     { | ||||
|         $this->validate($request, [$this->loginUsername() => 'required', 'password' => 'required',]); | ||||
|         $throttles = $this->isUsingThrottlesLoginsTrait(); | ||||
|  | ||||
|         if ($throttles && $this->hasTooManyLoginAttempts($request)) { | ||||
|             return $this->sendLockoutResponse($request); | ||||
|         } | ||||
|  | ||||
|         $credentials            = $this->getCredentials($request); | ||||
|         $credentials['blocked'] = 0; // most not be blocked. | ||||
|  | ||||
|         if (Auth::attempt($credentials, $request->has('remember'))) { | ||||
|             return $this->handleUserWasAuthenticated($request, $throttles); | ||||
|         } | ||||
|  | ||||
|         $message = $this->getFailedLoginMessage(); | ||||
|         /** @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; | ||||
|             if (strlen($code) == 0) { | ||||
|                 $code = 'general_blocked'; | ||||
|             } | ||||
|             $message = trans('firefly.' . $code . '_error', ['email' => $credentials['email']]); | ||||
|         } | ||||
|  | ||||
|         if ($throttles) { | ||||
|             $this->incrementLoginAttempts($request); | ||||
|         } | ||||
|  | ||||
|         return redirect($this->loginPath()) | ||||
|             ->withInput($request->only($this->loginUsername(), 'remember')) | ||||
|             ->withErrors([$this->loginUsername() => $message,]); | ||||
|     } | ||||
|  | ||||
|     use AuthenticatesAndRegistersUsers; | ||||
|  | ||||
|     public $redirectTo = '/'; | ||||
|  | ||||
| @@ -79,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!'); | ||||
| @@ -116,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,8 +6,11 @@ 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; | ||||
| use Response; | ||||
| use Session; | ||||
| @@ -18,7 +21,6 @@ use View; | ||||
|  * Class BudgetController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  * @SuppressWarnings(PHPMD.TooManyMethods) | ||||
|  */ | ||||
| class BudgetController extends Controller | ||||
| { | ||||
| @@ -132,28 +134,35 @@ 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(); | ||||
|         $spent    = '0'; | ||||
|         $budgeted = '0'; | ||||
|         $budgets           = $repository->getActiveBudgets(); | ||||
|         $inactive          = $repository->getInactiveBudgets(); | ||||
|         $spent             = '0'; | ||||
|         $budgeted          = '0'; | ||||
|         $range             = Preferences::get('viewRange', '1M')->data; | ||||
|         $start             = Navigation::startOfPeriod(Session::get('start', new Carbon), $range); | ||||
|         $end               = Navigation::endOfPeriod($start, $range); | ||||
|         $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: | ||||
|          */ | ||||
|         $repository->cleanupBudgets(); | ||||
|  | ||||
|  | ||||
|         // loop the budgets: | ||||
|         /** @var Budget $budget */ | ||||
|         foreach ($budgets as $budget) { | ||||
|             $date               = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|             $end                = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|             $budget->spent      = $repository->spentInPeriodCorrected($budget, $date, $end); | ||||
|             $budget->currentRep = $repository->getCurrentRepetition($budget, $date); | ||||
|             $budget->spent      = $repository->balanceInPeriod($budget, $start, $end, $accounts); | ||||
|             $budget->currentRep = $repository->getCurrentRepetition($budget, $start, $end); | ||||
|             if ($budget->currentRep) { | ||||
|                 $budgeted = bcadd($budgeted, $budget->currentRep->amount); | ||||
|             } | ||||
| @@ -161,13 +170,12 @@ class BudgetController extends Controller | ||||
|  | ||||
|         } | ||||
|  | ||||
|         $dateAsString      = Session::get('start', Carbon::now()->startOfMonth())->format('FY'); | ||||
|         $budgetIncomeTotal = Preferences::get('budgetIncomeTotal' . $dateAsString, 1000)->data; | ||||
|         $budgetMaximum     = Preferences::get('budgetMaximum', 1000)->data; | ||||
|         $defaultCurrency   = Amount::getDefaultCurrency(); | ||||
|  | ||||
|         $budgetMaximum   = Preferences::get('budgetMaximum', 1000)->data; | ||||
|         $defaultCurrency = Amount::getDefaultCurrency(); | ||||
|  | ||||
|         return view( | ||||
|             'budgets.index', compact('budgetMaximum', 'budgetIncomeTotal', 'defaultCurrency', 'inactive', 'budgets', 'spent', 'budgeted') | ||||
|             'budgets.index', compact('budgetMaximum', 'period', 'range', 'budgetIncomeTotal', 'defaultCurrency', 'inactive', 'budgets', 'spent', 'budgeted') | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| @@ -178,8 +186,9 @@ class BudgetController extends Controller | ||||
|      */ | ||||
|     public function noBudget(BudgetRepositoryInterface $repository) | ||||
|     { | ||||
|         $start    = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end      = Session::get('end', Carbon::now()->startOfMonth()); | ||||
|         $range    = Preferences::get('viewRange', '1M')->data; | ||||
|         $start    = Navigation::startOfPeriod(Session::get('start', new Carbon), $range); | ||||
|         $end      = Navigation::endOfPeriod($start, $range); | ||||
|         $list     = $repository->getWithoutBudget($start, $end); | ||||
|         $subTitle = trans( | ||||
|             'firefly.without_budget_between', | ||||
| @@ -194,9 +203,12 @@ class BudgetController extends Controller | ||||
|      */ | ||||
|     public function postUpdateIncome() | ||||
|     { | ||||
|         $range = Preferences::get('viewRange', '1M')->data; | ||||
|         $start = Navigation::startOfPeriod(Session::get('start', new Carbon), $range); | ||||
|         $end   = Navigation::endOfPeriod($start, $range); | ||||
|         $key   = 'budgetIncomeTotal' . $start->format('Ymd') . $end->format('Ymd'); | ||||
|  | ||||
|         $date = Session::get('start', Carbon::now()->startOfMonth())->format('FY'); | ||||
|         Preferences::set('budgetIncomeTotal' . $date, intval(Input::get('amount'))); | ||||
|         Preferences::set($key, intval(Input::get('amount'))); | ||||
|         Preferences::mark(); | ||||
|  | ||||
|         return redirect(route('budgets.index')); | ||||
| @@ -220,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')); | ||||
| @@ -272,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); | ||||
| @@ -297,8 +322,11 @@ class BudgetController extends Controller | ||||
|      */ | ||||
|     public function updateIncome() | ||||
|     { | ||||
|         $date   = Session::get('start', Carbon::now()->startOfMonth())->format('FY'); | ||||
|         $amount = Preferences::get('budgetIncomeTotal' . $date, 1000); | ||||
|         $range  = Preferences::get('viewRange', '1M')->data; | ||||
|         $start  = Navigation::startOfPeriod(Session::get('start', new Carbon), $range); | ||||
|         $end    = Navigation::endOfPeriod($start, $range); | ||||
|         $key    = 'budgetIncomeTotal' . $start->format('Ymd') . $end->format('Ymd'); | ||||
|         $amount = Preferences::get($key, 1000); | ||||
|  | ||||
|         return view('budgets.income', compact('amount')); | ||||
|     } | ||||
|   | ||||
| @@ -4,9 +4,13 @@ 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; | ||||
| use Input; | ||||
| use Navigation; | ||||
| use Preferences; | ||||
| use Session; | ||||
| use URL; | ||||
| @@ -65,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; | ||||
| @@ -104,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); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
| @@ -122,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)] | ||||
| @@ -140,30 +145,100 @@ class CategoryController extends Controller | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param Category                    $category | ||||
|      * @param SCRI                              $repository | ||||
|      * @param Category                          $category | ||||
|      * | ||||
|      * @param                                   $date | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function show(CategoryRepositoryInterface $repository, Category $category) | ||||
|     public function showWithDate(SCRI $repository, Category $category, $date) | ||||
|     { | ||||
|         $carbon   = new Carbon($date); | ||||
|         $range    = Preferences::get('viewRange', '1M')->data; | ||||
|         $start    = Navigation::startOfPeriod($carbon, $range); | ||||
|         $end      = Navigation::endOfPeriod($carbon, $range); | ||||
|         $subTitle = $category->name; | ||||
|  | ||||
|         $hideCategory = true; // used in list. | ||||
|         $page         = intval(Input::get('page')); | ||||
|  | ||||
|         $set      = $repository->getJournalsInRange($category, $page, $start, $end); | ||||
|         $count    = $repository->countJournalsInRange($category, $start, $end); | ||||
|         $journals = new LengthAwarePaginator($set, $count, 50, $page); | ||||
|         $journals->setPath('categories/show/' . $category->id . '/' . $date); | ||||
|  | ||||
|         return view('categories.show_with_date', compact('category', 'journals', 'hideCategory', 'subTitle', 'carbon')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param SCRI     $repository | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function show(SCRI $repository, Category $category) | ||||
|     { | ||||
|         $hideCategory = true; // used in list. | ||||
|         $page         = intval(Input::get('page')); | ||||
|         $set          = $repository->getJournals($category, $page); | ||||
|         $count        = $repository->countJournals($category); | ||||
|         $subTitle     = $category->name; | ||||
|         $journals     = new LengthAwarePaginator($set, $count, 50, $page); | ||||
|         $journals->setPath('categories/show/' . $category->id); | ||||
|  | ||||
|         return view('categories.show', compact('category', 'journals', 'hideCategory')); | ||||
|         // list of ranges for list of periods: | ||||
|  | ||||
|         // oldest transaction in category: | ||||
|         $start   = $repository->getFirstActivityDate($category); | ||||
|         $range   = Preferences::get('viewRange', '1M')->data; | ||||
|         $start   = Navigation::startOfPeriod($start, $range); | ||||
|         $end     = Navigation::endOfX(new Carbon, $range); | ||||
|         $entries = new Collection; | ||||
|  | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties(); | ||||
|         $cache->addProperty($start); | ||||
|         $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 { | ||||
|  | ||||
|             while ($end >= $start) { | ||||
|                 $end        = Navigation::startOfPeriod($end, $range); | ||||
|                 $currentEnd = Navigation::endOfPeriod($end, $range); | ||||
|  | ||||
|                 // 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]); | ||||
|  | ||||
|                 $end = Navigation::subtractPeriod($end, $range, 1); | ||||
|  | ||||
|             } | ||||
|             $cache->store($entries); | ||||
|         } | ||||
|  | ||||
|         return view('categories.show', compact('category', 'journals', 'entries', 'hideCategory', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @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'), | ||||
| @@ -185,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,58 +35,75 @@ 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); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Shows the balances for all the user's frontpage accounts. | ||||
|      * Shows the balances for all the user's expense accounts. | ||||
|      * | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * @param ARI $repository | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function frontpage(AccountRepositoryInterface $repository) | ||||
|     public function expenseAccounts(ARI $repository) | ||||
|     { | ||||
|         $start    = clone Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end      = clone Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $accounts = $repository->getAccounts(['Expense account', 'Beneficiary account']); | ||||
|  | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties(); | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty('expenseAccounts'); | ||||
|         $cache->addProperty('accounts'); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $data = $this->generator->expenseAccounts($accounts, $start, $end); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Shows the balances for all the user's frontpage accounts. | ||||
|      * | ||||
|      * @param ARI $repository | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     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->spentInPeriodCorrected($budget, $first, $end); | ||||
|             $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,81 +248,97 @@ 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->spentInPeriodCorrected($budget, $start, $end, true); | ||||
|                 $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->spentInPeriodCorrected($budget, $repetition->startdate, $repetition->enddate, true); | ||||
|                 // $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; | ||||
|         $budgets = $repository->getBudgets(); | ||||
|  | ||||
|         // 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 | ||||
|         } | ||||
|  | ||||
|         $entries = new Collection; | ||||
|         $budgetInformation = $repository->getBudgetsAndExpensesPerMonth($accounts, $start, $end); | ||||
|         $budgets           = new Collection; | ||||
|         $entries           = new Collection; | ||||
|  | ||||
|         /** @var array $row */ | ||||
|         foreach ($budgetInformation as $row) { | ||||
|             $budgets->push($row['budget']); | ||||
|         } | ||||
|  | ||||
|         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->spentInPeriodCorrected($budget, $start, $month, $shared); | ||||
|             // 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); | ||||
|   | ||||
| @@ -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,19 +40,18 @@ 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); | ||||
|         $range = Preferences::get('viewRange', '1M')->data; | ||||
|         $start = Navigation::startOfPeriod($start, $range); | ||||
|         $end   = new Carbon; | ||||
|  | ||||
|         $start   = $repository->getFirstActivityDate($category); | ||||
|         $range   = Preferences::get('viewRange', '1M')->data; | ||||
|         $start   = Navigation::startOfPeriod($start, $range); | ||||
|         $end     = new Carbon; | ||||
|         $entries = new Collection; | ||||
|  | ||||
|  | ||||
| @@ -63,14 +64,25 @@ 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->spentInPeriodCorrected($category, $start, $currentEnd); | ||||
|             $entries->push([clone $start, $spent]); | ||||
|             $start = Navigation::addPeriod($start, $range, 0); | ||||
|  | ||||
|             // 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); | ||||
|         } | ||||
|         // limit the set to the last 40: | ||||
|         $entries = $entries->reverse(); | ||||
|         $entries = $entries->slice(0, 48); | ||||
|         $entries = $entries->reverse(); | ||||
|  | ||||
|         $data = $this->generator->all($entries); | ||||
|         $cache->store($data); | ||||
| @@ -80,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()); | ||||
| @@ -103,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 month(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()); | ||||
| @@ -139,21 +250,75 @@ class CategoryController extends Controller | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty($category->id); | ||||
|         $cache->addProperty('category'); | ||||
|         $cache->addProperty('month'); | ||||
|         $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); | ||||
|  | ||||
|             $entries->push([clone $start, $spent]); | ||||
|             $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(); | ||||
|         } | ||||
|  | ||||
|         $data = $this->generator->month($entries); | ||||
|         $data = $this->generator->period($entries); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param SCRI                        $repository | ||||
|      * @param Category                    $category | ||||
|      * | ||||
|      * @param                             $date | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function specificPeriod(SCRI $repository, Category $category, $date) | ||||
|     { | ||||
|         $carbon = new Carbon($date); | ||||
|         $range  = Preferences::get('viewRange', '1M')->data; | ||||
|         $start  = Navigation::startOfPeriod($carbon, $range); | ||||
|         $end    = Navigation::endOfPeriod($carbon, $range); | ||||
|  | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties; | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty($category->id); | ||||
|         $cache->addProperty('category'); | ||||
|         $cache->addProperty('specificPeriod'); | ||||
|         $cache->addProperty($date); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|         $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) { | ||||
|             $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(); | ||||
|         } | ||||
|  | ||||
|         $data = $this->generator->period($entries); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
| @@ -162,49 +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 year(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('year'); | ||||
|         $cache->addProperty('earned-in-period'); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $shared     = $shared == 'shared' ? true : false; | ||||
|         $categories = $repository->getCategories(); | ||||
|         $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->spentInPeriodCorrected($category, $start, $month, $shared); | ||||
|                 $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->earned, 2); | ||||
|                 } else { | ||||
|                     $row[] = 0; | ||||
|                 } | ||||
|             } | ||||
|             $entries->push($row); | ||||
|  | ||||
|             $entries->push($row); | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|  | ||||
|         $data = $this->generator->year($categories, $entries); | ||||
|         $data = $this->generator->earnedInPeriod($categories, $entries); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
|         return $data; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a chart of what has been spent in this period in each category | ||||
|      * grouped by month. | ||||
|      * | ||||
|      * @param CRI                         $repository | ||||
|      * @param                             $reportType | ||||
|      * @param Carbon                      $start | ||||
|      * @param Carbon                      $end | ||||
|      * @param Collection                  $accounts | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function spentInPeriod(CRI $repository, $reportType, Carbon $start, Carbon $end, Collection $accounts) | ||||
|     { | ||||
|         $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-period'); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $set        = $repository->spentForAccountsPerMonth($accounts, $start, $end); | ||||
|         $categories = $set->unique('id')->sortBy( | ||||
|             function (Category $category) { | ||||
|                 return $category->name; | ||||
|             } | ||||
|         ); | ||||
|         $entries    = new Collection; | ||||
|  | ||||
|         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; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             $entries->push($row); | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|         $data = $this->generator->spentInPeriod($categories, $entries); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -36,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'); | ||||
|             $expenseSum = $query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount'); | ||||
|         // 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); | ||||
| @@ -80,46 +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: | ||||
|             $income  = bcadd($income, $query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount')); | ||||
|             $expense = bcadd($expense, $query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount')); | ||||
|             $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; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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,14 +1,12 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Auth; | ||||
| use Artisan; | ||||
| 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; | ||||
|  | ||||
| @@ -58,16 +56,17 @@ class HomeController extends Controller | ||||
|  | ||||
|  | ||||
|         Session::clear(); | ||||
|         Artisan::call('cache:clear'); | ||||
|  | ||||
|         return redirect(route('index')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @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); | ||||
| @@ -77,18 +76,16 @@ class HomeController extends Controller | ||||
|             return redirect(route('new-user.index')); | ||||
|         } | ||||
|  | ||||
|         $title         = 'Firefly'; | ||||
|         $subTitle      = trans('firefly.welcomeBack'); | ||||
|         $mainTitleIcon = 'fa-fire'; | ||||
|         $transactions  = []; | ||||
|         $frontPage     = Preferences::get('frontPageAccounts', []); | ||||
|         $start         = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end           = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $showTour      = Preferences::get('tour', true)->data; | ||||
|  | ||||
|         $accounts = $repository->getFrontpageAccounts($frontPage); | ||||
|         $savings  = $repository->getSavingsAccounts(); | ||||
|  | ||||
|         $title             = 'Firefly'; | ||||
|         $subTitle          = trans('firefly.welcomeBack'); | ||||
|         $mainTitleIcon     = 'fa-fire'; | ||||
|         $transactions      = []; | ||||
|         $frontPage         = Preferences::get('frontPageAccounts', []); | ||||
|         $start             = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end               = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $showTour          = Preferences::get('tour', true)->data; | ||||
|         $accounts          = $repository->getFrontpageAccounts($frontPage); | ||||
|         $savings           = $repository->getSavingsAccounts(); | ||||
|         $piggyBankAccounts = $repository->getPiggyBankAccounts(); | ||||
|  | ||||
|  | ||||
| @@ -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,109 +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); | ||||
|  | ||||
|         $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 = ($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); | ||||
|     } | ||||
| @@ -174,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()); | ||||
| @@ -189,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); | ||||
| @@ -201,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; | ||||
| @@ -218,7 +162,7 @@ class JsonController extends Controller | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $amount = $reportQuery->expenseInPeriodCorrected($start, $end, true)->sum('amount'); | ||||
|         $amount = $reportQuery->expense($accounts, $start, $end)->sum('journalAmount'); | ||||
|  | ||||
|         $data = ['box' => 'out', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]; | ||||
|         $cache->store($data); | ||||
| @@ -229,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); | ||||
|     } | ||||
| @@ -248,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 = []; | ||||
| @@ -265,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,25 +42,25 @@ 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'), | ||||
|             'iban'                   => null, | ||||
|             'accountType'            => 'asset', | ||||
|             'virtualBalance'         => 0, | ||||
|             'active'                 => true, | ||||
|             'user'                   => Auth::user()->id, | ||||
|             'accountRole'            => 'defaultAsset', | ||||
|             'openingBalance'         => floatval($request->input('bank_balance')), | ||||
|             '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); | ||||
| @@ -69,14 +69,15 @@ class NewUserController extends Controller | ||||
|         if (strlen($request->get('savings_balance') > 0)) { | ||||
|             $savingsAccount = [ | ||||
|                 'name'                   => $request->get('bank_name') . ' savings account', | ||||
|                 'iban'                   => null, | ||||
|                 'accountType'            => 'asset', | ||||
|                 'virtualBalance'         => 0, | ||||
|                 'active'                 => true, | ||||
|                 'user'                   => Auth::user()->id, | ||||
|                 'accountRole'            => 'savingAsset', | ||||
|                 'openingBalance'         => floatval($request->input('savings_balance')), | ||||
|                 '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); | ||||
|         } | ||||
| @@ -86,14 +87,15 @@ class NewUserController extends Controller | ||||
|         if (strlen($request->get('credit_card_limit') > 0)) { | ||||
|             $creditAccount = [ | ||||
|                 'name'                   => 'Credit card', | ||||
|                 'iban'                   => null, | ||||
|                 'accountType'            => 'asset', | ||||
|                 'virtualBalance'         => floatval($request->get('credit_card_limit')), | ||||
|                 'virtualBalance'         => round($request->get('credit_card_limit'), 2), | ||||
|                 'active'                 => true, | ||||
|                 'user'                   => Auth::user()->id, | ||||
|                 '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,33 +39,34 @@ 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()); | ||||
|         $leftOnAccount = $repository->leftOnAccount($piggyBank->account, $date); | ||||
|         $savedSoFar    = $piggyBank->currentRelevantRep()->currentamount; | ||||
|         $leftToSave    = $piggyBank->targetamount - $savedSoFar; | ||||
|         $leftToSave    = bcsub($piggyBank->targetamount, $savedSoFar); | ||||
|         $maxAmount     = min($leftOnAccount, $leftToSave); | ||||
|  | ||||
|         return view('piggy-banks.add', compact('piggyBank', 'maxAmount')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @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'); | ||||
|         $accounts     = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account'])); | ||||
|         $subTitle     = trans('firefly.create_new_piggybank'); | ||||
|         $subTitle     = trans('firefly.new_piggy_bank'); | ||||
|         $subTitleIcon = 'fa-plus'; | ||||
|  | ||||
|         // put previous url in session if not redirect from store (not "create another"). | ||||
| @@ -115,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'); | ||||
| @@ -156,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(); | ||||
| @@ -171,9 +171,9 @@ class PiggyBankController extends Controller | ||||
|         $accounts = []; | ||||
|         /** @var PiggyBank $piggyBank */ | ||||
|         foreach ($piggyBanks as $piggyBank) { | ||||
|             $piggyBank->savedSoFar = floatval($piggyBank->currentRelevantRep()->currentamount); | ||||
|             $piggyBank->savedSoFar = round($piggyBank->currentRelevantRep()->currentamount, 2); | ||||
|             $piggyBank->percentage = $piggyBank->savedSoFar != 0 ? intval($piggyBank->savedSoFar / $piggyBank->targetamount * 100) : 0; | ||||
|             $piggyBank->leftToSave = $piggyBank->targetamount - $piggyBank->savedSoFar; | ||||
|             $piggyBank->leftToSave = bcsub($piggyBank->targetamount, $piggyBank->savedSoFar); | ||||
|  | ||||
|             /* | ||||
|              * Fill account information: | ||||
| @@ -185,7 +185,7 @@ class PiggyBankController extends Controller | ||||
|                     'balance'           => Steam::balance($account, $end, true), | ||||
|                     'leftForPiggyBanks' => $repository->leftOnAccount($account, $end), | ||||
|                     'sumOfSaved'        => $piggyBank->savedSoFar, | ||||
|                     'sumOfTargets'      => floatval($piggyBank->targetamount), | ||||
|                     'sumOfTargets'      => round($piggyBank->targetamount, 2), | ||||
|                     'leftToSave'        => $piggyBank->leftToSave | ||||
|                 ]; | ||||
|             } else { | ||||
| @@ -211,27 +211,27 @@ class PiggyBankController extends Controller | ||||
|  | ||||
|         if (is_array($data)) { | ||||
|             foreach ($data as $order => $id) { | ||||
|                 $repository->setOrder(intval($id), (intval($order) + 1)); | ||||
|                 $repository->setOrder(intval($id), ($order + 1)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @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) | ||||
|     { | ||||
|         $amount        = round(floatval(Input::get('amount')), 2); | ||||
|         bcscale(2); | ||||
|         $amount        = round(Input::get('amount'), 2); | ||||
|         $date          = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $leftOnAccount = $accounts->leftOnAccount($piggyBank->account, $date); | ||||
|         $savedSoFar    = $piggyBank->currentRelevantRep()->currentamount; | ||||
|         $leftToSave    = $piggyBank->targetamount - $savedSoFar; | ||||
|         $leftToSave    = bcsub($piggyBank->targetamount, $savedSoFar); | ||||
|         $maxAmount     = round(min($leftOnAccount, $leftToSave), 2); | ||||
|         bcscale(2); | ||||
|  | ||||
|         if ($amount <= $maxAmount) { | ||||
|             $repetition                = $piggyBank->currentRelevantRep(); | ||||
| @@ -258,7 +258,7 @@ class PiggyBankController extends Controller | ||||
|      */ | ||||
|     public function postRemove(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank) | ||||
|     { | ||||
|         $amount = floatval(Input::get('amount')); | ||||
|         $amount = round(Input::get('amount'), 2); | ||||
|         bcscale(2); | ||||
|  | ||||
|         $savedSoFar = $piggyBank->currentRelevantRep()->currentamount; | ||||
| @@ -319,7 +319,7 @@ class PiggyBankController extends Controller | ||||
|             'name'          => $request->get('name'), | ||||
|             'startdate'     => new Carbon, | ||||
|             'account_id'    => intval($request->get('account_id')), | ||||
|             'targetamount'  => floatval($request->get('targetamount')), | ||||
|             'targetamount'  => round($request->get('targetamount'), 2), | ||||
|             'remind_me'     => false, | ||||
|             'reminder_skip' => 0, | ||||
|             'targetdate'    => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null, | ||||
| @@ -354,7 +354,7 @@ class PiggyBankController extends Controller | ||||
|             'name'          => $request->get('name'), | ||||
|             'startdate'     => is_null($piggyBank->startdate) ? $piggyBank->created_at : $piggyBank->startdate, | ||||
|             'account_id'    => intval($request->get('account_id')), | ||||
|             'targetamount'  => floatval($request->get('targetamount')), | ||||
|             'targetamount'  => round($request->get('targetamount'), 2), | ||||
|             'remind_me'     => false, | ||||
|             'reminder_skip' => 0, | ||||
|             'targetdate'    => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null, | ||||
|   | ||||
| @@ -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); | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -4,6 +4,7 @@ use Auth; | ||||
| use FireflyIII\Http\Requests; | ||||
| use FireflyIII\Http\Requests\DeleteAccountFormRequest; | ||||
| use FireflyIII\Http\Requests\ProfileFormRequest; | ||||
| use FireflyIII\User; | ||||
| use Hash; | ||||
| use Session; | ||||
|  | ||||
| @@ -20,7 +21,7 @@ class ProfileController extends Controller | ||||
|      */ | ||||
|     public function changePassword() | ||||
|     { | ||||
|         return view('profile.change-password')->with('title', Auth::user()->email)->with('subTitle', 'Change your password')->with( | ||||
|         return view('profile.change-password')->with('title', Auth::user()->email)->with('subTitle', trans('firefly.change_your_password'))->with( | ||||
|             'mainTitleIcon', 'fa-user' | ||||
|         ); | ||||
|     } | ||||
| @@ -30,7 +31,7 @@ class ProfileController extends Controller | ||||
|      */ | ||||
|     public function deleteAccount() | ||||
|     { | ||||
|         return view('profile.delete-account')->with('title', Auth::user()->email)->with('subTitle', 'Delete account')->with( | ||||
|         return view('profile.delete-account')->with('title', Auth::user()->email)->with('subTitle', trans('firefly.delete_account'))->with( | ||||
|             'mainTitleIcon', 'fa-user' | ||||
|         ); | ||||
|     } | ||||
| @@ -41,7 +42,7 @@ class ProfileController extends Controller | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         return view('profile.index')->with('title', 'Profile')->with('subTitle', Auth::user()->email)->with('mainTitleIcon', 'fa-user'); | ||||
|         return view('profile.index')->with('title', trans('firefly.profile'))->with('subTitle', Auth::user()->email)->with('mainTitleIcon', 'fa-user'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -53,7 +54,7 @@ class ProfileController extends Controller | ||||
|     { | ||||
|         // old, new1, new2 | ||||
|         if (!Hash::check($request->get('current_password'), Auth::user()->password)) { | ||||
|             Session::flash('error', 'Invalid current password!'); | ||||
|             Session::flash('error', trans('firefly.invalid_current_password')); | ||||
|  | ||||
|             return redirect(route('profile.change-password')); | ||||
|         } | ||||
| @@ -65,10 +66,10 @@ 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', 'Password changed!'); | ||||
|         Session::flash('success', trans('firefly.password_changed')); | ||||
|  | ||||
|         return redirect(route('profile')); | ||||
|     } | ||||
| @@ -83,7 +84,7 @@ class ProfileController extends Controller | ||||
|     protected function validatePassword($old, $new1) | ||||
|     { | ||||
|         if ($new1 == $old) { | ||||
|             return 'The idea is to change your password.'; | ||||
|             return trans('firefly.should_change'); | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
| @@ -100,17 +101,28 @@ class ProfileController extends Controller | ||||
|     { | ||||
|         // old, new1, new2 | ||||
|         if (!Hash::check($request->get('password'), Auth::user()->password)) { | ||||
|             Session::flash('error', 'Invalid password!'); | ||||
|             Session::flash('error', trans('firefly.invalid_password')); | ||||
|  | ||||
|             return redirect(route('profile.delete-account')); | ||||
|         } | ||||
|  | ||||
|         // DELETE! | ||||
|         $email = Auth::user()->email; | ||||
|         Auth::user()->delete(); | ||||
|         Session::flush(); | ||||
|         Session::flash('gaEventCategory', 'user'); | ||||
|         Session::flash('gaEventAction', 'delete-account'); | ||||
|  | ||||
|         // create a new user with the same email address so re-registration is blocked. | ||||
|         User::create( | ||||
|             [ | ||||
|                 'email'        => $email, | ||||
|                 'password'     => 'deleted', | ||||
|                 'blocked'      => 1, | ||||
|                 'blocked_code' => 'deleted' | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|         return redirect(route('index')); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -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); | ||||
|         } | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -44,9 +44,9 @@ class TagController extends Controller | ||||
|         View::share('mainTitleIcon', 'fa-tags'); | ||||
|         View::share('hideTags', true); | ||||
|         $this->tagOptions = [ | ||||
|             'nothing'        => 'Just a regular tag.', | ||||
|             'balancingAct'   => 'The tag takes at most two transactions; an expense and a transfer. They\'ll balance each other out.', | ||||
|             'advancePayment' => 'The tag accepts one expense and any number of deposits aimed to repay the original expense.', | ||||
|             'nothing'        => trans('firefly.regular_tag'), | ||||
|             'balancingAct'   => trans('firefly.balancing_act'), | ||||
|             'advancePayment' => trans('firefly.advance_payment'), | ||||
|         ]; | ||||
|         View::share('tagOptions', $this->tagOptions); | ||||
|     } | ||||
| @@ -188,22 +188,25 @@ class TagController extends Controller | ||||
|  | ||||
|             /** @var Collection $tags */ | ||||
|             $tags = Auth::user()->tags()->where('tagMode', $type)->orderBy('date', 'ASC')->get(); | ||||
|  | ||||
|             $tags = $tags->sortBy( | ||||
|                 function (Tag $tag) { | ||||
|                     return strtolower($tag->tag); | ||||
|                     $date = !is_null($tag->date) ? $tag->date->format('Ymd') : '000000'; | ||||
|  | ||||
|  | ||||
|                     return strtolower($date . $tag->tag); | ||||
|                 } | ||||
|             ); | ||||
|  | ||||
|             /** @var Tag $tag */ | ||||
|             foreach ($tags as $tag) { | ||||
|                 $year                               = is_null($tag->date) ? trans('firefly.no_year') : $tag->date->year; | ||||
|                 $month                              = is_null($tag->date) ? trans('firefly.no_month') : $tag->date->formatLocalized($this->monthFormat); | ||||
|                 $collection[$type][$year][$month][] = $tag; | ||||
|  | ||||
|                 $year           = is_null($tag->date) ? trans('firefly.no_year') : $tag->date->year; | ||||
|                 $monthFormatted = is_null($tag->date) ? trans('firefly.no_month') : $tag->date->formatLocalized($this->monthFormat); | ||||
|  | ||||
|                 $collection[$type][$year][$monthFormatted][] = $tag; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|  | ||||
|         return view('tags.index', compact('title', 'mainTitleIcon', 'types', 'helpHidden', 'collection')); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,20 +1,27 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Amount; | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use Config; | ||||
| use ExpandedForm; | ||||
| use FireflyIII\Events\JournalCreated; | ||||
| 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; | ||||
| use Session; | ||||
| use Steam; | ||||
| use URL; | ||||
| use View; | ||||
|  | ||||
| @@ -36,17 +43,29 @@ 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) | ||||
|     { | ||||
|         $accounts   = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account'])); | ||||
|         $budgets    = ExpandedForm::makeSelectList(Auth::user()->budgets()->get()); | ||||
|         $budgets[0] = trans('form.noBudget'); | ||||
|         $piggies    = ExpandedForm::makeSelectList(Auth::user()->piggyBanks()->get()); | ||||
|         $what        = strtolower($what); | ||||
|         $maxFileSize = Steam::phpBytes(ini_get('upload_max_filesize')); | ||||
|         $maxPostSize = Steam::phpBytes(ini_get('post_max_size')); | ||||
|         $uploadSize  = min($maxFileSize, $maxPostSize); | ||||
|         $accounts    = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account'])); | ||||
|         $budgets     = ExpandedForm::makeSelectList(Auth::user()->budgets()->get()); | ||||
|         $budgets[0]  = trans('form.noBudget'); | ||||
|  | ||||
|         // piggy bank list: | ||||
|         $piggyBanks = Auth::user()->piggyBanks()->orderBy('order', 'ASC')->get(); | ||||
|         /** @var PiggyBank $piggy */ | ||||
|         foreach ($piggyBanks as $piggy) { | ||||
|             $piggy->name = $piggy->name . ' (' . Amount::format($piggy->currentRelevantRep()->currentamount, false) . ')'; | ||||
|         } | ||||
|  | ||||
|         $piggies    = ExpandedForm::makeSelectList($piggyBanks); | ||||
|         $piggies[0] = trans('form.noPiggybank'); | ||||
|         $preFilled  = Session::has('preFilled') ? Session::get('preFilled') : []; | ||||
|         $respondTo  = ['account_id', 'account_from_id']; | ||||
| @@ -68,7 +87,7 @@ class TransactionController extends Controller | ||||
|         asort($piggies); | ||||
|  | ||||
|  | ||||
|         return view('transactions.create', compact('accounts', 'budgets', 'what', 'piggies', 'subTitle')); | ||||
|         return view('transactions.create', compact('accounts', 'uploadSize', 'budgets', 'what', 'piggies', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -80,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 | ||||
| @@ -114,32 +133,37 @@ 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) | ||||
|     { | ||||
|         $what       = strtolower($journal->transactionType->type); | ||||
|         $accounts   = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account'])); | ||||
|         $budgets    = ExpandedForm::makeSelectList(Auth::user()->budgets()->get()); | ||||
|         $budgets[0] = trans('form.noBudget'); | ||||
|         $piggies    = ExpandedForm::makeSelectList(Auth::user()->piggyBanks()->get()); | ||||
|         $piggies[0] = trans('form.noPiggybank'); | ||||
|         $subTitle   = trans('breadcrumbs.edit_journal', ['description' => $journal->description]); | ||||
|         $preFilled  = [ | ||||
|         // cannot edit opening balance | ||||
|         if ($journal->isOpeningBalance()) { | ||||
|             return view('error')->with('message', 'Cannot edit this transaction. Edit the account instead!'); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $maxFileSize = Steam::phpBytes(ini_get('upload_max_filesize')); | ||||
|         $maxPostSize = Steam::phpBytes(ini_get('post_max_size')); | ||||
|         $uploadSize  = min($maxFileSize, $maxPostSize); | ||||
|         $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'); | ||||
|         $piggies     = ExpandedForm::makeSelectList(Auth::user()->piggyBanks()->get()); | ||||
|         $piggies[0]  = trans('form.noPiggybank'); | ||||
|         $subTitle    = trans('breadcrumbs.edit_journal', ['description' => $journal->description]); | ||||
|         $preFilled   = [ | ||||
|             'date'          => $journal->date->format('Y-m-d'), | ||||
|             'category'      => '', | ||||
|             'budget_id'     => 0, | ||||
|             '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)) { | ||||
| @@ -155,9 +179,9 @@ class TransactionController extends Controller | ||||
|             $preFilled['piggy_bank_id'] = $journal->piggyBankEvents()->orderBy('date', 'DESC')->first()->piggy_bank_id; | ||||
|         } | ||||
|  | ||||
|         $preFilled['amount'] = $journal->actual_amount; | ||||
|         $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 { | ||||
| @@ -179,7 +203,7 @@ class TransactionController extends Controller | ||||
|         Session::forget('transactions.edit.fromUpdate'); | ||||
|  | ||||
|  | ||||
|         return view('transactions.edit', compact('journal', 'accounts', 'what', 'budgets', 'piggies', 'subTitle'))->with('data', $preFilled); | ||||
|         return view('transactions.edit', compact('journal', 'uploadSize', 'accounts', 'what', 'budgets', 'piggies', 'subTitle'))->with('data', $preFilled); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -238,34 +262,64 @@ 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) { | ||||
|                 $t->before = $repository->getAmountBefore($journal, $t); | ||||
|                 $t->after  = $t->before + $t->amount; | ||||
|                 $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) | ||||
|     public function store(JournalFormRequest $request, JournalRepositoryInterface $repository, AttachmentHelperInterface $att) | ||||
|     { | ||||
|  | ||||
|         $journalData = $request->getJournalData(); | ||||
|         $journal     = $repository->store($journalData); | ||||
|  | ||||
|         // if not withdrawal, unset budgetid. | ||||
|         if ($journalData['what'] != strtolower(TransactionType::WITHDRAWAL)) { | ||||
|             $journalData['budget_id'] = 0; | ||||
|         } | ||||
|  | ||||
|         $journal = $repository->store($journalData); | ||||
|  | ||||
|         // save attachments: | ||||
|         $att->saveAttachmentsForModel($journal); | ||||
|  | ||||
|         // flash errors | ||||
|         if (count($att->getErrors()->get('attachments')) > 0) { | ||||
|             Session::flash('error', $att->getErrors()->get('attachments')); | ||||
|         } | ||||
|         // flash messages | ||||
|         if (count($att->getMessages()->get('attachments')) > 0) { | ||||
|             Session::flash('info', $att->getMessages()->get('attachments')); | ||||
|         } | ||||
|  | ||||
|         // rescan journal, UpdateJournalConnection | ||||
|         event(new JournalSaved($journal)); | ||||
|         // ConnectJournalToPiggyBank | ||||
|         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')))); | ||||
|         } | ||||
|  | ||||
| @@ -288,16 +342,33 @@ class TransactionController extends Controller | ||||
|     /** | ||||
|      * @param JournalFormRequest         $request | ||||
|      * @param JournalRepositoryInterface $repository | ||||
|      * @param AttachmentHelperInterface  $att | ||||
|      * @param TransactionJournal         $journal | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      * @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector | ||||
|      */ | ||||
|     public function update(JournalFormRequest $request, JournalRepositoryInterface $repository, TransactionJournal $journal) | ||||
|     public function update(JournalFormRequest $request, JournalRepositoryInterface $repository, AttachmentHelperInterface $att, TransactionJournal $journal) | ||||
|     { | ||||
|  | ||||
|         if ($journal->isOpeningBalance()) { | ||||
|             return view('error')->with('message', 'Cannot edit this transaction. Edit the account instead!'); | ||||
|         } | ||||
|  | ||||
|         $journalData = $request->getJournalData(); | ||||
|         $repository->update($journal, $journalData); | ||||
|  | ||||
|         // save attachments: | ||||
|         $att->saveAttachmentsForModel($journal); | ||||
|  | ||||
|         // flash errors | ||||
|         if (count($att->getErrors()->get('attachments')) > 0) { | ||||
|             Session::flash('error', $att->getErrors()->get('attachments')); | ||||
|         } | ||||
|         // flash messages | ||||
|         if (count($att->getMessages()->get('attachments')) > 0) { | ||||
|             Session::flash('info', $att->getMessages()->get('attachments')); | ||||
|         } | ||||
|  | ||||
|         event(new JournalSaved($journal)); | ||||
|         // update, get events by date and sort DESC | ||||
|  | ||||
|   | ||||
| @@ -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,12 +54,23 @@ class Authenticate | ||||
|                 return redirect()->guest('auth/login'); | ||||
|             } | ||||
|         } | ||||
|         // if logged in, set user language: | ||||
|         $pref = Preferences::get('language', 'en'); | ||||
|         App::setLocale($pref->data); | ||||
|         Carbon::setLocale($pref->data); | ||||
|         /** @var User $user */ | ||||
|         $user = $this->auth->user(); | ||||
|         if ($user instanceof User && intval($user->blocked) == 1) { | ||||
|             Auth::logout(); | ||||
|  | ||||
|         setlocale(LC_TIME, Config::get('firefly.locales.' . $pref->data)); | ||||
|             return redirect()->route('index'); | ||||
|         } | ||||
|  | ||||
|         // if logged in, set user language: | ||||
|         $pref = Preferences::get('language', env('DEFAULT_LANGUAGE', 'en_US')); | ||||
|         App::setLocale($pref->data); | ||||
|         Carbon::setLocale(substr($pref->data, 0, 2)); | ||||
|         $locale = explode(',', trans('config.locale')); | ||||
|         $locale = array_map('trim', $locale); | ||||
|  | ||||
|         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 | ||||
|      */ | ||||
|   | ||||
| @@ -24,5 +24,4 @@ class VerifyCsrfToken extends BaseVerifier | ||||
|     { | ||||
|         return parent::handle($request, $next); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										36
									
								
								app/Http/Requests/AttachmentFormRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								app/Http/Requests/AttachmentFormRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Http\Requests; | ||||
|  | ||||
| use Auth; | ||||
|  | ||||
| /** | ||||
|  * Class AttachmentFormRequest | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @package FireflyIII\Http\Requests | ||||
|  */ | ||||
| class AttachmentFormRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize() | ||||
|     { | ||||
|         // Only allow logged in users | ||||
|         return Auth::check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules() | ||||
|     { | ||||
|  | ||||
|         return [ | ||||
|             'title'       => 'between:1,255', | ||||
|             'description' => 'between:1,65536', | ||||
|             'notes'       => 'between:1,65536', | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| @@ -29,17 +29,18 @@ class BillFormRequest extends Request | ||||
|     public function getBillData() | ||||
|     { | ||||
|         return [ | ||||
|             'name'               => $this->get('name'), | ||||
|             'match'              => $this->get('match'), | ||||
|             'amount_min'         => floatval($this->get('amount_min')), | ||||
|             'amount_currency_id' => floatval($this->get('amount_currency_id')), | ||||
|             'amount_max'         => floatval($this->get('amount_max')), | ||||
|             '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'             => floatval($this->get('amount')), | ||||
|             '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('breadcrumbs.new_' . strtolower(e($what)) . '_account'), route('accounts.create', [$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('breadcrumbs.newCategory'), route('categories.create')); | ||||
|     $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,20 @@ Breadcrumbs::register( | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'categories.noCategory', function (Generator $breadcrumbs, $subTitle) { | ||||
|     'categories.show.date', function (BreadCrumbGenerator $breadcrumbs, Category $category, Carbon $date) { | ||||
|  | ||||
|     // get current period preference. | ||||
|     $range = Preferences::get('viewRange', '1M')->data; | ||||
|  | ||||
|     $breadcrumbs->parent('categories.index'); | ||||
|     $breadcrumbs->push(e($category->name), route('categories.show', [$category->id])); | ||||
|     $breadcrumbs->push(Navigation::periodShow($date, $range), route('categories.show.date', [$category->id, $date->format('Y-m-d')])); | ||||
|  | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'categories.noCategory', function (BreadCrumbGenerator $breadcrumbs, $subTitle) { | ||||
|     $breadcrumbs->parent('categories.index'); | ||||
|     $breadcrumbs->push($subTitle, route('categories.noCategory')); | ||||
| } | ||||
| @@ -163,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')); | ||||
| } | ||||
| @@ -200,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])); | ||||
| } | ||||
| @@ -229,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('breadcrumbs.piggyBanks'), route('piggy-banks.index')); | ||||
|     $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('breadcrumbs.delete_piggyBank', ['name' => e($piggyBank->name)]), route('piggy-banks.delete', [$piggyBank->id])); | ||||
|     $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])); | ||||
|  | ||||
| @@ -264,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')); | ||||
|  | ||||
| @@ -273,49 +286,56 @@ 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( | ||||
|     'change-password', function (Generator $breadcrumbs) { | ||||
|     'profile.change-password', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('profile'); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.changePassword'), route('change-password')); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.changePassword'), route('profile.change-password')); | ||||
|  | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'profile.delete-account', function (BreadCrumbGenerator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('profile'); | ||||
|     $breadcrumbs->push(trans('firefly.delete_account'), route('profile.delete-account')); | ||||
|  | ||||
| } | ||||
| ); | ||||
|  | ||||
| // 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])); | ||||
|  | ||||
| @@ -324,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')); | ||||
| } | ||||
| @@ -368,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])); | ||||
|  | ||||
| } | ||||
| @@ -404,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])); | ||||
| } | ||||
| @@ -433,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,5 +1,7 @@ | ||||
| <?php | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Attachment; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\Category; | ||||
| @@ -28,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) { | ||||
| @@ -42,6 +149,19 @@ Route::bind( | ||||
| } | ||||
| ); | ||||
|  | ||||
| Route::bind( | ||||
|     'attachment', function ($value) { | ||||
|     if (Auth::check()) { | ||||
|         $object = Attachment::where('id', $value)->where('user_id', Auth::user()->id)->first(); | ||||
|         if ($object) { | ||||
|             return $object; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     throw new NotFoundHttpException; | ||||
| } | ||||
| ); | ||||
|  | ||||
| Route::bind( | ||||
|     'currency', function ($value) { | ||||
|     if (Auth::check()) { | ||||
| @@ -163,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 | ||||
|      */ | ||||
| @@ -177,6 +296,21 @@ Route::group( | ||||
|     Route::post('/accounts/update/{account}', ['uses' => 'AccountController@update', 'as' => 'accounts.update']); | ||||
|     Route::post('/accounts/destroy/{account}', ['uses' => 'AccountController@destroy', 'as' => 'accounts.destroy']); | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Attachment Controller | ||||
|      */ | ||||
|  | ||||
|     Route::post('/attachment/update/{attachment}', ['uses' => 'AttachmentController@update', 'as' => 'attachments.update']); | ||||
|     Route::post('/attachment/destroy/{attachment}', ['uses' => 'AttachmentController@destroy', 'as' => 'attachments.destroy']); | ||||
|  | ||||
|     Route::get('/attachment/edit/{attachment}', ['uses' => 'AttachmentController@edit', 'as' => 'attachments.edit']); | ||||
|     Route::get('/attachment/delete/{attachment}', ['uses' => 'AttachmentController@delete', 'as' => 'attachments.delete']); | ||||
|     Route::get('/attachment/show/{attachment}', ['uses' => 'AttachmentController@show', 'as' => 'attachments.show']); | ||||
|     Route::get('/attachment/preview/{attachment}', ['uses' => 'AttachmentController@preview', 'as' => 'attachments.preview']); | ||||
|     Route::get('/attachment/download/{attachment}', ['uses' => 'AttachmentController@download', 'as' => 'attachments.download']); | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Bills Controller | ||||
|      */ | ||||
| @@ -214,6 +348,7 @@ Route::group( | ||||
|     Route::get('/categories/edit/{category}', ['uses' => 'CategoryController@edit', 'as' => 'categories.edit']); | ||||
|     Route::get('/categories/delete/{category}', ['uses' => 'CategoryController@delete', 'as' => 'categories.delete']); | ||||
|     Route::get('/categories/show/{category}', ['uses' => 'CategoryController@show', 'as' => 'categories.show']); | ||||
|     Route::get('/categories/show/{category}/{date}', ['uses' => 'CategoryController@showWithDate', 'as' => 'categories.show.date']); | ||||
|     Route::get('/categories/list/noCategory', ['uses' => 'CategoryController@noCategory', 'as' => 'categories.noCategory']); | ||||
|     Route::post('/categories/store', ['uses' => 'CategoryController@store', 'as' => 'categories.store']); | ||||
|     Route::post('/categories/update/{category}', ['uses' => 'CategoryController@update', 'as' => 'categories.update']); | ||||
| @@ -252,9 +387,8 @@ Route::group( | ||||
|      */ | ||||
|     // accounts: | ||||
|     Route::get('/chart/account/frontpage', ['uses' => 'Chart\AccountController@frontpage']); | ||||
|     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/expense', ['uses' => 'Chart\AccountController@expenseAccounts']); | ||||
|     Route::get('/chart/account/report/{reportType}/{start_date}/{end_date}/{accountList}', ['uses' => 'Chart\AccountController@report']); | ||||
|     Route::get('/chart/account/{account}', ['uses' => 'Chart\AccountController@single']); | ||||
|  | ||||
|  | ||||
| @@ -264,24 +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/year/{year}/{shared?}', ['uses' => 'Chart\CategoryController@year'])->where(['year' => '[0-9]{4}', 'shared' => 'shared']); | ||||
|     Route::get('/chart/category/{category}/month', ['uses' => 'Chart\CategoryController@month']); // should be period. | ||||
|  | ||||
|     // 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']); | ||||
|  | ||||
|  | ||||
|     /** | ||||
| @@ -347,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']; | ||||
|   | ||||
							
								
								
									
										176
									
								
								app/Models/Attachment.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								app/Models/Attachment.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,176 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Models; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Crypt; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
|  | ||||
| /** | ||||
|  * FireflyIII\Models\Attachment | ||||
|  * | ||||
|  * @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 | ||||
| { | ||||
|     use SoftDeletes; | ||||
|  | ||||
|     protected $fillable = ['attachable_id', 'attachable_type', 'user_id', 'md5', 'filename', 'mime', 'title', 'notes', 'description', 'size', 'uploaded']; | ||||
|  | ||||
|     /** | ||||
|      * Get all of the owning imageable models. | ||||
|      */ | ||||
|     public function attachable() | ||||
|     { | ||||
|         return $this->morphTo(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|      */ | ||||
|     public function user() | ||||
|     { | ||||
|         return $this->belongsTo('FireflyIII\User'); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return null|string | ||||
|      */ | ||||
|     public function getFilenameAttribute($value) | ||||
|     { | ||||
|         if (is_null($value)) { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         return Crypt::decrypt($value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $value | ||||
|      */ | ||||
|     public function setFilenameAttribute($value) | ||||
|     { | ||||
|         $this->attributes['filename'] = Crypt::encrypt($value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return null|string | ||||
|      */ | ||||
|     public function getMimeAttribute($value) | ||||
|     { | ||||
|         if (is_null($value)) { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         return Crypt::decrypt($value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $value | ||||
|      */ | ||||
|     public function setMimeAttribute($value) | ||||
|     { | ||||
|         $this->attributes['mime'] = Crypt::encrypt($value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return null|string | ||||
|      */ | ||||
|     public function getTitleAttribute($value) | ||||
|     { | ||||
|         if (is_null($value)) { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         return Crypt::decrypt($value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $value | ||||
|      */ | ||||
|     public function setTitleAttribute($value) | ||||
|     { | ||||
|         $this->attributes['title'] = Crypt::encrypt($value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return null|string | ||||
|      */ | ||||
|     public function getDescriptionAttribute($value) | ||||
|     { | ||||
|         if (is_null($value)) { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         return Crypt::decrypt($value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $value | ||||
|      */ | ||||
|     public function setDescriptionAttribute($value) | ||||
|     { | ||||
|         $this->attributes['description'] = Crypt::encrypt($value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return null|string | ||||
|      */ | ||||
|     public function getNotesAttribute($value) | ||||
|     { | ||||
|         if (is_null($value)) { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         return Crypt::decrypt($value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $value | ||||
|      */ | ||||
|     public function setNotesAttribute($value) | ||||
|     { | ||||
|         $this->attributes['notes'] = Crypt::encrypt($value); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -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-read \Carbon\Carbon $nextExpectedMatch | ||||
|  * @property-read \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-read \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,43 +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 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 | ||||
|      */ | ||||
| @@ -64,7 +52,7 @@ class Tag extends Model | ||||
|         // everything but the tag: | ||||
|         unset($fields['tagMode']); | ||||
|         $search = $fields; | ||||
|         unset($search['name']); | ||||
|         unset($search['tag']); | ||||
|  | ||||
|         $query = Tag::orderBy('id'); | ||||
|         foreach ($search as $name => $value) { | ||||
|   | ||||
| @@ -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,71 +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-read string $name | ||||
|  * @property-read string $symbol | ||||
|  * @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 | ||||
| { | ||||
| @@ -119,7 +101,7 @@ class TransactionJournal extends Model | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getActualAmountAttribute() | ||||
|     public function getAmountPositiveAttribute() | ||||
|     { | ||||
|         $amount = '0'; | ||||
|         /** @var Transaction $t */ | ||||
| @@ -145,18 +127,10 @@ class TransactionJournal extends Model | ||||
|         } | ||||
|  | ||||
|         bcscale(2); | ||||
|         $set    = $this->transactions->sortByDesc('amount'); | ||||
|         $amount = $set->first()->amount; | ||||
|  | ||||
|         if (intval($this->tag_count) === 1) { | ||||
|             // get amount for single tag: | ||||
|             $amount = $this->amountByTag($this->tags()->first(), $amount); | ||||
|         } | ||||
|  | ||||
|         if (intval($this->tag_count) > 1) { | ||||
|             // get amount for either tag. | ||||
|             $amount = $this->amountByTags($amount); | ||||
|  | ||||
|         $transaction = $this->transactions->sortByDesc('amount')->first(); | ||||
|         $amount      = $transaction->amount; | ||||
|         if ($this->isWithdrawal()) { | ||||
|             $amount = $amount * -1; | ||||
|         } | ||||
|         $cache->store($amount); | ||||
|  | ||||
| @@ -172,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->actual_amount); | ||||
|                 $amount = bcsub($amount, $other->amount_positive); | ||||
|             } | ||||
|  | ||||
|             return $amount; | ||||
|         } | ||||
|         if ($this->transactionType->type == 'Deposit') { | ||||
|         if ($this->isDeposit()) { | ||||
|             return '0'; | ||||
|         } | ||||
|  | ||||
| @@ -195,10 +169,10 @@ 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->actual_amount); | ||||
|                 $amount = bcsub($amount, $transfer->amount_positive); | ||||
|  | ||||
|                 return $amount; | ||||
|             } | ||||
| @@ -259,21 +233,6 @@ class TransactionJournal extends Model | ||||
|         return $amount; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getCorrectAmountAttribute() | ||||
|     { | ||||
|  | ||||
|         switch ($this->transactionType->type) { | ||||
|             case 'Deposit': | ||||
|                 return $this->transactions()->where('amount', '>', 0)->first()->amount; | ||||
|             case 'Withdrawal': | ||||
|                 return $this->transactions()->where('amount', '<', 0)->first()->amount; | ||||
|         } | ||||
|  | ||||
|         return $this->transactions()->where('amount', '>', 0)->first()->amount; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
| @@ -467,6 +426,14 @@ class TransactionJournal extends Model | ||||
|         $this->attributes['encrypted']   = true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\MorphMany | ||||
|      */ | ||||
|     public function attachments() | ||||
|     { | ||||
|         return $this->morphMany('FireflyIII\Models\Attachment', 'attachable'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
| @@ -503,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,18 +83,22 @@ 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'); | ||||
|         $this->app->bind('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface', 'FireflyIII\Repositories\Currency\CurrencyRepository'); | ||||
|         $this->app->bind('FireflyIII\Repositories\Tag\TagRepositoryInterface', 'FireflyIII\Repositories\Tag\TagRepository'); | ||||
|         $this->app->bind('FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface', 'FireflyIII\Repositories\Attachment\AttachmentRepository'); | ||||
|         $this->app->bind('FireflyIII\Support\Search\SearchInterface', 'FireflyIII\Support\Search\Search'); | ||||
|  | ||||
|         // CSV import | ||||
|         $this->app->bind('FireflyIII\Helpers\Csv\WizardInterface', 'FireflyIII\Helpers\Csv\Wizard'); | ||||
|  | ||||
|         // attachments | ||||
|         $this->app->bind('FireflyIII\Helpers\Attachments\AttachmentHelperInterface', 'FireflyIII\Helpers\Attachments\AttachmentHelper'); | ||||
|  | ||||
|         // make charts: | ||||
|         // alternative is Google instead of ChartJs | ||||
|         $this->app->bind('FireflyIII\Generator\Chart\Account\AccountChartGenerator', 'FireflyIII\Generator\Chart\Account\ChartJsAccountChartGenerator'); | ||||
|         $this->app->bind('FireflyIII\Generator\Chart\Bill\BillChartGenerator', 'FireflyIII\Generator\Chart\Bill\ChartJsBillChartGenerator'); | ||||
|         $this->app->bind('FireflyIII\Generator\Chart\Budget\BudgetChartGenerator', 'FireflyIII\Generator\Chart\Budget\ChartJsBudgetChartGenerator'); | ||||
|   | ||||
| @@ -39,6 +39,8 @@ class RouteServiceProvider extends ServiceProvider | ||||
|      * | ||||
|      * @param  \Illuminate\Routing\Router $router | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.UnusedFormalParameter) | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function map(Router $router) | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user