mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-31 10:47:00 +00:00 
			
		
		
		
	Compare commits
	
		
			443 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | d485270e1f | ||
|  | 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 | ||
|  | b250a10e3c | ||
|  | a9f1b31dd6 | ||
|  | 7fe393acaf | ||
|  | 04faba4db5 | ||
|  | 91bba40c20 | ||
|  | 79e39f7de8 | ||
|  | 9c09353559 | ||
|  | 50752a5bfe | ||
|  | d59879db7d | ||
|  | aab125da27 | ||
|  | 74fc731f96 | ||
|  | bd0050fec2 | ||
|  | aa5e313b92 | ||
|  | e89d613b7e | ||
|  | 8757929ead | ||
|  | e0a9b19802 | ||
|  | 308da6dc6e | ||
|  | b6960fb0e5 | ||
|  | 137208c3fd | ||
|  | d7a9a62a1d | ||
|  | 075315bdaa | ||
|  | 3948fcd614 | ||
|  | 8e61e129ab | ||
|  | 20cffd0502 | ||
|  | 5df09dab09 | ||
|  | 7446b911e5 | ||
|  | f15267c1ab | ||
|  | 9c9fc2b5dc | ||
|  | 28f601b54b | ||
|  | 18b8a05014 | ||
|  | 910c995ed8 | ||
|  | 498468aa2c | ||
|  | 637aebcb34 | ||
|  | 9afd5cb277 | ||
|  | bc525e7272 | ||
|  | a80180780d | ||
|  | 0d73086c37 | ||
|  | 02ae39238d | ||
|  | 43d6b51d42 | ||
|  | 84566310de | ||
|  | 6a6ec9fbe4 | ||
|  | 84a7f825d7 | ||
|  | 0372c1aaf1 | ||
|  | c9fff197f7 | ||
|  | 6900392e43 | ||
|  | c00bcd78cc | ||
|  | b2b82124e6 | ||
|  | 3de57c668f | ||
|  | 43669648ce | ||
|  | 3b73b416d5 | ||
|  | 5153591c8f | ||
|  | 3172bc90da | ||
|  | 76a1b2cd51 | ||
|  | bdf7eee72f | ||
|  | 2d4b148b2c | ||
|  | d67db74ca2 | ||
|  | 516725456f | ||
|  | 001d72a484 | ||
|  | c555e28988 | ||
|  | af13d1943f | ||
|  | 52df2edc8f | ||
|  | cd08484a13 | ||
|  | f38d38f139 | ||
|  | 93b6c68938 | ||
|  | a4cc25175a | ||
|  | 3fb14b4708 | ||
|  | 6bdb6db330 | ||
|  | d05c165ace | ||
|  | ab53cdb896 | ||
|  | c1f142af78 | ||
|  | 6e261abb73 | ||
|  | 39af9e4414 | ||
|  | 5b50abb2c7 | ||
|  | 13bda0a264 | ||
|  | 1658c666ab | ||
|  | 170aebfe54 | ||
|  | c4ef379d0e | ||
|  | 18b038d8ff | ||
|  | 12ee5da872 | ||
|  | 601f9f86bb | ||
|  | d7329a5915 | ||
|  | 9e7b730002 | ||
|  | 2d59d845bc | ||
|  | c2645894e0 | ||
|  | 3751106317 | ||
|  | 60bb639351 | ||
|  | 74c50930bd | ||
|  | 9105104303 | ||
|  | 540dde135e | ||
|  | f8936210cf | ||
|  | 1dc6d8de40 | ||
|  | 1069db3c13 | ||
|  | 65122f0144 | ||
|  | d2c018f7da | ||
|  | 46493c2af6 | ||
|  | c303e03f76 | ||
|  | d8b65f62e7 | ||
|  | 854368a8f3 | ||
|  | 7653a34aea | ||
|  | ee50b58e00 | ||
|  | 1eb60ab100 | ||
|  | 4a20eef351 | ||
|  | 26c9b2c353 | ||
|  | 16374bce9b | ||
|  | 86011d4ea2 | ||
|  | fcb8b02da9 | ||
|  | 571165c2bb | ||
|  | c842113610 | ||
|  | 974a8b3b70 | ||
|  | 2e20c99ada | ||
|  | aa88ff6f2c | ||
|  | 5e6aa63d03 | ||
|  | ad6700c114 | ||
|  | f08c6efb00 | ||
|  | cc807ec132 | ||
|  | 24e7c68243 | ||
|  | ab25edd37a | ||
|  | be47fde6c2 | ||
|  | 1ffa8c5e72 | ||
|  | d855ccb8a7 | ||
|  | d88919474b | ||
|  | e139664301 | ||
|  | 5adf5f6e3f | ||
|  | aef2075c8e | ||
|  | 922b2962a3 | ||
|  | b4a401700e | ||
|  | e9601bb9c1 | ||
|  | 58af3dc6ea | ||
|  | 074295df61 | ||
|  | ec349b31c7 | ||
|  | 5ae236e016 | ||
|  | d7c5897aba | ||
|  | 5252e7efe7 | ||
|  | fc7d65629a | ||
|  | f28fdf8252 | ||
|  | 5d07c4a949 | ||
|  | fdd9eaab4b | ||
|  | e0d863a46f | ||
|  | 3aacb6f5f3 | ||
|  | 428e331b3e | ||
|  | 847e05e9a7 | ||
|  | 087eb5dbe6 | ||
|  | f15932b2ac | ||
|  | d3a4c3795d | ||
|  | b15d55e1d9 | ||
|  | 4f5889cc5b | ||
|  | bf2a104a4e | ||
|  | 0c6dd5cd16 | ||
|  | 5efb06a7aa | ||
|  | b13acef272 | ||
|  | cfa67d6c0f | ||
|  | e70444f19a | ||
|  | 0258982e60 | ||
|  | 70eed5cb5e | ||
|  | a650fa51f7 | ||
|  | cb205580d8 | ||
|  | f9329aac00 | ||
|  | 745f4a7523 | ||
|  | 60254dafd7 | ||
|  | a8d60388ba | ||
|  | 83ec60254c | ||
|  | c15c45f765 | ||
|  | cbe52b5089 | ||
|  | e4e2921f3e | ||
|  | 4673170531 | ||
|  | 2c2ed26c38 | ||
|  | 94be5244fe | ||
|  | f137a08493 | ||
|  | 48624d0a34 | ||
|  | 4cceb3ddaa | ||
|  | f728395603 | ||
|  | 3e82d43807 | ||
|  | 2194c4e0a9 | ||
|  | c581080f3f | ||
|  | f6b1ec27e5 | ||
|  | 368b183230 | ||
|  | 9028ad36ad | ||
|  | 6cc041cd39 | ||
|  | 63ff01e78d | ||
|  | 9e5484937e | ||
|  | b8ed489b14 | ||
|  | 765152d04b | ||
|  | 14934367d8 | ||
|  | 04164500c8 | ||
|  | 5160f2c298 | ||
|  | 124c9303b9 | ||
|  | cd27f0ad69 | ||
|  | a7555bcce3 | ||
|  | 6b5c4fd3f4 | ||
|  | cc55e2acee | ||
|  | 1511f75a80 | ||
|  | f01bbefc1f | ||
|  | 1d1eb5ffa8 | ||
|  | a465cb2191 | ||
|  | 42d13e02ef | ||
|  | d00786c43f | ||
|  | 4b47f99829 | ||
|  | 35aaf40003 | ||
|  | cc5b4a1e02 | ||
|  | 7079521e8c | ||
|  | b5025560a5 | ||
|  | 3f4bdd7f0e | ||
|  | e94bb9b549 | ||
|  | 1ddaacbef5 | ||
|  | e8b40518e0 | ||
|  | 0f88cbb41b | ||
|  | 780d137b76 | ||
|  | ad8a9717d1 | ||
|  | 9d6ea6b2f6 | ||
|  | 7559383089 | ||
|  | f84381c927 | ||
|  | cb0122a43f | ||
|  | 6776b20989 | ||
|  | e98d556022 | ||
|  | 5bf18b69d7 | ||
|  | ea17f045a7 | ||
|  | 526f565ea7 | ||
|  | 4aff9d6e73 | ||
|  | bf516d4d21 | ||
|  | ae92e409d9 | ||
|  | 4d017dc8a9 | ||
|  | 707f4e2965 | ||
|  | 1c3bffdc50 | ||
|  | e54ddcb8b0 | ||
|  | ddefb0debc | ||
|  | 92d8dde90d | ||
|  | 1bb0508ddf | ||
|  | a280a326b9 | ||
|  | 683e9b7c2c | ||
|  | a44e5da421 | ||
|  | 8cd2c90ad7 | ||
|  | 5e57a390a2 | ||
|  | 620848272e | ||
|  | 1e86794416 | ||
|  | e36717259b | ||
|  | 75b9238b90 | ||
|  | ce5b20027e | ||
|  | 0de1242c83 | ||
|  | 8bd445ab19 | ||
|  | fdef0de163 | ||
|  | b1b03a4325 | ||
|  | 0587d96474 | ||
|  | c2241567e4 | ||
|  | 7ac24ba418 | ||
|  | c933ffec66 | ||
|  | e587d934b1 | ||
|  | f354e90656 | ||
|  | 1b0bc7ec6e | ||
|  | ee1acb9c00 | ||
|  | 06862a2812 | ||
|  | 5fa87e18db | ||
|  | 77989e2720 | ||
|  | 3a1102fa4e | ||
|  | 8a9974ce53 | ||
|  | 4be8f1ca03 | ||
|  | 1ec2970ee3 | ||
|  | 81b3a22606 | ||
|  | f81a475cc9 | ||
|  | d7ee03d4f9 | ||
|  | c1c06410c2 | ||
|  | 657d16bb60 | ||
|  | e65a4c1010 | ||
|  | e23d3f5661 | ||
|  | e13611f7af | ||
|  | 596cd09489 | ||
|  | 0be5b27d34 | ||
|  | a27471ae55 | ||
|  | e27e3622a8 | ||
|  | e95273b72b | ||
|  | 583d4f3249 | ||
|  | d6967c4516 | ||
|  | 40b3097374 | ||
|  | 1a1f127993 | ||
|  | a0f34a7ce1 | ||
|  | db020db34b | ||
|  | 681167bc1b | ||
|  | 40e49ffc37 | ||
|  | 834b1afb38 | ||
|  | 62d5a1da87 | ||
|  | 8d8308e557 | ||
|  | e1aa63487a | ||
|  | b7fbe110d4 | ||
|  | 58859eb35a | ||
|  | 4b7e1ae1c6 | ||
|  | 3a06a6ac07 | ||
|  | db0f269dc8 | ||
|  | 3cabe6ca5a | ||
|  | d483005219 | ||
|  | fea9bc4e7e | ||
|  | d579992c98 | ||
|  | ad1c61d959 | ||
|  | bb1da31830 | ||
|  | a50949e554 | ||
|  | 14dce8a10b | ||
|  | 1240c8f685 | ||
|  | cc7c2e952c | ||
|  | 409ec2e086 | ||
|  | a7f6848e53 | ||
|  | 4b0b79199d | ||
|  | d1d6c48d9b | ||
|  | 21631780bb | ||
|  | b935e32340 | ||
|  | 72dd064932 | ||
|  | 2e75446665 | ||
|  | be17e4481e | ||
|  | 616c849b1f | ||
|  | 71947c097f | ||
|  | 546787802d | ||
|  | 294d0e388a | ||
|  | 193a1b0325 | ||
|  | 12743217a2 | 
| @@ -1,3 +1 @@ | ||||
| src_dir: . | ||||
| coverage_clover: build/logs/clover.xml | ||||
| json_path: build/logs/coveralls-upload.json | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| APP_ENV=production | ||||
| APP_DEBUG=false | ||||
| APP_KEY=SomeRandomString | ||||
| APP_KEY=SomeRandomStringOf32CharsExactly | ||||
|  | ||||
| DB_CONNECTION=mysql | ||||
| DB_HOST=localhost | ||||
| @@ -18,4 +18,7 @@ EMAIL_PASSWORD= | ||||
| ANALYTICS_ID= | ||||
| EMAIL_PRETEND=false | ||||
| RUNCLEANUP=true | ||||
| SITE_OWNER=mail@example.com | ||||
| SITE_OWNER=mail@example.com | ||||
|  | ||||
| SENDGRID_USERNAME= | ||||
| SENDGRID_PASSWORD= | ||||
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -31,3 +31,6 @@ addNewLines.php | ||||
| .phpstorm.meta.php | ||||
| .env.backup | ||||
| .env.local | ||||
|  | ||||
| tests/_output/* | ||||
| tests/_output/* | ||||
|   | ||||
| @@ -1,5 +1,3 @@ | ||||
| # .scrutinizer.yml | ||||
| tools: | ||||
|   external_code_coverage: | ||||
|     timeout: 1800    # Timeout in seconds. | ||||
|     runs: 2 | ||||
|   external_code_coverage: false | ||||
|   | ||||
| @@ -13,10 +13,3 @@ install: | ||||
|  | ||||
| script: | ||||
|   - phpunit | ||||
|  | ||||
| after_script: | ||||
|   - php vendor/bin/coveralls | ||||
|   - CODECLIMATE_REPO_TOKEN=26489f9e854fcdf7e7660ba29c1455694685465b1f90329a79f7d2bf448acb61 ./vendor/bin/test-reporter --stdout > codeclimate.json | ||||
|   - "curl -X POST -d @codeclimate.json -H 'Content-Type: application/json' -H 'User-Agent: Code Climate (PHP Test Reporter v0.1.1)' https://codeclimate.com/test_reports" | ||||
|   - wget https://scrutinizer-ci.com/ocular.phar | ||||
|   - php ocular.phar code-coverage:upload --format=php-clover build/logs/clover.xml | ||||
							
								
								
									
										43
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,7 +1,9 @@ | ||||
| # Firefly III (v3.4.3) | ||||
| # Firefly III | ||||
|  | ||||
| [](https://packagist.org/packages/grumpydictator/firefly-iii) | ||||
| [](https://packagist.org/packages/grumpydictator/firefly-iii) | ||||
|  | ||||
| [](https://scrutinizer-ci.com/g/JC5/firefly-iii/?branch=master) | ||||
| [](https://scrutinizer-ci.com/g/JC5/firefly-iii/?branch=master) | ||||
| [](https://scrutinizer-ci.com/g/JC5/firefly-iii/build-status/master) | ||||
|  | ||||
| ## About | ||||
| @@ -26,7 +28,7 @@ To get to know Firefly, and to see if it fits you, check out these resources: | ||||
| and the philosophy behind it. | ||||
|  | ||||
|  | ||||
| #### About the name (if you care) | ||||
| #### About the name (should you care) | ||||
|  | ||||
| It's III, or 3, because [version 2](https://github.com/JC5/Firefly) and version 1 (not online) preceded it. It has been growing steadily ever since. | ||||
|  | ||||
| @@ -59,19 +61,19 @@ Everything is organised: | ||||
|  | ||||
| _Please note that everything in these screenshots is fictional and may not be realistic._ | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| ## Running and installing | ||||
|  | ||||
| @@ -80,13 +82,28 @@ 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 week. | ||||
|  | ||||
| ## Credits | ||||
|  | ||||
| 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/) | ||||
| * For development, some of the excellent tools made by [Barry van den Heuvel](https://github.com/barryvdh) | ||||
| * [Bootstrap sortable](https://github.com/drvic10k/bootstrap-sortable) by [Matúš Brliť](https://github.com/drvic10k). | ||||
| * [Date range picker](https://github.com/dangrossman/bootstrap-daterangepicker/) by [Dan Grossman](https://github.com/dangrossman) | ||||
| * The [real favicon generator](http://realfavicongenerator.net/) | ||||
| * Various other open source components (see [composer.json](https://github.com/JC5/firefly-iii/blob/master/composer.json)) | ||||
|  | ||||
|  | ||||
| ## Current state | ||||
|  | ||||
| Firefly III is pretty much all grown up. Full test coverage (nerd alert!) is coming. One of the things on the todo-list | ||||
| is adding translations. | ||||
| Firefly III is pretty much all grown up. Full test coverage (nerd alert!) is coming. Translations are a work in progress. | ||||
|  | ||||
| Questions, ideas, bugs or other things to contribute? [Let me know](https://github.com/JC5/firefly-iii/issues/new)! | ||||
|  | ||||
|   | ||||
							
								
								
									
										52
									
								
								app/Generator/Chart/Account/AccountChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								app/Generator/Chart/Account/AccountChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Account; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\Account; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Interface AccountChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Account | ||||
|  */ | ||||
| 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 | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage(Collection $accounts, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @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); | ||||
| } | ||||
							
								
								
									
										174
									
								
								app/Generator/Chart/Account/ChartJsAccountChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								app/Generator/Chart/Account/ChartJsAccountChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,174 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Account; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Config; | ||||
| use FireflyIII\Models\Account; | ||||
| use Illuminate\Support\Collection; | ||||
| use Preferences; | ||||
| use Steam; | ||||
|  | ||||
| /** | ||||
|  * Class ChartJsAccountChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Account | ||||
|  */ | ||||
| class ChartJsAccountChartGenerator implements AccountChartGenerator | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function all(Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         return $this->frontpage($accounts, $start, $end); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function expenseAccounts(Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         // language: | ||||
|  | ||||
|         $data = [ | ||||
|             'count'    => 1, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [ | ||||
|                 [ | ||||
|                     'label' => trans('firefly.spent'), | ||||
|                     'data'  => [] | ||||
|                 ] | ||||
|             ], | ||||
|         ]; | ||||
|         $ids  = []; | ||||
|  | ||||
|         foreach ($accounts as $account) { | ||||
|             $ids[] = $account->id; | ||||
|         } | ||||
|         $start->subDay(); | ||||
|  | ||||
|         $startBalances = Steam::balancesById($ids, $start); | ||||
|         $endBalances   = Steam::balancesById($ids, $end); | ||||
|  | ||||
|         $accounts->each( | ||||
|             function (Account $account) use ($startBalances, $endBalances) { | ||||
|                 $id                  = $account->id; | ||||
|                 $startBalance        = isset($startBalances[$id]) ? $startBalances[$id] : 0; | ||||
|                 $endBalance          = isset($endBalances[$id]) ? $endBalances[$id] : 0; | ||||
|                 $diff                = $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 Collection $accounts | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage(Collection $accounts, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         // language: | ||||
|         $language = Preferences::get('language', 'en')->data; | ||||
|         $format   = Config::get('firefly.monthAndDay.' . $language); | ||||
|         $data     = [ | ||||
|             'count'    => 0, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [], | ||||
|         ]; | ||||
|         $current  = clone $start; | ||||
|         while ($current <= $end) { | ||||
|             $data['labels'][] = $current->formatLocalized($format); | ||||
|             $current->addDay(); | ||||
|         } | ||||
|  | ||||
|         foreach ($accounts as $account) { | ||||
|             $set     = [ | ||||
|                 'label'                => $account->name, | ||||
|                 'fillColor'            => 'rgba(220,220,220,0.2)', | ||||
|                 'strokeColor'          => 'rgba(220,220,220,1)', | ||||
|                 'pointColor'           => 'rgba(220,220,220,1)', | ||||
|                 'pointStrokeColor'     => '#fff', | ||||
|                 'pointHighlightFill'   => '#fff', | ||||
|                 'pointHighlightStroke' => 'rgba(220,220,220,1)', | ||||
|                 'data'                 => [], | ||||
|             ]; | ||||
|             $current = clone $start; | ||||
|             while ($current <= $end) { | ||||
|                 $set['data'][] = Steam::balance($account, $current); | ||||
|                 $current->addDay(); | ||||
|             } | ||||
|             $data['datasets'][] = $set; | ||||
|         } | ||||
|         $data['count'] = count($data['datasets']); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function single(Account $account, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         // language: | ||||
|         $language = Preferences::get('language', 'en')->data; | ||||
|         $format   = Config::get('firefly.monthAndDay.' . $language); | ||||
|  | ||||
|         $data = [ | ||||
|             'count'    => 1, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [ | ||||
|                 [ | ||||
|                     'label' => $account->name, | ||||
|                     'data'  => [] | ||||
|                 ] | ||||
|             ], | ||||
|         ]; | ||||
|  | ||||
|         $current = clone $start; | ||||
|  | ||||
|         while ($end >= $current) { | ||||
|             $data['labels'][]              = $current->formatLocalized($format); | ||||
|             $data['datasets'][0]['data'][] = Steam::balance($account, $current); | ||||
|             $current->addDay(); | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										32
									
								
								app/Generator/Chart/Bill/BillChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								app/Generator/Chart/Bill/BillChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| <?php | ||||
| namespace FireflyIII\Generator\Chart\Bill; | ||||
|  | ||||
|  | ||||
| use FireflyIII\Models\Bill; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Interface BillChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Bill | ||||
|  */ | ||||
| interface BillChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $paid | ||||
|      * @param Collection $unpaid | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage(Collection $paid, Collection $unpaid); | ||||
|  | ||||
|     /** | ||||
|      * @param Bill       $bill | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function single(Bill $bill, Collection $entries); | ||||
|  | ||||
| } | ||||
							
								
								
									
										114
									
								
								app/Generator/Chart/Bill/ChartJsBillChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								app/Generator/Chart/Bill/ChartJsBillChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,114 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Bill; | ||||
|  | ||||
| use Config; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Illuminate\Support\Collection; | ||||
| use Preferences; | ||||
|  | ||||
| /** | ||||
|  * Class ChartJsBillChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Bill | ||||
|  */ | ||||
| class ChartJsBillChartGenerator implements BillChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $paid | ||||
|      * @param Collection $unpaid | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage(Collection $paid, Collection $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               = bcdiv(bcadd($entry[0]->amount_max, $entry[0]->amount_min), 2); | ||||
|             $unpaidDescriptions[] = $description; | ||||
|             $unpaidAmount         = bcadd($unpaidAmount, $amount); | ||||
|             unset($amount, $description); | ||||
|         } | ||||
|  | ||||
|         $data = [ | ||||
|             [ | ||||
|                 'value'     => $unpaidAmount, | ||||
|                 'color'     => 'rgba(53, 124, 165,0.7)', | ||||
|                 'highlight' => 'rgba(53, 124, 165,0.9)', | ||||
|                 'label'     => trans('firefly.unpaid'), | ||||
|             ], | ||||
|             [ | ||||
|                 'value'     => $paidAmount, | ||||
|                 'color'     => 'rgba(0, 141, 76, 0.7)', | ||||
|                 'highlight' => 'rgba(0, 141, 76, 0.9)', | ||||
|                 'label'     => trans('firefly.paid'), | ||||
|             ] | ||||
|         ]; | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill       $bill | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function single(Bill $bill, Collection $entries) | ||||
|     { | ||||
|         // language: | ||||
|         $language = Preferences::get('language', 'en')->data; | ||||
|         $format   = Config::get('firefly.month.' . $language); | ||||
|  | ||||
|         $data = [ | ||||
|             'count'    => 3, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [], | ||||
|         ]; | ||||
|  | ||||
|         // dataset: max amount | ||||
|         // dataset: min amount | ||||
|         // dataset: actual amount | ||||
|  | ||||
|         $minAmount    = []; | ||||
|         $maxAmount    = []; | ||||
|         $actualAmount = []; | ||||
|         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); | ||||
|         } | ||||
|  | ||||
|         $data['datasets'][] = [ | ||||
|             'label' => trans('firefly.minAmount'), | ||||
|             'data'  => $minAmount, | ||||
|         ]; | ||||
|         $data['datasets'][] = [ | ||||
|             'label' => trans('firefly.billEntry'), | ||||
|             'data'  => $actualAmount, | ||||
|         ]; | ||||
|         $data['datasets'][] = [ | ||||
|             'label' => trans('firefly.maxAmount'), | ||||
|             'data'  => $maxAmount, | ||||
|         ]; | ||||
|  | ||||
|         $data['count'] = count($data['datasets']); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										43
									
								
								app/Generator/Chart/Budget/BudgetChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								app/Generator/Chart/Budget/BudgetChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Budget; | ||||
|  | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Interface BudgetChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Budget | ||||
|  */ | ||||
| interface BudgetChartGenerator | ||||
| { | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function budget(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function budgetLimit(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $budgets | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function year(Collection $budgets, Collection $entries); | ||||
|  | ||||
| } | ||||
							
								
								
									
										144
									
								
								app/Generator/Chart/Budget/ChartJsBudgetChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								app/Generator/Chart/Budget/ChartJsBudgetChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,144 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Budget; | ||||
|  | ||||
|  | ||||
| use Config; | ||||
| use Illuminate\Support\Collection; | ||||
| use Preferences; | ||||
|  | ||||
| /** | ||||
|  * Class ChartJsBudgetChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Budget | ||||
|  */ | ||||
| class ChartJsBudgetChartGenerator implements BudgetChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * @param string     $dateFormat | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function budget(Collection $entries, $dateFormat = 'month') | ||||
|     { | ||||
|         // language: | ||||
|         $language = Preferences::get('language', 'en')->data; | ||||
|         $format   = Config::get('firefly.' . $dateFormat . '.' . $language); | ||||
|  | ||||
|         $data = [ | ||||
|             'labels'   => [], | ||||
|             'datasets' => [ | ||||
|                 [ | ||||
|                     'label' => 'Amount', | ||||
|                     'data'  => [], | ||||
|                 ] | ||||
|             ], | ||||
|         ]; | ||||
|  | ||||
|         /** @var array $entry */ | ||||
|         foreach ($entries as $entry) { | ||||
|             $data['labels'][]              = $entry[0]->formatLocalized($format); | ||||
|             $data['datasets'][0]['data'][] = $entry[1]; | ||||
|  | ||||
|         } | ||||
|  | ||||
|         $data['count'] = count($data['datasets']); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function budgetLimit(Collection $entries) | ||||
|     { | ||||
|         return $this->budget($entries, 'monthAndDay'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage(Collection $entries) | ||||
|     { | ||||
|         $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); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $data['datasets'][] = [ | ||||
|             'label' => trans('firefly.left'), | ||||
|             'data'  => $left, | ||||
|         ]; | ||||
|         $data['datasets'][] = [ | ||||
|             'label' => trans('firefly.spent'), | ||||
|             'data'  => $spent, | ||||
|         ]; | ||||
|         $data['datasets'][] = [ | ||||
|             'label' => trans('firefly.overspent'), | ||||
|             'data'  => $overspent, | ||||
|         ]; | ||||
|  | ||||
|         $data['count'] = count($data['datasets']); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $budgets | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function year(Collection $budgets, Collection $entries) | ||||
|     { | ||||
|         // language: | ||||
|         $language = Preferences::get('language', 'en')->data; | ||||
|         $format   = Config::get('firefly.month.' . $language); | ||||
|  | ||||
|         $data = [ | ||||
|             'labels'   => [], | ||||
|             'datasets' => [], | ||||
|         ]; | ||||
|  | ||||
|         foreach ($budgets as $budget) { | ||||
|             $data['labels'][] = $budget->name; | ||||
|         } | ||||
|         /** @var array $entry */ | ||||
|         foreach ($entries as $entry) { | ||||
|             $array = [ | ||||
|                 'label' => $entry[0]->formatLocalized($format), | ||||
|                 'data'  => [], | ||||
|             ]; | ||||
|             array_shift($entry); | ||||
|             $array['data']      = $entry; | ||||
|             $data['datasets'][] = $array; | ||||
|  | ||||
|         } | ||||
|         $data['count'] = count($data['datasets']); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										52
									
								
								app/Generator/Chart/Category/CategoryChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								app/Generator/Chart/Category/CategoryChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Category; | ||||
|  | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Interface CategoryChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Category | ||||
|  */ | ||||
| interface CategoryChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function all(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function month(Collection $entries); | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $categories | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function spentInYear(Collection $categories, Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $categories | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function earnedInYear(Collection $categories, Collection $entries); | ||||
| } | ||||
							
								
								
									
										168
									
								
								app/Generator/Chart/Category/ChartJsCategoryChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								app/Generator/Chart/Category/ChartJsCategoryChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,168 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Category; | ||||
|  | ||||
| use Config; | ||||
| use Illuminate\Support\Collection; | ||||
| use Preferences; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class ChartJsCategoryChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Category | ||||
|  */ | ||||
| class ChartJsCategoryChartGenerator implements CategoryChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * @param string     $dateFormat | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function all(Collection $entries, $dateFormat = 'month') | ||||
|     { | ||||
|  | ||||
|         // language: | ||||
|         $language = Preferences::get('language', 'en')->data; | ||||
|         $format   = Config::get('firefly.' . $dateFormat . '.' . $language); | ||||
|  | ||||
|         $data = [ | ||||
|             'count'    => 2, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [ | ||||
|                 [ | ||||
|                     'label' => trans('firefly.spent'), | ||||
|                     'data'  => [] | ||||
|                 ], | ||||
|                 [ | ||||
|                     'label' => trans('firefly.earned'), | ||||
|                     'data'  => [] | ||||
|                 ] | ||||
|             ], | ||||
|         ]; | ||||
|  | ||||
|         foreach ($entries as $entry) { | ||||
|             $data['labels'][] = $entry[0]->formatLocalized($format); | ||||
|             $amount           = round($entry[1], 2); | ||||
|             if ($amount > 0) { | ||||
|                 $data['datasets'][0]['data'][] = null; | ||||
|                 $data['datasets'][1]['data'][] = $amount; | ||||
|             } else { | ||||
|                 $data['datasets'][0]['data'][] = $amount * -1; | ||||
|                 $data['datasets'][1]['data'][] = null; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function frontpage(Collection $entries) | ||||
|     { | ||||
|         $data = [ | ||||
|             'count'    => 1, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [ | ||||
|                 [ | ||||
|                     'label' => trans('firefly.spent'), | ||||
|                     'data'  => [] | ||||
|                 ] | ||||
|             ], | ||||
|         ]; | ||||
|         foreach ($entries as $entry) { | ||||
|             if ($entry['sum'] != 0) { | ||||
|                 $data['labels'][]              = $entry['name']; | ||||
|                 $data['datasets'][0]['data'][] = round($entry['sum'], 2); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function month(Collection $entries) | ||||
|     { | ||||
|         return $this->all($entries, 'monthAndDay'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $categories | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function spentInYear(Collection $categories, Collection $entries) | ||||
|     { | ||||
|  | ||||
|         // language: | ||||
|         $language = Preferences::get('language', 'en')->data; | ||||
|         $format   = Config::get('firefly.month.' . $language); | ||||
|  | ||||
|         $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 $categories | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function earnedInYear(Collection $categories, Collection $entries) | ||||
|     { | ||||
|  | ||||
|         // language: | ||||
|         $language = Preferences::get('language', 'en')->data; | ||||
|         $format   = Config::get('firefly.month.' . $language); | ||||
|  | ||||
|         $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; | ||||
|  | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,52 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\PiggyBank; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Config; | ||||
| use Illuminate\Support\Collection; | ||||
| use Preferences; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class ChartJsPiggyBankChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\PiggyBank | ||||
|  */ | ||||
| class ChartJsPiggyBankChartGenerator implements PiggyBankChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $set | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function history(Collection $set) | ||||
|     { | ||||
|  | ||||
|         // language: | ||||
|         $language = Preferences::get('language', 'en')->data; | ||||
|         $format   = Config::get('firefly.monthAndDay.' . $language); | ||||
|  | ||||
|         $data = [ | ||||
|             'count'    => 1, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [ | ||||
|                 [ | ||||
|                     'label' => 'Diff', | ||||
|                     'data'  => [] | ||||
|                 ] | ||||
|             ], | ||||
|         ]; | ||||
|         $sum  = '0'; | ||||
|         bcscale(2); | ||||
|         foreach ($set as $entry) { | ||||
|             $date                          = new Carbon($entry->date); | ||||
|             $sum                           = bcadd($sum, $entry->sum); | ||||
|             $data['labels'][]              = $date->formatLocalized($format); | ||||
|             $data['datasets'][0]['data'][] = round($sum, 2); | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										20
									
								
								app/Generator/Chart/PiggyBank/PiggyBankChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								app/Generator/Chart/PiggyBank/PiggyBankChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\PiggyBank; | ||||
|  | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Interface PiggyBankChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\PiggyBank | ||||
|  */ | ||||
| interface PiggyBankChartGenerator | ||||
| { | ||||
|     /** | ||||
|      * @param Collection $set | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function history(Collection $set); | ||||
| } | ||||
							
								
								
									
										83
									
								
								app/Generator/Chart/Report/ChartJsReportChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								app/Generator/Chart/Report/ChartJsReportChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Report; | ||||
|  | ||||
| use Config; | ||||
| use Illuminate\Support\Collection; | ||||
| use Preferences; | ||||
|  | ||||
| /** | ||||
|  * Class ChartJsReportChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Report | ||||
|  */ | ||||
| class ChartJsReportChartGenerator implements ReportChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function yearInOut(Collection $entries) | ||||
|     { | ||||
|         // language: | ||||
|         $language = Preferences::get('language', 'en')->data; | ||||
|         $format   = Config::get('firefly.month.' . $language); | ||||
|  | ||||
|         $data = [ | ||||
|             'count'    => 2, | ||||
|             'labels'   => [], | ||||
|             'datasets' => [ | ||||
|                 [ | ||||
|                     'label' => trans('firefly.income'), | ||||
|                     'data'  => [] | ||||
|                 ], | ||||
|                 [ | ||||
|                     'label' => trans('firefly.expenses'), | ||||
|                     'data'  => [] | ||||
|                 ] | ||||
|             ], | ||||
|         ]; | ||||
|  | ||||
|         foreach ($entries as $entry) { | ||||
|             $data['labels'][]              = $entry[0]->formatLocalized($format); | ||||
|             $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 yearInOutSummarized($income, $expense, $count) | ||||
|     { | ||||
|  | ||||
|         $data                          = [ | ||||
|             'count'    => 2, | ||||
|             'labels'   => [trans('firefly.sum_of_year'), trans('firefly.average_of_year')], | ||||
|             '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; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										31
									
								
								app/Generator/Chart/Report/ReportChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								app/Generator/Chart/Report/ReportChartGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Generator\Chart\Report; | ||||
|  | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Interface ReportChartGenerator | ||||
|  * | ||||
|  * @package FireflyIII\Generator\Chart\Report | ||||
|  */ | ||||
| interface ReportChartGenerator | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $entries | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function yearInOut(Collection $entries); | ||||
|  | ||||
|     /** | ||||
|      * @param string $income | ||||
|      * @param string $expense | ||||
|      * @param int    $count | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function yearInOutSummarized($income, $expense, $count); | ||||
|  | ||||
| } | ||||
| @@ -4,7 +4,6 @@ use Auth; | ||||
| use FireflyIII\Events\JournalCreated; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\PiggyBankEvent; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
|  | ||||
| /** | ||||
| @@ -52,18 +51,16 @@ class ConnectJournalToPiggyBank | ||||
|         if (is_null($repetition)) { | ||||
|             return false; | ||||
|         } | ||||
|         bcscale(2); | ||||
|  | ||||
|         $amount = $journal->amount; | ||||
|         /** @var Transaction $transaction */ | ||||
|         foreach ($journal->transactions()->get() as $transaction) { | ||||
|             if ($transaction->account_id == $piggyBank->account_id) { | ||||
|                 if ($transaction->amount < 0) { | ||||
|                     $amount = $transaction->amount * -1; | ||||
|                 } | ||||
|             } | ||||
|         $amount = $journal->actual_amount; | ||||
|         // if piggy account matches source account, the amount is positive | ||||
|         if ($piggyBank->account_id == $journal->source_account->id) { | ||||
|             $amount = $amount * -1; | ||||
|         } | ||||
|  | ||||
|         $repetition->currentamount += $amount; | ||||
|  | ||||
|         $repetition->currentamount = bcadd($repetition->currentamount, $amount); | ||||
|         $repetition->save(); | ||||
|  | ||||
|         PiggyBankEvent::create(['piggy_bank_id' => $piggyBank->id, 'transaction_journal_id' => $journal->id, 'date' => $journal->date, 'amount' => $amount]); | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| <?php namespace FireflyIII\Handlers\Events; | ||||
|  | ||||
| use App; | ||||
| use FireflyIII\Events\JournalSaved; | ||||
| use Log; | ||||
|  | ||||
| @@ -36,7 +35,7 @@ class RescanJournal | ||||
|         Log::debug('Triggered saved event for journal #' . $journal->id . ' (' . $journal->description . ')'); | ||||
|  | ||||
|         /** @var \FireflyIII\Repositories\Bill\BillRepositoryInterface $repository */ | ||||
|         $repository = App::make('FireflyIII\Repositories\Bill\BillRepositoryInterface'); | ||||
|         $repository = app('FireflyIII\Repositories\Bill\BillRepositoryInterface'); | ||||
|         $list       = $journal->user->bills()->where('active', 1)->where('automatch', 1)->get(); | ||||
|  | ||||
|         Log::debug('Found ' . $list->count() . ' bills to check.'); | ||||
|   | ||||
| @@ -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(); | ||||
|  | ||||
|  | ||||
|   | ||||
							
								
								
									
										222
									
								
								app/Helpers/Attachments/AttachmentHelper.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										222
									
								
								app/Helpers/Attachments/AttachmentHelper.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,222 @@ | ||||
| <?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 { | ||||
|             $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); | ||||
|  | ||||
| } | ||||
| @@ -64,6 +64,7 @@ class BalanceLine | ||||
|         if ($this->getRole() == self::ROLE_DIFFROLE) { | ||||
|             return trans('firefly.leftUnbalanced'); | ||||
|         } | ||||
|  | ||||
|         return ''; | ||||
|     } | ||||
|  | ||||
| @@ -158,10 +159,11 @@ class BalanceLine | ||||
|      */ | ||||
|     public function sumOfLeft() | ||||
|     { | ||||
|         $sum = 0.0; | ||||
|         $sum = '0'; | ||||
|         bcscale(2); | ||||
|         /** @var BalanceEntry $balanceEntry */ | ||||
|         foreach ($this->getBalanceEntries() as $balanceEntry) { | ||||
|             $sum += $balanceEntry->getLeft(); | ||||
|             $sum = bcadd($sum, $balanceEntry->getLeft()); | ||||
|         } | ||||
|  | ||||
|         return $sum; | ||||
|   | ||||
| @@ -40,8 +40,8 @@ class Bill | ||||
|      */ | ||||
|     public function getBills() | ||||
|     { | ||||
|         $this->bills->sortBy( | ||||
|             function(BillLine $bill) { | ||||
|         $set = $this->bills->sortBy( | ||||
|             function (BillLine $bill) { | ||||
|                 $active = intval($bill->getBill()->active) == 0 ? 1 : 0; | ||||
|                 $name   = $bill->getBill()->name; | ||||
|  | ||||
| @@ -50,7 +50,7 @@ class Bill | ||||
|         ); | ||||
|  | ||||
|  | ||||
|         return $this->bills; | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -16,19 +16,19 @@ class BillLine | ||||
|  | ||||
|     /** @var  bool */ | ||||
|     protected $active; | ||||
|     /** @var  float */ | ||||
|     /** @var  string */ | ||||
|     protected $amount; | ||||
|     /** @var  BillModel */ | ||||
|     protected $bill; | ||||
|     /** @var  bool */ | ||||
|     protected $hit; | ||||
|     /** @var  float */ | ||||
|     /** @var  string */ | ||||
|     protected $max; | ||||
|     /** @var  float */ | ||||
|     /** @var  string */ | ||||
|     protected $min; | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getAmount() | ||||
|     { | ||||
| @@ -36,7 +36,7 @@ class BillLine | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $amount | ||||
|      * @param string $amount | ||||
|      */ | ||||
|     public function setAmount($amount) | ||||
|     { | ||||
| @@ -60,7 +60,7 @@ class BillLine | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getMax() | ||||
|     { | ||||
| @@ -68,7 +68,7 @@ class BillLine | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $max | ||||
|      * @param string $max | ||||
|      */ | ||||
|     public function setMax($max) | ||||
|     { | ||||
| @@ -76,7 +76,7 @@ class BillLine | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getMin() | ||||
|     { | ||||
| @@ -84,7 +84,7 @@ class BillLine | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $min | ||||
|      * @param string $min | ||||
|      */ | ||||
|     public function setMin($min) | ||||
|     { | ||||
|   | ||||
| @@ -34,7 +34,8 @@ 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); | ||||
|         } | ||||
|     } | ||||
| @@ -54,14 +55,14 @@ class Category | ||||
|      */ | ||||
|     public function getCategories() | ||||
|     { | ||||
|         $this->categories->sortByDesc( | ||||
|             function(CategoryModel $category) { | ||||
|         $set = $this->categories->sortByDesc( | ||||
|             function (CategoryModel $category) { | ||||
|                 return $category->spent; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|  | ||||
|         return $this->categories; | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -66,13 +66,13 @@ class Expense | ||||
|      */ | ||||
|     public function getExpenses() | ||||
|     { | ||||
|         $this->expenses->sortByDesc( | ||||
|             function(stdClass $object) { | ||||
|         $set = $this->expenses->sortByDesc( | ||||
|             function (stdClass $object) { | ||||
|                 return $object->amount; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return $this->expenses; | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -67,13 +67,13 @@ class Income | ||||
|      */ | ||||
|     public function getIncomes() | ||||
|     { | ||||
|         $this->incomes->sortByDesc( | ||||
|             function(stdClass $object) { | ||||
|         $set = $this->incomes->sortByDesc( | ||||
|             function (stdClass $object) { | ||||
|                 return $object->amount; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return $this->incomes; | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
							
								
								
									
										38
									
								
								app/Helpers/Csv/Converter/AccountId.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								app/Helpers/Csv/Converter/AccountId.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| <?php | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Account; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class AccountId | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class AccountId extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Account | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         // is mapped? Then it's easy! | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|  | ||||
|             /** @var Account $account */ | ||||
|             $account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]); | ||||
|         } else { | ||||
|  | ||||
|             /** @var Account $account */ | ||||
|             $account = Auth::user()->accounts()->find($this->value); | ||||
|  | ||||
|             if (!is_null($account)) { | ||||
|                 Log::debug('Found ' . $account->accountType->type . ' named "******" with ID: ' . $this->value . ' (not mapped) '); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $account; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										26
									
								
								app/Helpers/Csv/Converter/Amount.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								app/Helpers/Csv/Converter/Amount.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use FireflyIII\Models\Account; | ||||
|  | ||||
| /** | ||||
|  * Class Amount | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class Amount extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         if (is_numeric($this->value)) { | ||||
|             return $this->value; | ||||
|         } | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										68
									
								
								app/Helpers/Csv/Converter/AssetAccountIban.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								app/Helpers/Csv/Converter/AssetAccountIban.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
|  | ||||
| /** | ||||
|  * Class AssetAccountIban | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class AssetAccountIban extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         // is mapped? Then it's easy! | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]); | ||||
|  | ||||
|             return $account; | ||||
|         } | ||||
|         if (strlen($this->value) > 0) { | ||||
|             // find or create new account: | ||||
|             $account     = $this->findAccount(); | ||||
|             $accountType = AccountType::where('type', 'Asset account')->first(); | ||||
|  | ||||
|             if (is_null($account)) { | ||||
|                 // create it if doesn't exist. | ||||
|                 $account = Account::firstOrCreateEncrypted( | ||||
|                     [ | ||||
|                         'name'            => $this->value, | ||||
|                         'iban'            => $this->value, | ||||
|                         'user_id'         => Auth::user()->id, | ||||
|                         'account_type_id' => $accountType->id, | ||||
|                         'active'          => 1, | ||||
|                     ] | ||||
|                 ); | ||||
|             } | ||||
|  | ||||
|             return $account; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     protected function findAccount() | ||||
|     { | ||||
|         $set = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']); | ||||
|         /** @var Account $entry */ | ||||
|         foreach ($set as $entry) { | ||||
|             if ($entry->iban == $this->value) { | ||||
|  | ||||
|                 return $entry; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										51
									
								
								app/Helpers/Csv/Converter/AssetAccountName.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								app/Helpers/Csv/Converter/AssetAccountName.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
|  | ||||
| /** | ||||
|  * Class AssetAccountName | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class AssetAccountName extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         // is mapped? Then it's easy! | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]); | ||||
|  | ||||
|             return $account; | ||||
|         } | ||||
|         // find or create new account: | ||||
|         $accountType = AccountType::where('type', 'Asset account')->first(); | ||||
|         $set         = Auth::user()->accounts()->accountTypeIn(['Asset account', 'Default account'])->get(); | ||||
|         /** @var Account $entry */ | ||||
|         foreach ($set as $entry) { | ||||
|             if ($entry->name == $this->value) { | ||||
|                 return $entry; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // create it if doesnt exist. | ||||
|         $account = Account::firstOrCreateEncrypted( | ||||
|             [ | ||||
|                 'name'            => $this->value, | ||||
|                 'iban'            => '', | ||||
|                 'user_id'         => Auth::user()->id, | ||||
|                 'account_type_id' => $accountType->id, | ||||
|                 'active'          => 1, | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|         return $account; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										122
									
								
								app/Helpers/Csv/Converter/BasicConverter.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								app/Helpers/Csv/Converter/BasicConverter.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,122 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| /** | ||||
|  * Class BasicConverter | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class BasicConverter | ||||
| { | ||||
|     /** @var  array */ | ||||
|     protected $data; | ||||
|     /** @var string */ | ||||
|     protected $field; | ||||
|     /** @var int */ | ||||
|     protected $index; | ||||
|     /** @var  array */ | ||||
|     protected $mapped; | ||||
|     /** @var string */ | ||||
|     protected $role; | ||||
|     /** @var string */ | ||||
|     protected $value; | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getData() | ||||
|     { | ||||
|         return $this->data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData(array $data) | ||||
|     { | ||||
|         $this->data = $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getField() | ||||
|     { | ||||
|         return $this->field; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $field | ||||
|      */ | ||||
|     public function setField($field) | ||||
|     { | ||||
|         $this->field = $field; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return int | ||||
|      */ | ||||
|     public function getIndex() | ||||
|     { | ||||
|         return $this->index; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param int $index | ||||
|      */ | ||||
|     public function setIndex($index) | ||||
|     { | ||||
|         $this->index = $index; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMapped() | ||||
|     { | ||||
|         return $this->mapped; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $mapped | ||||
|      */ | ||||
|     public function setMapped($mapped) | ||||
|     { | ||||
|         $this->mapped = $mapped; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getRole() | ||||
|     { | ||||
|         return $this->role; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $role | ||||
|      */ | ||||
|     public function setRole($role) | ||||
|     { | ||||
|         $this->role = $role; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getValue() | ||||
|     { | ||||
|         return $this->value; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $value | ||||
|      */ | ||||
|     public function setValue($value) | ||||
|     { | ||||
|         $this->value = $value; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										30
									
								
								app/Helpers/Csv/Converter/BillId.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								app/Helpers/Csv/Converter/BillId.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Bill; | ||||
|  | ||||
| /** | ||||
|  * Class BillId | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class BillId extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Bill | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         // is mapped? Then it's easy! | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $bill = Auth::user()->bills()->find($this->mapped[$this->index][$this->value]); | ||||
|         } else { | ||||
|             $bill = Auth::user()->bills()->find($this->value); | ||||
|         } | ||||
|  | ||||
|         return $bill; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										38
									
								
								app/Helpers/Csv/Converter/BillName.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								app/Helpers/Csv/Converter/BillName.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Bill; | ||||
|  | ||||
| /** | ||||
|  * Class BillName | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class BillName extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Bill | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         $bill = null; | ||||
|         // is mapped? Then it's easy! | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $bill = Auth::user()->bills()->find($this->mapped[$this->index][$this->value]); | ||||
|         } else { | ||||
|  | ||||
|             $bills = Auth::user()->bills()->get(); | ||||
|             /** @var Bill $bill */ | ||||
|             foreach ($bills as $bill) { | ||||
|                 if ($bill->name == $this->value) { | ||||
|                     return $bill; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $bill; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										29
									
								
								app/Helpers/Csv/Converter/BudgetId.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								app/Helpers/Csv/Converter/BudgetId.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| <?php | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Budget; | ||||
|  | ||||
| /** | ||||
|  * Class AccountId | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class BudgetId extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Budget | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         // is mapped? Then it's easy! | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $budget = Auth::user()->budgets()->find($this->mapped[$this->index][$this->value]); | ||||
|         } else { | ||||
|             $budget = Auth::user()->budgets()->find($this->value); | ||||
|         } | ||||
|  | ||||
|         return $budget; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										35
									
								
								app/Helpers/Csv/Converter/BudgetName.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								app/Helpers/Csv/Converter/BudgetName.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| <?php | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Budget; | ||||
|  | ||||
| /** | ||||
|  * Class BudgetName | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class BudgetName extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Budget | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         // is mapped? Then it's easy! | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $budget = Auth::user()->budgets()->find($this->mapped[$this->index][$this->value]); | ||||
|         } else { | ||||
|             $budget = Budget::firstOrCreateEncrypted( | ||||
|                 [ | ||||
|                     'name'    => $this->value, | ||||
|                     'user_id' => Auth::user()->id, | ||||
|                     'active'  => true, | ||||
|                 ] | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         return $budget; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										29
									
								
								app/Helpers/Csv/Converter/CategoryId.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								app/Helpers/Csv/Converter/CategoryId.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| <?php | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Category; | ||||
|  | ||||
| /** | ||||
|  * Class CategoryId | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class CategoryId extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Category | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         // is mapped? Then it's easy! | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $category = Auth::user()->categories()->find($this->mapped[$this->index][$this->value]); | ||||
|         } else { | ||||
|             $category = Auth::user()->categories()->find($this->value); | ||||
|         } | ||||
|  | ||||
|         return $category; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										34
									
								
								app/Helpers/Csv/Converter/CategoryName.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								app/Helpers/Csv/Converter/CategoryName.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| <?php | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Category; | ||||
|  | ||||
| /** | ||||
|  * Class CategoryName | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class CategoryName extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Category | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         // is mapped? Then it's easy! | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $category = Auth::user()->categories()->find($this->mapped[$this->index][$this->value]); | ||||
|         } else { | ||||
|             $category = Category::firstOrCreateEncrypted( | ||||
|                 [ | ||||
|                     'name'    => $this->value, | ||||
|                     'user_id' => Auth::user()->id | ||||
|                 ] | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         return $category; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										49
									
								
								app/Helpers/Csv/Converter/ConverterInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								app/Helpers/Csv/Converter/ConverterInterface.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| /** | ||||
|  * Interface ConverterInterface | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| interface ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function convert(); | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData(array $data); | ||||
|  | ||||
|     /** | ||||
|      * @param string $field | ||||
|      * | ||||
|      */ | ||||
|     public function setField($field); | ||||
|  | ||||
|     /** | ||||
|      * @param int $index | ||||
|      */ | ||||
|     public function setIndex($index); | ||||
|  | ||||
|     /** | ||||
|      * @param array $mapped | ||||
|      */ | ||||
|     public function setMapped($mapped); | ||||
|  | ||||
|     /** | ||||
|      * @param string $role | ||||
|      */ | ||||
|     public function setRole($role); | ||||
|  | ||||
|     /** | ||||
|      * @param string $value | ||||
|      */ | ||||
|     public function setValue($value); | ||||
|  | ||||
| } | ||||
							
								
								
									
										28
									
								
								app/Helpers/Csv/Converter/CurrencyCode.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								app/Helpers/Csv/Converter/CurrencyCode.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
|  | ||||
| /** | ||||
|  * Class CurrencyCode | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class CurrencyCode extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return mixed|static | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $currency = TransactionCurrency::find($this->mapped[$this->index][$this->value]); | ||||
|         } else { | ||||
|             $currency = TransactionCurrency::whereCode($this->value)->first(); | ||||
|         } | ||||
|  | ||||
|         return $currency; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										28
									
								
								app/Helpers/Csv/Converter/CurrencyId.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								app/Helpers/Csv/Converter/CurrencyId.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
|  | ||||
| /** | ||||
|  * Class CurrencyId | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class CurrencyId extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return mixed|static | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $currency = TransactionCurrency::find($this->mapped[$this->index][$this->value]); | ||||
|         } else { | ||||
|             $currency = TransactionCurrency::find($this->value); | ||||
|         } | ||||
|  | ||||
|         return $currency; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										28
									
								
								app/Helpers/Csv/Converter/CurrencyName.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								app/Helpers/Csv/Converter/CurrencyName.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
|  | ||||
| /** | ||||
|  * Class CurrencyName | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class CurrencyName extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return mixed|static | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $currency = TransactionCurrency::find($this->mapped[$this->index][$this->value]); | ||||
|         } else { | ||||
|             $currency = TransactionCurrency::whereName($this->value)->first(); | ||||
|         } | ||||
|  | ||||
|         return $currency; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										28
									
								
								app/Helpers/Csv/Converter/CurrencySymbol.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								app/Helpers/Csv/Converter/CurrencySymbol.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
|  | ||||
| /** | ||||
|  * Class CurrencySymbol | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class CurrencySymbol extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return mixed|static | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $currency = TransactionCurrency::find($this->mapped[$this->index][$this->value]); | ||||
|         } else { | ||||
|             $currency = TransactionCurrency::whereSymbol($this->value)->first(); | ||||
|         } | ||||
|  | ||||
|         return $currency; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										38
									
								
								app/Helpers/Csv/Converter/Date.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								app/Helpers/Csv/Converter/Date.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use InvalidArgumentException; | ||||
| use Log; | ||||
| use Session; | ||||
|  | ||||
| /** | ||||
|  * Class Date | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class Date extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Carbon | ||||
|      */ | ||||
|     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); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         return $date; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										21
									
								
								app/Helpers/Csv/Converter/Description.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								app/Helpers/Csv/Converter/Description.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| /** | ||||
|  * Class Description | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class Description extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         return trim($this->data['description'] . ' ' . $this->value); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										22
									
								
								app/Helpers/Csv/Converter/Ignore.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								app/Helpers/Csv/Converter/Ignore.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use FireflyIII\Models\Account; | ||||
|  | ||||
| /** | ||||
|  * Class Amount | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class Ignore extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         return null; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										57
									
								
								app/Helpers/Csv/Converter/OpposingAccountIban.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								app/Helpers/Csv/Converter/OpposingAccountIban.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Account; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class OpposingAccountIban | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class OpposingAccountIban extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * If mapped, return account. Otherwise, only return the name itself. | ||||
|      * | ||||
|      * @return Account|string | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]); | ||||
|  | ||||
|             return $account; | ||||
|         } else { | ||||
|             if (strlen($this->value) > 0) { | ||||
|                 $account = $this->findAccount(); | ||||
|                 if (!is_null($account)) { | ||||
|                     return $account; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return $this->value; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     protected function findAccount() | ||||
|     { | ||||
|         $set = Auth::user()->accounts()->get(); | ||||
|         /** @var Account $account */ | ||||
|         foreach ($set as $account) { | ||||
|             if ($account->iban == $this->value) { | ||||
|                 Log::debug('OpposingAccountIban::convert found an Account (#' . $account->id . ': ******) with IBAN ******'); | ||||
|  | ||||
|                 return $account; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										32
									
								
								app/Helpers/Csv/Converter/OpposingAccountId.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								app/Helpers/Csv/Converter/OpposingAccountId.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Account; | ||||
|  | ||||
| /** | ||||
|  * Class OpposingName | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class OpposingAccountId extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @return Account | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]); | ||||
|  | ||||
|         } else { | ||||
|             $account = Auth::user()->accounts()->find($this->value); | ||||
|         } | ||||
|  | ||||
|         return $account; | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										31
									
								
								app/Helpers/Csv/Converter/OpposingAccountName.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								app/Helpers/Csv/Converter/OpposingAccountName.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Account; | ||||
|  | ||||
| /** | ||||
|  * Class OpposingName | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class OpposingAccountName extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * If mapped, return account. Otherwise, only return the name itself. | ||||
|      * | ||||
|      * @return Account|string | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         if (isset($this->mapped[$this->index][$this->value])) { | ||||
|             $account = Auth::user()->accounts()->find($this->mapped[$this->index][$this->value]); | ||||
|  | ||||
|             return $account; | ||||
|         } else { | ||||
|             return $this->value; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										26
									
								
								app/Helpers/Csv/Converter/RabobankDebetCredit.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								app/Helpers/Csv/Converter/RabobankDebetCredit.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class RabobankDebetCredit | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class RabobankDebetCredit extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         if ($this->value == 'D') { | ||||
|             return -1; | ||||
|         } | ||||
|  | ||||
|         return 1; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										40
									
								
								app/Helpers/Csv/Converter/TagsComma.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								app/Helpers/Csv/Converter/TagsComma.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\Tag; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class TagsComma | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class TagsComma extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Bill | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         $tags = new Collection; | ||||
|  | ||||
|         $strings = explode(',', $this->value); | ||||
|         foreach ($strings as $string) { | ||||
|             $tag = Tag::firstOrCreateEncrypted( | ||||
|                 [ | ||||
|                     'tag'     => $string, | ||||
|                     'tagMode' => 'nothing', | ||||
|                     'user_id' => Auth::user()->id, | ||||
|                 ] | ||||
|             ); | ||||
|             $tags->push($tag); | ||||
|         } | ||||
|         $tags = $tags->merge($this->data['tags']); | ||||
|  | ||||
|         return $tags; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										40
									
								
								app/Helpers/Csv/Converter/TagsSpace.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								app/Helpers/Csv/Converter/TagsSpace.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Converter; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\Tag; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class TagsSpace | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Converter | ||||
|  */ | ||||
| class TagsSpace extends BasicConverter implements ConverterInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return Bill | ||||
|      */ | ||||
|     public function convert() | ||||
|     { | ||||
|         $tags = new Collection; | ||||
|  | ||||
|         $strings = explode(' ', $this->value); | ||||
|         foreach ($strings as $string) { | ||||
|             $tag = Tag::firstOrCreateEncrypted( | ||||
|                 [ | ||||
|                     'tag'     => $string, | ||||
|                     'tagMode' => 'nothing', | ||||
|                     'user_id' => Auth::user()->id, | ||||
|                 ] | ||||
|             ); | ||||
|             $tags->push($tag); | ||||
|         } | ||||
|         $tags = $tags->merge($this->data['tags']); | ||||
|  | ||||
|         return $tags; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										283
									
								
								app/Helpers/Csv/Data.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										283
									
								
								app/Helpers/Csv/Data.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,283 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv; | ||||
|  | ||||
| use Crypt; | ||||
| use League\Csv\Reader; | ||||
| use Session; | ||||
|  | ||||
| /** | ||||
|  * Class Data | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv | ||||
|  */ | ||||
| class Data | ||||
| { | ||||
|  | ||||
|     /** @var string */ | ||||
|     protected $csvFileContent; | ||||
|  | ||||
|     /** @var string */ | ||||
|     protected $csvFileLocation; | ||||
|     /** @var  string */ | ||||
|     protected $dateFormat; | ||||
|     /** @var  bool */ | ||||
|     protected $hasHeaders; | ||||
|  | ||||
|     /** @var  array */ | ||||
|     protected $map = []; | ||||
|     /** @var  array */ | ||||
|     protected $mapped = []; | ||||
|     /** @var  Reader */ | ||||
|     protected $reader; | ||||
|     /** @var  array */ | ||||
|     protected $roles = []; | ||||
|  | ||||
|     /** @var  array */ | ||||
|     protected $specifix = []; | ||||
|  | ||||
|     /** @var int */ | ||||
|     protected $importAccount = 0; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->sessionHasHeaders(); | ||||
|         $this->sessionDateFormat(); | ||||
|         $this->sessionCsvFileLocation(); | ||||
|         $this->sessionMap(); | ||||
|         $this->sessionRoles(); | ||||
|         $this->sessionMapped(); | ||||
|         $this->sessionSpecifix(); | ||||
|         $this->sessionImportAccount(); | ||||
|     } | ||||
|  | ||||
|     protected function sessionHasHeaders() | ||||
|     { | ||||
|         if (Session::has('csv-has-headers')) { | ||||
|             $this->hasHeaders = (bool)Session::get('csv-has-headers'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     protected function sessionImportAccount() | ||||
|     { | ||||
|         if (Session::has('csv-import-account')) { | ||||
|             $this->importAccount = intval(Session::get('csv-import-account')); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     protected function sessionDateFormat() | ||||
|     { | ||||
|         if (Session::has('csv-date-format')) { | ||||
|             $this->dateFormat = (string)Session::get('csv-date-format'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     protected function sessionCsvFileLocation() | ||||
|     { | ||||
|         if (Session::has('csv-file')) { | ||||
|             $this->csvFileLocation = (string)Session::get('csv-file'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     protected function sessionMap() | ||||
|     { | ||||
|         if (Session::has('csv-map')) { | ||||
|             $this->map = (array)Session::get('csv-map'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     protected function sessionRoles() | ||||
|     { | ||||
|         if (Session::has('csv-roles')) { | ||||
|             $this->roles = (array)Session::get('csv-roles'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     protected function sessionMapped() | ||||
|     { | ||||
|         if (Session::has('csv-mapped')) { | ||||
|             $this->mapped = (array)Session::get('csv-mapped'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     protected function sessionSpecifix() | ||||
|     { | ||||
|         if (Session::has('csv-specifix')) { | ||||
|             $this->specifix = (array)Session::get('csv-specifix'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getDateFormat() | ||||
|     { | ||||
|         return $this->dateFormat; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param mixed $dateFormat | ||||
|      */ | ||||
|     public function setDateFormat($dateFormat) | ||||
|     { | ||||
|         Session::put('csv-date-format', $dateFormat); | ||||
|         $this->dateFormat = $dateFormat; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param int $importAccount | ||||
|      */ | ||||
|     public function setImportAccount($importAccount) | ||||
|     { | ||||
|         Session::put('csv-import-account', $importAccount); | ||||
|         $this->importAccount = $importAccount; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function hasHeaders() | ||||
|     { | ||||
|         return $this->hasHeaders; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param bool $hasHeaders | ||||
|      */ | ||||
|     public function setHasHeaders($hasHeaders) | ||||
|     { | ||||
|         Session::put('csv-has-headers', $hasHeaders); | ||||
|         $this->hasHeaders = $hasHeaders; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMap() | ||||
|     { | ||||
|         return $this->map; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $map | ||||
|      */ | ||||
|     public function setMap(array $map) | ||||
|     { | ||||
|         Session::put('csv-map', $map); | ||||
|         $this->map = $map; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMapped() | ||||
|     { | ||||
|         return $this->mapped; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $mapped | ||||
|      */ | ||||
|     public function setMapped(array $mapped) | ||||
|     { | ||||
|         Session::put('csv-mapped', $mapped); | ||||
|         $this->mapped = $mapped; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Reader | ||||
|      */ | ||||
|     public function getReader() | ||||
|     { | ||||
|  | ||||
|         if (strlen($this->csvFileContent) === 0) { | ||||
|             $this->loadCsvFile(); | ||||
|         } | ||||
|  | ||||
|         if (is_null($this->reader)) { | ||||
|             $this->reader = Reader::createFromString($this->getCsvFileContent()); | ||||
|         } | ||||
|  | ||||
|         return $this->reader; | ||||
|     } | ||||
|  | ||||
|     protected function loadCsvFile() | ||||
|     { | ||||
|         $file             = $this->getCsvFileLocation(); | ||||
|         $content          = file_get_contents($file); | ||||
|         $contentDecrypted = Crypt::decrypt($content); | ||||
|         $this->setCsvFileContent($contentDecrypted); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getCsvFileLocation() | ||||
|     { | ||||
|         return $this->csvFileLocation; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $csvFileLocation | ||||
|      */ | ||||
|     public function setCsvFileLocation($csvFileLocation) | ||||
|     { | ||||
|         Session::put('csv-file', $csvFileLocation); | ||||
|         $this->csvFileLocation = $csvFileLocation; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getCsvFileContent() | ||||
|     { | ||||
|         return $this->csvFileContent; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $csvFileContent | ||||
|      */ | ||||
|     public function setCsvFileContent($csvFileContent) | ||||
|     { | ||||
|         $this->csvFileContent = $csvFileContent; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getRoles() | ||||
|     { | ||||
|         return $this->roles; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $roles | ||||
|      */ | ||||
|     public function setRoles(array $roles) | ||||
|     { | ||||
|         Session::put('csv-roles', $roles); | ||||
|         $this->roles = $roles; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getSpecifix() | ||||
|     { | ||||
|         return is_array($this->specifix) ? $this->specifix : []; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $specifix | ||||
|      */ | ||||
|     public function setSpecifix($specifix) | ||||
|     { | ||||
|         Session::put('csv-specifix', $specifix); | ||||
|         $this->specifix = $specifix; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										371
									
								
								app/Helpers/Csv/Importer.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										371
									
								
								app/Helpers/Csv/Importer.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,371 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv; | ||||
|  | ||||
| use Auth; | ||||
| use Config; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Csv\Converter\ConverterInterface; | ||||
| use FireflyIII\Helpers\Csv\PostProcessing\PostProcessorInterface; | ||||
| use FireflyIII\Helpers\Csv\Specifix\SpecifixInterface; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use Illuminate\Support\Collection; | ||||
| use Illuminate\Support\MessageBag; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class Importer | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv | ||||
|  */ | ||||
| class Importer | ||||
| { | ||||
|  | ||||
|     /** @var Data */ | ||||
|     protected $data; | ||||
|     /** @var array */ | ||||
|     protected $errors; | ||||
|     /** @var  array */ | ||||
|     protected $importData; | ||||
|     /** @var  array */ | ||||
|     protected $importRow; | ||||
|     /** @var int */ | ||||
|     protected $imported = 0; | ||||
|     /** @var array */ | ||||
|     protected $map; | ||||
|     /** @var  array */ | ||||
|     protected $mapped; | ||||
|     /** @var  array */ | ||||
|     protected $roles; | ||||
|     /** @var  int */ | ||||
|     protected $rows = 0; | ||||
|     /** @var array */ | ||||
|     protected $specifix = []; | ||||
|  | ||||
|     /** @var  Collection */ | ||||
|     protected $journals; | ||||
|  | ||||
|     /** | ||||
|      * Used by CsvController. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getErrors() | ||||
|     { | ||||
|         return $this->errors; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Used by CsvController | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function getImported() | ||||
|     { | ||||
|         return $this->imported; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Used by CsvController | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function getRows() | ||||
|     { | ||||
|         return $this->rows; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getJournals() | ||||
|     { | ||||
|         return $this->journals; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function run() | ||||
|     { | ||||
|         set_time_limit(0); | ||||
|  | ||||
|         $this->journals = new Collection; | ||||
|         $this->map      = $this->data->getMap(); | ||||
|         $this->roles    = $this->data->getRoles(); | ||||
|         $this->mapped   = $this->data->getMapped(); | ||||
|         $this->specifix = $this->data->getSpecifix(); | ||||
|  | ||||
|         foreach ($this->data->getReader() as $index => $row) { | ||||
|             if ($this->parseRow($index)) { | ||||
|                 Log::debug('--- Importing row ' . $index); | ||||
|                 $this->rows++; | ||||
|                 $result = $this->importRow($row); | ||||
|                 if (!($result instanceof TransactionJournal)) { | ||||
|                     Log::error('Caught error at row #' . $index . ': ' . $result); | ||||
|                     $this->errors[$index] = $result; | ||||
|                 } else { | ||||
|                     $this->imported++; | ||||
|                     $this->journals->push($result); | ||||
|                 } | ||||
|                 Log::debug('---'); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param int $index | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     protected function parseRow($index) | ||||
|     { | ||||
|         return (($this->data->hasHeaders() && $index >= 1) || !$this->data->hasHeaders()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $row | ||||
|      * | ||||
|      * @throws FireflyException | ||||
|      * @return string|bool | ||||
|      */ | ||||
|     protected function importRow($row) | ||||
|     { | ||||
|  | ||||
|         $data = $this->getFiller(); // These fields are necessary to create a new transaction journal. Some are optional | ||||
|         foreach ($row as $index => $value) { | ||||
|             $role  = isset($this->roles[$index]) ? $this->roles[$index] : '_ignore'; | ||||
|             $class = Config::get('csv.roles.' . $role . '.converter'); | ||||
|             $field = Config::get('csv.roles.' . $role . '.field'); | ||||
|  | ||||
|             Log::debug('Column #' . $index . ' (role: ' . $role . ') : converter ' . $class . ' stores its data into field ' . $field . ':'); | ||||
|  | ||||
|             /** @var ConverterInterface $converter */ | ||||
|             $converter = app('FireflyIII\Helpers\Csv\Converter\\' . $class); | ||||
|             $converter->setData($data); // the complete array so far. | ||||
|             $converter->setField($field); | ||||
|             $converter->setIndex($index); | ||||
|             $converter->setMapped($this->mapped); | ||||
|             $converter->setValue($value); | ||||
|             $converter->setRole($role); | ||||
|             $data[$field] = $converter->convert(); | ||||
|         } | ||||
|         // move to class vars. | ||||
|         $this->importData = $data; | ||||
|         $this->importRow  = $row; | ||||
|         unset($data, $row); | ||||
|         // post processing and validating. | ||||
|         $this->postProcess(); | ||||
|         $result = $this->validateData(); | ||||
|  | ||||
|         if (!($result === true)) { | ||||
|             return $result; // return error. | ||||
|         } | ||||
|         $journal = $this->createTransactionJournal(); | ||||
|  | ||||
|         return $journal; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function getFiller() | ||||
|     { | ||||
|         $filler = []; | ||||
|         foreach (Config::get('csv.roles') as $role) { | ||||
|             if (isset($role['field'])) { | ||||
|                 $fieldName          = $role['field']; | ||||
|                 $filler[$fieldName] = null; | ||||
|             } | ||||
|         } | ||||
|         // some extra's: | ||||
|         $filler['bill-id']                 = null; | ||||
|         $filler['opposing-account-object'] = null; | ||||
|         $filler['asset-account-object']    = null; | ||||
|         $filler['amount-modifier']         = '1'; | ||||
|  | ||||
|         return $filler; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Row denotes the original data. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     protected function postProcess() | ||||
|     { | ||||
|         // do bank specific fixes (must be enabled but now all of them. | ||||
|  | ||||
|         foreach ($this->getSpecifix() as $className) { | ||||
|             /** @var SpecifixInterface $specifix */ | ||||
|             $specifix = app('FireflyIII\Helpers\Csv\Specifix\\' . $className); | ||||
|             $specifix->setData($this->importData); | ||||
|             $specifix->setRow($this->importRow); | ||||
|             Log::debug('Now post-process specifix named ' . $className . ':'); | ||||
|             $this->importData = $specifix->fix(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $set = Config::get('csv.post_processors'); | ||||
|         foreach ($set as $className) { | ||||
|             /** @var PostProcessorInterface $postProcessor */ | ||||
|             $postProcessor = app('FireflyIII\Helpers\Csv\PostProcessing\\' . $className); | ||||
|             $postProcessor->setData($this->importData); | ||||
|             Log::debug('Now post-process processor named ' . $className . ':'); | ||||
|             $this->importData = $postProcessor->process(); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getSpecifix() | ||||
|     { | ||||
|         return is_array($this->specifix) ? $this->specifix : []; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @return bool|string | ||||
|      */ | ||||
|     protected function validateData() | ||||
|     { | ||||
|         if (is_null($this->importData['date']) && is_null($this->importData['date-rent'])) { | ||||
|             return 'No date value for this row.'; | ||||
|         } | ||||
|         if (is_null($this->importData['opposing-account-object'])) { | ||||
|             return 'Opposing account is null'; | ||||
|         } | ||||
|  | ||||
|         if (!($this->importData['asset-account-object'] instanceof Account)) { | ||||
|             return 'No asset account to import into.'; | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @return TransactionJournal|string | ||||
|      */ | ||||
|     protected function createTransactionJournal() | ||||
|     { | ||||
|         bcscale(2); | ||||
|         $date = $this->importData['date']; | ||||
|         if (is_null($this->importData['date'])) { | ||||
|             $date = $this->importData['date-rent']; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $transactionType = $this->getTransactionType(); // defaults to deposit | ||||
|         $errors          = new MessageBag; | ||||
|         $journal         = TransactionJournal::create( | ||||
|             ['user_id'     => Auth::user()->id, 'transaction_type_id' => $transactionType->id, 'transaction_currency_id' => $this->importData['currency']->id, | ||||
|              'description' => $this->importData['description'], 'completed' => 0, 'date' => $date, 'bill_id' => $this->importData['bill-id'],] | ||||
|         ); | ||||
|         if ($journal->getErrors()->count() == 0) { | ||||
|             // first transaction | ||||
|             $accountId   = $this->importData['asset-account-object']->id; // create first transaction: | ||||
|             $amount      = $this->importData['amount']; | ||||
|             $transaction = Transaction::create(['transaction_journal_id' => $journal->id, 'account_id' => $accountId, 'amount' => $amount]); | ||||
|             $errors      = $transaction->getErrors(); | ||||
|  | ||||
|             // second transaction | ||||
|             $accountId   = $this->importData['opposing-account-object']->id; // create second transaction: | ||||
|             $amount      = bcmul($this->importData['amount'], -1); | ||||
|             $transaction = Transaction::create(['transaction_journal_id' => $journal->id, 'account_id' => $accountId, 'amount' => $amount]); | ||||
|             $errors      = $transaction->getErrors()->merge($errors); | ||||
|         } | ||||
|         if ($errors->count() == 0) { | ||||
|             $journal->completed = 1; | ||||
|             $journal->save(); | ||||
|         } else { | ||||
|             $text = join(',', $errors->all()); | ||||
|  | ||||
|             return $text; | ||||
|         } | ||||
|         $this->saveBudget($journal); | ||||
|         $this->saveCategory($journal); | ||||
|         $this->saveTags($journal); | ||||
|  | ||||
|         // some debug info: | ||||
|         $journalId = $journal->id; | ||||
|         $type      = $journal->transactionType->type; | ||||
|         /** @var Account $asset */ | ||||
|         $asset = $this->importData['asset-account-object']; | ||||
|         /** @var Account $opposing */ | ||||
|         $opposing = $this->importData['opposing-account-object']; | ||||
|  | ||||
|         Log::info('Created journal #' . $journalId . ' of type ' . $type . '!'); | ||||
|         Log::info('Asset account ****** (#' . $asset->id . ') lost/gained: ' . $this->importData['amount']); | ||||
|         Log::info($opposing->accountType->type . ' ****** (#' . $opposing->id . ') lost/gained: ' . bcmul($this->importData['amount'], -1)); | ||||
|  | ||||
|         return $journal; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return TransactionType | ||||
|      */ | ||||
|     protected function getTransactionType() | ||||
|     { | ||||
|         $transactionType = TransactionType::where('type', 'Deposit')->first(); | ||||
|         if ($this->importData['amount'] < 0) { | ||||
|             $transactionType = TransactionType::where('type', 'Withdrawal')->first(); | ||||
|         } | ||||
|  | ||||
|         if (in_array($this->importData['opposing-account-object']->accountType->type, ['Asset account', 'Default account'])) { | ||||
|             $transactionType = TransactionType::where('type', 'Transfer')->first(); | ||||
|         } | ||||
|  | ||||
|         return $transactionType; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $journal | ||||
|      */ | ||||
|     protected function saveBudget(TransactionJournal $journal) | ||||
|     { | ||||
|         // add budget: | ||||
|         if (!is_null($this->importData['budget'])) { | ||||
|             $journal->budgets()->save($this->importData['budget']); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $journal | ||||
|      */ | ||||
|     protected function saveCategory(TransactionJournal $journal) | ||||
|     { | ||||
|         // add category: | ||||
|         if (!is_null($this->importData['category'])) { | ||||
|             $journal->categories()->save($this->importData['category']); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $journal | ||||
|      */ | ||||
|     protected function saveTags(TransactionJournal $journal) | ||||
|     { | ||||
|         if (!is_null($this->importData['tags'])) { | ||||
|             foreach ($this->importData['tags'] as $tag) { | ||||
|                 $journal->tags()->save($tag); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Data $data | ||||
|      */ | ||||
|     public function setData($data) | ||||
|     { | ||||
|         $this->data = $data; | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										34
									
								
								app/Helpers/Csv/Mapper/AnyAccount.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								app/Helpers/Csv/Mapper/AnyAccount.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Mapper; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Account; | ||||
|  | ||||
| /** | ||||
|  * Class AnyAccount | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Mapper | ||||
|  */ | ||||
| class AnyAccount implements MapperInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMap() | ||||
|     { | ||||
|         $result = Auth::user()->accounts()->with('accountType')->orderBy('accounts.name', 'ASC')->get(['accounts.*']); | ||||
|  | ||||
|         $list = []; | ||||
|         /** @var Account $account */ | ||||
|         foreach ($result as $account) { | ||||
|             $list[$account->id] = $account->name . ' (' . $account->accountType->type . ')'; | ||||
|         } | ||||
|         asort($list); | ||||
|  | ||||
|         $list = [0 => trans('firefly.csv_do_not_map')] + $list; | ||||
|  | ||||
|         return $list; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										45
									
								
								app/Helpers/Csv/Mapper/AssetAccount.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								app/Helpers/Csv/Mapper/AssetAccount.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Mapper; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Account; | ||||
| use Illuminate\Database\Eloquent\Relations\HasMany; | ||||
|  | ||||
| /** | ||||
|  * Class AssetAccount | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Mapper | ||||
|  */ | ||||
| class AssetAccount implements MapperInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMap() | ||||
|     { | ||||
|         $result = Auth::user()->accounts()->with( | ||||
|             ['accountmeta' => function (HasMany $query) { | ||||
|                 $query->where('name', 'accountRole'); | ||||
|             }] | ||||
|         )->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->get(['accounts.*']); | ||||
|  | ||||
|         $list = []; | ||||
|  | ||||
|         /** @var Account $account */ | ||||
|         foreach ($result as $account) { | ||||
|             $name = $account->name; | ||||
|             if (strlen($account->iban) > 0) { | ||||
|                 $name .= ' (' . $account->iban . ')'; | ||||
|             } | ||||
|             $list[$account->id] = $name; | ||||
|         } | ||||
|  | ||||
|         asort($list); | ||||
|  | ||||
|         $list = [0 => trans('firefly.csv_do_not_map')] + $list; | ||||
|  | ||||
|         return $list; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										34
									
								
								app/Helpers/Csv/Mapper/Bill.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								app/Helpers/Csv/Mapper/Bill.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Mapper; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Bill as BillModel; | ||||
|  | ||||
| /** | ||||
|  * Class Bill | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Mapper | ||||
|  */ | ||||
| class Bill implements MapperInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMap() | ||||
|     { | ||||
|         $result = Auth::user()->bills()->get(['bills.*']); | ||||
|         $list   = []; | ||||
|  | ||||
|         /** @var BillModel $bill */ | ||||
|         foreach ($result as $bill) { | ||||
|             $list[$bill->id] = $bill->name . ' [' . $bill->match . ']'; | ||||
|         } | ||||
|         asort($list); | ||||
|  | ||||
|         $list = [0 => trans('firefly.csv_do_not_map')] + $list; | ||||
|  | ||||
|         return $list; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										34
									
								
								app/Helpers/Csv/Mapper/Budget.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								app/Helpers/Csv/Mapper/Budget.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Mapper; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Budget as BudgetModel; | ||||
|  | ||||
| /** | ||||
|  * Class Budget | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Mapper | ||||
|  */ | ||||
| class Budget implements MapperInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMap() | ||||
|     { | ||||
|         $result = Auth::user()->budgets()->get(['budgets.*']); | ||||
|         $list   = []; | ||||
|  | ||||
|         /** @var BudgetModel $budget */ | ||||
|         foreach ($result as $budget) { | ||||
|             $list[$budget->id] = $budget->name; | ||||
|         } | ||||
|         asort($list); | ||||
|  | ||||
|         $list = [0 => trans('firefly.csv_do_not_map')] + $list; | ||||
|  | ||||
|         return $list; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										34
									
								
								app/Helpers/Csv/Mapper/Category.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								app/Helpers/Csv/Mapper/Category.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Mapper; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Category as CategoryModel; | ||||
|  | ||||
| /** | ||||
|  * Class Category | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Mapper | ||||
|  */ | ||||
| class Category implements MapperInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMap() | ||||
|     { | ||||
|         $result = Auth::user()->categories()->get(['categories.*']); | ||||
|         $list   = []; | ||||
|  | ||||
|         /** @var CategoryModel $category */ | ||||
|         foreach ($result as $category) { | ||||
|             $list[$category->id] = $category->name; | ||||
|         } | ||||
|         asort($list); | ||||
|  | ||||
|         $list = [0 => trans('firefly.csv_do_not_map')] + $list; | ||||
|  | ||||
|         return $list; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										16
									
								
								app/Helpers/Csv/Mapper/MapperInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								app/Helpers/Csv/Mapper/MapperInterface.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Mapper; | ||||
|  | ||||
| /** | ||||
|  * Interface MapperInterface | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Mapper | ||||
|  */ | ||||
| interface MapperInterface | ||||
| { | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMap(); | ||||
| } | ||||
							
								
								
									
										34
									
								
								app/Helpers/Csv/Mapper/Tag.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								app/Helpers/Csv/Mapper/Tag.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Mapper; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Tag as TagModel; | ||||
|  | ||||
| /** | ||||
|  * Class Tag | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Mapper | ||||
|  */ | ||||
| class Tag implements MapperInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMap() | ||||
|     { | ||||
|         $result = Auth::user()->budgets()->get(['tags.*']); | ||||
|         $list   = []; | ||||
|  | ||||
|         /** @var TagModel $tag */ | ||||
|         foreach ($result as $tag) { | ||||
|             $list[$tag->id] = $tag->tag; | ||||
|         } | ||||
|         asort($list); | ||||
|  | ||||
|         $list = [0 => trans('firefly.csv_do_not_map')] + $list; | ||||
|  | ||||
|         return $list; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										32
									
								
								app/Helpers/Csv/Mapper/TransactionCurrency.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								app/Helpers/Csv/Mapper/TransactionCurrency.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Mapper; | ||||
|  | ||||
| use FireflyIII\Models\TransactionCurrency as TC; | ||||
|  | ||||
| /** | ||||
|  * Class TransactionCurrency | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Mapper | ||||
|  */ | ||||
| class TransactionCurrency implements MapperInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMap() | ||||
|     { | ||||
|         $currencies = TC::get(); | ||||
|         $list       = []; | ||||
|         foreach ($currencies as $currency) { | ||||
|             $list[$currency->id] = $currency->name . ' (' . $currency->code . ')'; | ||||
|         } | ||||
|  | ||||
|         asort($list); | ||||
|  | ||||
|         $list = [0 => trans('firefly.csv_do_not_map')] + $list; | ||||
|  | ||||
|         return $list; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										35
									
								
								app/Helpers/Csv/PostProcessing/Amount.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								app/Helpers/Csv/PostProcessing/Amount.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| <?php | ||||
|  | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\PostProcessing; | ||||
|  | ||||
| /** | ||||
|  * Class Amount | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\PostProcessing | ||||
|  */ | ||||
| class Amount implements PostProcessorInterface | ||||
| { | ||||
|  | ||||
|     /** @var  array */ | ||||
|     protected $data; | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function process() | ||||
|     { | ||||
|         bcscale(2); | ||||
|         $this->data['amount'] = bcmul($this->data['amount'], $this->data['amount-modifier']); | ||||
|  | ||||
|         return $this->data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData(array $data) | ||||
|     { | ||||
|         $this->data = $data; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										185
									
								
								app/Helpers/Csv/PostProcessing/AssetAccount.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								app/Helpers/Csv/PostProcessing/AssetAccount.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,185 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\PostProcessing; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use Log; | ||||
| use Validator; | ||||
|  | ||||
| /** | ||||
|  * Class AssetAccount | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\PostProcessing | ||||
|  */ | ||||
| class AssetAccount implements PostProcessorInterface | ||||
| { | ||||
|  | ||||
|     /** @var  array */ | ||||
|     protected $data; | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function process() | ||||
|     { | ||||
|         $result = $this->checkIdNameObject(); // has object in ID or Name? | ||||
|         if (!is_null($result)) { | ||||
|             return $result; | ||||
|         } | ||||
|  | ||||
|         $result = $this->checkIbanString(); | ||||
|         if (!is_null($result)) { | ||||
|             return $result; | ||||
|         } | ||||
|  | ||||
|         $result = $this->checkNameString(); | ||||
|         if (!is_null($result)) { | ||||
|             return $result; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData(array $data) | ||||
|     { | ||||
|         $this->data = $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function checkIdNameObject() | ||||
|     { | ||||
|         if ($this->data['asset-account-id'] instanceof Account) { // first priority. try to find the account based on ID, if any | ||||
|             $this->data['asset-account-object'] = $this->data['asset-account-id']; | ||||
|  | ||||
|             return $this->data; | ||||
|         } | ||||
|         if ($this->data['asset-account-iban'] instanceof Account) { // second: try to find the account based on IBAN, if any. | ||||
|             $this->data['asset-account-object'] = $this->data['asset-account-iban']; | ||||
|  | ||||
|             return $this->data; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array|null | ||||
|      */ | ||||
|     protected function checkIbanString() | ||||
|     { | ||||
|         $rules     = ['iban' => 'iban']; | ||||
|         $check     = ['iban' => $this->data['asset-account-iban']]; | ||||
|         $validator = Validator::make($check, $rules); | ||||
|         if (!$validator->fails()) { | ||||
|             $this->data['asset-account-object'] = $this->parseIbanString(); | ||||
|  | ||||
|             return $this->data; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     protected function parseIbanString() | ||||
|     { | ||||
|         // create by name and/or iban. | ||||
|         $accounts = Auth::user()->accounts()->get(); | ||||
|         foreach ($accounts as $entry) { | ||||
|             if ($entry->iban == $this->data['asset-account-iban']) { | ||||
|  | ||||
|                 return $entry; | ||||
|             } | ||||
|         } | ||||
|         $account = $this->createAccount(); | ||||
|  | ||||
|         return $account; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     protected function createAccount() | ||||
|     { | ||||
|         $accountType = $this->getAccountType(); | ||||
|  | ||||
|         // create if not exists: | ||||
|         $name    = is_string($this->data['asset-account-name']) && strlen($this->data['asset-account-name']) > 0 ? $this->data['asset-account-name'] | ||||
|             : $this->data['asset-account-iban']; | ||||
|         $account = Account::firstOrCreateEncrypted( | ||||
|             [ | ||||
|                 'user_id'         => Auth::user()->id, | ||||
|                 'account_type_id' => $accountType->id, | ||||
|                 'name'            => $name, | ||||
|                 'iban'            => $this->data['asset-account-iban'], | ||||
|                 'active'          => true, | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|         return $account; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @return AccountType | ||||
|      */ | ||||
|     protected function getAccountType() | ||||
|     { | ||||
|         return AccountType::where('type', 'Asset account')->first(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array|null | ||||
|      */ | ||||
|     protected function checkNameString() | ||||
|     { | ||||
|         if ($this->data['asset-account-name'] instanceof Account) { // third: try to find account based on name, if any. | ||||
|             $this->data['asset-account-object'] = $this->data['asset-account-name']; | ||||
|  | ||||
|             return $this->data; | ||||
|         } | ||||
|         if (is_string($this->data['asset-account-name'])) { | ||||
|             $this->data['asset-account-object'] = $this->parseNameString(); | ||||
|  | ||||
|             return $this->data; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     protected function parseNameString() | ||||
|     { | ||||
|         $accountType = $this->getAccountType(); | ||||
|         $accounts    = Auth::user()->accounts()->where('account_type_id', $accountType->id)->get(); | ||||
|         foreach ($accounts as $entry) { | ||||
|             if ($entry->name == $this->data['asset-account-name']) { | ||||
|                 Log::debug('Found an asset account with this name (#' . $entry->id . ': ******)'); | ||||
|  | ||||
|                 return $entry; | ||||
|             } | ||||
|         } | ||||
|         // create if not exists: | ||||
|         $account = Account::firstOrCreateEncrypted( | ||||
|             [ | ||||
|                 'user_id'         => Auth::user()->id, | ||||
|                 'account_type_id' => $accountType->id, | ||||
|                 'name'            => $this->data['asset-account-name'], | ||||
|                 'iban'            => '', | ||||
|                 'active'          => true, | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|         return $account; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										37
									
								
								app/Helpers/Csv/PostProcessing/Bill.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								app/Helpers/Csv/PostProcessing/Bill.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\PostProcessing; | ||||
|  | ||||
| /** | ||||
|  * Class Bill | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\PostProcessing | ||||
|  */ | ||||
| class Bill implements PostProcessorInterface | ||||
| { | ||||
|  | ||||
|     /** @var  array */ | ||||
|     protected $data; | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function process() | ||||
|     { | ||||
|  | ||||
|         // get bill id. | ||||
|         if (!is_null($this->data['bill'])) { | ||||
|             $this->data['bill-id'] = $this->data['bill']->id; | ||||
|         } | ||||
|  | ||||
|         return $this->data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData(array $data) | ||||
|     { | ||||
|         $this->data = $data; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										41
									
								
								app/Helpers/Csv/PostProcessing/Currency.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								app/Helpers/Csv/PostProcessing/Currency.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\PostProcessing; | ||||
|  | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use Preferences; | ||||
|  | ||||
| /** | ||||
|  * Class Currency | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\PostProcessing | ||||
|  */ | ||||
| class Currency implements PostProcessorInterface | ||||
| { | ||||
|  | ||||
|     /** @var  array */ | ||||
|     protected $data; | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function process() | ||||
|     { | ||||
|  | ||||
|         // fix currency | ||||
|         if (is_null($this->data['currency'])) { | ||||
|             $currencyPreference     = Preferences::get('currencyPreference', 'EUR'); | ||||
|             $this->data['currency'] = TransactionCurrency::whereCode($currencyPreference->data)->first(); | ||||
|         } | ||||
|  | ||||
|         return $this->data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData(array $data) | ||||
|     { | ||||
|         $this->data = $data; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										38
									
								
								app/Helpers/Csv/PostProcessing/Description.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								app/Helpers/Csv/PostProcessing/Description.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\PostProcessing; | ||||
|  | ||||
| /** | ||||
|  * Class Description | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\PostProcessing | ||||
|  */ | ||||
| class Description implements PostProcessorInterface | ||||
| { | ||||
|  | ||||
|     /** @var  array */ | ||||
|     protected $data; | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function process() | ||||
|     { | ||||
|         $this->data['description'] = trim($this->data['description']); | ||||
|         if (strlen($this->data['description']) == 0) { | ||||
|             $this->data['description'] = trans('firefly.csv_empty_description'); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         return $this->data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData(array $data) | ||||
|     { | ||||
|  | ||||
|         $this->data = $data; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										210
									
								
								app/Helpers/Csv/PostProcessing/OpposingAccount.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								app/Helpers/Csv/PostProcessing/OpposingAccount.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,210 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\PostProcessing; | ||||
|  | ||||
| use Auth; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use Log; | ||||
| use Validator; | ||||
|  | ||||
| /** | ||||
|  * Class OpposingAccount | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\PostProcessing | ||||
|  */ | ||||
| class OpposingAccount implements PostProcessorInterface | ||||
| { | ||||
|  | ||||
|     /** @var  array */ | ||||
|     protected $data; | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function process() | ||||
|     { | ||||
|         // three values: | ||||
|         // opposing-account-id, opposing-account-iban, opposing-account-name | ||||
|  | ||||
|  | ||||
|         $result = $this->checkIdNameObject(); | ||||
|         if (!is_null($result)) { | ||||
|             return $result; | ||||
|         } | ||||
|  | ||||
|         $result = $this->checkIbanString(); | ||||
|         if (!is_null($result)) { | ||||
|             return $result; | ||||
|         } | ||||
|  | ||||
|         $result = $this->checkNameString(); | ||||
|         if (!is_null($result)) { | ||||
|             return $result; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData(array $data) | ||||
|     { | ||||
|         $this->data = $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function checkIdNameObject() | ||||
|     { | ||||
|         if ($this->data['opposing-account-id'] instanceof Account) { // first priority. try to find the account based on ID, if any | ||||
|             Log::debug('OpposingAccountPostProcession: opposing-account-id is an Account.'); | ||||
|             $this->data['opposing-account-object'] = $this->data['opposing-account-id']; | ||||
|  | ||||
|             return $this->data; | ||||
|         } | ||||
|         if ($this->data['opposing-account-iban'] instanceof Account) { // second: try to find the account based on IBAN, if any. | ||||
|             Log::debug('OpposingAccountPostProcession: opposing-account-iban is an Account.'); | ||||
|             $this->data['opposing-account-object'] = $this->data['opposing-account-iban']; | ||||
|  | ||||
|             return $this->data; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array|null | ||||
|      */ | ||||
|     protected function checkIbanString() | ||||
|     { | ||||
|         $rules     = ['iban' => 'iban']; | ||||
|         $iban      = $this->data['opposing-account-iban']; | ||||
|         $check     = ['iban' => $iban]; | ||||
|         $validator = Validator::make($check, $rules); | ||||
|         if (is_string($iban) && strlen($iban) > 0 && !$validator->fails()) { | ||||
|  | ||||
|             Log::debug('OpposingAccountPostProcession: opposing-account-iban is a string (******).'); | ||||
|             $this->data['opposing-account-object'] = $this->parseIbanString(); | ||||
|  | ||||
|             return $this->data; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     protected function parseIbanString() | ||||
|     { | ||||
|         // create by name and/or iban. | ||||
|         $accounts = Auth::user()->accounts()->get(); | ||||
|         foreach ($accounts as $entry) { | ||||
|             if ($entry->iban == $this->data['opposing-account-iban']) { | ||||
|                 Log::debug('OpposingAccountPostProcession: opposing-account-iban matches an Account.'); | ||||
|  | ||||
|                 return $entry; | ||||
|             } | ||||
|         } | ||||
|         $account = $this->createAccount(); | ||||
|  | ||||
|  | ||||
|         return $account; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     protected function createAccount() | ||||
|     { | ||||
|         $accountType = $this->getAccountType(); | ||||
|  | ||||
|         // create if not exists: | ||||
|         $name    = is_string($this->data['opposing-account-name']) && strlen($this->data['opposing-account-name']) > 0 ? $this->data['opposing-account-name'] | ||||
|             : $this->data['opposing-account-iban']; | ||||
|         $account = Account::firstOrCreateEncrypted( | ||||
|             [ | ||||
|                 'user_id'         => Auth::user()->id, | ||||
|                 'account_type_id' => $accountType->id, | ||||
|                 'name'            => $name, | ||||
|                 'iban'            => $this->data['opposing-account-iban'], | ||||
|                 'active'          => true, | ||||
|             ] | ||||
|         ); | ||||
|         Log::debug('OpposingAccountPostProcession: created a new account.'); | ||||
|  | ||||
|         return $account; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @return AccountType | ||||
|      */ | ||||
|     protected function getAccountType() | ||||
|     { | ||||
|         // opposing account type: | ||||
|         if ($this->data['amount'] < 0) { | ||||
|             // create expense account: | ||||
|  | ||||
|             return AccountType::where('type', 'Expense account')->first(); | ||||
|         } else { | ||||
|             // create revenue account: | ||||
|  | ||||
|             return AccountType::where('type', 'Revenue account')->first(); | ||||
|  | ||||
|  | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array|null | ||||
|      */ | ||||
|     protected function checkNameString() | ||||
|     { | ||||
|         if ($this->data['opposing-account-name'] instanceof Account) { // third: try to find account based on name, if any. | ||||
|             Log::debug('OpposingAccountPostProcession: opposing-account-name is an Account.'); | ||||
|             $this->data['opposing-account-object'] = $this->data['opposing-account-name']; | ||||
|  | ||||
|             return $this->data; | ||||
|         } | ||||
|         if (is_string($this->data['opposing-account-name'])) { | ||||
|  | ||||
|             $this->data['opposing-account-object'] = $this->parseNameString(); | ||||
|  | ||||
|             return $this->data; | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Account|null | ||||
|      */ | ||||
|     protected function parseNameString() | ||||
|     { | ||||
|         $accountType = $this->getAccountType(); | ||||
|         $accounts    = Auth::user()->accounts()->where('account_type_id', $accountType->id)->get(); | ||||
|         foreach ($accounts as $entry) { | ||||
|             if ($entry->name == $this->data['opposing-account-name']) { | ||||
|                 Log::debug('Found an account with this name (#' . $entry->id . ': ******)'); | ||||
|  | ||||
|                 return $entry; | ||||
|             } | ||||
|         } | ||||
|         // create if not exists: | ||||
|         $account = Account::firstOrCreateEncrypted( | ||||
|             [ | ||||
|                 'user_id'         => Auth::user()->id, | ||||
|                 'account_type_id' => $accountType->id, | ||||
|                 'name'            => $this->data['opposing-account-name'], | ||||
|                 'iban'            => '', | ||||
|                 'active'          => true, | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|         return $account; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										29
									
								
								app/Helpers/Csv/PostProcessing/PostProcessorInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								app/Helpers/Csv/PostProcessing/PostProcessorInterface.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Created by PhpStorm. | ||||
|  * User: sander | ||||
|  * Date: 05/07/15 | ||||
|  * Time: 19:20 | ||||
|  */ | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\PostProcessing; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Interface PostProcessorInterface | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\PostProcessing | ||||
|  */ | ||||
| interface PostProcessorInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function process(); | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData(array $data); | ||||
| } | ||||
							
								
								
									
										45
									
								
								app/Helpers/Csv/Specifix/Dummy.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								app/Helpers/Csv/Specifix/Dummy.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Specifix; | ||||
|  | ||||
| /** | ||||
|  * Class Dummy | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Specifix | ||||
|  */ | ||||
| class Dummy | ||||
| { | ||||
|     /** @var array */ | ||||
|     protected $data; | ||||
|  | ||||
|     /** @var array */ | ||||
|     protected $row; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function fix() | ||||
|     { | ||||
|         return $this->data; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData($data) | ||||
|     { | ||||
|         $this->data = $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $row | ||||
|      */ | ||||
|     public function setRow($row) | ||||
|     { | ||||
|         $this->row = $row; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										66
									
								
								app/Helpers/Csv/Specifix/RabobankDescription.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								app/Helpers/Csv/Specifix/RabobankDescription.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv\Specifix; | ||||
|  | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class RabobankDescription | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Specifix | ||||
|  */ | ||||
| class RabobankDescription | ||||
| { | ||||
|     /** @var array */ | ||||
|     protected $data; | ||||
|  | ||||
|     /** @var array */ | ||||
|     protected $row; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function fix() | ||||
|     { | ||||
|         $this->rabobankFixEmptyOpposing(); | ||||
|  | ||||
|         return $this->data; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Fixes Rabobank specific thing. | ||||
|      */ | ||||
|     protected function rabobankFixEmptyOpposing() | ||||
|     { | ||||
|         Log::debug('RaboSpecifix: Opposing account name is "******".'); | ||||
|         if (is_string($this->data['opposing-account-name']) && strlen($this->data['opposing-account-name']) == 0) { | ||||
|             Log::debug('RaboSpecifix: opp-name is zero length, changed to: "******"'); | ||||
|             $this->data['opposing-account-name'] = $this->row[10]; | ||||
|  | ||||
|             Log::debug('Description was: "******".'); | ||||
|             $this->data['description'] = trim(str_replace($this->row[10], '', $this->data['description'])); | ||||
|             Log::debug('Description is now: "******".'); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData($data) | ||||
|     { | ||||
|         $this->data = $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $row | ||||
|      */ | ||||
|     public function setRow($row) | ||||
|     { | ||||
|         $this->row = $row; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										25
									
								
								app/Helpers/Csv/Specifix/SpecifixInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								app/Helpers/Csv/Specifix/SpecifixInterface.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| <?php | ||||
| namespace FireflyIII\Helpers\Csv\Specifix; | ||||
|  | ||||
| /** | ||||
|  * Interface SpecifixInterface | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv\Specifix | ||||
|  */ | ||||
| interface SpecifixInterface | ||||
| { | ||||
|     /** | ||||
|      * Implement bank and locale related fixes. | ||||
|      */ | ||||
|     public function fix(); | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      */ | ||||
|     public function setData($data); | ||||
|  | ||||
|     /** | ||||
|      * @param array $row | ||||
|      */ | ||||
|     public function setRow($row); | ||||
| } | ||||
							
								
								
									
										194
									
								
								app/Helpers/Csv/Wizard.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								app/Helpers/Csv/Wizard.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,194 @@ | ||||
| <?php | ||||
| namespace FireflyIII\Helpers\Csv; | ||||
|  | ||||
| use Auth; | ||||
| use Config; | ||||
| use Crypt; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Csv\Mapper\MapperInterface; | ||||
| use League\Csv\Reader; | ||||
| use Log; | ||||
| use ReflectionException; | ||||
| use Session; | ||||
|  | ||||
| /** | ||||
|  * Class Wizard | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv | ||||
|  */ | ||||
| class Wizard implements WizardInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Reader $reader | ||||
|      * @param array  $map | ||||
|      * @param bool   $hasHeaders | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMappableValues($reader, array $map, $hasHeaders) | ||||
|     { | ||||
|         $values = []; | ||||
|         /* | ||||
|          * Loop over the CSV and collect mappable data: | ||||
|          */ | ||||
|         $keys = array_keys($map); | ||||
|         foreach ($reader as $index => $row) { | ||||
|             if ($this->useRow($hasHeaders, $index)) { | ||||
|                 // collect all map values | ||||
|  | ||||
|                 foreach ($keys as $column) { | ||||
|                     $values[$column][] = $row[$column]; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         /* | ||||
|          * Make each one unique. | ||||
|          */ | ||||
|         $values = $this->uniqueRecursive($values); | ||||
|  | ||||
|         return $values; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $roles | ||||
|      * @param mixed $map | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function processSelectedMapping(array $roles, $map) | ||||
|     { | ||||
|         $configRoles = Config::get('csv.roles'); | ||||
|         $maps        = []; | ||||
|  | ||||
|  | ||||
|         if (is_array($map)) { | ||||
|             foreach ($map as $index => $field) { | ||||
|                 if (isset($roles[$index])) { | ||||
|                     $name = $roles[$index]; | ||||
|                     if ($configRoles[$name]['mappable']) { | ||||
|                         $maps[$index] = $name; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $maps; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param mixed $input | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function processSelectedRoles($input) | ||||
|     { | ||||
|         $roles = []; | ||||
|  | ||||
|  | ||||
|         /* | ||||
|          * Store all rows for each column: | ||||
|          */ | ||||
|         if (is_array($input)) { | ||||
|             foreach ($input as $index => $role) { | ||||
|                 if ($role != '_ignore') { | ||||
|                     $roles[$index] = $role; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $roles; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $fields | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function sessionHasValues(array $fields) | ||||
|     { | ||||
|         foreach ($fields as $field) { | ||||
|             if (!Session::has($field)) { | ||||
|                 Log::error('Session is missing field: ' . $field); | ||||
|  | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $map | ||||
|      * | ||||
|      * @return array | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function showOptions(array $map) | ||||
|     { | ||||
|         $options = []; | ||||
|         foreach ($map as $index => $columnRole) { | ||||
|  | ||||
|             $mapper = Config::get('csv.roles.' . $columnRole . '.mapper'); | ||||
|             if (is_null($mapper)) { | ||||
|                 throw new FireflyException('Cannot map field of type "' . $columnRole . '".'); | ||||
|             } | ||||
|             $class = 'FireflyIII\Helpers\Csv\Mapper\\' . $mapper; | ||||
|             try { | ||||
|                 /** @var MapperInterface $mapObject */ | ||||
|                 $mapObject = app($class); | ||||
|             } catch (ReflectionException $e) { | ||||
|                 throw new FireflyException('Column "' . $columnRole . '" cannot be mapped because class ' . $mapper . ' does not exist.'); | ||||
|             } | ||||
|             $set             = $mapObject->getMap(); | ||||
|             $options[$index] = $set; | ||||
|         } | ||||
|  | ||||
|         return $options; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $path | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function storeCsvFile($path) | ||||
|     { | ||||
|         $time             = str_replace(' ', '-', microtime()); | ||||
|         $fileName         = 'csv-upload-' . Auth::user()->id . '-' . $time . '.csv.encrypted'; | ||||
|         $fullPath         = storage_path('upload') . DIRECTORY_SEPARATOR . $fileName; | ||||
|         $content          = file_get_contents($path); | ||||
|         $contentEncrypted = Crypt::encrypt($content); | ||||
|         file_put_contents($fullPath, $contentEncrypted); | ||||
|  | ||||
|         return $fullPath; | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param bool $hasHeaders | ||||
|      * @param int  $index | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     protected function useRow($hasHeaders, $index) | ||||
|     { | ||||
|         return ($hasHeaders && $index > 1) || !$hasHeaders; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $array | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function uniqueRecursive(array $array) | ||||
|     { | ||||
|         foreach ($array as $column => $found) { | ||||
|             $array[$column] = array_unique($found); | ||||
|         } | ||||
|  | ||||
|         return $array; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										59
									
								
								app/Helpers/Csv/WizardInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								app/Helpers/Csv/WizardInterface.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Csv; | ||||
|  | ||||
| use League\Csv\Reader; | ||||
|  | ||||
| /** | ||||
|  * Interface WizardInterface | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Csv | ||||
|  */ | ||||
| interface WizardInterface | ||||
| { | ||||
|     /** | ||||
|      * @param Reader $reader | ||||
|      * @param array  $map | ||||
|      * @param bool   $hasHeaders | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getMappableValues($reader, array $map, $hasHeaders); | ||||
|  | ||||
|     /** | ||||
|      * @param array $roles | ||||
|      * @param mixed $map | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function processSelectedMapping(array $roles, $map); | ||||
|  | ||||
|     /** | ||||
|      * @param mixed $input | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function processSelectedRoles($input); | ||||
|  | ||||
|     /** | ||||
|      * @param array $fields | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function sessionHasValues(array $fields); | ||||
|  | ||||
|     /** | ||||
|      * @param array $map | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function showOptions(array $map); | ||||
|  | ||||
|     /** | ||||
|      * @param $path | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function storeCsvFile($path); | ||||
|  | ||||
| } | ||||
| @@ -37,10 +37,12 @@ class Help implements HelpInterface | ||||
|      */ | ||||
|     public function getFromGithub($route) | ||||
|     { | ||||
|         $uri     = 'https://raw.githubusercontent.com/JC5/firefly-iii-help/master/en/' . e($route) . '.md'; | ||||
|         $content = [ | ||||
|         $uri        = 'https://raw.githubusercontent.com/JC5/firefly-iii-help/master/en/' . e($route) . '.md'; | ||||
|         $routeIndex = str_replace('.', '-', $route); | ||||
|         $title      = trans('help.' . $routeIndex); | ||||
|         $content    = [ | ||||
|             'text'  => '<p>There is no help for this route!</p>', | ||||
|             'title' => $route, | ||||
|             'title' => $title, | ||||
|         ]; | ||||
|         try { | ||||
|             $content['text'] = file_get_contents($uri); | ||||
| @@ -69,6 +71,18 @@ class Help implements HelpInterface | ||||
|         return Route::has($route); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $route | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function inCache($route) | ||||
|     { | ||||
|         return Cache::has('help.' . $route . '.title') && Cache::has('help.' . $route . '.text'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
| @@ -82,16 +96,4 @@ class Help implements HelpInterface | ||||
|         Cache::put('help.' . $route . '.text', $content['text'], 10080); // a week. | ||||
|         Cache::put('help.' . $route . '.title', $content['title'], 10080); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $route | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function inCache($route) | ||||
|     { | ||||
|         return Cache::has('help.' . $route . '.title') && Cache::has('help.' . $route . '.text'); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,176 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Reminders; | ||||
|  | ||||
| use Amount; | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use Config; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\Reminder; | ||||
| use Navigation; | ||||
| use Preferences; | ||||
|  | ||||
| /** | ||||
|  * Class ReminderHelper | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Reminders | ||||
|  */ | ||||
| class ReminderHelper implements ReminderHelperInterface | ||||
| { | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * @param Carbon    $start | ||||
|      * @param Carbon    $end | ||||
|      * | ||||
|      * @return Reminder | ||||
|      */ | ||||
|     public function createReminder(PiggyBank $piggyBank, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $reminder = Auth::user()->reminders()->where('remindersable_id', $piggyBank->id)->onDates($start, $end)->first(); | ||||
|         if (is_null($reminder)) { | ||||
|  | ||||
|             if (!is_null($piggyBank->targetdate)) { | ||||
|                 // get ranges again, but now for the start date | ||||
|                 $ranges      = $this->getReminderRanges($piggyBank, $start); | ||||
|                 $currentRep  = $piggyBank->currentRelevantRep(); | ||||
|                 $left        = $piggyBank->targetamount - $currentRep->currentamount; | ||||
|                 $perReminder = count($ranges) == 0 ? $left : $left / count($ranges); | ||||
|             } else { | ||||
|                 $perReminder = null; | ||||
|                 $ranges      = []; | ||||
|                 $left        = 0; | ||||
|             } | ||||
|             $metaData = [ | ||||
|                 'perReminder' => $perReminder, | ||||
|                 'rangesCount' => count($ranges), | ||||
|                 'ranges'      => $ranges, | ||||
|                 'leftToSave'  => $left, | ||||
|             ]; | ||||
|  | ||||
|             $reminder = new Reminder; | ||||
|             $reminder->user()->associate(Auth::user()); | ||||
|             $reminder->startdate = $start; | ||||
|             $reminder->enddate   = $end; | ||||
|             $reminder->active    = true; | ||||
|             $reminder->metadata  = $metaData; | ||||
|             $reminder->notnow    = false; | ||||
|             $reminder->remindersable()->associate($piggyBank); | ||||
|             $reminder->save(); | ||||
|  | ||||
|             return $reminder; | ||||
|  | ||||
|         } else { | ||||
|             return $reminder; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Create all reminders for a piggy bank for a given date. | ||||
|      * | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @param Carbon    $date | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function createReminders(PiggyBank $piggyBank, Carbon $date) | ||||
|     { | ||||
|         $ranges = $this->getReminderRanges($piggyBank); | ||||
|  | ||||
|         foreach ($ranges as $range) { | ||||
|             if ($date < $range['end'] && $date > $range['start']) { | ||||
|                 // create a reminder here! | ||||
|                 $this->createReminder($piggyBank, $range['start'], $range['end']); | ||||
|                 // stop looping, we're done. | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This routine will return an array consisting of two dates which indicate the start | ||||
|      * and end date for each reminder that this piggy bank will have, if the piggy bank has | ||||
|      * any reminders. For example: | ||||
|      * | ||||
|      * [12 mar - 15 mar] | ||||
|      * [15 mar - 18 mar] | ||||
|      * | ||||
|      * etcetera. | ||||
|      * | ||||
|      * Array is filled with tiny arrays with Carbon objects in them. | ||||
|      * | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * @param Carbon    $date ; | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getReminderRanges(PiggyBank $piggyBank, Carbon $date = null) | ||||
|     { | ||||
|         $ranges = []; | ||||
|         if (is_null($date)) { | ||||
|             $date = new Carbon; | ||||
|         } | ||||
|  | ||||
|         if ($piggyBank->remind_me === false) { | ||||
|             return $ranges; | ||||
|         } | ||||
|  | ||||
|         if (!is_null($piggyBank->targetdate)) { | ||||
|             // count back until now. | ||||
|             $start = $piggyBank->targetdate; | ||||
|             $end   = $piggyBank->startdate; | ||||
|  | ||||
|             while ($start > $end) { | ||||
|                 $currentEnd   = clone $start; | ||||
|                 $start        = Navigation::subtractPeriod($start, $piggyBank->reminder, 1); | ||||
|                 $currentStart = clone $start; | ||||
|                 $ranges[]     = ['start' => clone $currentStart, 'end' => clone $currentEnd]; | ||||
|             } | ||||
|         } else { | ||||
|             $start = clone $piggyBank->startdate; | ||||
|             while ($start < $date) { | ||||
|                 $currentStart = clone $start; | ||||
|                 $start        = Navigation::addPeriod($start, $piggyBank->reminder, 0); | ||||
|                 $currentEnd   = clone $start; | ||||
|                 $ranges[]     = ['start' => clone $currentStart, 'end' => clone $currentEnd]; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $ranges; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Takes a reminder, finds the piggy bank and tells you what to do now. | ||||
|      * Aka how much money to put in. | ||||
|      * | ||||
|      * | ||||
|      * @param Reminder $reminder | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getReminderText(Reminder $reminder) | ||||
|     { | ||||
|         /** @var PiggyBank $piggyBank */ | ||||
|         $piggyBank = $reminder->remindersable; | ||||
|  | ||||
|         if (is_null($piggyBank)) { | ||||
|             return trans('firefly.piggy_bank_not_exists'); | ||||
|         } | ||||
|  | ||||
|         if (is_null($piggyBank->targetdate)) { | ||||
|             return trans('firefly.add_any_amount_to_piggy', ['amount' => Amount::format($piggyBank->targetamount)]); | ||||
|         } | ||||
|  | ||||
|         $lang = Preferences::get('language', 'en')->data; | ||||
|  | ||||
|         return trans( | ||||
|             'firefly.add_set_amount_to_piggy', | ||||
|             [ | ||||
|                 'amount' => Amount::format($reminder->metadata->perReminder), | ||||
|                 'date'   => $piggyBank->targetdate->formatLocalized(Config::get('firefly.monthAndDay.' . $lang)) | ||||
|             ] | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| @@ -1,63 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Reminders; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\Reminder; | ||||
|  | ||||
| /** | ||||
|  * Interface ReminderHelperInterface | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Reminders | ||||
|  */ | ||||
| interface ReminderHelperInterface | ||||
| { | ||||
|     /** | ||||
|      * Takes a reminder, finds the piggy bank and tells you what to do now. | ||||
|      * Aka how much money to put in. | ||||
|      * | ||||
|      * @param Reminder $reminder | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getReminderText(Reminder $reminder); | ||||
|  | ||||
|     /** | ||||
|      * This routine will return an array consisting of two dates which indicate the start | ||||
|      * and end date for each reminder that this piggy bank will have, if the piggy bank has | ||||
|      * any reminders. For example: | ||||
|      * | ||||
|      * [12 mar - 15 mar] | ||||
|      * [15 mar - 18 mar] | ||||
|      * | ||||
|      * etcetera. | ||||
|      * | ||||
|      * Array is filled with tiny arrays with Carbon objects in them. | ||||
|      * | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getReminderRanges(PiggyBank $piggyBank); | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * @param Carbon    $start | ||||
|      * @param Carbon    $end | ||||
|      * | ||||
|      * @return Reminder | ||||
|      */ | ||||
|     public function createReminder(PiggyBank $piggyBank, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * Create all reminders for a piggy bank for a given date. | ||||
|      * | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @param Carbon    $date | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function createReminders(PiggyBank $piggyBank, Carbon $date); | ||||
| } | ||||
| @@ -2,7 +2,6 @@ | ||||
|  | ||||
| namespace FireflyIII\Helpers\Report; | ||||
|  | ||||
| use App; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Helpers\Collection\Account as AccountCollection; | ||||
| use FireflyIII\Helpers\Collection\Balance; | ||||
| @@ -60,25 +59,27 @@ class ReportHelper implements ReportHelperInterface | ||||
|  | ||||
|  | ||||
|         $accounts = $this->query->getAllAccounts($date, $end, $shared); | ||||
|         $start    = 0; | ||||
|         $end      = 0; | ||||
|         $diff     = 0; | ||||
|         $start    = '0'; | ||||
|         $end      = '0'; | ||||
|         $diff     = '0'; | ||||
|         bcscale(2); | ||||
|  | ||||
|         // remove cash account, if any: | ||||
|         $accounts = $accounts->filter( | ||||
|             function(Account $account) { | ||||
|             function (Account $account) { | ||||
|                 if ($account->accountType->type != 'Cash account') { | ||||
|                     return $account; | ||||
|                 } | ||||
|  | ||||
|                 return null; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         // summarize: | ||||
|         foreach ($accounts as $account) { | ||||
|             $start += $account->startBalance; | ||||
|             $end += $account->endBalance; | ||||
|             $diff += ($account->endBalance - $account->startBalance); | ||||
|             $start = bcadd($start, $account->startBalance); | ||||
|             $end   = bcadd($end, $account->endBalance); | ||||
|             $diff  = bcadd($diff, bcsub($account->endBalance, $account->startBalance)); | ||||
|         } | ||||
|  | ||||
|         $object = new AccountCollection; | ||||
| @@ -113,8 +114,8 @@ class ReportHelper implements ReportHelperInterface | ||||
|      */ | ||||
|     public function getBalanceReport(Carbon $start, Carbon $end, $shared) | ||||
|     { | ||||
|         $repository    = App::make('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); | ||||
|         $tagRepository = App::make('FireflyIII\Repositories\Tag\TagRepositoryInterface'); | ||||
|         $repository    = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); | ||||
|         $tagRepository = app('FireflyIII\Repositories\Tag\TagRepositoryInterface'); | ||||
|         $balance       = new Balance; | ||||
|  | ||||
|         // build a balance header: | ||||
| @@ -162,7 +163,8 @@ class ReportHelper implements ReportHelperInterface | ||||
|         foreach ($accounts as $account) { | ||||
|             $spent = $this->query->spentNoBudget($account, $start, $end); | ||||
|             $left  = $tagRepository->coveredByBalancingActs($account, $start, $end); | ||||
|             $diff  = $spent + $left; | ||||
|             bcscale(2); | ||||
|             $diff = bcsub($spent, $left); | ||||
|  | ||||
|             // budget | ||||
|             $budgetEntry = new BalanceEntry; | ||||
| @@ -197,16 +199,15 @@ 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 | ||||
|      * @param boolean $shared | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return BillCollection | ||||
|      */ | ||||
|     public function getBillReport(Carbon $start, Carbon $end, $shared) | ||||
|     public function getBillReport(Carbon $start, Carbon $end) | ||||
|     { | ||||
|         /** @var \FireflyIII\Repositories\Bill\BillRepositoryInterface $repository */ | ||||
|         $repository = App::make('FireflyIII\Repositories\Bill\BillRepositoryInterface'); | ||||
|         $repository = app('FireflyIII\Repositories\Bill\BillRepositoryInterface'); | ||||
|         $bills      = $repository->getBills(); | ||||
|         $collection = new BillCollection; | ||||
|  | ||||
| @@ -215,18 +216,19 @@ class ReportHelper implements ReportHelperInterface | ||||
|             $billLine = new BillLine; | ||||
|             $billLine->setBill($bill); | ||||
|             $billLine->setActive(intval($bill->active) == 1); | ||||
|             $billLine->setMin(floatval($bill->amount_min)); | ||||
|             $billLine->setMax(floatval($bill->amount_max)); | ||||
|             $billLine->setMin($bill->amount_min); | ||||
|             $billLine->setMax($bill->amount_max); | ||||
|  | ||||
|             // 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; | ||||
|                 $amount = '0'; | ||||
|                 foreach ($set as $entry) { | ||||
|                     $amount += $entry->amount; | ||||
|                     $amount = bcadd($amount, $entry->amount); | ||||
|                 } | ||||
|                 $billLine->setAmount($amount); | ||||
|             } | ||||
| @@ -250,16 +252,18 @@ class ReportHelper implements ReportHelperInterface | ||||
|     { | ||||
|         $object = new BudgetCollection; | ||||
|         /** @var \FireflyIII\Repositories\Budget\BudgetRepositoryInterface $repository */ | ||||
|         $repository = App::make('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); | ||||
|         $repository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); | ||||
|         $set        = $repository->getBudgets(); | ||||
|  | ||||
|         bcscale(2); | ||||
|  | ||||
|         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); | ||||
|                 $spent      = $repository->balanceInPeriod($budget, $start, $end, $shared); | ||||
|                 $budgetLine = new BudgetLine; | ||||
|                 $budgetLine->setBudget($budget); | ||||
|                 $budgetLine->setOverspent($spent); | ||||
| @@ -274,10 +278,10 @@ class ReportHelper implements ReportHelperInterface | ||||
|                 $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; | ||||
|                 $expenses  = $repository->balanceInPeriod($budget, $repetition->startdate, $repetition->enddate, $shared); | ||||
|                 $left      = $expenses < $repetition->amount ? bcsub($repetition->amount, $expenses) : 0; | ||||
|                 $spent     = $expenses > $repetition->amount ? 0 : $expenses; | ||||
|                 $overspent = $expenses > $repetition->amount ? bcsub($expenses, $repetition->amount) : 0; | ||||
|  | ||||
|                 $budgetLine->setLeft($left); | ||||
|                 $budgetLine->setSpent($spent); | ||||
| @@ -320,10 +324,10 @@ class ReportHelper implements ReportHelperInterface | ||||
|          * GET CATEGORIES: | ||||
|          */ | ||||
|         /** @var \FireflyIII\Repositories\Category\CategoryRepositoryInterface $repository */ | ||||
|         $repository = App::make('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); | ||||
|         $repository = app('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); | ||||
|         $set        = $repository->getCategories(); | ||||
|         foreach ($set as $category) { | ||||
|             $spent           = $repository->spentInPeriodCorrected($category, $start, $end, $shared); | ||||
|             $spent = $repository->balanceInPeriod($category, $start, $end, $shared); | ||||
|             $category->spent = $spent; | ||||
|             $object->addCategory($category); | ||||
|             $object->addTotal($spent); | ||||
|   | ||||
| @@ -5,9 +5,9 @@ namespace FireflyIII\Helpers\Report; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Helpers\Collection\Account as AccountCollection; | ||||
| use FireflyIII\Helpers\Collection\Balance; | ||||
| use FireflyIII\Helpers\Collection\Bill as BillCollection; | ||||
| use FireflyIII\Helpers\Collection\Budget as BudgetCollection; | ||||
| use FireflyIII\Helpers\Collection\Category as CategoryCollection; | ||||
| use FireflyIII\Helpers\Collection\Bill as BillCollection; | ||||
| use FireflyIII\Helpers\Collection\Expense; | ||||
| use FireflyIII\Helpers\Collection\Income; | ||||
|  | ||||
| @@ -35,13 +35,12 @@ interface 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 | ||||
|      * @param boolean $shared | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return BillCollection | ||||
|      */ | ||||
|     public function getBillReport(Carbon $start, Carbon $end, $shared); | ||||
|     public function getBillReport(Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon  $start | ||||
|   | ||||
| @@ -21,7 +21,11 @@ use Steam; | ||||
| class ReportQuery implements ReportQueryInterface | ||||
| { | ||||
|     /** | ||||
|      * See ReportQueryInterface::incomeInPeriodCorrected | ||||
|      * See ReportQueryInterface::incomeInPeriodCorrected. | ||||
|      * | ||||
|      * This method's length is caused mainly by the query build stuff. Therefor: | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
| @@ -35,15 +39,15 @@ class ReportQuery implements ReportQueryInterface | ||||
|         $query = $this->queryJournalsWithTransactions($start, $end); | ||||
|         if ($includeShared === false) { | ||||
|             $query->where( | ||||
|                 function(Builder $query) { | ||||
|                 function (Builder $query) { | ||||
|                     $query->where( | ||||
|                         function(Builder $q) { // only get withdrawals not from a shared account | ||||
|                         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. | ||||
|                         function (Builder $q) { // and transfers from a shared account. | ||||
|                             $q->where('transaction_types.type', 'Transfer'); | ||||
|                             $q->where('acm_to.data', '=', '"sharedAsset"'); | ||||
|                         } | ||||
| @@ -54,24 +58,23 @@ class ReportQuery implements ReportQueryInterface | ||||
|             $query->where('transaction_types.type', 'Withdrawal'); // any withdrawal is fine. | ||||
|         } | ||||
|         $query->orderBy('transaction_journals.date'); | ||||
|  | ||||
|         // get everything | ||||
|         $data = $query->get( | ||||
|         $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) { | ||||
|             function (TransactionJournal $journal) { | ||||
|                 if (intval($journal->account_encrypted) == 1) { | ||||
|                     $journal->name = Crypt::decrypt($journal->name); | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|         $data = $data->filter( | ||||
|             function(TransactionJournal $journal) { | ||||
|             function (TransactionJournal $journal) { | ||||
|                 if ($journal->amount != 0) { | ||||
|                     return $journal; | ||||
|                 } | ||||
|  | ||||
|                 return null; | ||||
|             } | ||||
|         ); | ||||
| @@ -91,26 +94,25 @@ class ReportQuery implements ReportQueryInterface | ||||
|     public function getAllAccounts(Carbon $start, Carbon $end, $includeShared = false) | ||||
|     { | ||||
|         $query = Auth::user()->accounts()->orderBy('accounts.name', 'ASC') | ||||
|                         ->accountTypeIn(['Default account', 'Asset account', 'Cash account']); | ||||
|                      ->accountTypeIn(['Default account', 'Asset account', 'Cash account']); | ||||
|         if ($includeShared === false) { | ||||
|             $query->leftJoin( | ||||
|                 'account_meta', function(JoinClause $join) { | ||||
|                 'account_meta', function (JoinClause $join) { | ||||
|                 $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole'); | ||||
|             } | ||||
|             ) | ||||
|                     ->orderBy('accounts.name', 'ASC') | ||||
|                     ->where( | ||||
|                         function(Builder $query) { | ||||
|                   ->where( | ||||
|                       function (Builder $query) { | ||||
|  | ||||
|                             $query->where('account_meta.data', '!=', '"sharedAsset"'); | ||||
|                             $query->orWhereNull('account_meta.data'); | ||||
|                           $query->where('account_meta.data', '!=', '"sharedAsset"'); | ||||
|                           $query->orWhereNull('account_meta.data'); | ||||
|  | ||||
|                         } | ||||
|                     ); | ||||
|                       } | ||||
|                   ); | ||||
|         } | ||||
|         $set = $query->get(['accounts.*']); | ||||
|         $set->each( | ||||
|             function(Account $account) use ($start, $end) { | ||||
|             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 | ||||
| @@ -151,15 +153,15 @@ class ReportQuery implements ReportQueryInterface | ||||
|             // only get deposits not to a shared account | ||||
|             // and transfers to a shared account. | ||||
|             $query->where( | ||||
|                 function(Builder $query) { | ||||
|                 function (Builder $query) { | ||||
|                     $query->where( | ||||
|                         function(Builder $q) { | ||||
|                         function (Builder $q) { | ||||
|                             $q->where('transaction_types.type', 'Deposit'); | ||||
|                             $q->where('acm_to.data', '!=', '"sharedAsset"'); | ||||
|                         } | ||||
|                     ); | ||||
|                     $query->orWhere( | ||||
|                         function(Builder $q) { | ||||
|                         function (Builder $q) { | ||||
|                             $q->where('transaction_types.type', 'Transfer'); | ||||
|                             $q->where('acm_from.data', '=', '"sharedAsset"'); | ||||
|                         } | ||||
| @@ -178,17 +180,18 @@ class ReportQuery implements ReportQueryInterface | ||||
|         ); | ||||
|  | ||||
|         $data->each( | ||||
|             function(TransactionJournal $journal) { | ||||
|             function (TransactionJournal $journal) { | ||||
|                 if (intval($journal->account_encrypted) == 1) { | ||||
|                     $journal->name = Crypt::decrypt($journal->name); | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|         $data = $data->filter( | ||||
|             function(TransactionJournal $journal) { | ||||
|             function (TransactionJournal $journal) { | ||||
|                 if ($journal->amount != 0) { | ||||
|                     return $journal; | ||||
|                 } | ||||
|  | ||||
|                 return null; | ||||
|             } | ||||
|         ); | ||||
| @@ -209,30 +212,9 @@ class ReportQuery implements ReportQueryInterface | ||||
|     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; | ||||
|     } | ||||
|         bcscale(2); | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param bool    $shared | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function spentNoBudget(Account $account, Carbon $start, Carbon $end, $shared = false) | ||||
|     { | ||||
|         return floatval( | ||||
|         return bcmul( | ||||
|             Auth::user()->transactionjournals() | ||||
|                 ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                 ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
| @@ -240,10 +222,31 @@ class ReportQuery implements ReportQueryInterface | ||||
|                 ->where('transactions.account_id', $account->id) | ||||
|                 ->before($end) | ||||
|                 ->after($start) | ||||
|                 ->whereNull('budget_transaction_journal.budget_id')->get(['transaction_journals.*'])->sum('amount') | ||||
|                 ->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 | ||||
| @@ -254,28 +257,28 @@ class ReportQuery implements ReportQueryInterface | ||||
|     { | ||||
|         $query = TransactionJournal:: | ||||
|         leftJoin( | ||||
|             'transactions as t_from', function(JoinClause $join) { | ||||
|             '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'); | ||||
|                                    ->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; | ||||
|   | ||||
| @@ -71,11 +71,10 @@ interface ReportQueryInterface | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param bool    $shared | ||||
|      * | ||||
|      * @return float | ||||
|      * @return string | ||||
|      */ | ||||
|     public function spentNoBudget(Account $account, Carbon $start, Carbon $end, $shared = false); | ||||
|     public function spentNoBudget(Account $account, Carbon $start, Carbon $end); | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -3,11 +3,12 @@ | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use Config; | ||||
| use ExpandedForm; | ||||
| use FireflyIII\Http\Requests\AccountFormRequest; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use Input; | ||||
| use Redirect; | ||||
| use Preferences; | ||||
| use Session; | ||||
| use Steam; | ||||
| use URL; | ||||
| @@ -57,17 +58,19 @@ class AccountController extends Controller | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function delete(Account $account) | ||||
|     public function delete(AccountRepositoryInterface $repository, Account $account) | ||||
|     { | ||||
|         $typeName = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type); | ||||
|         $subTitle = trans('firefly.delete_' . $typeName . '_account', ['name' => $account->name]); | ||||
|         $typeName    = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type); | ||||
|         $subTitle    = trans('firefly.delete_' . $typeName . '_account', ['name' => $account->name]); | ||||
|         $accountList = Expandedform::makeSelectList($repository->getAccounts([$account->accountType->type]), true); | ||||
|         unset($accountList[$account->id]); | ||||
|  | ||||
|         // put previous url in session | ||||
|         Session::put('accounts.delete.url', URL::previous()); | ||||
|         Session::flash('gaEventCategory', 'accounts'); | ||||
|         Session::flash('gaEventAction', 'delete-' . $typeName); | ||||
|  | ||||
|         return view('accounts.delete', compact('account', 'subTitle')); | ||||
|         return view('accounts.delete', compact('account', 'subTitle', 'accountList')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -78,16 +81,17 @@ class AccountController extends Controller | ||||
|      */ | ||||
|     public function destroy(AccountRepositoryInterface $repository, Account $account) | ||||
|     { | ||||
|  | ||||
|         $type     = $account->accountType->type; | ||||
|         $typeName = Config::get('firefly.shortNamesByFullName.' . $type); | ||||
|         $name     = $account->name; | ||||
|         $moveTo   = Auth::user()->accounts()->find(intval(Input::get('move_account_before_delete'))); | ||||
|  | ||||
|         $repository->destroy($account); | ||||
|         $repository->destroy($account, $moveTo); | ||||
|  | ||||
|         Session::flash('success', trans('firefly.' . $typeName . '_deleted', ['name' => $name])); | ||||
|         Preferences::mark(); | ||||
|  | ||||
|         return Redirect::to(Session::get('accounts.delete.url')); | ||||
|         return redirect(Session::get('accounts.delete.url')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -126,7 +130,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'); | ||||
| @@ -152,12 +156,24 @@ class AccountController extends Controller | ||||
|          * HERE WE ARE | ||||
|          */ | ||||
|         $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; | ||||
|         } | ||||
|  | ||||
|         $startBalances = Steam::balancesById($ids, $start); | ||||
|         $endBalances   = Steam::balancesById($ids, $end); | ||||
|         $activities    = Steam::getLastActivities($ids); | ||||
|  | ||||
|         $accounts->each( | ||||
|             function(Account $account) use ($start, $repository) { | ||||
|                 $account->lastActivityDate = $repository->getLastActivity($account); | ||||
|                 $account->startBalance     = Steam::balance($account, $start); | ||||
|                 $account->endBalance       = Steam::balance($account, clone Session::get('end', Carbon::now()->endOfMonth())); | ||||
|             function (Account $account) use ($activities, $startBalances, $endBalances) { | ||||
|                 $account->lastActivityDate = isset($activities[$account->id]) ? $activities[$account->id] : null; | ||||
|                 $account->startBalance     = isset($startBalances[$account->id]) ? $startBalances[$account->id] : null; | ||||
|                 $account->endBalance       = isset($endBalances[$account->id]) ? $endBalances[$account->id] : null; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
| @@ -194,30 +210,31 @@ class AccountController extends Controller | ||||
|         $accountData = [ | ||||
|             'name'                   => $request->input('name'), | ||||
|             'accountType'            => $request->input('what'), | ||||
|             'virtualBalance'         => floatval($request->input('virtualBalance')), | ||||
|             'virtualBalance'         => round($request->input('virtualBalance'), 2), | ||||
|             'active'                 => true, | ||||
|             'user'                   => Auth::user()->id, | ||||
|             'iban'                   => $request->input('iban'), | ||||
|             'accountRole'            => $request->input('accountRole'), | ||||
|             'openingBalance'         => floatval($request->input('openingBalance')), | ||||
|             'openingBalanceDate'     => new Carbon((string) $request->input('openingBalanceDate')), | ||||
|             'openingBalance'         => round($request->input('openingBalance'), 2), | ||||
|             'openingBalanceDate'     => new Carbon((string)$request->input('openingBalanceDate')), | ||||
|             'openingBalanceCurrency' => intval($request->input('balance_currency_id')), | ||||
|  | ||||
|         ]; | ||||
|  | ||||
|         $account = $repository->store($accountData); | ||||
|  | ||||
|         Session::flash('success', 'New account "' . $account->name . '" stored!'); | ||||
|         Preferences::mark(); | ||||
|  | ||||
|         if (intval(Input::get('create_another')) === 1) { | ||||
|             // set value so create routine will not overwrite URL: | ||||
|             Session::put('accounts.create.fromStore', true); | ||||
|  | ||||
|             return Redirect::route('accounts.create')->withInput(); | ||||
|             return redirect(route('accounts.create', [$request->input('what')]))->withInput(); | ||||
|         } | ||||
|  | ||||
|         // redirect to previous URL. | ||||
|         return Redirect::to(Session::get('accounts.create.url')); | ||||
|  | ||||
|  | ||||
|         return redirect(Session::get('accounts.create.url')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -234,28 +251,31 @@ class AccountController extends Controller | ||||
|             'name'                   => $request->input('name'), | ||||
|             'active'                 => $request->input('active'), | ||||
|             'user'                   => Auth::user()->id, | ||||
|             'iban'                   => $request->input('iban'), | ||||
|             'accountRole'            => $request->input('accountRole'), | ||||
|             'virtualBalance'         => floatval($request->input('virtualBalance')), | ||||
|             'openingBalance'         => floatval($request->input('openingBalance')), | ||||
|             'openingBalanceDate'     => new Carbon((string) $request->input('openingBalanceDate')), | ||||
|             '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'), | ||||
|             'ccMonthlyPaymentDate'   => $request->input('ccMonthlyPaymentDate'), | ||||
|         ]; | ||||
|  | ||||
|  | ||||
|         $repository->update($account, $accountData); | ||||
|  | ||||
|         Session::flash('success', 'Account "' . $account->name . '" updated.'); | ||||
|         Preferences::mark(); | ||||
|  | ||||
|         if (intval(Input::get('return_to_edit')) === 1) { | ||||
|             // set value so edit routine will not overwrite URL: | ||||
|             Session::put('accounts.edit.fromUpdate', true); | ||||
|  | ||||
|             return Redirect::route('accounts.edit', [$account->id])->withInput(['return_to_edit' => 1]); | ||||
|             return redirect(route('accounts.edit', [$account->id]))->withInput(['return_to_edit' => 1]); | ||||
|         } | ||||
|  | ||||
|         // redirect to previous URL. | ||||
|         return Redirect::to(Session::get('accounts.edit.url')); | ||||
|         return redirect(Session::get('accounts.edit.url')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|   | ||||
							
								
								
									
										173
									
								
								app/Http/Controllers/AttachmentController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								app/Http/Controllers/AttachmentController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,173 @@ | ||||
| <?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 | ||||
|      */ | ||||
|     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,17 +1,18 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers\Auth; | ||||
|  | ||||
| use App; | ||||
| use Auth; | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Models\Role; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Contracts\Auth\Guard; | ||||
| use Illuminate\Contracts\Auth\Registrar; | ||||
| use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers; | ||||
| use Illuminate\Foundation\Auth\ThrottlesLogins; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Mail\Message; | ||||
| use Mail; | ||||
| use Request as Rq; | ||||
| use Session; | ||||
| use Twig; | ||||
| use Validator; | ||||
|  | ||||
| /** | ||||
|  * Class AuthController | ||||
| @@ -20,35 +21,93 @@ use Twig; | ||||
|  */ | ||||
| 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? | ||||
|     | | ||||
|     */ | ||||
|     /** | ||||
|      * 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', | ||||
|                     ] | ||||
|         ); | ||||
|  | ||||
|         // If the class is using the ThrottlesLogins trait, we can automatically throttle | ||||
|         // the login attempts for this application. We'll key this by the username and | ||||
|         // the IP address of the client making these requests into this application. | ||||
|         $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); | ||||
|         } | ||||
|  | ||||
|         // default error message: | ||||
|         $message = $this->getFailedLoginMessage(); | ||||
|  | ||||
|         // try to find a blocked user with this email address. | ||||
|         /** @var User $foundUser */ | ||||
|         $foundUser = User::where('email', $credentials['email'])->where('blocked', 1)->first(); | ||||
|         if (!is_null($foundUser)) { | ||||
|             // if it exists, show message: | ||||
|             $code    = $foundUser->blocked_code; | ||||
|             $message = trans('firefly.' . $code . '_error', ['email' => $credentials['email']]); | ||||
|         } | ||||
|  | ||||
|         // try | ||||
|  | ||||
|         // If the login attempt was unsuccessful we will increment the number of attempts | ||||
|         // to login and redirect the user back to the login form. Of course, when this | ||||
|         // user surpasses their maximum number of attempts they will get locked out. | ||||
|         if ($throttles) { | ||||
|             $this->incrementLoginAttempts($request); | ||||
|         } | ||||
|  | ||||
|         return redirect($this->loginPath()) | ||||
|             ->withInput($request->only($this->loginUsername(), 'remember')) | ||||
|             ->withErrors( | ||||
|                 [ | ||||
|                     $this->loginUsername() => $message, | ||||
|                 ] | ||||
|             ); | ||||
|     } | ||||
|  | ||||
|     use AuthenticatesAndRegistersUsers; | ||||
|  | ||||
|     public $redirectTo = '/'; | ||||
|  | ||||
|     /** | ||||
|      * Create a new authentication controller instance. | ||||
|      * | ||||
|      * @param  \Illuminate\Contracts\Auth\Guard     $auth | ||||
|      * @param  \Illuminate\Contracts\Auth\Registrar $registrar | ||||
|      * | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      */ | ||||
|     public function __construct(Guard $auth, Registrar $registrar) | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->auth      = $auth; | ||||
|         $this->registrar = $registrar; | ||||
|         parent::__construct(); | ||||
|  | ||||
|         $this->middleware('guest', ['except' => 'getLogout']); | ||||
|     } | ||||
| @@ -74,7 +133,7 @@ class AuthController extends Controller | ||||
|      */ | ||||
|     public function postRegister(Request $request) | ||||
|     { | ||||
|         $validator = $this->registrar->validator($request->all()); | ||||
|         $validator = $this->validator($request->all()); | ||||
|  | ||||
|         if ($validator->fails()) { | ||||
|             $this->throwValidationException( | ||||
| @@ -87,16 +146,16 @@ class AuthController extends Controller | ||||
|         $data             = $request->all(); | ||||
|         $data['password'] = bcrypt($data['password']); | ||||
|  | ||||
|         $this->auth->login($this->registrar->create($data)); | ||||
|         Auth::login($this->create($data)); | ||||
|  | ||||
|         // get the email address | ||||
|         if ($this->auth->user() instanceof User) { | ||||
|             $email = $this->auth->user()->email; | ||||
|  | ||||
|         if (Auth::user() instanceof User) { | ||||
|             $email   = Auth::user()->email; | ||||
|             $address = route('index'); | ||||
|             // send email. | ||||
|             Mail::send( | ||||
|                 'emails.registered', [], function (Message $message) use ($email) { | ||||
|                 $message->to($email, $email)->subject('Welcome to Firefly III!'); | ||||
|                 ['emails.registered-html', 'emails.registered'], ['address' => $address], function (Message $message) use ($email) { | ||||
|                 $message->to($email, $email)->subject('Welcome to Firefly III! '); | ||||
|             } | ||||
|             ); | ||||
|  | ||||
| @@ -108,16 +167,50 @@ class AuthController extends Controller | ||||
|             // first user ever? | ||||
|             if (User::count() == 1) { | ||||
|                 $admin = Role::where('name', 'owner')->first(); | ||||
|                 $this->auth->user()->attachRole($admin); | ||||
| //                $this->auth->user()->roles()->save($admin); | ||||
|                 Auth::user()->attachRole($admin); | ||||
|             } | ||||
|  | ||||
|  | ||||
|             return redirect($this->redirectPath()); | ||||
|         } | ||||
|         App::abort(500, 'Not a user!'); | ||||
|         // @codeCoverageIgnoreStart | ||||
|         abort(500, 'Not a user!'); | ||||
|  | ||||
|         return redirect('/'); | ||||
|         // @codeCoverageIgnoreEnd | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get a validator for an incoming registration request. | ||||
|      * | ||||
|      * @param  array $data | ||||
|      * | ||||
|      * @return \Illuminate\Contracts\Validation\Validator | ||||
|      */ | ||||
|     public function validator(array $data) | ||||
|     { | ||||
|         return Validator::make( | ||||
|             $data, [ | ||||
|                      'email'    => 'required|email|max:255|unique:users', | ||||
|                      'password' => 'required|confirmed|min:6', | ||||
|                  ] | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Create a new user instance after a valid registration. | ||||
|      * | ||||
|      * @param  array $data | ||||
|      * | ||||
|      * @return User | ||||
|      */ | ||||
|     public function create(array $data) | ||||
|     { | ||||
|         return User::create( | ||||
|             [ | ||||
|                 'email'    => $data['email'], | ||||
|                 'password' => $data['password'], | ||||
|             ] | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,6 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers\Auth; | ||||
|  | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use Illuminate\Contracts\Auth\Guard; | ||||
| use Illuminate\Contracts\Auth\PasswordBroker; | ||||
| use Illuminate\Foundation\Auth\ResetsPasswords; | ||||
|  | ||||
| /** | ||||
| @@ -33,17 +31,12 @@ class PasswordController extends Controller | ||||
|     /** | ||||
|      * Create a new password controller instance. | ||||
|      * | ||||
|      * @param  \Illuminate\Contracts\Auth\Guard          $auth | ||||
|      * @param  \Illuminate\Contracts\Auth\PasswordBroker $passwords | ||||
|      * | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      */ | ||||
|     public function __construct(Guard $auth, PasswordBroker $passwords) | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->auth      = $auth; | ||||
|         $this->passwords = $passwords; | ||||
|  | ||||
|         parent::__construct(); | ||||
|  | ||||
|         $this->middleware('guest'); | ||||
|     } | ||||
|   | ||||
| @@ -6,7 +6,7 @@ use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Repositories\Bill\BillRepositoryInterface; | ||||
| use Input; | ||||
| use Redirect; | ||||
| use Preferences; | ||||
| use Session; | ||||
| use URL; | ||||
| use View; | ||||
| @@ -34,7 +34,9 @@ class BillController extends Controller | ||||
|      */ | ||||
|     public function create() | ||||
|     { | ||||
|         $periods = Config::get('firefly.periods_to_text'); | ||||
|         $periods  = Config::get('firefly.periods_to_text'); | ||||
|         $subTitle = trans('firefly.create_new_bill'); | ||||
|  | ||||
|  | ||||
|         // put previous url in session if not redirect from store (not "create another"). | ||||
|         if (Session::get('bills.create.fromStore') !== true) { | ||||
| @@ -43,7 +45,6 @@ class BillController extends Controller | ||||
|         Session::forget('bills.create.fromStore'); | ||||
|         Session::flash('gaEventCategory', 'bills'); | ||||
|         Session::flash('gaEventAction', 'create'); | ||||
|         $subTitle = 'Create new bill'; | ||||
|  | ||||
|         return view('bills.create', compact('periods', 'subTitle')); | ||||
|     } | ||||
| @@ -75,9 +76,9 @@ class BillController extends Controller | ||||
|         $repository->destroy($bill); | ||||
|  | ||||
|         Session::flash('success', 'The bill was deleted.'); | ||||
|         Preferences::mark(); | ||||
|  | ||||
|         return Redirect::to(Session::get('bills.delete.url')); | ||||
|  | ||||
|         return redirect(Session::get('bills.delete.url')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -88,7 +89,7 @@ class BillController extends Controller | ||||
|     public function edit(Bill $bill) | ||||
|     { | ||||
|         $periods  = Config::get('firefly.periods_to_text'); | ||||
|         $subTitle = 'Edit "' . e($bill->name) . '"'; | ||||
|         $subTitle = trans('firefly.edit_bill', ['name' => $bill->name]); | ||||
|  | ||||
|         // put previous url in session if not redirect from store (not "return_to_edit"). | ||||
|         if (Session::get('bills.edit.fromUpdate') !== true) { | ||||
| @@ -110,7 +111,7 @@ class BillController extends Controller | ||||
|     { | ||||
|         $bills = $repository->getBills(); | ||||
|         $bills->each( | ||||
|             function(Bill $bill) use ($repository) { | ||||
|             function (Bill $bill) use ($repository) { | ||||
|                 $bill->nextExpectedMatch = $repository->nextExpectedMatch($bill); | ||||
|                 $bill->lastFoundMatch    = $repository->lastFoundMatch($bill); | ||||
|             } | ||||
| @@ -130,7 +131,7 @@ class BillController extends Controller | ||||
|         if (intval($bill->active) == 0) { | ||||
|             Session::flash('warning', 'Inactive bills cannot be scanned.'); | ||||
|  | ||||
|             return Redirect::to(URL::previous()); | ||||
|             return redirect(URL::previous()); | ||||
|         } | ||||
|  | ||||
|         $journals = $repository->getPossiblyRelatedJournals($bill); | ||||
| @@ -141,8 +142,9 @@ class BillController extends Controller | ||||
|  | ||||
|  | ||||
|         Session::flash('success', 'Rescanned everything.'); | ||||
|         Preferences::mark(); | ||||
|  | ||||
|         return Redirect::to(URL::previous()); | ||||
|         return redirect(URL::previous()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -172,16 +174,17 @@ class BillController extends Controller | ||||
|         $billData = $request->getBillData(); | ||||
|         $bill     = $repository->store($billData); | ||||
|         Session::flash('success', 'Bill "' . e($bill->name) . '" stored.'); | ||||
|         Preferences::mark(); | ||||
|  | ||||
|         if (intval(Input::get('create_another')) === 1) { | ||||
|             // set value so create routine will not overwrite URL: | ||||
|             Session::put('bills.create.fromStore', true); | ||||
|  | ||||
|             return Redirect::route('bills.create')->withInput(); | ||||
|             return redirect(route('bills.create'))->withInput(); | ||||
|         } | ||||
|  | ||||
|         // redirect to previous URL. | ||||
|         return Redirect::to(Session::get('bills.create.url')); | ||||
|         return redirect(Session::get('bills.create.url')); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -198,16 +201,17 @@ class BillController extends Controller | ||||
|         $bill     = $repository->update($bill, $billData); | ||||
|  | ||||
|         Session::flash('success', 'Bill "' . e($bill->name) . '" updated.'); | ||||
|         Preferences::mark(); | ||||
|  | ||||
|         if (intval(Input::get('return_to_edit')) === 1) { | ||||
|             // set value so edit routine will not overwrite URL: | ||||
|             Session::put('bills.edit.fromUpdate', true); | ||||
|  | ||||
|             return Redirect::route('bills.edit', [$bill->id])->withInput(['return_to_edit' => 1]); | ||||
|             return redirect(route('bills.edit', [$bill->id]))->withInput(['return_to_edit' => 1]); | ||||
|         } | ||||
|  | ||||
|         // redirect to previous URL. | ||||
|         return Redirect::to(Session::get('bills.edit.url')); | ||||
|         return redirect(Session::get('bills.edit.url')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -9,7 +9,6 @@ use FireflyIII\Models\LimitRepetition; | ||||
| use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| use Input; | ||||
| use Preferences; | ||||
| use Redirect; | ||||
| use Response; | ||||
| use Session; | ||||
| use URL; | ||||
| @@ -49,6 +48,7 @@ class BudgetController extends Controller | ||||
|         if ($amount == 0) { | ||||
|             $limitRepetition = null; | ||||
|         } | ||||
|         Preferences::mark(); | ||||
|  | ||||
|         return Response::json(['name' => $budget->name, 'repetition' => $limitRepetition ? $limitRepetition->id : 0]); | ||||
|  | ||||
| @@ -102,9 +102,10 @@ class BudgetController extends Controller | ||||
|  | ||||
|  | ||||
|         Session::flash('success', 'The  budget "' . e($name) . '" was deleted.'); | ||||
|         Preferences::mark(); | ||||
|  | ||||
|  | ||||
|         return Redirect::to(Session::get('budgets.delete.url')); | ||||
|         return redirect(Session::get('budgets.delete.url')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -114,7 +115,7 @@ class BudgetController extends Controller | ||||
|      */ | ||||
|     public function edit(Budget $budget) | ||||
|     { | ||||
|         $subTitle = 'Edit budget "' . e($budget->name) . '"'; | ||||
|         $subTitle = trans('firefly.edit_budget', ['name' => $budget->name]); | ||||
|  | ||||
|         // put previous url in session if not redirect from store (not "return_to_edit"). | ||||
|         if (Session::get('budgets.edit.fromUpdate') !== true) { | ||||
| @@ -151,7 +152,7 @@ class BudgetController extends Controller | ||||
|         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->spent      = $repository->balanceInPeriod($budget, $date, $end); | ||||
|             $budget->currentRep = $repository->getCurrentRepetition($budget, $date); | ||||
|             if ($budget->currentRep) { | ||||
|                 $budgeted = bcadd($budgeted, $budget->currentRep->amount); | ||||
| @@ -196,8 +197,9 @@ class BudgetController extends Controller | ||||
|  | ||||
|         $date = Session::get('start', Carbon::now()->startOfMonth())->format('FY'); | ||||
|         Preferences::set('budgetIncomeTotal' . $date, intval(Input::get('amount'))); | ||||
|         Preferences::mark(); | ||||
|  | ||||
|         return Redirect::route('budgets.index'); | ||||
|         return redirect(route('budgets.index')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -216,12 +218,15 @@ class BudgetController extends Controller | ||||
|         } | ||||
|  | ||||
|         $journals = $repository->getJournals($budget, $repetition); | ||||
|         $limits   = !is_null($repetition->id) ? [$repetition->budgetLimit] : $repository->getBudgetLimits($budget); | ||||
|         $subTitle = !is_null($repetition->id) | ||||
|             ? | ||||
|             trans('firefly.budget_in_month', ['name' => $budget->name, 'month' => $repetition->startdate->formatLocalized($this->monthFormat)]) | ||||
|             : | ||||
|             e($budget->name); | ||||
|  | ||||
|         if (is_null($repetition->id)) { | ||||
|             $limits   = $repository->getBudgetLimits($budget); | ||||
|             $subTitle = e($budget->name); | ||||
|         } else { | ||||
|             $limits   = [$repetition->budgetLimit]; | ||||
|             $subTitle = trans('firefly.budget_in_month', ['name' => $budget->name, 'month' => $repetition->startdate->formatLocalized($this->monthFormat)]); | ||||
|         } | ||||
|  | ||||
|         $journals->setPath('/budgets/show/' . $budget->id); | ||||
|  | ||||
|         return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle')); | ||||
| @@ -239,19 +244,20 @@ class BudgetController extends Controller | ||||
|             'name' => $request->input('name'), | ||||
|             'user' => Auth::user()->id, | ||||
|         ]; | ||||
|         $budget = $repository->store($budgetData); | ||||
|         $budget     = $repository->store($budgetData); | ||||
|  | ||||
|         Session::flash('success', 'New budget "' . $budget->name . '" stored!'); | ||||
|         Preferences::mark(); | ||||
|  | ||||
|         if (intval(Input::get('create_another')) === 1) { | ||||
|             // set value so create routine will not overwrite URL: | ||||
|             Session::put('budgets.create.fromStore', true); | ||||
|  | ||||
|             return Redirect::route('budgets.create')->withInput(); | ||||
|             return redirect(route('budgets.create'))->withInput(); | ||||
|         } | ||||
|  | ||||
|         // redirect to previous URL. | ||||
|         return Redirect::to(Session::get('budgets.create.url')); | ||||
|         return redirect(Session::get('budgets.create.url')); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -272,16 +278,17 @@ class BudgetController extends Controller | ||||
|         $repository->update($budget, $budgetData); | ||||
|  | ||||
|         Session::flash('success', 'Budget "' . $budget->name . '" updated.'); | ||||
|         Preferences::mark(); | ||||
|  | ||||
|         if (intval(Input::get('return_to_edit')) === 1) { | ||||
|             // set value so edit routine will not overwrite URL: | ||||
|             Session::put('budgets.edit.fromUpdate', true); | ||||
|  | ||||
|             return Redirect::route('budgets.edit', [$budget->id])->withInput(['return_to_edit' => 1]); | ||||
|             return redirect(route('budgets.edit', [$budget->id]))->withInput(['return_to_edit' => 1]); | ||||
|         } | ||||
|  | ||||
|         // redirect to previous URL. | ||||
|         return Redirect::to(Session::get('budgets.edit.url')); | ||||
|         return redirect(Session::get('budgets.edit.url')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -7,7 +7,7 @@ use FireflyIII\Models\Category; | ||||
| use FireflyIII\Repositories\Category\CategoryRepositoryInterface; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use Input; | ||||
| use Redirect; | ||||
| use Preferences; | ||||
| use Session; | ||||
| use URL; | ||||
| use View; | ||||
| @@ -42,7 +42,7 @@ class CategoryController extends Controller | ||||
|         Session::forget('categories.create.fromStore'); | ||||
|         Session::flash('gaEventCategory', 'categories'); | ||||
|         Session::flash('gaEventAction', 'create'); | ||||
|         $subTitle = 'Create a new category'; | ||||
|         $subTitle = trans('firefly.create_new_category'); | ||||
|  | ||||
|         return view('categories.create', compact('subTitle')); | ||||
|     } | ||||
| @@ -77,8 +77,9 @@ class CategoryController extends Controller | ||||
|         $repository->destroy($category); | ||||
|  | ||||
|         Session::flash('success', 'The  category "' . e($name) . '" was deleted.'); | ||||
|         Preferences::mark(); | ||||
|  | ||||
|         return Redirect::to(Session::get('categories.delete.url')); | ||||
|         return redirect(Session::get('categories.delete.url')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -88,7 +89,7 @@ class CategoryController extends Controller | ||||
|      */ | ||||
|     public function edit(Category $category) | ||||
|     { | ||||
|         $subTitle = 'Edit category "' . e($category->name) . '"'; | ||||
|         $subTitle = trans('firefly.edit_category', ['name' => $category->name]); | ||||
|  | ||||
|         // put previous url in session if not redirect from store (not "return_to_edit"). | ||||
|         if (Session::get('categories.edit.fromUpdate') !== true) { | ||||
| @@ -112,7 +113,7 @@ class CategoryController extends Controller | ||||
|         $categories = $repository->getCategories(); | ||||
|  | ||||
|         $categories->each( | ||||
|             function(Category $category) use ($repository) { | ||||
|             function (Category $category) use ($repository) { | ||||
|                 $category->lastActivity = $repository->getLatestActivity($category); | ||||
|             } | ||||
|         ); | ||||
| @@ -130,7 +131,10 @@ class CategoryController extends Controller | ||||
|         $start    = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end      = Session::get('end', Carbon::now()->startOfMonth()); | ||||
|         $list     = $repository->getWithoutCategory($start, $end); | ||||
|         $subTitle = 'Transactions without a category between ' . $start->format('jS F Y') . ' and ' . $end->format('jS F Y'); | ||||
|         $subTitle = trans( | ||||
|             'firefly.without_category_between', | ||||
|             ['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)] | ||||
|         ); | ||||
|  | ||||
|         return view('categories.noCategory', compact('list', 'subTitle')); | ||||
|     } | ||||
| @@ -147,10 +151,12 @@ class CategoryController extends Controller | ||||
|         $page         = intval(Input::get('page')); | ||||
|         $set          = $repository->getJournals($category, $page); | ||||
|         $count        = $repository->countJournals($category); | ||||
|         $totalSum     = $repository->journalsSum($category); | ||||
|         $periodSum    = $repository->journalsSum($category, Session::get('start'), Session::get('end')); | ||||
|         $journals     = new LengthAwarePaginator($set, $count, 50, $page); | ||||
|         $journals->setPath('categories/show/' . $category->id); | ||||
|  | ||||
|         return view('categories.show', compact('category', 'journals', 'hideCategory')); | ||||
|         return view('categories.show', compact('category', 'journals', 'hideCategory', 'totalSum', 'periodSum')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -165,17 +171,18 @@ class CategoryController extends Controller | ||||
|             'name' => $request->input('name'), | ||||
|             'user' => Auth::user()->id, | ||||
|         ]; | ||||
|         $category = $repository->store($categoryData); | ||||
|         $category     = $repository->store($categoryData); | ||||
|  | ||||
|         Session::flash('success', 'New category "' . $category->name . '" stored!'); | ||||
|         Preferences::mark(); | ||||
|  | ||||
|         if (intval(Input::get('create_another')) === 1) { | ||||
|             Session::put('categories.create.fromStore', true); | ||||
|  | ||||
|             return Redirect::route('categories.create')->withInput(); | ||||
|             return redirect(route('categories.create'))->withInput(); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('categories.index'); | ||||
|         return redirect(route('categories.index')); | ||||
|     } | ||||
|  | ||||
|  | ||||
| @@ -195,15 +202,16 @@ class CategoryController extends Controller | ||||
|         $repository->update($category, $categoryData); | ||||
|  | ||||
|         Session::flash('success', 'Category "' . $category->name . '" updated.'); | ||||
|         Preferences::mark(); | ||||
|  | ||||
|         if (intval(Input::get('return_to_edit')) === 1) { | ||||
|             Session::put('categories.edit.fromUpdate', true); | ||||
|  | ||||
|             return Redirect::route('categories.edit', [$category->id]); | ||||
|             return redirect(route('categories.edit', [$category->id])); | ||||
|         } | ||||
|  | ||||
|         // redirect to previous URL. | ||||
|         return Redirect::to(Session::get('categories.edit.url')); | ||||
|         return redirect(Session::get('categories.edit.url')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -6,12 +6,11 @@ use Carbon\Carbon; | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use Grumpydictator\Gchart\GChart; | ||||
| use FireflyIII\Support\CacheProperties; | ||||
| use Illuminate\Support\Collection; | ||||
| use Preferences; | ||||
| use Response; | ||||
| use Session; | ||||
| use Steam; | ||||
|  | ||||
| /** | ||||
|  * Class AccountController | ||||
| @@ -20,10 +19,24 @@ use Steam; | ||||
|  */ | ||||
| class AccountController extends Controller | ||||
| { | ||||
|  | ||||
|     /** @var  \FireflyIII\Generator\Chart\Account\AccountChartGenerator */ | ||||
|     protected $generator; | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         // create chart generator: | ||||
|         $this->generator = app('FireflyIII\Generator\Chart\Account\AccountChartGenerator'); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Shows the balances for all the user's accounts. | ||||
|      * | ||||
|      * @param GChart                     $chart | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * | ||||
|      * @param                            $year | ||||
| @@ -32,12 +45,21 @@ class AccountController extends Controller | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function all(GChart $chart, AccountRepositoryInterface $repository, $year, $month, $shared = false) | ||||
|     public function all(AccountRepositoryInterface $repository, $year, $month, $shared = false) | ||||
|     { | ||||
|         $start = new Carbon($year . '-' . $month . '-01'); | ||||
|         $end   = clone $start; | ||||
|         $end->endOfMonth(); | ||||
|         $chart->addColumn(trans('firefly.dayOfMonth'), 'date'); | ||||
|  | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties(); | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty('all'); | ||||
|         $cache->addProperty('accounts'); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         /** @var Collection $accounts */ | ||||
|         $accounts = $repository->getAccounts(['Default account', 'Asset account']); | ||||
| @@ -50,103 +72,102 @@ class AccountController extends Controller | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // make chart: | ||||
|         $data = $this->generator->all($accounts, $start, $end); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         $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 Response::json($data); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Shows the balances for all the user's expense accounts. | ||||
|      * | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function expenseAccounts(AccountRepositoryInterface $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); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Shows the balances for all the user's frontpage accounts. | ||||
|      * | ||||
|      * @param GChart                     $chart | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function frontpage(GChart $chart, AccountRepositoryInterface $repository) | ||||
|     public function frontpage(AccountRepositoryInterface $repository) | ||||
|     { | ||||
|         $chart->addColumn(trans('firefly.dayOfMonth'), 'date'); | ||||
|  | ||||
|         $frontPage = Preferences::get('frontPageAccounts', []); | ||||
|         $start     = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end       = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $start     = clone Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end       = clone Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $accounts  = $repository->getFrontpageAccounts($frontPage); | ||||
|  | ||||
|         $index = 1; | ||||
|         /** @var Account $account */ | ||||
|         foreach ($accounts as $account) { | ||||
|             $chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number'); | ||||
|             $chart->addCertainty($index); | ||||
|             $index++; | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties(); | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty('frontpage'); | ||||
|         $cache->addProperty('accounts'); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|         $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 Response::json($chart->getData()); | ||||
|         $data = $this->generator->frontpage($accounts, $start, $end); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Shows an account's balance for a single month. | ||||
|      * | ||||
|      * @param GChart  $chart | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function single(GChart $chart, Account $account) | ||||
|     public function single(Account $account) | ||||
|     { | ||||
|         $chart->addColumn(trans('firefly.dayOfMonth'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number'); | ||||
|         $chart->addCertainty(1); | ||||
|  | ||||
|         $start   = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end     = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $current = clone $start; | ||||
|         $today   = new Carbon; | ||||
|  | ||||
|         while ($end >= $current) { | ||||
|             $certain = $current < $today; | ||||
|             $chart->addRow(clone $current, Steam::balance($account, $current), $certain); | ||||
|             $current->addDay(); | ||||
|         $start = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end   = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|  | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties(); | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty('frontpage'); | ||||
|         $cache->addProperty('single'); | ||||
|         $cache->addProperty($account->id); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $data = $this->generator->single($account, $start, $end); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|         return Response::json($data); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -6,13 +6,10 @@ use Carbon\Carbon; | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Bill\BillRepositoryInterface; | ||||
| use Grumpydictator\Gchart\GChart; | ||||
| use Illuminate\Support\Collection; | ||||
| use FireflyIII\Support\CacheProperties; | ||||
| use Response; | ||||
| use Session; | ||||
| use Steam; | ||||
|  | ||||
| /** | ||||
|  * Class BillController | ||||
| @@ -21,120 +18,86 @@ use Steam; | ||||
|  */ | ||||
| class BillController extends Controller | ||||
| { | ||||
|  | ||||
|     /** @var  \FireflyIII\Generator\Chart\Bill\BillChartGenerator */ | ||||
|     protected $generator; | ||||
|  | ||||
|     /** | ||||
|      * Shows the overview for a bill. The min/max amount and matched journals. | ||||
|      * | ||||
|      * @param GChart                  $chart | ||||
|      * @param BillRepositoryInterface $repository | ||||
|      * @param Bill                    $bill | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      * @codeCoverageIgnore | ||||
|      */ | ||||
|     public function single(GChart $chart, BillRepositoryInterface $repository, Bill $bill) | ||||
|     public function __construct() | ||||
|     { | ||||
|  | ||||
|         $chart->addColumn(trans('firefly.date'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.maxAmount'), 'number'); | ||||
|         $chart->addColumn(trans('firefly.minAmount'), 'number'); | ||||
|         $chart->addColumn(trans('firefly.billEntry'), 'number'); | ||||
|  | ||||
|         // get first transaction or today for start: | ||||
|         $results = $repository->getJournals($bill); | ||||
|         /** @var TransactionJournal $result */ | ||||
|         foreach ($results as $result) { | ||||
|             $chart->addRow(clone $result->date, floatval($bill->amount_max), floatval($bill->amount_min), floatval($result->amount)); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|         parent::__construct(); | ||||
|         // create chart generator: | ||||
|         $this->generator = app('FireflyIII\Generator\Chart\Bill\BillChartGenerator'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Shows all bills and whether or not theyve been paid this month (pie chart). | ||||
|      * | ||||
|      * @param GChart                     $chart | ||||
|      * | ||||
|      * @param BillRepositoryInterface    $repository | ||||
|      * @param AccountRepositoryInterface $accounts | ||||
|      * @param BillRepositoryInterface $repository | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function frontpage(GChart $chart, BillRepositoryInterface $repository, AccountRepositoryInterface $accounts) | ||||
|     public function frontpage(BillRepositoryInterface $repository) | ||||
|     { | ||||
|         $chart->addColumn(trans('firefly.name'), 'string'); | ||||
|         $chart->addColumn(trans('firefly.amount'), 'number'); | ||||
|         $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()); | ||||
|         $bills  = $repository->getActiveBills(); | ||||
|         $paid   = new Collection; // journals. | ||||
|         $unpaid = new Collection; // bills | ||||
|         // loop paid and create single entry: | ||||
|         $paidDescriptions   = []; | ||||
|         $paidAmount         = 0; | ||||
|         $unpaidDescriptions = []; | ||||
|         $unpaidAmount       = 0; | ||||
|         $set = $repository->getBillsForChart($start, $end); | ||||
|  | ||||
|         /** @var Bill $bill */ | ||||
|         foreach ($bills as $bill) { | ||||
|             $ranges = $repository->getRanges($bill, $start, $end); | ||||
|         // optionally expand this set with credit card data | ||||
|         $set    = $repository->getCreditCardInfoForChart($set, $start, $end); | ||||
|         $paid   = $set->get('paid'); | ||||
|         $unpaid = $set->get('unpaid'); | ||||
|  | ||||
|             foreach ($ranges as $range) { | ||||
|                 // paid a bill in this range? | ||||
|                 $journals = $repository->getJournalsInRange($bill, $range['start'], $range['end']); | ||||
|                 if ($journals->count() == 0) { | ||||
|                     $unpaid->push([$bill, $range['start']]); | ||||
|                 } else { | ||||
|                     $paid = $paid->merge($journals); | ||||
|                 } | ||||
|  | ||||
|         // build chart: | ||||
|         $data = $this->generator->frontpage($paid, $unpaid); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Shows the overview for a bill. The min/max amount and matched journals. | ||||
|      * | ||||
|      * @param BillRepositoryInterface $repository | ||||
|      * @param Bill                    $bill | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function single(BillRepositoryInterface $repository, Bill $bill) | ||||
|     { | ||||
|         $cache = new CacheProperties; | ||||
|         $cache->addProperty('single'); | ||||
|         $cache->addProperty('bill'); | ||||
|         $cache->addProperty($bill->id); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         // get first transaction or today for start: | ||||
|         $results = $repository->getJournals($bill); | ||||
|  | ||||
|         // resort: | ||||
|         $results = $results->sortBy( | ||||
|             function (TransactionJournal $journal) { | ||||
|                 return $journal->date->format('U'); | ||||
|             } | ||||
|         } | ||||
|         ); | ||||
|  | ||||
|         $creditCards = $accounts->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; | ||||
|                 $amount      = $balance * -1; | ||||
|                 $fakeBill    = $repository->createFakeBill($description, $date, $amount); | ||||
|                 unset($description, $amount); | ||||
|                 $unpaid->push([$fakeBill, $date]); | ||||
|             } | ||||
|             if ($balance == 0) { | ||||
|                 // find transfer(s) TO the credit card which should account for | ||||
|                 // anything paid. If not, the CC is not yet used. | ||||
|                 $journals = $accounts->getTransfersInRange($creditCard, $start, $end); | ||||
|                 $paid     = $paid->merge($journals); | ||||
|             } | ||||
|         } | ||||
|         $data = $this->generator->single($bill, $results); | ||||
|         $cache->store($data); | ||||
|  | ||||
|  | ||||
|         /** @var TransactionJournal $entry */ | ||||
|         foreach ($paid as $entry) { | ||||
|  | ||||
|             $paidDescriptions[] = $entry->description; | ||||
|             $paidAmount += floatval($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 += $amount; | ||||
|             unset($amount, $description); | ||||
|         } | ||||
|  | ||||
|         $chart->addRow(trans('firefly.unpaid') . ': ' . join(', ', $unpaidDescriptions), $unpaidAmount); | ||||
|         $chart->addRow(trans('firefly.paid') . ': ' . join(', ', $paidDescriptions), $paidAmount); | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|         return Response::json($data); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -7,7 +7,7 @@ use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\LimitRepetition; | ||||
| use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| use Grumpydictator\Gchart\GChart; | ||||
| use FireflyIII\Support\CacheProperties; | ||||
| use Illuminate\Support\Collection; | ||||
| use Navigation; | ||||
| use Preferences; | ||||
| @@ -21,19 +21,30 @@ use Session; | ||||
|  */ | ||||
| class BudgetController extends Controller | ||||
| { | ||||
|  | ||||
|     /** @var  \FireflyIII\Generator\Chart\Budget\BudgetChartGenerator */ | ||||
|     protected $generator; | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         // create chart generator: | ||||
|         $this->generator = app('FireflyIII\Generator\Chart\Budget\BudgetChartGenerator'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param GChart                    $chart | ||||
|      * @param BudgetRepositoryInterface $repository | ||||
|      * @param Budget                    $budget | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function budget(GChart $chart, BudgetRepositoryInterface $repository, Budget $budget) | ||||
|     public function budget(BudgetRepositoryInterface $repository, Budget $budget) | ||||
|     { | ||||
|         $chart->addColumn(trans('firefly.period'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.spent'), 'number'); | ||||
|  | ||||
|  | ||||
|         // dates and times | ||||
|         $first = $repository->getFirstBudgetLimitDate($budget); | ||||
|         $range = Preferences::get('viewRange', '1M')->data; | ||||
|         $last  = Session::get('end', new Carbon); | ||||
| @@ -41,157 +52,198 @@ class BudgetController extends Controller | ||||
|         $final->addYears(2); | ||||
|         $last = Navigation::endOfX($last, $range, $final); | ||||
|  | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties(); | ||||
|         $cache->addProperty($first); | ||||
|         $cache->addProperty($last); | ||||
|         $cache->addProperty('budget'); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $entries = new Collection; | ||||
|  | ||||
|         while ($first < $last) { | ||||
|             $end = Navigation::addPeriod($first, $range, 0); | ||||
|  | ||||
|             $spent = $repository->spentInPeriodCorrected($budget, $first, $end); | ||||
|             $chart->addRow($end, $spent); | ||||
|  | ||||
|  | ||||
|             $end->subDay(); | ||||
|             $chartDate = clone $end; | ||||
|             $chartDate->startOfMonth(); | ||||
|             $spent = $repository->balanceInPeriod($budget, $first, $end); | ||||
|             $entries->push([$chartDate, $spent]); | ||||
|             $first = Navigation::addPeriod($first, $range, 0); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|         $data = $this->generator->budget($entries); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|         return Response::json($data); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Shows the amount left in a specific budget limit. | ||||
|      * | ||||
|      * @param GChart                    $chart | ||||
|      * @param BudgetRepositoryInterface $repository | ||||
|      * @param Budget                    $budget | ||||
|      * @param LimitRepetition           $repetition | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function budgetLimit(GChart $chart, BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition) | ||||
|     public function budgetLimit(BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition) | ||||
|     { | ||||
|         $start = clone $repetition->startdate; | ||||
|         $end   = $repetition->enddate; | ||||
|         bcscale(2); | ||||
|  | ||||
|         $chart->addColumn(trans('firefly.day'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.left'), 'number'); | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties(); | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty('budget'); | ||||
|         $cache->addProperty('limit'); | ||||
|         $cache->addProperty($budget->id); | ||||
|         $cache->addProperty($repetition->id); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $amount = $repetition->amount; | ||||
|         $entries = new Collection; | ||||
|         $amount  = $repetition->amount; | ||||
|  | ||||
|         while ($start <= $end) { | ||||
|             /* | ||||
|              * Sum of expenses on this day: | ||||
|              */ | ||||
|             $sum = $repository->expensesOnDayCorrected($budget, $start); | ||||
|             $amount += $sum; | ||||
|             $chart->addRow(clone $start, $amount); | ||||
|             $sum    = $repository->expensesOnDayCorrected($budget, $start); | ||||
|             $amount = bcadd($amount, $sum); | ||||
|             $entries->push([clone $start, $amount]); | ||||
|             $start->addDay(); | ||||
|         } | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|         $data = $this->generator->budgetLimit($entries); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Shows a budget list with spent/left/overspent. | ||||
|      * | ||||
|      * @param GChart                    $chart | ||||
|      * @param BudgetRepositoryInterface $repository | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function frontpage(GChart $chart, BudgetRepositoryInterface $repository) | ||||
|     public function frontpage(BudgetRepositoryInterface $repository) | ||||
|     { | ||||
|         $chart->addColumn(trans('firefly.budget'), 'string'); | ||||
|         $chart->addColumn(trans('firefly.left'), 'number'); | ||||
|         $chart->addColumn(trans('firefly.spent'), 'number'); | ||||
|         $chart->addColumn(trans('firefly.overspent'), 'number'); | ||||
|  | ||||
|         $budgets    = $repository->getBudgets(); | ||||
|         $start      = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end        = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $allEntries = new Collection; | ||||
|  | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties(); | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty('budget'); | ||||
|         $cache->addProperty('all'); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         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]); | ||||
|                 $expenses = $repository->balanceInPeriod($budget, $start, $end, true); | ||||
|                 $allEntries->push([$budget->name, 0, 0, $expenses, 0, 0]); | ||||
|                 continue; | ||||
|             } | ||||
|             /** @var LimitRepetition $repetition */ | ||||
|             foreach ($repetitions as $repetition) { | ||||
|                 $expenses  = $repository->spentInPeriodCorrected($budget, $repetition->startdate, $repetition->enddate, true); | ||||
|                 $left      = $expenses < floatval($repetition->amount) ? floatval($repetition->amount) - $expenses : 0; | ||||
|                 $spent     = $expenses > floatval($repetition->amount) ? floatval($repetition->amount) : $expenses; | ||||
|                 $overspent = $expenses > floatval($repetition->amount) ? $expenses - floatval($repetition->amount) : 0; | ||||
|                 $allEntries->push( | ||||
|                     [$budget->name . ' (' . $repetition->startdate->formatLocalized($this->monthAndDayFormat) . ')', | ||||
|                         $left, | ||||
|                         $spent, | ||||
|                         $overspent | ||||
|                     ] | ||||
|                 ); | ||||
|                 $expenses = $repository->balanceInPeriod($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]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $noBudgetExpenses = $repository->getWithoutBudgetSum($start, $end) * -1; | ||||
|         $allEntries->push([trans('firefly.noBudget'), 0, 0, $noBudgetExpenses]); | ||||
|         $allEntries->push([trans('firefly.noBudget'), 0, 0, $noBudgetExpenses, 0, 0]); | ||||
|  | ||||
|         foreach ($allEntries as $entry) { | ||||
|             if ($entry[1] != 0 || $entry[2] != 0 || $entry[3] != 0) { | ||||
|                 $chart->addRow($entry[0], $entry[1], $entry[2], $entry[3]); | ||||
|             } | ||||
|         } | ||||
|         $data = $this->generator->frontpage($allEntries); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|         return Response::json($data); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show a yearly overview for a budget. | ||||
|      * | ||||
|      * @param GChart                    $chart | ||||
|      * @param BudgetRepositoryInterface $repository | ||||
|      * @param                           $year | ||||
|      * @param bool                      $shared | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function year(GChart $chart, BudgetRepositoryInterface $repository, $year, $shared = false) | ||||
|     public function year(BudgetRepositoryInterface $repository, $year, $shared = false) | ||||
|     { | ||||
|         $start   = new Carbon($year . '-01-01'); | ||||
|         $end     = new Carbon($year . '-12-31'); | ||||
|         $shared  = $shared == 'shared' ? true : false; | ||||
|         $budgets = $repository->getBudgets(); | ||||
|         $start      = new Carbon($year . '-01-01'); | ||||
|         $end        = new Carbon($year . '-12-31'); | ||||
|         $shared     = $shared == 'shared' ? true : false; | ||||
|         $allBudgets = $repository->getBudgets(); | ||||
|         $budgets    = new Collection; | ||||
|  | ||||
|         // add columns: | ||||
|         $chart->addColumn(trans('firefly.month'), 'date'); | ||||
|         foreach ($budgets as $budget) { | ||||
|             $chart->addColumn($budget->name, 'number'); | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties(); | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty('budget'); | ||||
|         $cache->addProperty('year'); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         // filter empty budgets: | ||||
|  | ||||
|         foreach ($allBudgets as $budget) { | ||||
|             $spent = $repository->balanceInPeriod($budget, $start, $end, $shared); | ||||
|             if ($spent != 0) { | ||||
|                 $budgets->push($budget); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $entries = new Collection; | ||||
|  | ||||
|         while ($start < $end) { | ||||
|             // month is the current end of the period: | ||||
|             $month = clone $start; | ||||
|             $month->endOfMonth(); | ||||
|             // make a row: | ||||
|             $row = [clone $start]; | ||||
|  | ||||
|             // each budget, fill the row: | ||||
|             foreach ($budgets as $budget) { | ||||
|                 $spent = $repository->spentInPeriodCorrected($budget, $start, $month, $shared); | ||||
|                 $row[] = $spent; | ||||
|                 $spent = $repository->balanceInPeriod($budget, $start, $month, $shared); | ||||
|                 $row[] = $spent * -1; | ||||
|             } | ||||
|             $chart->addRowArray($row); | ||||
|  | ||||
|             $start->addMonth(); | ||||
|             $entries->push($row); | ||||
|             $start->endOfMonth()->addDay(); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|         $data = $this->generator->year($allBudgets, $entries); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|         return Response::json($data); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -7,7 +7,8 @@ use Carbon\Carbon; | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Models\Category; | ||||
| use FireflyIII\Repositories\Category\CategoryRepositoryInterface; | ||||
| use Grumpydictator\Gchart\GChart; | ||||
| use FireflyIII\Support\CacheProperties; | ||||
| use Illuminate\Support\Collection; | ||||
| use Navigation; | ||||
| use Preferences; | ||||
| use Response; | ||||
| @@ -20,42 +21,60 @@ use Session; | ||||
|  */ | ||||
| class CategoryController extends Controller | ||||
| { | ||||
|     /** @var  \FireflyIII\Generator\Chart\Category\CategoryChartGenerator */ | ||||
|     protected $generator; | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         // create chart generator: | ||||
|         $this->generator = app('FireflyIII\Generator\Chart\Category\CategoryChartGenerator'); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Show an overview for a category for all time, per month/week/year. | ||||
|      * | ||||
|      * @param GChart                      $chart | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param Category                    $category | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function all(GChart $chart, CategoryRepositoryInterface $repository, Category $category) | ||||
|     public function all(CategoryRepositoryInterface $repository, Category $category) | ||||
|     { | ||||
|         // oldest transaction in category: | ||||
|         $start = $repository->getFirstActivityDate($category); | ||||
|         $range = Preferences::get('viewRange', '1M')->data; | ||||
|         // jump to start of week / month / year / etc | ||||
|         $start = Navigation::startOfPeriod($start, $range); | ||||
|  | ||||
|         $chart->addColumn(trans('firefly.period'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.spent'), 'number'); | ||||
|         $start   = $repository->getFirstActivityDate($category); | ||||
|         $range   = Preferences::get('viewRange', '1M')->data; | ||||
|         $start   = Navigation::startOfPeriod($start, $range); | ||||
|         $end     = new Carbon; | ||||
|         $entries = new Collection; | ||||
|  | ||||
|  | ||||
|         $end = new Carbon; | ||||
|         while ($start <= $end) { | ||||
|  | ||||
|             $currentEnd = Navigation::endOfPeriod($start, $range); | ||||
|             $spent      = $repository->spentInPeriodCorrected($category, $start, $currentEnd); | ||||
|             $chart->addRow(clone $start, $spent); | ||||
|  | ||||
|             $start = Navigation::addPeriod($start, $range, 0); | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties(); | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty('all'); | ||||
|         $cache->addProperty('categories'); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|         while ($start <= $end) { | ||||
|             $currentEnd = Navigation::endOfPeriod($start, $range); | ||||
|             $spent      = $repository->balanceInPeriod($category, $start, $currentEnd); | ||||
|             $entries->push([clone $start, $spent]); | ||||
|             $start = Navigation::addPeriod($start, $range, 0); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|         } | ||||
|  | ||||
|         $data = $this->generator->all($entries); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
|  | ||||
|  | ||||
|     } | ||||
| @@ -63,24 +82,31 @@ class CategoryController extends Controller | ||||
|     /** | ||||
|      * Show this month's category overview. | ||||
|      * | ||||
|      * @param GChart                      $chart | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function frontpage(GChart $chart, CategoryRepositoryInterface $repository) | ||||
|     public function frontpage(CategoryRepositoryInterface $repository) | ||||
|     { | ||||
|         $chart->addColumn(trans('firefly.category'), 'string'); | ||||
|         $chart->addColumn(trans('firefly.spent'), 'number'); | ||||
|  | ||||
|         $start = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end   = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $set   = $repository->getCategoriesAndExpensesCorrected($start, $end); | ||||
|  | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties; | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty('category'); | ||||
|         $cache->addProperty('frontpage'); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $array = $repository->getCategoriesAndExpensesCorrected($start, $end); | ||||
|         // sort by callback: | ||||
|         uasort( | ||||
|             $set, | ||||
|             function($left, $right) { | ||||
|             $array, | ||||
|             function ($left, $right) { | ||||
|                 if ($left['sum'] == $right['sum']) { | ||||
|                     return 0; | ||||
|                 } | ||||
| @@ -88,45 +114,48 @@ class CategoryController extends Controller | ||||
|                 return ($left['sum'] < $right['sum']) ? 1 : -1; | ||||
|             } | ||||
|         ); | ||||
|         $set  = new Collection($array); | ||||
|         $data = $this->generator->frontpage($set); | ||||
|  | ||||
|  | ||||
|         foreach ($set as $entry) { | ||||
|             $sum = floatval($entry['sum']); | ||||
|             if ($sum != 0) { | ||||
|                 $chart->addRow($entry['name'], $sum); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|         return Response::json($data); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param GChart                      $chart | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param Category                    $category | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function month(GChart $chart, CategoryRepositoryInterface $repository, Category $category) | ||||
|     public function month(CategoryRepositoryInterface $repository, Category $category) | ||||
|     { | ||||
|         $start = clone Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end   = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|  | ||||
|         $chart->addColumn(trans('firefly.period'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.spent'), 'number'); | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties; | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty($category->id); | ||||
|         $cache->addProperty('category'); | ||||
|         $cache->addProperty('month'); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|         $entries = new Collection; | ||||
|  | ||||
|  | ||||
|         while ($start <= $end) { | ||||
|             $spent = $repository->spentOnDaySumCorrected($category, $start); | ||||
|             $chart->addRow(clone $start, $spent); | ||||
|  | ||||
|             $entries->push([clone $start, $spent]); | ||||
|             $start->addDay(); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|         $data = $this->generator->month($entries); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|         return Response::json($data); | ||||
|  | ||||
|  | ||||
|     } | ||||
| @@ -134,45 +163,118 @@ class CategoryController extends Controller | ||||
|     /** | ||||
|      * This chart will only show expenses. | ||||
|      * | ||||
|      * @param GChart                      $chart | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param                             $year | ||||
|      * @param bool                        $shared | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function year(GChart $chart, CategoryRepositoryInterface $repository, $year, $shared = false) | ||||
|     public function spentInYear(CategoryRepositoryInterface $repository, $year, $shared = false) | ||||
|     { | ||||
|         $start      = new Carbon($year . '-01-01'); | ||||
|         $end        = new Carbon($year . '-12-31'); | ||||
|         $shared     = $shared == 'shared' ? true : false; | ||||
|         $categories = $repository->getCategories(); | ||||
|         $start = new Carbon($year . '-01-01'); | ||||
|         $end   = new Carbon($year . '-12-31'); | ||||
|  | ||||
|         // add columns: | ||||
|         $chart->addColumn(trans('firefly.month'), 'date'); | ||||
|         foreach ($categories as $category) { | ||||
|             $chart->addColumn($category->name, 'number'); | ||||
|         $cache = new CacheProperties; // chart properties for cache: | ||||
|         $cache->addProperty($start); | ||||
|         $cache->addProperty($end); | ||||
|         $cache->addProperty('category'); | ||||
|         $cache->addProperty('spent-in-year'); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $shared        = $shared == 'shared' ? true : false; | ||||
|         $allCategories = $repository->getCategories(); | ||||
|         $entries       = new Collection; | ||||
|         $categories    = $allCategories->filter( | ||||
|             function (Category $category) use ($repository, $start, $end, $shared) { | ||||
|                 $spent = $repository->balanceInPeriod($category, $start, $end, $shared); | ||||
|                 if ($spent < 0) { | ||||
|                     return $category; | ||||
|                 } | ||||
|  | ||||
|                 return null; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         while ($start < $end) { | ||||
|             // month is the current end of the period: | ||||
|             $month = clone $start; | ||||
|             $month = clone $start; // month is the current end of the period | ||||
|             $month->endOfMonth(); | ||||
|             // make a row: | ||||
|             $row = [clone $start]; | ||||
|             $row = [clone $start]; // make a row: | ||||
|  | ||||
|             // each budget, fill the row: | ||||
|             foreach ($categories as $category) { | ||||
|                 $spent = $repository->spentInPeriodCorrected($category, $start, $month, $shared); | ||||
|                 $row[] = $spent; | ||||
|             foreach ($categories as $category) { // each budget, fill the row | ||||
|                 $spent = $repository->balanceInPeriod($category, $start, $month, $shared); | ||||
|                 if ($spent < 0) { | ||||
|                     $row[] = $spent * -1; | ||||
|                 } else { | ||||
|                     $row[] = 0; | ||||
|                 } | ||||
|             } | ||||
|             $chart->addRowArray($row); | ||||
|  | ||||
|             $entries->push($row); | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|         $data = $this->generator->spentInYear($categories, $entries); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         $chart->generate(); | ||||
|         return Response::json($data); | ||||
|     } | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|     /** | ||||
|      * This chart will only show income. | ||||
|      * | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param                             $year | ||||
|      * @param bool                        $shared | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function earnedInYear(CategoryRepositoryInterface $repository, $year, $shared = false) | ||||
|     { | ||||
|         $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('category'); | ||||
|         $cache->addProperty('earned-in-year'); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $shared        = $shared == 'shared' ? true : false; | ||||
|         $allCategories = $repository->getCategories(); | ||||
|         $allEntries    = new Collection; | ||||
|         $categories    = $allCategories->filter( | ||||
|             function (Category $category) use ($repository, $start, $end, $shared) { | ||||
|                 $spent = $repository->balanceInPeriod($category, $start, $end, $shared); | ||||
|                 if ($spent > 0) { | ||||
|                     return $category; | ||||
|                 } | ||||
|  | ||||
|                 return null; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         while ($start < $end) { | ||||
|             $month = clone $start; // month is the current end of the period | ||||
|             $month->endOfMonth(); | ||||
|             $row = [clone $start]; // make a row: | ||||
|  | ||||
|             foreach ($categories as $category) { // each budget, fill the row | ||||
|                 $spent = $repository->balanceInPeriod($category, $start, $month, $shared); | ||||
|                 if ($spent > 0) { | ||||
|                     $row[] = $spent; | ||||
|                 } else { | ||||
|                     $row[] = 0; | ||||
|                 } | ||||
|             } | ||||
|             $allEntries->push($row); | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|         $data = $this->generator->earnedInYear($categories, $allEntries); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -2,11 +2,10 @@ | ||||
|  | ||||
| namespace FireflyIII\Http\Controllers\Chart; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; | ||||
| use Grumpydictator\Gchart\GChart; | ||||
| use FireflyIII\Support\CacheProperties; | ||||
| use Illuminate\Support\Collection; | ||||
| use Response; | ||||
|  | ||||
| @@ -18,32 +17,44 @@ use Response; | ||||
|  */ | ||||
| class PiggyBankController extends Controller | ||||
| { | ||||
|  | ||||
|     /** @var  \FireflyIII\Generator\Chart\PiggyBank\PiggyBankChartGenerator */ | ||||
|     protected $generator; | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         // create chart generator: | ||||
|         $this->generator = app('FireflyIII\Generator\Chart\PiggyBank\PiggyBankChartGenerator'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Shows the piggy bank history. | ||||
|      * | ||||
|      * @param GChart                       $chart | ||||
|      * @param PiggyBankRepositoryInterface $repository | ||||
|      * @param PiggyBank                    $piggyBank | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function history(GChart $chart, PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank) | ||||
|     public function history(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank) | ||||
|     { | ||||
|         $chart->addColumn(trans('firefly.date'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.balance'), 'number'); | ||||
|  | ||||
|         /** @var Collection $set */ | ||||
|         $set = $repository->getEventSummarySet($piggyBank); | ||||
|         $sum = 0; | ||||
|  | ||||
|         foreach ($set as $entry) { | ||||
|             $sum += floatval($entry->sum); | ||||
|             $chart->addRow(new Carbon($entry->date), $sum); | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties; | ||||
|         $cache->addProperty('piggy-history'); | ||||
|         $cache->addProperty($piggyBank->id); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|         /** @var Collection $set */ | ||||
|         $set  = new Collection($repository->getEventSummarySet($piggyBank)); | ||||
|         $data = $this->generator->history($set); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|         return Response::json($data); | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -6,7 +6,8 @@ namespace FireflyIII\Http\Controllers\Chart; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Helpers\Report\ReportQueryInterface; | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use Grumpydictator\Gchart\GChart; | ||||
| use FireflyIII\Support\CacheProperties; | ||||
| use Illuminate\Support\Collection; | ||||
| use Response; | ||||
|  | ||||
| /** | ||||
| @@ -17,85 +18,108 @@ use Response; | ||||
| class ReportController extends Controller | ||||
| { | ||||
|  | ||||
|     /** @var  \FireflyIII\Generator\Chart\Report\ReportChartGenerator */ | ||||
|     protected $generator; | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         // create chart generator: | ||||
|         $this->generator = app('FireflyIII\Generator\Chart\Report\ReportChartGenerator'); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Summarizes all income and expenses, per month, for a given year. | ||||
|      * | ||||
|      * @param GChart               $chart | ||||
|      * @param ReportQueryInterface $query | ||||
|      * @param                      $year | ||||
|      * @param bool                 $shared | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function yearInOut(GChart $chart, ReportQueryInterface $query, $year, $shared = false) | ||||
|     public function yearInOut(ReportQueryInterface $query, $year, $shared = false) | ||||
|     { | ||||
|         // get start and end of year | ||||
|         $start  = new Carbon($year . '-01-01'); | ||||
|         $end    = new Carbon($year . '-12-31'); | ||||
|         $shared = $shared == 'shared' ? true : false; | ||||
|  | ||||
|         $chart->addColumn(trans('firefly.month'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.income'), 'number'); | ||||
|         $chart->addColumn(trans('firefly.expenses'), 'number'); | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties; | ||||
|         $cache->addProperty('yearInOut'); | ||||
|         $cache->addProperty($year); | ||||
|         $cache->addProperty($shared); | ||||
|         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  = floatval($query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount')); | ||||
|             $expenseSum = floatval($query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount')); | ||||
|             $incomeSum  = $query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount'); | ||||
|             $expenseSum = $query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount'); | ||||
|  | ||||
|             $chart->addRow(clone $start, $incomeSum, $expenseSum); | ||||
|             $entries->push([clone $start, $incomeSum, $expenseSum]); | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|         $data = $this->generator->yearInOut($entries); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         return Response::json($data); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Summarizes all income and expenses for a given year. Gives a total and an average. | ||||
|      * | ||||
|      * @param GChart               $chart | ||||
|      * @param ReportQueryInterface $query | ||||
|      * @param                      $year | ||||
|      * @param bool                 $shared | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function yearInOutSummarized(GChart $chart, ReportQueryInterface $query, $year, $shared = false) | ||||
|     public function yearInOutSummarized(ReportQueryInterface $query, $year, $shared = false) | ||||
|     { | ||||
|  | ||||
|         // chart properties for cache: | ||||
|         $cache = new CacheProperties; | ||||
|         $cache->addProperty('yearInOutSummarized'); | ||||
|         $cache->addProperty($year); | ||||
|         $cache->addProperty($shared); | ||||
|         if ($cache->has()) { | ||||
|             return Response::json($cache->get()); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $start   = new Carbon($year . '-01-01'); | ||||
|         $end     = new Carbon($year . '-12-31'); | ||||
|         $shared  = $shared == 'shared' ? true : false; | ||||
|         $income  = 0; | ||||
|         $expense = 0; | ||||
|         $income  = '0'; | ||||
|         $expense = '0'; | ||||
|         $count   = 0; | ||||
|  | ||||
|         $chart->addColumn(trans('firefly.summary'), 'string'); | ||||
|         $chart->addColumn(trans('firefly.income'), 'number'); | ||||
|         $chart->addColumn(trans('firefly.expenses'), 'number'); | ||||
|         bcscale(2); | ||||
|  | ||||
|         while ($start < $end) { | ||||
|             $month = clone $start; | ||||
|             $month->endOfMonth(); | ||||
|             // total income and total expenses: | ||||
|             $income += floatval($query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount')); | ||||
|             $expense += floatval($query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount')); | ||||
|             $income  = bcadd($income, $query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount')); | ||||
|             $expense = bcadd($expense, $query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount')); | ||||
|             $count++; | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|  | ||||
|         // add total + average: | ||||
|         $chart->addRow(trans('firefly.sum'), $income, $expense); | ||||
|         $count = $count > 0 ? $count : 1; | ||||
|         $chart->addRow(trans('firefly.average'), ($income / $count), ($expense / $count)); | ||||
|         $data = $this->generator->yearInOutSummarized($income, $expense, $count); | ||||
|         $cache->store($data); | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|         return Response::json($data); | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
|  | ||||
| use Auth; | ||||
| use Config; | ||||
| use Illuminate\Foundation\Bus\DispatchesCommands; | ||||
| use Illuminate\Foundation\Bus\DispatchesJobs; | ||||
| use Illuminate\Foundation\Validation\ValidatesRequests; | ||||
| use Illuminate\Routing\Controller as BaseController; | ||||
| use Preferences; | ||||
| @@ -16,7 +16,7 @@ use View; | ||||
| abstract class Controller extends BaseController | ||||
| { | ||||
|  | ||||
|     use DispatchesCommands, ValidatesRequests; | ||||
|     use DispatchesJobs, ValidatesRequests; | ||||
|  | ||||
|     /** @var string */ | ||||
|     protected $monthAndDayFormat; | ||||
|   | ||||
							
								
								
									
										64
									
								
								app/Http/Controllers/CronController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								app/Http/Controllers/CronController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use FireflyIII\User; | ||||
|  | ||||
| /** | ||||
|  * Class WebhookController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| class CronController extends Controller | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Firefly doesn't have anything that should be in the a cron job, except maybe this one, and it's fairly exceptional. | ||||
|      * | ||||
|      * If you use SendGrid like I do, you can detect bounces and thereby check if users gave an invalid address. If they did, | ||||
|      * it's easy to block them and change their password. Optionally, you could notify yourself about it and send them a message. | ||||
|      * | ||||
|      * But thats something not supported right now. | ||||
|      */ | ||||
|     public function sendgrid() | ||||
|     { | ||||
|  | ||||
|         if (strlen(env('SENDGRID_USERNAME')) > 0 && strlen(env('SENDGRID_PASSWORD')) > 0) { | ||||
|  | ||||
|             $URL        = 'https://api.sendgrid.com/api/bounces.get.json'; | ||||
|             $parameters = [ | ||||
|                 'api_user' => env('SENDGRID_USERNAME'), | ||||
|                 'api_key'  => env('SENDGRID_PASSWORD'), | ||||
|                 'date'     => 1, | ||||
|                 'days'     => 7 | ||||
|             ]; | ||||
|             $fullURL    = $URL . '?' . http_build_query($parameters); | ||||
|             $data       = json_decode(file_get_contents($fullURL)); | ||||
|  | ||||
|             /* | ||||
|              * Loop the result, if any. | ||||
|              */ | ||||
|             if (is_array($data)) { | ||||
|                 echo 'Found ' . count($data) . ' entries in the SendGrid bounce list.' . "\n"; | ||||
|                 foreach ($data as $entry) { | ||||
|                     $address = $entry->email; | ||||
|                     $user    = User::where('email', $address)->where('blocked', 0)->first(); | ||||
|                     if (!is_null($user)) { | ||||
|                         echo 'Found a user: ' . $address . ', who is now blocked.' . "\n"; | ||||
|                         $user->blocked      = 1; | ||||
|                         $user->blocked_code = 'bounced'; | ||||
|                         $user->password     = 'bounced'; | ||||
|                         $user->save(); | ||||
|                     } else { | ||||
|                         echo 'Found no user: ' . $address . ', did nothing.' . "\n"; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             echo 'Done!' . "\n"; | ||||
|         } else { | ||||
|             echo 'Please fill in SendGrid details.'; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										410
									
								
								app/Http/Controllers/CsvController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										410
									
								
								app/Http/Controllers/CsvController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,410 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Config; | ||||
| use ExpandedForm; | ||||
| 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 Illuminate\Http\Request; | ||||
| use Input; | ||||
| use Log; | ||||
| use Preferences; | ||||
| use Session; | ||||
| use View; | ||||
|  | ||||
| /** | ||||
|  * Class CsvController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| class CsvController extends Controller | ||||
| { | ||||
|  | ||||
|     /** @var  Data */ | ||||
|     protected $data; | ||||
|     /** @var  WizardInterface */ | ||||
|     protected $wizard; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         View::share('title', trans('firefly.csv')); | ||||
|         View::share('mainTitleIcon', 'fa-file-text-o'); | ||||
|  | ||||
|         if (Config::get('firefly.csv_import_enabled') === false) { | ||||
|             throw new FireflyException('CSV Import is not enabled.'); | ||||
|         } | ||||
|  | ||||
|         $this->wizard = app('FireflyIII\Helpers\Csv\WizardInterface'); | ||||
|         $this->data   = app('FireflyIII\Helpers\Csv\Data'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Define column roles and mapping. | ||||
|      * | ||||
|      * STEP THREE | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View | ||||
|      */ | ||||
|     public function columnRoles() | ||||
|     { | ||||
|  | ||||
|         $fields = ['csv-file', 'csv-date-format', 'csv-has-headers', 'csv-import-account']; | ||||
|         if (!$this->wizard->sessionHasValues($fields)) { | ||||
|             Session::flash('warning', 'Could not recover upload.'); | ||||
|  | ||||
|             return redirect(route('csv.index')); | ||||
|         } | ||||
|  | ||||
|         $subTitle       = trans('firefly.csv_define_column_roles'); | ||||
|         $firstRow       = $this->data->getReader()->fetchOne(); | ||||
|         $count          = count($firstRow); | ||||
|         $headers        = []; | ||||
|         $example        = $this->data->getReader()->fetchOne(1); | ||||
|         $availableRoles = []; | ||||
|         $roles          = $this->data->getRoles(); | ||||
|         $map            = $this->data->getMap(); | ||||
|  | ||||
|         for ($i = 1; $i <= $count; $i++) { | ||||
|             $headers[] = trans('firefly.csv_column') . ' #' . $i; | ||||
|         } | ||||
|         if ($this->data->hasHeaders()) { | ||||
|             $headers = $firstRow; | ||||
|         } | ||||
|  | ||||
|         foreach (Config::get('csv.roles') as $name => $role) { | ||||
|             $availableRoles[$name] = trans('firefly.csv_column_' . $name);//$role['name']; | ||||
|         } | ||||
|         ksort($availableRoles); | ||||
|  | ||||
|         return view('csv.column-roles', compact('availableRoles', 'map', 'roles', 'headers', 'example', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Optional download of mapping. | ||||
|      * | ||||
|      * STEP FOUR THREE-A | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse|string | ||||
|      */ | ||||
|     public function downloadConfig() | ||||
|     { | ||||
|         $fields = ['csv-date-format', 'csv-has-headers']; | ||||
|         if (!$this->wizard->sessionHasValues($fields)) { | ||||
|             Session::flash('warning', 'Could not recover upload.'); | ||||
|  | ||||
|             return redirect(route('csv.index')); | ||||
|         } | ||||
|         $data = [ | ||||
|             'date-format' => Session::get('csv-date-format'), | ||||
|             'has-headers' => Session::get('csv-has-headers') | ||||
|         ]; | ||||
|         if (Session::has('csv-map')) { | ||||
|             $data['map'] = Session::get('csv-map'); | ||||
|         } | ||||
|         if (Session::has('csv-roles')) { | ||||
|             $data['roles'] = Session::get('csv-roles'); | ||||
|         } | ||||
|         if (Session::has('csv-mapped')) { | ||||
|             $data['mapped'] = Session::get('csv-mapped'); | ||||
|         } | ||||
|  | ||||
|         if (Session::has('csv-specifix')) { | ||||
|             $data['specifix'] = Session::get('csv-specifix'); | ||||
|         } | ||||
|  | ||||
|         $result = json_encode($data, JSON_PRETTY_PRINT); | ||||
|         $name   = 'csv-configuration-' . date('Y-m-d') . '.json'; | ||||
|  | ||||
|         header('Content-disposition: attachment; filename=' . $name); | ||||
|         header('Content-type: application/json'); | ||||
|         echo $result; | ||||
|  | ||||
|         return ''; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function downloadConfigPage() | ||||
|     { | ||||
|         $subTitle = trans('firefly.csv_download_config_title'); | ||||
|  | ||||
|         return view('csv.download-config', compact('subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method shows the initial upload form. | ||||
|      * | ||||
|      * STEP ONE | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function index(AccountRepositoryInterface $repository) | ||||
|     { | ||||
|         $subTitle = trans('firefly.csv_import'); | ||||
|  | ||||
|         Session::forget('csv-date-format'); | ||||
|         Session::forget('csv-has-headers'); | ||||
|         Session::forget('csv-file'); | ||||
|         Session::forget('csv-import-account'); | ||||
|         Session::forget('csv-map'); | ||||
|         Session::forget('csv-roles'); | ||||
|         Session::forget('csv-mapped'); | ||||
|         Session::forget('csv-specifix'); | ||||
|  | ||||
|         // get list of supported specifix | ||||
|         $specifix = []; | ||||
|         foreach (Config::get('csv.specifix') as $entry) { | ||||
|             $specifix[$entry] = trans('firefly.csv_specifix_' . $entry); | ||||
|         } | ||||
|  | ||||
|         // get a list of asset accounts: | ||||
|         $accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Asset account', 'Default account'])); | ||||
|  | ||||
|         // can actually upload? | ||||
|         $uploadPossible = is_writable(storage_path('upload')); | ||||
|         $path           = storage_path('upload'); | ||||
|  | ||||
|         return view('csv.index', compact('subTitle', 'uploadPossible', 'path', 'specifix', 'accounts')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Parse the file. | ||||
|      * | ||||
|      * STEP FOUR | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function initialParse() | ||||
|     { | ||||
|         $fields = ['csv-file', 'csv-date-format', 'csv-has-headers']; | ||||
|         if (!$this->wizard->sessionHasValues($fields)) { | ||||
|             Session::flash('warning', 'Could not recover upload.'); | ||||
|  | ||||
|             return redirect(route('csv.index')); | ||||
|         } | ||||
|  | ||||
|         // process given roles and mapping: | ||||
|         $roles = $this->wizard->processSelectedRoles(Input::get('role')); | ||||
|         $maps  = $this->wizard->processSelectedMapping($roles, Input::get('map')); | ||||
|  | ||||
|         Session::put('csv-map', $maps); | ||||
|         Session::put('csv-roles', $roles); | ||||
|  | ||||
|         // Go back when no roles defined: | ||||
|         if (count($roles) === 0) { | ||||
|             Session::flash('warning', 'Please select some roles.'); | ||||
|  | ||||
|             return redirect(route('csv.column-roles')); | ||||
|         } | ||||
|  | ||||
|         /* | ||||
|          * Continue with map specification when necessary. | ||||
|          */ | ||||
|         if (count($maps) > 0) { | ||||
|             return redirect(route('csv.map')); | ||||
|         } | ||||
|  | ||||
|         /* | ||||
|          * Or simply start processing. | ||||
|          */ | ||||
|  | ||||
|         // proceed to download config | ||||
|         return redirect(route('csv.download-config-page')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * Map first if necessary, | ||||
|      * | ||||
|      * STEP FIVE. | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function map() | ||||
|     { | ||||
|  | ||||
|         // Make sure all fields we need are accounted for. | ||||
|         $fields = ['csv-file', 'csv-date-format', 'csv-has-headers', 'csv-map', 'csv-roles']; | ||||
|         if (!$this->wizard->sessionHasValues($fields)) { | ||||
|             Session::flash('warning', 'Could not recover upload.'); | ||||
|  | ||||
|             return redirect(route('csv.index')); | ||||
|         } | ||||
|         /* | ||||
|          * The "options" array contains all options the user has | ||||
|          * per column, where the key represents the column. | ||||
|          * | ||||
|          * For each key there is an array which in turn represents | ||||
|          * all the options available: grouped by ID. | ||||
|          * | ||||
|          * options[column index] = [ | ||||
|          *       field id => field identifier. | ||||
|          * ] | ||||
|          */ | ||||
|         try { | ||||
|             $options = $this->wizard->showOptions($this->data->getMap()); | ||||
|         } catch (FireflyException $e) { | ||||
|             return view('error', ['message' => $e->getMessage()]); | ||||
|         } | ||||
|  | ||||
|         // After these values are prepped, read the actual CSV file | ||||
|         $reader     = $this->data->getReader(); | ||||
|         $map        = $this->data->getMap(); | ||||
|         $hasHeaders = $this->data->hasHeaders(); | ||||
|         $values     = $this->wizard->getMappableValues($reader, $map, $hasHeaders); | ||||
|         $map        = $this->data->getMap(); | ||||
|         $mapped     = $this->data->getMapped(); | ||||
|         $subTitle   = trans('firefly.csv_map_values'); | ||||
|  | ||||
|         return view('csv.map', compact('map', 'options', 'values', 'mapped', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * Finally actually process the CSV file. | ||||
|      * | ||||
|      * STEP SEVEN | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View | ||||
|      */ | ||||
|     public function process() | ||||
|     { | ||||
|         /* | ||||
|          * Make sure all fields we need are accounted for. | ||||
|          */ | ||||
|         $fields = ['csv-file', 'csv-date-format', 'csv-has-headers', 'csv-map', 'csv-roles', 'csv-mapped']; | ||||
|         if (!$this->wizard->sessionHasValues($fields)) { | ||||
|             Session::flash('warning', 'Could not recover upload.'); | ||||
|  | ||||
|             return redirect(route('csv.index')); | ||||
|         } | ||||
|  | ||||
|         Log::debug('Created importer'); | ||||
|         $importer = new Importer; | ||||
|         $importer->setData($this->data); | ||||
|         try { | ||||
|             $importer->run(); | ||||
|         } catch (FireflyException $e) { | ||||
|             Log::error('Catch error: ' . $e->getMessage()); | ||||
|  | ||||
|             return view('error', ['message' => $e->getMessage()]); | ||||
|         } | ||||
|         Log::debug('Done importing!'); | ||||
|  | ||||
|         $rows     = $importer->getRows(); | ||||
|         $errors   = $importer->getErrors(); | ||||
|         $imported = $importer->getImported(); | ||||
|         $journals = $importer->getJournals(); | ||||
|  | ||||
|         Preferences::mark(); | ||||
|  | ||||
|         $subTitle = trans('firefly.csv_process_title'); | ||||
|  | ||||
|         return view('csv.process', compact('rows', 'errors', 'imported', 'subTitle', 'journals')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store the mapping the user has made. This is | ||||
|      * | ||||
|      * STEP SIX | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function saveMapping() | ||||
|     { | ||||
|         /* | ||||
|          * Make sure all fields we need are accounted for. | ||||
|          */ | ||||
|         $fields = ['csv-file', 'csv-date-format', 'csv-has-headers', 'csv-map', 'csv-roles']; | ||||
|         if (!$this->wizard->sessionHasValues($fields)) { | ||||
|             Session::flash('warning', 'Could not recover upload.'); | ||||
|  | ||||
|             return redirect(route('csv.index')); | ||||
|         } | ||||
|  | ||||
|         // save mapping to session. | ||||
|         $mapped = []; | ||||
|         if (!is_array(Input::get('mapping'))) { | ||||
|             Session::flash('warning', 'Invalid mapping.'); | ||||
|  | ||||
|             return redirect(route('csv.map')); | ||||
|         } | ||||
|  | ||||
|         foreach (Input::get('mapping') as $index => $data) { | ||||
|             $mapped[$index] = []; | ||||
|             foreach ($data as $value => $mapping) { | ||||
|                 if (intval($mapping) !== 0) { | ||||
|                     $mapped[$index][$value] = $mapping; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         Session::put('csv-mapped', $mapped); | ||||
|  | ||||
|         // proceed to process. | ||||
|         return redirect(route('csv.download-config-page')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * This method processes the file, puts it away somewhere safe | ||||
|      * and sends you onwards. | ||||
|      * | ||||
|      * STEP TWO | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function upload(Request $request) | ||||
|     { | ||||
|         if (!$request->hasFile('csv')) { | ||||
|             Session::flash('warning', 'No file uploaded.'); | ||||
|  | ||||
|             return redirect(route('csv.index')); | ||||
|         } | ||||
|  | ||||
|         $fullPath                   = $this->wizard->storeCsvFile($request->file('csv')->getRealPath()); | ||||
|         $settings                   = []; | ||||
|         $settings['date-format']    = Input::get('date_format'); | ||||
|         $settings['has-headers']    = intval(Input::get('has_headers')) === 1; | ||||
|         $settings['specifix']       = Input::get('specifix'); | ||||
|         $settings['import-account'] = intval(Input::get('csv_import_account')); | ||||
|         $settings['map']            = []; | ||||
|         $settings['mapped']         = []; | ||||
|         $settings['roles']          = []; | ||||
|  | ||||
|         if ($request->hasFile('csv_config')) { // Process config file if present. | ||||
|             $data = file_get_contents($request->file('csv_config')->getRealPath()); | ||||
|             $json = json_decode($data, true); | ||||
|             if (is_array($json)) { | ||||
|                 $settings = array_merge($settings, $json); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $this->data->setCsvFileLocation($fullPath); | ||||
|         $this->data->setDateFormat($settings['date-format']); | ||||
|         $this->data->setHasHeaders($settings['has-headers']); | ||||
|         $this->data->setMap($settings['map']); | ||||
|         $this->data->setMapped($settings['mapped']); | ||||
|         $this->data->setRoles($settings['roles']); | ||||
|         $this->data->setSpecifix($settings['specifix']); | ||||
|         $this->data->setImportAccount($settings['import-account']); | ||||
|  | ||||
|         return redirect(route('csv.column-roles')); | ||||
|  | ||||
|     } | ||||
| } | ||||
| @@ -7,7 +7,6 @@ use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; | ||||
| use Input; | ||||
| use Preferences; | ||||
| use Redirect; | ||||
| use Session; | ||||
| use URL; | ||||
| use View; | ||||
| @@ -37,7 +36,7 @@ class CurrencyController extends Controller | ||||
|     public function create() | ||||
|     { | ||||
|         $subTitleIcon = 'fa-plus'; | ||||
|         $subTitle     = 'Create a new currency'; | ||||
|         $subTitle     = trans('firefly.create_currency'); | ||||
|  | ||||
|         // put previous url in session if not redirect from store (not "create another"). | ||||
|         if (Session::get('currency.create.fromStore') !== true) { | ||||
| @@ -59,12 +58,13 @@ class CurrencyController extends Controller | ||||
|     { | ||||
|  | ||||
|         Preferences::set('currencyPreference', $currency->code); | ||||
|         Preferences::mark(); | ||||
|  | ||||
|         Session::flash('success', $currency->name . ' is now the default currency.'); | ||||
|         Cache::forget('FFCURRENCYSYMBOL'); | ||||
|         Cache::forget('FFCURRENCYCODE'); | ||||
|  | ||||
|         return Redirect::route('currency.index'); | ||||
|         return redirect(route('currency.index')); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -80,16 +80,17 @@ class CurrencyController extends Controller | ||||
|         if ($repository->countJournals($currency) > 0) { | ||||
|             Session::flash('error', 'Cannot delete ' . e($currency->name) . ' because there are still transactions attached to it.'); | ||||
|  | ||||
|             return Redirect::route('currency.index'); | ||||
|             return redirect(route('currency.index')); | ||||
|         } | ||||
|  | ||||
|         // put previous url in session | ||||
|         Session::put('currency.delete.url', URL::previous()); | ||||
|         Session::flash('gaEventCategory', 'currency'); | ||||
|         Session::flash('gaEventAction', 'delete'); | ||||
|         $subTitle = trans('form.delete_currency', ['name' => $currency->name]); | ||||
|  | ||||
|  | ||||
|         return view('currency.delete', compact('currency')); | ||||
|         return view('currency.delete', compact('currency', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -104,7 +105,7 @@ class CurrencyController extends Controller | ||||
|         if ($repository->countJournals($currency) > 0) { | ||||
|             Session::flash('error', 'Cannot destroy ' . e($currency->name) . ' because there are still transactions attached to it.'); | ||||
|  | ||||
|             return Redirect::route('currency.index'); | ||||
|             return redirect(route('currency.index')); | ||||
|         } | ||||
|  | ||||
|         Session::flash('success', 'Currency "' . e($currency->name) . '" deleted'); | ||||
| @@ -112,7 +113,7 @@ class CurrencyController extends Controller | ||||
|             $currency->delete(); | ||||
|         } | ||||
|  | ||||
|         return Redirect::to(Session::get('currency.delete.url')); | ||||
|         return redirect(Session::get('currency.delete.url')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -123,7 +124,7 @@ class CurrencyController extends Controller | ||||
|     public function edit(TransactionCurrency $currency) | ||||
|     { | ||||
|         $subTitleIcon     = 'fa-pencil'; | ||||
|         $subTitle         = 'Edit currency "' . e($currency->name) . '"'; | ||||
|         $subTitle         = trans('firefly.edit_currency', ['name' => $currency->name]); | ||||
|         $currency->symbol = htmlentities($currency->symbol); | ||||
|  | ||||
|         // put previous url in session if not redirect from store (not "return_to_edit"). | ||||
| @@ -170,16 +171,17 @@ class CurrencyController extends Controller | ||||
|         if (Auth::user()->hasRole('owner')) { | ||||
|             $currency = $repository->store($data); | ||||
|             Session::flash('success', 'Currency "' . $currency->name . '" created'); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         if (intval(Input::get('create_another')) === 1) { | ||||
|             Session::put('currency.create.fromStore', true); | ||||
|  | ||||
|             return Redirect::route('currency.create')->withInput(); | ||||
|             return redirect(route('currency.create'))->withInput(); | ||||
|         } | ||||
|  | ||||
|         // redirect to previous URL. | ||||
|         return Redirect::to(Session::get('currency.create.url')); | ||||
|         return redirect(Session::get('currency.create.url')); | ||||
|  | ||||
|  | ||||
|     } | ||||
| @@ -198,16 +200,17 @@ class CurrencyController extends Controller | ||||
|             $currency = $repository->update($currency, $data); | ||||
|         } | ||||
|         Session::flash('success', 'Currency "' . e($currency->name) . '" updated.'); | ||||
|         Preferences::mark(); | ||||
|  | ||||
|  | ||||
|         if (intval(Input::get('return_to_edit')) === 1) { | ||||
|             Session::put('currency.edit.fromUpdate', true); | ||||
|  | ||||
|             return Redirect::route('currency.edit', [$currency->id]); | ||||
|             return redirect(route('currency.edit', [$currency->id])); | ||||
|         } | ||||
|  | ||||
|         // redirect to previous URL. | ||||
|         return Redirect::to(Session::get('currency.edit.url')); | ||||
|         return redirect(Session::get('currency.edit.url')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user