mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-31 02:36:28 +00:00 
			
		
		
		
	Compare commits
	
		
			508 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 144e329eca | ||
|  | 21d5420b2a | ||
|  | 3011b5074d | ||
|  | 83190572c7 | ||
|  | 9cf9e5f865 | ||
|  | 5bdef7f1c7 | ||
|  | ba285a2d2d | ||
|  | 0dff371e62 | ||
|  | ce4a2a5851 | ||
|  | 2c978dc89a | ||
|  | 4b8b819109 | ||
|  | c230b3a806 | ||
|  | df08b9c5c6 | ||
|  | eca65376a3 | ||
|  | 88e3705636 | ||
|  | 5476509ef5 | ||
|  | 0bd6636453 | ||
|  | 105894e00d | ||
|  | 230a319510 | ||
|  | ae16a2b14f | ||
|  | da0c0742bf | ||
|  | 61d60a9048 | ||
|  | 3e28e9a016 | ||
|  | 423f9fefa9 | ||
|  | 5707dc7579 | ||
|  | 3be1cdb249 | ||
|  | 426d3d948c | ||
|  | 9a3aed8038 | ||
|  | fb58bf1bf5 | ||
|  | a6dbd912c6 | ||
|  | 65ce277a20 | ||
|  | 0b2d423c87 | ||
|  | da056092fb | ||
|  | 45aa85d690 | ||
|  | 5c35fee0c2 | ||
|  | 24bdc319dd | ||
|  | f1dcc41e42 | ||
|  | 550f301ba2 | ||
|  | d9bf4d1c0d | ||
|  | c3c1a6eb22 | ||
|  | 2c4454418e | ||
|  | e44de572f5 | ||
|  | f27919f91b | ||
|  | ba9968bde0 | ||
|  | 05ea8216ff | ||
|  | fa1695672a | ||
|  | ac6f98fc47 | ||
|  | 1a1f89f555 | ||
|  | 6c3262e176 | ||
|  | b4bdb48f1e | ||
|  | 823afe877b | ||
|  | cb8e082414 | ||
|  | 98c1fcc68f | ||
|  | 8c439a2852 | ||
|  | 50c6109be7 | ||
|  | 6e362663b5 | ||
|  | 74c9feb53f | ||
|  | 402e8588cf | ||
|  | 778a42bcc0 | ||
|  | 584f7ced84 | ||
|  | 8e892e7ea5 | ||
|  | 3386c8b455 | ||
|  | 6fa73ee28d | ||
|  | 8ec8042045 | ||
|  | cddc123539 | ||
|  | 4c2938c5cd | ||
|  | 6d03ddadcc | ||
|  | 64311da4b4 | ||
|  | 0cbb50ae9d | ||
|  | 7e96054dc2 | ||
|  | 578298580e | ||
|  | ee5afaa6bc | ||
|  | 15b023d116 | ||
|  | 1ef96c0b4d | ||
|  | 8c3ae40de1 | ||
|  | 94fcfacec4 | ||
|  | ba7c01c6bc | ||
|  | 9f92e1b7bd | ||
|  | 1f0e692ee2 | ||
|  | 0acd75a24f | ||
|  | eedf27f8a5 | ||
|  | b451e207e2 | ||
|  | c0c37eec7b | ||
|  | 89363ecfa3 | ||
|  | 593e799ca1 | ||
|  | 8fc055cad9 | ||
|  | 75f86462e2 | ||
|  | 40892ccfa7 | ||
|  | 87fbf9c1a5 | ||
|  | 4944b233b6 | ||
|  | 9f23462c42 | ||
|  | 84a24f0333 | ||
|  | 7a885bfc3c | ||
|  | 3ba0cf1454 | ||
|  | 2d67a3159d | ||
|  | 290f25f1a0 | ||
|  | 1659904f81 | ||
|  | 230bd6e40a | ||
|  | ce27e97b92 | ||
|  | 18c1223c7b | ||
|  | 8ef659f5de | ||
|  | 037452e525 | ||
|  | e3482011d5 | ||
|  | 62748fa255 | ||
|  | 7a9df05f6b | ||
|  | 335279e728 | ||
|  | 0332104738 | ||
|  | 9f04854902 | ||
|  | 73008a35fe | ||
|  | eae96cd2af | ||
|  | cb670bb27d | ||
|  | fe1fb23e5b | ||
|  | c2dd61e96b | ||
|  | 80f5e61b6b | ||
|  | dbcae16b75 | ||
|  | 886dcae822 | ||
|  | ed495ec600 | ||
|  | ddb60ccdc5 | ||
|  | 335e2083af | ||
|  | 7b1d9d4962 | ||
|  | da6ff9f90a | ||
|  | 48f26c7bf1 | ||
|  | 3ce317b170 | ||
|  | b741565f57 | ||
|  | d8fea44968 | ||
|  | 778300b67e | ||
|  | cb2b44fef3 | ||
|  | cdb5875d6b | ||
|  | 01c5e15bcd | ||
|  | f0babb4be7 | ||
|  | 10b00da874 | ||
|  | e9f391b2eb | ||
|  | 50be39b054 | ||
|  | a94e0bb3da | ||
|  | 3f65d5d760 | ||
|  | 48cb528ae4 | ||
|  | e62e0345df | ||
|  | 441f011fba | ||
|  | af1349160a | ||
|  | 2072607889 | ||
|  | 073fd5aa0d | ||
|  | 7b4703e4ff | ||
|  | 1484621300 | ||
|  | 40709c8367 | ||
|  | b6ab5770a2 | ||
|  | 83b7cb4ff9 | ||
|  | 256dba66b2 | ||
|  | 6ac12f8ffa | ||
|  | 82e438d29b | ||
|  | e86547645c | ||
|  | 8b901084fe | ||
|  | 1a0cbbdb31 | ||
|  | 30ac62ffb7 | ||
|  | 8ab294e90b | ||
|  | f5edb15f43 | ||
|  | eed6107ce7 | ||
|  | d49dc599a2 | ||
|  | 3c5179f145 | ||
|  | 067d17c09c | ||
|  | 4c88c9af86 | ||
|  | 1c84afe186 | ||
|  | 9d4c4be468 | ||
|  | de7db8db78 | ||
|  | 407ba4dd6d | ||
|  | 5135be3000 | ||
|  | b8ab7d1a14 | ||
|  | 6211fd8496 | ||
|  | a4f273b48b | ||
|  | 68d820a97c | ||
|  | ebadfd6358 | ||
|  | cf93a88adc | ||
|  | bd2c4252bb | ||
|  | 84e7af04b9 | ||
|  | 37c63bc6b5 | ||
|  | e7d3716549 | ||
|  | 73bc5372c0 | ||
|  | b999a8f0fb | ||
|  | 16678aa5e1 | ||
|  | f9ab49911d | ||
|  | 3fabe2e9fb | ||
|  | 9a8a3e94d6 | ||
|  | 32ef2ef801 | ||
|  | 76cd3d35e2 | ||
|  | 900dea2c66 | ||
|  | 8e6ca0dd05 | ||
|  | 4b4ad7f1a8 | ||
|  | 21a0a5d573 | ||
|  | 3cfa3f3b27 | ||
|  | c77b43458e | ||
|  | 9ab0a83f7c | ||
|  | d3cda8811d | ||
|  | 55740c0d97 | ||
|  | c0a524c8a3 | ||
|  | e51c2d10f0 | ||
|  | 7af55b7268 | ||
|  | 7350b1da1b | ||
|  | 136adbe723 | ||
|  | cb2863eaf3 | ||
|  | d054f9b92f | ||
|  | 9c83c18137 | ||
|  | 999a7481e4 | ||
|  | a3b684b4ed | ||
|  | cb312ca025 | ||
|  | 1335a52db3 | ||
|  | 727221e2cb | ||
|  | 360f286ed3 | ||
|  | 6aecd77b77 | ||
|  | ca85cab6fb | ||
|  | 742479bb01 | ||
|  | 68e54a9297 | ||
|  | 056d83eda4 | ||
|  | 42ec55d0db | ||
|  | c89bd89d9a | ||
|  | 31a0be5bb4 | ||
|  | 07610ae8fb | ||
|  | dbc95dd878 | ||
|  | 792e8a9947 | ||
|  | d774cde109 | ||
|  | cc111d14b0 | ||
|  | bb3ba42ce2 | ||
|  | f4ecf2d1aa | ||
|  | 1997666196 | ||
|  | 3aa9057c5f | ||
|  | 834f8382e9 | ||
|  | 357638a26c | ||
|  | 919a0c01e4 | ||
|  | 6ff618e388 | ||
|  | ac765b7e4c | ||
|  | 2134e87c31 | ||
|  | 0d37288129 | ||
|  | 7cbd41137d | ||
|  | ba43d7063f | ||
|  | c9b2e29ba0 | ||
|  | 4720519aef | ||
|  | d7b0106e7d | ||
|  | 0a2cbaa047 | ||
|  | 3e5f615ffc | ||
|  | 00dc73e6d9 | ||
|  | aa5b9a1727 | ||
|  | f63a287a6c | ||
|  | b9d4c8dcd6 | ||
|  | 94433f1714 | ||
|  | a4dd4358b4 | ||
|  | 4e79b43395 | ||
|  | 6bb54bfa85 | ||
|  | 0df6c3a8dc | ||
|  | dc25086eab | ||
|  | 3299188edf | ||
|  | f6afb46f6f | ||
|  | 98993cfa9b | ||
|  | 5a920d5efd | ||
|  | 935276af88 | ||
|  | 5a505c8469 | ||
|  | 2c2abe8b8e | ||
|  | 638099d989 | ||
|  | 0f32f6be4c | ||
|  | 1f7c98bdcf | ||
|  | 72068a4b78 | ||
|  | c8038e0774 | ||
|  | 6b39beecb4 | ||
|  | b1ba64db12 | ||
|  | ad53832766 | ||
|  | d5bffc8ed7 | ||
|  | 69b36ddd1d | ||
|  | 9f926394a6 | ||
|  | 1e7ecbdf9d | ||
|  | beb8a461cf | ||
|  | e235a57e2f | ||
|  | 114b27079e | ||
|  | 6e19bc01f5 | ||
|  | f9dfdeafb3 | ||
|  | f05d626e38 | ||
|  | 918041258e | ||
|  | a5b13aa67f | ||
|  | 1383cbd4d5 | ||
|  | e9b7e82aea | ||
|  | fd6e7fc1ab | ||
|  | 743deb4227 | ||
|  | b051278d2e | ||
|  | bfda4bc199 | ||
|  | 4456ef2326 | ||
|  | 7336367eff | ||
|  | 9cb6c7697e | ||
|  | cd44f51072 | ||
|  | d8976379b1 | ||
|  | 8aa847c718 | ||
|  | 6691b238f7 | ||
|  | cca2758138 | ||
|  | 4a74e68e31 | ||
|  | 3d3842b9d6 | ||
|  | 9d889d05e4 | ||
|  | 9f920bcfe3 | ||
|  | 1bb49fa496 | ||
|  | 6b1d8d3aaa | ||
|  | c6b6ed7fa8 | ||
|  | 34454261d2 | ||
|  | ddf9f52737 | ||
|  | 10b969a074 | ||
|  | 5df0634380 | ||
|  | f0f965421c | ||
|  | 6381408fba | ||
|  | 43e738cb44 | ||
|  | 6d4303aa3f | ||
|  | 13c2db5378 | ||
|  | 36f6bda525 | ||
|  | 78886e7b1f | ||
|  | 3dce194930 | ||
|  | ec776bb6eb | ||
|  | 243d942a6e | ||
|  | ea6aba62c4 | ||
|  | 73743721b1 | ||
|  | 61eb5b341d | ||
|  | d758f72393 | ||
|  | 1b1367f4c2 | ||
|  | 07388dd58a | ||
|  | 359c71ef2f | ||
|  | 93d4d3df1d | ||
|  | d3a7596be2 | ||
|  | 114d3812cc | ||
|  | b2d4dcfbf1 | ||
|  | 0baf8f6d18 | ||
|  | 2f8e3a0707 | ||
|  | d7a4bf22c6 | ||
|  | 0c2f9d22b9 | ||
|  | e75c5aac49 | ||
|  | 77e5024f54 | ||
|  | 7329c0b200 | ||
|  | 0afe3c48a1 | ||
|  | 1ab5e923bc | ||
|  | 90b3bd77e7 | ||
|  | 9c60443f97 | ||
|  | 058e5602a3 | ||
|  | eebac2a66d | ||
|  | 7e8f5c9548 | ||
|  | d34b49bd48 | ||
|  | ccffae287d | ||
|  | ad69011ac5 | ||
|  | f8ea0f971d | ||
|  | 9918410954 | ||
|  | 4f4e6fac16 | ||
|  | 15e99bd672 | ||
|  | 696e9a6fde | ||
|  | 36cbb3d71f | ||
|  | f69598c6aa | ||
|  | 5fc31f3c1e | ||
|  | 6581ee0ee0 | ||
|  | 69e7501d47 | ||
|  | 314abbea8b | ||
|  | 82c9a75578 | ||
|  | 651101912c | ||
|  | fb0d463040 | ||
|  | 8c254554eb | ||
|  | 2d9c89375a | ||
|  | 61aba29df7 | ||
|  | 8c949e6190 | ||
|  | 6eb9188690 | ||
|  | 6832f2ebd0 | ||
|  | 3e02b50ea1 | ||
|  | 7b7743c03e | ||
|  | de20563275 | ||
|  | 9e720c3a38 | ||
|  | 54685c1f5f | ||
|  | eb8f8fa935 | ||
|  | 9adbbd872c | ||
|  | 4bd38f97a2 | ||
|  | 78ab1e200a | ||
|  | 11280e473d | ||
|  | f9750a64f8 | ||
|  | ac2ab65471 | ||
|  | 0530c0402c | ||
|  | a58a560bbb | ||
|  | 96ab112b22 | ||
|  | b388dcc7d4 | ||
|  | f511a25c94 | ||
|  | 58d8b6f95b | ||
|  | 953d68c3a2 | ||
|  | 9e2f7af59b | ||
|  | 840dfa6696 | ||
|  | 4a20c008ff | ||
|  | 981ffe4194 | ||
|  | 2597633b0e | ||
|  | 71d174d765 | ||
|  | 4aa9a04516 | ||
|  | 258d6a1688 | ||
|  | 2e2c12d6a4 | ||
|  | 44d189d7d3 | ||
|  | ab508a3d9e | ||
|  | 4e166c7d2e | ||
|  | 7f175a4870 | ||
|  | 0a627f6f9e | ||
|  | d34cc65984 | ||
|  | 78d034d366 | ||
|  | 638fa9005f | ||
|  | 5cb9907bf8 | ||
|  | f08fcc36fb | ||
|  | d231cd9f61 | ||
|  | 86a586f866 | ||
|  | 9d4cba1620 | ||
|  | e9afd55e9d | ||
|  | 9fa326f630 | ||
|  | af9473c126 | ||
|  | cb08df0770 | ||
|  | d49ca2eb11 | ||
|  | a3f8841ec3 | ||
|  | fd678c286d | ||
|  | 2a3f9b621b | ||
|  | 359e1b3943 | ||
|  | 754336b3cf | ||
|  | 4918f1c4cb | ||
|  | 5d5e308942 | ||
|  | 6a18f81cec | ||
|  | 1ff135d172 | ||
|  | e666e5e9e3 | ||
|  | 9874e77ddf | ||
|  | 27e3ec693a | ||
|  | 6bb1415ad7 | ||
|  | 83594e6f1f | ||
|  | 0f6008705c | ||
|  | c58b653bb7 | ||
|  | f69b6f9b4e | ||
|  | 7750b06476 | ||
|  | 873384a34b | ||
|  | ac299e7279 | ||
|  | 7895d7f5d0 | ||
|  | fe05d218fc | ||
|  | 8196313ac0 | ||
|  | 6d8f84654f | ||
|  | ab4f34a96b | ||
|  | 139d985904 | ||
|  | 44705f0e18 | ||
|  | ddea7d696a | ||
|  | f814f45e36 | ||
|  | f7117d47c2 | ||
|  | 01b0a1058d | ||
|  | 21f362c7b9 | ||
|  | aaab7f8e0e | ||
|  | 09e1f68c69 | ||
|  | 03729aa5ae | ||
|  | ef39f31ea1 | ||
|  | 0f1437dd6a | ||
|  | 03aac2f744 | ||
|  | 2f8b10e82c | ||
|  | 3231effd20 | ||
|  | f7722c1189 | ||
|  | 70c2450ac4 | ||
|  | 2d5b0d0f99 | ||
|  | f0c0002a6d | ||
|  | dd9f08d4fa | ||
|  | de2e384225 | ||
|  | ffcd1fde0f | ||
|  | d5e1da5948 | ||
|  | ad479a5c7f | ||
|  | 0707603b63 | ||
|  | 2f9c383004 | ||
|  | 8ad0d7af93 | ||
|  | 9b4391c0bf | ||
|  | da7802a0a4 | ||
|  | 9c69949e8c | ||
|  | b1d7a9451a | ||
|  | 004488d453 | ||
|  | fc91372dd0 | ||
|  | 5970a9dc91 | ||
|  | 264cac4f9b | ||
|  | 633328a965 | ||
|  | 4d4b62a766 | ||
|  | aeb2c7deeb | ||
|  | c323942d92 | ||
|  | a0afa25145 | ||
|  | 4533b46436 | ||
|  | e5f8db78f9 | ||
|  | 899f61671f | ||
|  | d84d88cc10 | ||
|  | 97e7ac4052 | ||
|  | ba4ffa44d2 | ||
|  | 07caeccf68 | ||
|  | d54832f61f | ||
|  | b212753633 | ||
|  | f38d80cbf5 | ||
|  | 8bea1acd8e | ||
|  | 42458ce11d | ||
|  | aceb683d07 | ||
|  | b7517b49ed | ||
|  | 849b711b79 | ||
|  | 25585b28c7 | ||
|  | 073da8fb2a | ||
|  | a787ff3f3c | ||
|  | 733b6d7eb7 | ||
|  | 36d8dee853 | ||
|  | 65a2e07d24 | ||
|  | 7c97c558ab | ||
|  | a6bb61050c | ||
|  | b184aa2315 | ||
|  | e4595333e7 | ||
|  | 41dd139bde | ||
|  | c577dd302a | ||
|  | 0ab87de78b | ||
|  | 8a22509b41 | ||
|  | b024c18441 | ||
|  | d9ac681a68 | ||
|  | 637a5579ec | ||
|  | 4794156e80 | ||
|  | 5f4db7874c | ||
|  | b4ea1839a5 | ||
|  | 6a6d889983 | ||
|  | 287c2e7af8 | ||
|  | 0fe6acc8cf | ||
|  | 7d2dab7ca0 | ||
|  | f68c1aff26 | 
| @@ -1 +1,3 @@ | ||||
| src_dir: . | ||||
| coverage_clover: tests/_output/coverage.xml | ||||
| json_path: tests/_output/coveralls-upload.json | ||||
|   | ||||
							
								
								
									
										15
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,10 +1,8 @@ | ||||
| /bootstrap/compiled.php | ||||
| /vendor | ||||
| composer.phar | ||||
| composer.lock | ||||
| .env.*.php | ||||
| .env.php | ||||
| .DS_Store | ||||
| Thumbs.db | ||||
| .idea/ | ||||
| tests/_output/* | ||||
| @@ -14,3 +12,16 @@ index.html* | ||||
| app/storage/firefly-export* | ||||
| .vagrant | ||||
| firefly-iii-import-*.json | ||||
| tests/_output/* | ||||
| testing.sqlite | ||||
| _ide_helper_models.php | ||||
| clean.sqlite | ||||
| tests/acceptance/AcceptanceTester.php | ||||
| tests/functional/FunctionalTester.php | ||||
| tests/unit/UnitTester.php | ||||
| pi.php | ||||
| tests/_data/db.sqlite | ||||
| tests/_data/dump.sql | ||||
| db.sqlite_snapshot | ||||
| c3.php | ||||
| db.sqlite-journal | ||||
|   | ||||
| @@ -2,12 +2,15 @@ language: php | ||||
|  | ||||
| php: | ||||
|   - 5.5 | ||||
|   - 5.4 | ||||
|   - hhvm | ||||
|   - 5.6 | ||||
|  | ||||
| install: | ||||
|   - composer install | ||||
|  | ||||
| script: | ||||
|   - ./tests/_data/db.sh | ||||
|   - php vendor/bin/codecept build | ||||
|   - php vendor/bin/codecept run --coverage --coverage-xml | ||||
|  | ||||
| after_script: | ||||
|   - php vendor/bin/coveralls | ||||
|  | ||||
|   | ||||
							
								
								
									
										41
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,49 +1,54 @@ | ||||
| firefly-iii | ||||
| Firefly III | ||||
| =========== | ||||
|  | ||||
| [](https://travis-ci.org/JC5/firefly-iii) | ||||
|  | ||||
| [](https://travis-ci.org/JC5/firefly-iii) | ||||
| [](http://stillmaintained.com/JC5/firefly-iii) | ||||
| [](https://coveralls.io/r/JC5/firefly-iii?branch=master) | ||||
| [](https://insight.sensiolabs.com/projects/d44c7012-5f50-41ad-add8-8445330e4102) | ||||
|  | ||||
| [](https://packagist.org/packages/grumpydictator/firefly-iii) | ||||
| [](https://packagist.org/packages/grumpydictator/firefly-iii) | ||||
| [](https://packagist.org/packages/grumpydictator/firefly-iii) | ||||
| [](https://packagist.org/packages/grumpydictator/firefly-iii) | ||||
|  | ||||
| Firefly II is a tool to help you manage your finances. Please read the full description [in the wiki](https://github.com/JC5/firefly-iii/wiki/full-description). | ||||
|  | ||||
| Firefly Mark III is a new version of Firefly built upon best practices and lessons learned | ||||
| from building [Firefly](https://github.com/JC5/Firefly). It's Mark III since the original Firefly never made it outside of my | ||||
| laptop and [Firefly II](https://github.com/JC5/Firefly) is live. | ||||
|  | ||||
| ## Current features | ||||
|  | ||||
| - [A double-entry bookkeeping system](http://en.wikipedia.org/wiki/Double-entry_bookkeeping_system). | ||||
| - [A double-entry bookkeeping system](http://en.wikipedia.org/wiki/Double-entry_bookkeeping_system); | ||||
| - You can store, edit and remove withdrawals, deposits and transfers. This allows you full financial management; | ||||
| - It's possible to create, change and manage money using _budgets_; | ||||
| - Organize transactions using categories; | ||||
| - Save towards a goal using piggy banks; | ||||
| - Predict and anticipate large expenses using "repeated expenses" (ie. yearly taxes); | ||||
| - Predict and anticipate bills using "recurring transactions" (rent for example). | ||||
| - Predict and anticipate bills using "recurring transactions" (rent for example); | ||||
| - View basic income / expense reports. | ||||
| - Lots of help text in case you don't get it; | ||||
|  | ||||
| Everything is organised: | ||||
|  | ||||
| - Clear views that should show you how you're doing; | ||||
| - Easy navigation through your records; | ||||
| - Browse back and forth to see previous months or even years; | ||||
| - Lots of help text in case you don't get it; | ||||
| - Lots of charts because we all love them. | ||||
| - Financial reporting showing you how well you are doing; | ||||
|  | ||||
| ## Changes | ||||
|  | ||||
| Firefly III will feature, but does not feature yet: | ||||
|  | ||||
| - Financial reporting showing you how well you are doing; | ||||
|  | ||||
| - More control over other resources outside of personal finance | ||||
|   - Accounts shared with a partner (household accounts) | ||||
|   - Debts | ||||
|   - Credit cards | ||||
| - More test-coverage (aka: actual test coverage); | ||||
| - More test-coverage; | ||||
| - Firefly will be able to split transactions; a single purchase can be split in multiple entries, for more fine-grained control. | ||||
| - Firefly will be able to join transactions. | ||||
| - Transfers and transactions are combined into one internal datatype which is more consistent with what you're actually doing: moving money from A to B. The fact that A or B or both are yours should not matter. | ||||
| - Any other features I might not have thought of. | ||||
|  | ||||
| Some stuff has been removed: | ||||
| @@ -51,14 +56,20 @@ Some stuff has been removed: | ||||
| - The nesting of budgets, categories and beneficiaries is removed because it was pretty pointless. | ||||
| - Firefly will not encrypt the content of the (MySQL) tables. Old versions of Firefly had this capability but it sucks when searching, sorting and organizing entries. | ||||
|  | ||||
| ## Screenshots | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| ## Current state | ||||
| I have the basics up and running. Test coverage is currently non-existent. | ||||
| I have the basics up and running. Test coverage is currently coming, slowly. | ||||
|  | ||||
| Although I have not checked extensively, some forms and views have CSRF vulnerabilities. This is because not all | ||||
| views escape all characters by default. Will be fixed. | ||||
|  | ||||
| The current layout / look & feel is a pretty basic Bootstrap3 template. I am currently working on a more consistent, | ||||
| expanded layout which will feature shiny AJAX things and data tables and all the Web 3.0 goodies you've come to expect | ||||
| from social media sites. | ||||
|  | ||||
| Questions, ideas or other things to contribute? [Let me know](https://github.com/JC5/firefly-iii/issues/new)! | ||||
| Questions, ideas or other things to contribute? [Let me know](https://github.com/JC5/firefly-iii/issues/new)! | ||||
|   | ||||
							
								
								
									
										606
									
								
								_sql/firefly-iii-reference-3.2.2.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										606
									
								
								_sql/firefly-iii-reference-3.2.2.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,606 @@ | ||||
| # ************************************************************ | ||||
| # Sequel Pro SQL dump | ||||
| # Version 4096 | ||||
| # | ||||
| # http://www.sequelpro.com/ | ||||
| # http://code.google.com/p/sequel-pro/ | ||||
| # | ||||
| # Host: 127.0.0.1 (MySQL 5.6.19-0ubuntu0.14.04.1) | ||||
| # Database: homestead | ||||
| # Generation Time: 2015-01-02 19:01:30 +0000 | ||||
| # ************************************************************ | ||||
|  | ||||
|  | ||||
| /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; | ||||
| /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; | ||||
| /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; | ||||
| /*!40101 SET NAMES utf8 */; | ||||
| /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; | ||||
| /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; | ||||
| /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; | ||||
|  | ||||
|  | ||||
| # Dump of table account_meta | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `account_meta`; | ||||
|  | ||||
| CREATE TABLE `account_meta` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `account_id` int(10) unsigned NOT NULL, | ||||
|   `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL, | ||||
|   `data` text COLLATE utf8_unicode_ci NOT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `account_meta_account_id_name_unique` (`account_id`,`name`) | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|  | ||||
|  | ||||
| # Dump of table account_types | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `account_types`; | ||||
|  | ||||
| CREATE TABLE `account_types` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `type` varchar(30) COLLATE utf8_unicode_ci NOT NULL, | ||||
|   `editable` tinyint(1) NOT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `account_types_type_unique` (`type`) | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
| LOCK TABLES `account_types` WRITE; | ||||
| /*!40000 ALTER TABLE `account_types` DISABLE KEYS */; | ||||
|  | ||||
| INSERT INTO `account_types` (`id`, `created_at`, `updated_at`, `type`, `editable`) | ||||
| VALUES | ||||
| 	(1,'2015-01-02 19:00:13','2015-01-02 19:00:13','Default account',1), | ||||
| 	(2,'2015-01-02 19:00:13','2015-01-02 19:00:13','Cash account',0), | ||||
| 	(3,'2015-01-02 19:00:13','2015-01-02 19:00:13','Asset account',1), | ||||
| 	(4,'2015-01-02 19:00:13','2015-01-02 19:00:13','Expense account',1), | ||||
| 	(5,'2015-01-02 19:00:13','2015-01-02 19:00:13','Revenue account',1), | ||||
| 	(6,'2015-01-02 19:00:13','2015-01-02 19:00:13','Initial balance account',0), | ||||
| 	(7,'2015-01-02 19:00:13','2015-01-02 19:00:13','Beneficiary account',1), | ||||
| 	(8,'2015-01-02 19:00:13','2015-01-02 19:00:13','Import account',0); | ||||
|  | ||||
| /*!40000 ALTER TABLE `account_types` ENABLE KEYS */; | ||||
| UNLOCK TABLES; | ||||
|  | ||||
|  | ||||
| # Dump of table accounts | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `accounts`; | ||||
|  | ||||
| CREATE TABLE `accounts` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `deleted_at` timestamp NULL DEFAULT NULL, | ||||
|   `user_id` int(10) unsigned NOT NULL, | ||||
|   `account_type_id` int(10) unsigned NOT NULL, | ||||
|   `name` varchar(100) COLLATE utf8_unicode_ci NOT NULL, | ||||
|   `active` tinyint(1) NOT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `accounts_user_id_account_type_id_name_unique` (`user_id`,`account_type_id`,`name`), | ||||
|   KEY `accounts_account_type_id_foreign` (`account_type_id`), | ||||
|   CONSTRAINT `accounts_account_type_id_foreign` FOREIGN KEY (`account_type_id`) REFERENCES `account_types` (`id`) ON DELETE CASCADE, | ||||
|   CONSTRAINT `accounts_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|  | ||||
|  | ||||
| # Dump of table bills | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `bills`; | ||||
|  | ||||
| CREATE TABLE `bills` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `user_id` int(10) unsigned NOT NULL, | ||||
|   `name` varchar(50) COLLATE utf8_unicode_ci NOT NULL, | ||||
|   `match` varchar(255) COLLATE utf8_unicode_ci NOT NULL, | ||||
|   `amount_min` decimal(10,2) NOT NULL, | ||||
|   `amount_max` decimal(10,2) NOT NULL, | ||||
|   `date` date NOT NULL, | ||||
|   `active` tinyint(1) NOT NULL, | ||||
|   `automatch` tinyint(1) NOT NULL, | ||||
|   `repeat_freq` enum('daily','weekly','monthly','quarterly','half-year','yearly') COLLATE utf8_unicode_ci NOT NULL, | ||||
|   `skip` smallint(5) unsigned NOT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `uid_name_unique` (`user_id`,`name`), | ||||
|   CONSTRAINT `bills_uid_for` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|  | ||||
|  | ||||
| # Dump of table budget_limits | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `budget_limits`; | ||||
|  | ||||
| CREATE TABLE `budget_limits` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `budget_id` int(10) unsigned DEFAULT NULL, | ||||
|   `startdate` date NOT NULL, | ||||
|   `amount` decimal(10,2) NOT NULL, | ||||
|   `repeats` tinyint(1) NOT NULL, | ||||
|   `repeat_freq` enum('daily','weekly','monthly','quarterly','half-year','yearly') COLLATE utf8_unicode_ci NOT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `unique_ci_combi` (`startdate`,`repeat_freq`), | ||||
|   UNIQUE KEY `unique_bl_combi` (`budget_id`,`startdate`,`repeat_freq`), | ||||
|   CONSTRAINT `bid_foreign` FOREIGN KEY (`budget_id`) REFERENCES `budgets` (`id`) ON DELETE CASCADE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|  | ||||
|  | ||||
| # Dump of table budget_transaction_journal | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `budget_transaction_journal`; | ||||
|  | ||||
| CREATE TABLE `budget_transaction_journal` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `budget_id` int(10) unsigned NOT NULL, | ||||
|   `transaction_journal_id` int(10) unsigned NOT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `budid_tjid_unique` (`budget_id`,`transaction_journal_id`), | ||||
|   KEY `budget_transaction_journal_transaction_journal_id_foreign` (`transaction_journal_id`), | ||||
|   CONSTRAINT `budget_transaction_journal_transaction_journal_id_foreign` FOREIGN KEY (`transaction_journal_id`) REFERENCES `transaction_journals` (`id`) ON DELETE CASCADE, | ||||
|   CONSTRAINT `budget_transaction_journal_budget_id_foreign` FOREIGN KEY (`budget_id`) REFERENCES `budgets` (`id`) ON DELETE CASCADE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|  | ||||
|  | ||||
| # Dump of table budgets | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `budgets`; | ||||
|  | ||||
| CREATE TABLE `budgets` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `deleted_at` timestamp NULL DEFAULT NULL, | ||||
|   `name` varchar(50) COLLATE utf8_unicode_ci NOT NULL, | ||||
|   `user_id` int(10) unsigned NOT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `budgets_user_id_name_unique` (`user_id`,`name`), | ||||
|   CONSTRAINT `budgets_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|  | ||||
|  | ||||
| # Dump of table categories | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `categories`; | ||||
|  | ||||
| CREATE TABLE `categories` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `deleted_at` timestamp NULL DEFAULT NULL, | ||||
|   `name` varchar(50) COLLATE utf8_unicode_ci NOT NULL, | ||||
|   `user_id` int(10) unsigned NOT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `categories_user_id_name_unique` (`user_id`,`name`), | ||||
|   CONSTRAINT `categories_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|  | ||||
|  | ||||
| # Dump of table category_transaction_journal | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `category_transaction_journal`; | ||||
|  | ||||
| CREATE TABLE `category_transaction_journal` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `category_id` int(10) unsigned NOT NULL, | ||||
|   `transaction_journal_id` int(10) unsigned NOT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `catid_tjid_unique` (`category_id`,`transaction_journal_id`), | ||||
|   KEY `category_transaction_journal_transaction_journal_id_foreign` (`transaction_journal_id`), | ||||
|   CONSTRAINT `category_transaction_journal_transaction_journal_id_foreign` FOREIGN KEY (`transaction_journal_id`) REFERENCES `transaction_journals` (`id`) ON DELETE CASCADE, | ||||
|   CONSTRAINT `category_transaction_journal_category_id_foreign` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`) ON DELETE CASCADE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|  | ||||
|  | ||||
| # Dump of table components | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `components`; | ||||
|  | ||||
| CREATE TABLE `components` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `deleted_at` timestamp NULL DEFAULT NULL, | ||||
|   `name` varchar(50) COLLATE utf8_unicode_ci NOT NULL, | ||||
|   `user_id` int(10) unsigned NOT NULL, | ||||
|   `class` varchar(20) COLLATE utf8_unicode_ci NOT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `components_user_id_class_name_unique` (`user_id`,`class`,`name`), | ||||
|   CONSTRAINT `components_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|  | ||||
|  | ||||
| # Dump of table limit_repetitions | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `limit_repetitions`; | ||||
|  | ||||
| CREATE TABLE `limit_repetitions` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `budget_limit_id` int(10) unsigned NOT NULL, | ||||
|   `startdate` date NOT NULL, | ||||
|   `enddate` date NOT NULL, | ||||
|   `amount` decimal(10,2) NOT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `limit_repetitions_limit_id_startdate_enddate_unique` (`budget_limit_id`,`startdate`,`enddate`), | ||||
|   CONSTRAINT `limit_repetitions_limit_id_foreign` FOREIGN KEY (`budget_limit_id`) REFERENCES `budget_limits` (`id`) ON DELETE CASCADE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|  | ||||
|  | ||||
| # Dump of table migrations | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `migrations`; | ||||
|  | ||||
| CREATE TABLE `migrations` ( | ||||
|   `migration` varchar(255) COLLATE utf8_unicode_ci NOT NULL, | ||||
|   `batch` int(11) NOT NULL | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
| LOCK TABLES `migrations` WRITE; | ||||
| /*!40000 ALTER TABLE `migrations` DISABLE KEYS */; | ||||
|  | ||||
| INSERT INTO `migrations` (`migration`, `batch`) | ||||
| VALUES | ||||
| 	('2014_06_27_163032_create_users_table',1), | ||||
| 	('2014_06_27_163145_create_account_types_table',1), | ||||
| 	('2014_06_27_163259_create_accounts_table',1), | ||||
| 	('2014_06_27_163817_create_components_table',1), | ||||
| 	('2014_06_27_163818_create_piggybanks_table',1), | ||||
| 	('2014_06_27_164042_create_transaction_currencies_table',1), | ||||
| 	('2014_06_27_164512_create_transaction_types_table',1), | ||||
| 	('2014_06_27_164619_create_recurring_transactions_table',1), | ||||
| 	('2014_06_27_164620_create_transaction_journals_table',1), | ||||
| 	('2014_06_27_164836_create_transactions_table',1), | ||||
| 	('2014_06_27_165344_create_component_transaction_table',1), | ||||
| 	('2014_07_05_171326_create_component_transaction_journal_table',1), | ||||
| 	('2014_07_06_123842_create_preferences_table',1), | ||||
| 	('2014_07_09_204843_create_session_table',1), | ||||
| 	('2014_07_17_183717_create_limits_table',1), | ||||
| 	('2014_07_19_055011_create_limit_repeat_table',1), | ||||
| 	('2014_08_06_044416_create_component_recurring_transaction_table',1), | ||||
| 	('2014_08_12_173919_create_piggybank_repetitions_table',1), | ||||
| 	('2014_08_18_100330_create_piggybank_events_table',1), | ||||
| 	('2014_08_23_113221_create_reminders_table',1), | ||||
| 	('2014_11_10_172053_create_account_meta_table',1), | ||||
| 	('2014_11_29_135749_create_transaction_groups_table',1), | ||||
| 	('2014_11_29_140217_create_transaction_group_transaction_journal_table',1), | ||||
| 	('2014_12_13_190730_changes_for_v321',1), | ||||
| 	('2014_12_24_191544_changes_for_v322',1); | ||||
|  | ||||
| /*!40000 ALTER TABLE `migrations` ENABLE KEYS */; | ||||
| UNLOCK TABLES; | ||||
|  | ||||
|  | ||||
| # Dump of table piggy_bank_events | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `piggy_bank_events`; | ||||
|  | ||||
| CREATE TABLE `piggy_bank_events` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `piggy_bank_id` int(10) unsigned NOT NULL, | ||||
|   `transaction_journal_id` int(10) unsigned DEFAULT NULL, | ||||
|   `date` date NOT NULL, | ||||
|   `amount` decimal(10,2) NOT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   KEY `piggybank_events_piggybank_id_foreign` (`piggy_bank_id`), | ||||
|   KEY `piggybank_events_transaction_journal_id_foreign` (`transaction_journal_id`), | ||||
|   CONSTRAINT `piggybank_events_transaction_journal_id_foreign` FOREIGN KEY (`transaction_journal_id`) REFERENCES `transaction_journals` (`id`) ON DELETE SET NULL, | ||||
|   CONSTRAINT `piggybank_events_piggybank_id_foreign` FOREIGN KEY (`piggy_bank_id`) REFERENCES `piggy_banks` (`id`) ON DELETE CASCADE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|  | ||||
|  | ||||
| # Dump of table piggy_bank_repetitions | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `piggy_bank_repetitions`; | ||||
|  | ||||
| CREATE TABLE `piggy_bank_repetitions` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `piggy_bank_id` int(10) unsigned NOT NULL, | ||||
|   `startdate` date DEFAULT NULL, | ||||
|   `targetdate` date DEFAULT NULL, | ||||
|   `currentamount` decimal(10,2) NOT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `piggybank_repetitions_piggybank_id_startdate_targetdate_unique` (`piggy_bank_id`,`startdate`,`targetdate`), | ||||
|   CONSTRAINT `piggybank_repetitions_piggybank_id_foreign` FOREIGN KEY (`piggy_bank_id`) REFERENCES `piggy_banks` (`id`) ON DELETE CASCADE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|  | ||||
|  | ||||
| # Dump of table piggy_banks | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `piggy_banks`; | ||||
|  | ||||
| CREATE TABLE `piggy_banks` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `account_id` int(10) unsigned NOT NULL, | ||||
|   `name` varchar(100) COLLATE utf8_unicode_ci NOT NULL, | ||||
|   `targetamount` decimal(10,2) NOT NULL, | ||||
|   `startdate` date DEFAULT NULL, | ||||
|   `targetdate` date DEFAULT NULL, | ||||
|   `repeats` tinyint(1) NOT NULL, | ||||
|   `rep_length` enum('day','week','quarter','month','year') COLLATE utf8_unicode_ci DEFAULT NULL, | ||||
|   `rep_every` smallint(5) unsigned NOT NULL, | ||||
|   `rep_times` smallint(5) unsigned DEFAULT NULL, | ||||
|   `reminder` enum('day','week','quarter','month','year') COLLATE utf8_unicode_ci DEFAULT NULL, | ||||
|   `reminder_skip` smallint(5) unsigned NOT NULL, | ||||
|   `remind_me` tinyint(1) NOT NULL, | ||||
|   `order` int(10) unsigned NOT NULL, | ||||
|   `deleted_at` timestamp NULL DEFAULT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `piggybanks_account_id_name_unique` (`account_id`,`name`), | ||||
|   CONSTRAINT `piggybanks_account_id_foreign` FOREIGN KEY (`account_id`) REFERENCES `accounts` (`id`) ON DELETE CASCADE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|  | ||||
|  | ||||
| # Dump of table preferences | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `preferences`; | ||||
|  | ||||
| CREATE TABLE `preferences` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `user_id` int(10) unsigned NOT NULL, | ||||
|   `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL, | ||||
|   `data` text COLLATE utf8_unicode_ci NOT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `preferences_user_id_name_unique` (`user_id`,`name`), | ||||
|   CONSTRAINT `preferences_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|  | ||||
|  | ||||
| # Dump of table reminders | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `reminders`; | ||||
|  | ||||
| CREATE TABLE `reminders` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `user_id` int(10) unsigned NOT NULL, | ||||
|   `startdate` date NOT NULL, | ||||
|   `enddate` date DEFAULT NULL, | ||||
|   `active` tinyint(1) NOT NULL, | ||||
|   `notnow` tinyint(1) NOT NULL DEFAULT '0', | ||||
|   `remindersable_id` int(10) unsigned DEFAULT NULL, | ||||
|   `remindersable_type` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   KEY `reminders_user_id_foreign` (`user_id`), | ||||
|   CONSTRAINT `reminders_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|  | ||||
|  | ||||
| # Dump of table sessions | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `sessions`; | ||||
|  | ||||
| CREATE TABLE `sessions` ( | ||||
|   `id` varchar(255) COLLATE utf8_unicode_ci NOT NULL, | ||||
|   `payload` text COLLATE utf8_unicode_ci NOT NULL, | ||||
|   `last_activity` int(11) NOT NULL, | ||||
|   UNIQUE KEY `sessions_id_unique` (`id`) | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|  | ||||
|  | ||||
| # Dump of table transaction_currencies | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `transaction_currencies`; | ||||
|  | ||||
| CREATE TABLE `transaction_currencies` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `deleted_at` timestamp NULL DEFAULT NULL, | ||||
|   `code` varchar(3) COLLATE utf8_unicode_ci NOT NULL, | ||||
|   `name` varchar(48) COLLATE utf8_unicode_ci DEFAULT NULL, | ||||
|   `symbol` varchar(8) COLLATE utf8_unicode_ci DEFAULT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `transaction_currencies_code_unique` (`code`) | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
| LOCK TABLES `transaction_currencies` WRITE; | ||||
| /*!40000 ALTER TABLE `transaction_currencies` DISABLE KEYS */; | ||||
|  | ||||
| INSERT INTO `transaction_currencies` (`id`, `created_at`, `updated_at`, `deleted_at`, `code`, `name`, `symbol`) | ||||
| VALUES | ||||
| 	(1,'2015-01-02 19:00:13','2015-01-02 19:00:13',NULL,'EUR','Euro','€'), | ||||
| 	(2,'2015-01-02 19:00:13','2015-01-02 19:00:13',NULL,'USD','US Dollar','$'), | ||||
| 	(3,'2015-01-02 19:00:13','2015-01-02 19:00:13',NULL,'HUF','Hungarian forint','Ft'); | ||||
|  | ||||
| /*!40000 ALTER TABLE `transaction_currencies` ENABLE KEYS */; | ||||
| UNLOCK TABLES; | ||||
|  | ||||
|  | ||||
| # Dump of table transaction_group_transaction_journal | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `transaction_group_transaction_journal`; | ||||
|  | ||||
| CREATE TABLE `transaction_group_transaction_journal` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `transaction_group_id` int(10) unsigned NOT NULL, | ||||
|   `transaction_journal_id` int(10) unsigned NOT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `tt_joined` (`transaction_group_id`,`transaction_journal_id`), | ||||
|   KEY `tr_trj_id` (`transaction_journal_id`), | ||||
|   CONSTRAINT `tr_trj_id` FOREIGN KEY (`transaction_journal_id`) REFERENCES `transaction_journals` (`id`) ON DELETE CASCADE, | ||||
|   CONSTRAINT `tr_grp_id` FOREIGN KEY (`transaction_group_id`) REFERENCES `transaction_groups` (`id`) ON DELETE CASCADE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|  | ||||
|  | ||||
| # Dump of table transaction_groups | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `transaction_groups`; | ||||
|  | ||||
| CREATE TABLE `transaction_groups` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `deleted_at` timestamp NULL DEFAULT NULL, | ||||
|   `user_id` int(10) unsigned NOT NULL, | ||||
|   `relation` enum('balance') COLLATE utf8_unicode_ci NOT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   KEY `transaction_groups_user_id_foreign` (`user_id`), | ||||
|   CONSTRAINT `transaction_groups_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|  | ||||
|  | ||||
| # Dump of table transaction_journals | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `transaction_journals`; | ||||
|  | ||||
| CREATE TABLE `transaction_journals` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `deleted_at` timestamp NULL DEFAULT NULL, | ||||
|   `user_id` int(10) unsigned NOT NULL, | ||||
|   `transaction_type_id` int(10) unsigned NOT NULL, | ||||
|   `bill_id` int(10) unsigned DEFAULT NULL, | ||||
|   `transaction_currency_id` int(10) unsigned NOT NULL, | ||||
|   `description` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, | ||||
|   `completed` tinyint(1) NOT NULL, | ||||
|   `date` date NOT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   KEY `transaction_journals_user_id_foreign` (`user_id`), | ||||
|   KEY `transaction_journals_transaction_type_id_foreign` (`transaction_type_id`), | ||||
|   KEY `transaction_journals_transaction_currency_id_foreign` (`transaction_currency_id`), | ||||
|   KEY `bill_id_foreign` (`bill_id`), | ||||
|   CONSTRAINT `bill_id_foreign` FOREIGN KEY (`bill_id`) REFERENCES `bills` (`id`) ON DELETE SET NULL, | ||||
|   CONSTRAINT `transaction_journals_transaction_currency_id_foreign` FOREIGN KEY (`transaction_currency_id`) REFERENCES `transaction_currencies` (`id`) ON DELETE CASCADE, | ||||
|   CONSTRAINT `transaction_journals_transaction_type_id_foreign` FOREIGN KEY (`transaction_type_id`) REFERENCES `transaction_types` (`id`) ON DELETE CASCADE, | ||||
|   CONSTRAINT `transaction_journals_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|  | ||||
|  | ||||
| # Dump of table transaction_types | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `transaction_types`; | ||||
|  | ||||
| CREATE TABLE `transaction_types` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `deleted_at` timestamp NULL DEFAULT NULL, | ||||
|   `type` varchar(50) COLLATE utf8_unicode_ci NOT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `transaction_types_type_unique` (`type`) | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
| LOCK TABLES `transaction_types` WRITE; | ||||
| /*!40000 ALTER TABLE `transaction_types` DISABLE KEYS */; | ||||
|  | ||||
| INSERT INTO `transaction_types` (`id`, `created_at`, `updated_at`, `deleted_at`, `type`) | ||||
| VALUES | ||||
| 	(1,'2015-01-02 19:00:13','2015-01-02 19:00:13',NULL,'Withdrawal'), | ||||
| 	(2,'2015-01-02 19:00:13','2015-01-02 19:00:13',NULL,'Deposit'), | ||||
| 	(3,'2015-01-02 19:00:13','2015-01-02 19:00:13',NULL,'Transfer'), | ||||
| 	(4,'2015-01-02 19:00:13','2015-01-02 19:00:13',NULL,'Opening balance'); | ||||
|  | ||||
| /*!40000 ALTER TABLE `transaction_types` ENABLE KEYS */; | ||||
| UNLOCK TABLES; | ||||
|  | ||||
|  | ||||
| # Dump of table transactions | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `transactions`; | ||||
|  | ||||
| CREATE TABLE `transactions` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `deleted_at` timestamp NULL DEFAULT NULL, | ||||
|   `account_id` int(10) unsigned NOT NULL, | ||||
|   `transaction_journal_id` int(10) unsigned NOT NULL, | ||||
|   `description` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, | ||||
|   `amount` decimal(10,2) NOT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   KEY `transactions_account_id_foreign` (`account_id`), | ||||
|   KEY `transactions_transaction_journal_id_foreign` (`transaction_journal_id`), | ||||
|   CONSTRAINT `transactions_account_id_foreign` FOREIGN KEY (`account_id`) REFERENCES `accounts` (`id`) ON DELETE CASCADE, | ||||
|   CONSTRAINT `transactions_transaction_journal_id_foreign` FOREIGN KEY (`transaction_journal_id`) REFERENCES `transaction_journals` (`id`) ON DELETE CASCADE | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|  | ||||
|  | ||||
| # Dump of table users | ||||
| # ------------------------------------------------------------ | ||||
|  | ||||
| DROP TABLE IF EXISTS `users`; | ||||
|  | ||||
| CREATE TABLE `users` ( | ||||
|   `id` int(10) unsigned NOT NULL AUTO_INCREMENT, | ||||
|   `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', | ||||
|   `email` varchar(100) COLLATE utf8_unicode_ci NOT NULL, | ||||
|   `password` varchar(60) COLLATE utf8_unicode_ci NOT NULL, | ||||
|   `reset` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL, | ||||
|   `remember_token` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, | ||||
|   PRIMARY KEY (`id`), | ||||
|   UNIQUE KEY `users_email_unique` (`email`) | ||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; | ||||
| /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; | ||||
| /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; | ||||
| /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; | ||||
| /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; | ||||
| /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; | ||||
| @@ -1,7 +1,369 @@ | ||||
| <?php | ||||
| use Carbon\Carbon; | ||||
| use DaveJamesMiller\Breadcrumbs\Generator; | ||||
| use FireflyIII\Exception\FireflyException; | ||||
|  | ||||
| /* | ||||
|  * Back home. | ||||
|  */ | ||||
| Breadcrumbs::register('home', function($breadcrumbs) { | ||||
|     $breadcrumbs->push('Home', route('index')); | ||||
| }); | ||||
| Breadcrumbs::register( | ||||
|     'home', | ||||
|     function (Generator $breadcrumbs) { | ||||
|  | ||||
|         $breadcrumbs->push('Home', route('index')); | ||||
|     } | ||||
| ); | ||||
|  | ||||
| // accounts | ||||
| Breadcrumbs::register( | ||||
|     'accounts.index', function (Generator $breadcrumbs, $what) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push(ucfirst(e($what)) . ' accounts', route('accounts.index', $what)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'accounts.show', function (Generator $breadcrumbs, \Account $account) { | ||||
|     switch ($account->accountType->type) { | ||||
|         default: | ||||
|             throw new FireflyException('Cannot handle account type "' . e($account->accountType->type) . '"'); | ||||
|             break; | ||||
|         case 'Default account': | ||||
|         case 'Asset account': | ||||
|             $what = 'asset'; | ||||
|             break; | ||||
|         case 'Cash account': | ||||
|             $what = 'cash'; | ||||
|             break; | ||||
|         case 'Expense account': | ||||
|         case 'Beneficiary account': | ||||
|             $what = 'expense'; | ||||
|             break; | ||||
|         case 'Revenue account': | ||||
|             $what = 'revenue'; | ||||
|             break; | ||||
|     } | ||||
|     $breadcrumbs->parent('accounts.index', $what); | ||||
|     $breadcrumbs->push(e($account->name), route('accounts.show', $account->id)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'accounts.delete', function (Generator $breadcrumbs, \Account $account) { | ||||
|     $breadcrumbs->parent('accounts.show', $account); | ||||
|     $breadcrumbs->push('Delete ' . e($account->name), route('accounts.delete', $account->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'accounts.edit', function (Generator $breadcrumbs, \Account $account) { | ||||
|     $breadcrumbs->parent('accounts.show', $account); | ||||
|     $breadcrumbs->push('Edit ' . e($account->name), route('accounts.edit', $account->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| // budgets. | ||||
| Breadcrumbs::register( | ||||
|     'budgets.index', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Budgets', route('budgets.index')); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'budgets.create', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('budgets.index'); | ||||
|     $breadcrumbs->push('Create new budget', route('budgets.create')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'budgets.edit', function (Generator $breadcrumbs, Budget $budget) { | ||||
|     $breadcrumbs->parent('budgets.show', $budget); | ||||
|     $breadcrumbs->push('Edit ' . e($budget->name), route('budgets.edit', $budget->id)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'budgets.delete', function (Generator $breadcrumbs, Budget $budget) { | ||||
|     $breadcrumbs->parent('budgets.show', $budget); | ||||
|     $breadcrumbs->push('Delete ' . e($budget->name), route('budgets.delete', $budget->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'budgets.show', function (Generator $breadcrumbs, Budget $budget, LimitRepetition $repetition = null) { | ||||
|     $breadcrumbs->parent('budgets.index'); | ||||
|     $breadcrumbs->push(e($budget->name), route('budgets.show', $budget->id)); | ||||
|     if (!is_null($repetition)) { | ||||
|         $breadcrumbs->push( | ||||
|             DateKit::periodShow($repetition->startdate, $repetition->budgetlimit->repeat_freq), route('budgets.show', $budget->id, $repetition->id) | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| ); | ||||
|  | ||||
| // categories | ||||
| Breadcrumbs::register( | ||||
|     'categories.index', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Categories', route('categories.index')); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'categories.create', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('categories.index'); | ||||
|     $breadcrumbs->push('Create new category', route('categories.create')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'categories.edit', function (Generator $breadcrumbs, Category $category) { | ||||
|     $breadcrumbs->parent('categories.show', $category); | ||||
|     $breadcrumbs->push('Edit ' . e($category->name), route('categories.edit', $category->id)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'categories.delete', function (Generator $breadcrumbs, Category $category) { | ||||
|     $breadcrumbs->parent('categories.show', $category); | ||||
|     $breadcrumbs->push('Delete ' . e($category->name), route('categories.delete', $category->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'categories.show', function (Generator $breadcrumbs, Category $category) { | ||||
|     $breadcrumbs->parent('categories.index'); | ||||
|     $breadcrumbs->push(e($category->name), route('categories.show', $category->id)); | ||||
|  | ||||
| } | ||||
| ); | ||||
|  | ||||
|  | ||||
| // piggy banks | ||||
| Breadcrumbs::register( | ||||
|     'piggyBanks.index', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Piggy banks', route('piggyBanks.index')); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'piggyBanks.create', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('piggyBanks.index'); | ||||
|     $breadcrumbs->push('Create new piggy bank', route('piggyBanks.create')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'piggyBanks.edit', function (Generator $breadcrumbs, PiggyBank $piggyBank) { | ||||
|     $breadcrumbs->parent('piggyBanks.show', $piggyBank); | ||||
|     $breadcrumbs->push('Edit ' . e($piggyBank->name), route('piggyBanks.edit', $piggyBank->id)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'piggyBanks.delete', function (Generator $breadcrumbs, PiggyBank $piggyBank) { | ||||
|     $breadcrumbs->parent('piggyBanks.show', $piggyBank); | ||||
|     $breadcrumbs->push('Delete ' . e($piggyBank->name), route('piggyBanks.delete', $piggyBank->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'piggyBanks.show', function (Generator $breadcrumbs, PiggyBank $piggyBank) { | ||||
|     $breadcrumbs->parent('piggyBanks.index'); | ||||
|     $breadcrumbs->push(e($piggyBank->name), route('piggyBanks.show', $piggyBank->id)); | ||||
|  | ||||
| } | ||||
| ); | ||||
|  | ||||
| // preferences | ||||
| Breadcrumbs::register( | ||||
|     'preferences', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Preferences', route('preferences')); | ||||
|  | ||||
| } | ||||
| ); | ||||
|  | ||||
| // profile | ||||
| Breadcrumbs::register( | ||||
|     'profile', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Profile', route('profile')); | ||||
|  | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'change-password', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('profile'); | ||||
|     $breadcrumbs->push('Change your password', route('change-password')); | ||||
|  | ||||
| } | ||||
| ); | ||||
|  | ||||
| // bills | ||||
| Breadcrumbs::register( | ||||
|     'bills.index', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Bills', route('bills.index')); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'bills.create', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('bills.index'); | ||||
|     $breadcrumbs->push('Create new bill', route('bills.create')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'bills.edit', function (Generator $breadcrumbs, Bill $bill) { | ||||
|     $breadcrumbs->parent('bills.show', $bill); | ||||
|     $breadcrumbs->push('Edit ' . e($bill->name), route('bills.edit', $bill->id)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'bills.delete', function (Generator $breadcrumbs, Bill $bill) { | ||||
|     $breadcrumbs->parent('bills.show', $bill); | ||||
|     $breadcrumbs->push('Delete ' . e($bill->name), route('bills.delete', $bill->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'bills.show', function (Generator $breadcrumbs, Bill $bill) { | ||||
|     $breadcrumbs->parent('bills.index'); | ||||
|     $breadcrumbs->push(e($bill->name), route('bills.show', $bill->id)); | ||||
|  | ||||
| } | ||||
| ); | ||||
|  | ||||
| // reminders | ||||
| Breadcrumbs::register( | ||||
|     'reminders.show', function (Generator $breadcrumbs, Reminder $reminder) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Reminder #' . $reminder->id, route('reminders.show', $reminder->id)); | ||||
|  | ||||
| } | ||||
| ); | ||||
|  | ||||
| // repeated expenses | ||||
| Breadcrumbs::register( | ||||
|     'repeated.index', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Repeated expenses', route('repeated.index')); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'repeated.create', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('repeated.index'); | ||||
|     $breadcrumbs->push('Create new repeated expense', route('repeated.create')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'repeated.edit', function (Generator $breadcrumbs, PiggyBank $piggyBank) { | ||||
|     $breadcrumbs->parent('repeated.show', $piggyBank); | ||||
|     $breadcrumbs->push('Edit ' . e($piggyBank->name), route('repeated.edit', $piggyBank->id)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'repeated.delete', function (Generator $breadcrumbs, PiggyBank $piggyBank) { | ||||
|     $breadcrumbs->parent('repeated.show', $piggyBank); | ||||
|     $breadcrumbs->push('Delete ' . e($piggyBank->name), route('repeated.delete', $piggyBank->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'repeated.show', function (Generator $breadcrumbs, PiggyBank $piggyBank) { | ||||
|     $breadcrumbs->parent('repeated.index'); | ||||
|     $breadcrumbs->push(e($piggyBank->name), route('repeated.show', $piggyBank->id)); | ||||
|  | ||||
| } | ||||
| ); | ||||
|  | ||||
| // reports | ||||
| Breadcrumbs::register( | ||||
|     'reports.index', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Reports', route('reports.index')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'reports.year', function (Generator $breadcrumbs, Carbon $date) { | ||||
|     $breadcrumbs->parent('reports.index'); | ||||
|     $breadcrumbs->push($date->format('Y'), route('reports.year', $date->format('Y'))); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'reports.month', function (Generator $breadcrumbs, Carbon $date) { | ||||
|     $breadcrumbs->parent('reports.index'); | ||||
|     $breadcrumbs->push('Monthly report for ' . $date->format('F Y'), route('reports.month', $date)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'reports.budget', function (Generator $breadcrumbs, Carbon $date) { | ||||
|     $breadcrumbs->parent('reports.index'); | ||||
|     $breadcrumbs->push('Budget report for ' . $date->format('F Y'), route('reports.budget', $date)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| // search | ||||
| Breadcrumbs::register( | ||||
|     'search', function (Generator $breadcrumbs, $query) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Search for "' . e($query) . '"', route('search')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| // transactions | ||||
| Breadcrumbs::register( | ||||
|     'transactions.index', function (Generator $breadcrumbs, $what) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|  | ||||
|     switch ($what) { | ||||
|         case 'expenses': | ||||
|         case 'withdrawal': | ||||
|             $subTitle = 'Expenses'; | ||||
|             break; | ||||
|         case 'revenue': | ||||
|         case 'deposit': | ||||
|             $subTitle = 'Revenue, income and deposits'; | ||||
|             break; | ||||
|         case 'transfer': | ||||
|         case 'transfers': | ||||
|             $subTitle = 'Transfers'; | ||||
|             break; | ||||
|         case 'opening balance': | ||||
|             $subTitle = 'Opening balances'; | ||||
|             break; | ||||
|         default: | ||||
|             throw new FireflyException('Cannot handle $what "' . e($what) . '" in bread crumbs'); | ||||
|     } | ||||
|  | ||||
|     $breadcrumbs->push($subTitle, route('transactions.index', $what)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'transactions.create', function (Generator $breadcrumbs, $what) { | ||||
|     $breadcrumbs->parent('transactions.index', $what); | ||||
|     $breadcrumbs->push('Create new ' .e($what), route('transactions.create', $what)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'transactions.edit', function (Generator $breadcrumbs, TransactionJournal $journal) { | ||||
|     $breadcrumbs->parent('transactions.show', $journal); | ||||
|     $breadcrumbs->push('Edit ' . e($journal->description), route('transactions.edit', $journal->id)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'transactions.delete', function (Generator $breadcrumbs, TransactionJournal $journal) { | ||||
|     $breadcrumbs->parent('transactions.show', $journal); | ||||
|     $breadcrumbs->push('Delete ' . e($journal->description), route('transactions.delete', $journal->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'transactions.show', function (Generator $breadcrumbs, TransactionJournal $journal) { | ||||
|  | ||||
|     $breadcrumbs->parent('transactions.index', strtolower($journal->transactionType->type)); | ||||
|     $breadcrumbs->push(e($journal->description), route('transactions.show', $journal->id)); | ||||
|  | ||||
| } | ||||
| ); | ||||
|   | ||||
							
								
								
									
										76
									
								
								app/commands/Cleanup.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								app/commands/Cleanup.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | ||||
| <?php | ||||
|  | ||||
| use Illuminate\Console\Command; | ||||
|  | ||||
| /** | ||||
|  * Class Cleanup | ||||
|  */ | ||||
| class Cleanup extends Command | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * The console command description. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $description = 'Clean caches, regenerate some stuff.'; | ||||
|     /** | ||||
|      * The console command name. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $name = 'firefly:cleanup'; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Execute the console command. | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function fire() | ||||
|     { | ||||
|         $this->info('Start!'); | ||||
|         Artisan::call('clear-compiled'); | ||||
|         $this->info('Cleared compiled...'); | ||||
|         Artisan::call('ide-helper:generate'); | ||||
|         $this->info('IDE helper, done...'); | ||||
|         Artisan::call('ide-helper:models'); | ||||
|         $this->info('IDE models, done...'); | ||||
|         Artisan::call('optimize'); | ||||
|         $this->info('Optimized...'); | ||||
|         Artisan::call('dump-autoload'); | ||||
|         $this->info('Done!'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the console command arguments. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function getArguments() | ||||
|     { | ||||
|         return [ | ||||
|         //    ['example', InputArgument::REQUIRED, 'An example argument.'], | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the console command options. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function getOptions() | ||||
|     { | ||||
|         return [ | ||||
|           //  ['example', null, InputOption::VALUE_OPTIONAL, 'An example option.', null], | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										3
									
								
								app/config/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								app/config/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,3 +1,4 @@ | ||||
| local/ | ||||
| laptop/ | ||||
| vagrant/ | ||||
| vagrant/ | ||||
| production/ | ||||
|   | ||||
| @@ -37,13 +37,11 @@ return [ | ||||
|         'Illuminate\Validation\ValidationServiceProvider', | ||||
|         'Illuminate\View\ViewServiceProvider', | ||||
|         'Illuminate\Workbench\WorkbenchServiceProvider', | ||||
|         'Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider', | ||||
|         'Barryvdh\Debugbar\ServiceProvider', | ||||
|         'Firefly\Storage\StorageServiceProvider', | ||||
|         'Firefly\Helper\HelperServiceProvider', | ||||
|         'Firefly\Validation\ValidationServiceProvider', | ||||
|         //'Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider', | ||||
|         //'Barryvdh\Debugbar\ServiceProvider', | ||||
|         'FireflyIII\FF3ServiceProvider', | ||||
|         'DaveJamesMiller\Breadcrumbs\ServiceProvider', | ||||
|         'TwigBridge\ServiceProvider' | ||||
|         'Grumpydictator\Gchart\GchartServiceProvider', | ||||
|     ], | ||||
|     'manifest'        => storage_path() . '/meta', | ||||
|     'aliases'         => [ | ||||
| @@ -86,8 +84,7 @@ return [ | ||||
|         'URL'               => 'Illuminate\Support\Facades\URL', | ||||
|         'Validator'         => 'Illuminate\Support\Facades\Validator', | ||||
|         'View'              => 'Illuminate\Support\Facades\View', | ||||
|         'Breadcrumbs'       => 'DaveJamesMiller\Breadcrumbs\Facade', | ||||
|         'Twig'              => 'TwigBridge\Facade\Twig', | ||||
|         'Breadcrumbs'       => 'DaveJamesMiller\Breadcrumbs\Facade' | ||||
|  | ||||
|     ], | ||||
|  | ||||
|   | ||||
| @@ -1,3 +1,3 @@ | ||||
| <?php | ||||
|  | ||||
| return []; | ||||
| return []; | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| <?php | ||||
| return [ | ||||
|     'import' => '' | ||||
| ]; | ||||
| ]; | ||||
|   | ||||
| @@ -1,11 +1,15 @@ | ||||
| <?php | ||||
| use Carbon\Carbon; | ||||
|  | ||||
| return [ | ||||
|     'index_periods'          => ['1D', '1W', '1M', '3M', '6M', 'custom'], | ||||
|     'budget_periods'         => ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly'], | ||||
|     'piggybank_periods'      => ['day', 'week', 'month', 'year'], | ||||
|     'periods_to_text'        => [ | ||||
|     'index_periods'        => ['1D', '1W', '1M', '3M', '6M', '1Y', 'custom'], | ||||
|     'budget_periods'       => ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly'], | ||||
|     'piggy_bank_periods'    => [ | ||||
|         'week'    => 'Week', | ||||
|         'month'   => 'Month', | ||||
|         'quarter' => 'Quarter', | ||||
|         'year'    => 'Year' | ||||
|     ], | ||||
|     'periods_to_text'      => [ | ||||
|         'weekly'    => 'A week', | ||||
|         'monthly'   => 'A month', | ||||
|         'quarterly' => 'A quarter', | ||||
| @@ -13,7 +17,12 @@ return [ | ||||
|         'yearly'    => 'A year', | ||||
|     ], | ||||
|  | ||||
|     'range_to_text'          => [ | ||||
|     'accountRoles'         => [ | ||||
|         'defaultExpense' => 'Default expense account', | ||||
|         'sharedExpense'  => 'Shared expense account' | ||||
|     ], | ||||
|  | ||||
|     'range_to_text'        => [ | ||||
|         '1D'     => 'day', | ||||
|         '1W'     => 'week', | ||||
|         '1M'     => 'month', | ||||
| @@ -21,7 +30,15 @@ return [ | ||||
|         '6M'     => 'half year', | ||||
|         'custom' => '(custom)' | ||||
|     ], | ||||
|     'range_to_repeat_freq'   => [ | ||||
|     'range_to_name'        => [ | ||||
|         '1D' => 'one day', | ||||
|         '1W' => 'one week', | ||||
|         '1M' => 'one month', | ||||
|         '3M' => 'three months', | ||||
|         '6M' => 'six months', | ||||
|         '1Y' => 'one year', | ||||
|     ], | ||||
|     'range_to_repeat_freq' => [ | ||||
|         '1D'     => 'weekly', | ||||
|         '1W'     => 'weekly', | ||||
|         '1M'     => 'monthly', | ||||
| @@ -29,4 +46,4 @@ return [ | ||||
|         '6M'     => 'half-year', | ||||
|         'custom' => 'monthly' | ||||
|     ], | ||||
| ]; | ||||
| ]; | ||||
|   | ||||
							
								
								
									
										15
									
								
								app/config/homestead/app.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								app/config/homestead/app.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| <?php | ||||
| return [ | ||||
|     /* | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | Application Debug Mode | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | | ||||
|     | When your application is in debug mode, detailed error messages with | ||||
|     | stack traces will be shown on every error that occurs within your | ||||
|     | application. If disabled, a simple generic error page is shown. | ||||
|     | | ||||
|     */ | ||||
|     'debug' => true, | ||||
|     'log_level'       => 'debug', | ||||
| ]; | ||||
							
								
								
									
										12
									
								
								app/config/homestead/cache.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								app/config/homestead/cache.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| <?php | ||||
|  | ||||
| return [ | ||||
|     'driver'     => 'file', | ||||
|     'path'       => storage_path() . '/cache', | ||||
|     'connection' => null, | ||||
|     'table'      => 'cache', | ||||
|     'memcached'  => [ | ||||
|         ['host' => '127.0.0.1', 'port' => 11211, 'weight' => 100], | ||||
|     ], | ||||
|     'prefix'     => 'laravel', | ||||
| ]; | ||||
							
								
								
									
										37
									
								
								app/config/homestead/database.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								app/config/homestead/database.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| <?php | ||||
|  | ||||
| return [ | ||||
|  | ||||
|     'default'     => 'mysql', | ||||
|     'connections' => [ | ||||
|  | ||||
|         'mysql' => [ | ||||
|             'driver'    => 'mysql', | ||||
|             'host'      => 'localhost', | ||||
|             'database'  => 'homestead', | ||||
|             'username'  => 'homestead', | ||||
|             'password'  => 'secret', | ||||
|             'charset'   => 'utf8', | ||||
|             'collation' => 'utf8_unicode_ci', | ||||
|             'prefix'    => '', | ||||
|         ], | ||||
|         'sqlite' => [ | ||||
|             'driver'   => 'sqlite', | ||||
|             'database' => realpath(__DIR__.'/../../../tests/_data/testing.sqlite'), | ||||
|             'prefix'   => '' | ||||
|         ], | ||||
|  | ||||
|         'pgsql' => [ | ||||
|             'driver'   => 'pgsql', | ||||
|             'host'     => 'localhost', | ||||
|             'database' => 'homestead', | ||||
|             'username' => 'homestead', | ||||
|             'password' => 'secret', | ||||
|             'charset'  => 'utf8', | ||||
|             'prefix'   => '', | ||||
|             'schema'   => 'public', | ||||
|         ], | ||||
|  | ||||
|     ], | ||||
|  | ||||
| ]; | ||||
							
								
								
									
										13
									
								
								app/config/homestead/mail.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								app/config/homestead/mail.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| <?php | ||||
|  | ||||
| return [ | ||||
|     'driver'     => 'smtp', | ||||
|     'host'       => 'smtp.gmail.com', | ||||
|     'port'       => 587, | ||||
|     'from'       => ['address' => '@gmail.com', 'name' => 'Firefly III'], | ||||
|     'encryption' => 'tls', | ||||
|     'username'   => '@gmail.com', | ||||
|     'password'   => '', | ||||
|     'sendmail'   => '/usr/sbin/sendmail -bs', | ||||
|     'pretend'    => false, | ||||
| ]; | ||||
| @@ -2,14 +2,14 @@ | ||||
|  | ||||
| use Illuminate\Support\Facades\Config; | ||||
|  | ||||
| return array( | ||||
| return [ | ||||
|  | ||||
|     'enabled' => Config::get('app.debug'), | ||||
|     'enabled'         => Config::get('app.debug'), | ||||
|  | ||||
|     'storage' => array( | ||||
|     'storage'         => [ | ||||
|         'enabled' => true, | ||||
|         'path' => storage_path() . '/debugbar', | ||||
|     ), | ||||
|         'path'    => storage_path() . '/debugbar', | ||||
|     ], | ||||
|  | ||||
|     /* | ||||
|      |-------------------------------------------------------------------------- | ||||
| @@ -37,8 +37,8 @@ return array( | ||||
|      | | ||||
|      */ | ||||
|  | ||||
|     'capture_ajax' => true, | ||||
|      | ||||
|     'capture_ajax'    => true, | ||||
|  | ||||
|     /* | ||||
|      |-------------------------------------------------------------------------- | ||||
|      | Capture Console Commands | ||||
| @@ -59,7 +59,7 @@ return array( | ||||
|      | | ||||
|      */ | ||||
|  | ||||
|     'collectors' => array( | ||||
|     'collectors'      => [ | ||||
|         'phpinfo'         => true,  // Php version | ||||
|         'messages'        => true,  // Messages | ||||
|         'time'            => true,  // Time Datalogger | ||||
| @@ -78,7 +78,7 @@ return array( | ||||
|         'files'           => false, // Show the included files | ||||
|         'config'          => false, // Display config settings | ||||
|         'auth'            => false, // Display Laravel authentication status | ||||
|     ), | ||||
|     ], | ||||
|  | ||||
|     /* | ||||
|      |-------------------------------------------------------------------------- | ||||
| @@ -89,27 +89,27 @@ return array( | ||||
|      | | ||||
|      */ | ||||
|  | ||||
|     'options' => array( | ||||
|         'auth' => array( | ||||
|     'options'         => [ | ||||
|         'auth'  => [ | ||||
|             'show_name' => false,   // Also show the users name/email in the debugbar | ||||
|         ), | ||||
|         'db' => array( | ||||
|             'with_params'       => true,   // Render SQL with the parameters substituted | ||||
|             'timeline'          => false,   // Add the queries to the timeline | ||||
|         ), | ||||
|         'mail' => array( | ||||
|         ], | ||||
|         'db'    => [ | ||||
|             'with_params' => true,   // Render SQL with the parameters substituted | ||||
|             'timeline'    => false,   // Add the queries to the timeline | ||||
|         ], | ||||
|         'mail'  => [ | ||||
|             'full_log' => false | ||||
|         ), | ||||
|         'views' => array( | ||||
|         ], | ||||
|         'views' => [ | ||||
|             'data' => false,    //Note: Can slow down the application, because the data can be quite large.. | ||||
|         ), | ||||
|         'route' => array( | ||||
|         ], | ||||
|         'route' => [ | ||||
|             'label' => true  // show complete route on bar | ||||
|         ), | ||||
|         'logs' => array( | ||||
|         ], | ||||
|         'logs'  => [ | ||||
|             'file' => null | ||||
|         ), | ||||
|     ), | ||||
|         ], | ||||
|     ], | ||||
|  | ||||
|     /* | ||||
|      |-------------------------------------------------------------------------- | ||||
| @@ -122,6 +122,6 @@ return array( | ||||
|      | | ||||
|      */ | ||||
|  | ||||
|     'inject' => true, | ||||
|     'inject'          => true, | ||||
|  | ||||
| ); | ||||
| ]; | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| <?php | ||||
|  | ||||
| return array( | ||||
| return [ | ||||
|  | ||||
|     /* | ||||
|     |-------------------------------------------------------------------------- | ||||
| @@ -11,7 +11,7 @@ return array( | ||||
|     | | ||||
|     */ | ||||
|  | ||||
|     'filename' => '_ide_helper.php', | ||||
|     'filename'        => '_ide_helper.php', | ||||
|  | ||||
|     /* | ||||
|     |-------------------------------------------------------------------------- | ||||
| @@ -25,9 +25,9 @@ return array( | ||||
|  | ||||
|     'include_helpers' => false, | ||||
|  | ||||
|     'helper_files' => array( | ||||
|         base_path().'/vendor/laravel/framework/src/Illuminate/Support/helpers.php', | ||||
|     ), | ||||
|     'helper_files'    => [ | ||||
|         base_path() . '/vendor/laravel/framework/src/Illuminate/Support/helpers.php', | ||||
|     ], | ||||
|  | ||||
|     /* | ||||
|     |-------------------------------------------------------------------------- | ||||
| @@ -39,9 +39,9 @@ return array( | ||||
|     | | ||||
|     */ | ||||
|  | ||||
|     'model_locations' => array( | ||||
|     'model_locations' => [ | ||||
|         'app/models', | ||||
|     ), | ||||
|     ], | ||||
|  | ||||
|  | ||||
|     /* | ||||
| @@ -53,14 +53,14 @@ return array( | ||||
|     | | ||||
|     */ | ||||
|  | ||||
|     'extra' => array( | ||||
|         'Artisan' => array('Illuminate\Foundation\Artisan'), | ||||
|         'Eloquent' => array('Illuminate\Database\Eloquent\Builder', 'Illuminate\Database\Query\Builder'), | ||||
|         'Session' => array('Illuminate\Session\Store'), | ||||
|     ), | ||||
|     'extra'           => [ | ||||
|         'Artisan'  => ['Illuminate\Foundation\Artisan'], | ||||
|         'Eloquent' => ['Illuminate\Database\Eloquent\Builder', 'Illuminate\Database\Query\Builder'], | ||||
|         'Session'  => ['Illuminate\Session\Store'], | ||||
|     ], | ||||
|  | ||||
|     'magic' => array( | ||||
|         'Log' => array( | ||||
|     'magic'           => [ | ||||
|         'Log' => [ | ||||
|             'debug'     => 'Monolog\Logger::addDebug', | ||||
|             'info'      => 'Monolog\Logger::addInfo', | ||||
|             'notice'    => 'Monolog\Logger::addNotice', | ||||
| @@ -69,7 +69,8 @@ return array( | ||||
|             'critical'  => 'Monolog\Logger::addCritical', | ||||
|             'alert'     => 'Monolog\Logger::addAlert', | ||||
|             'emergency' => 'Monolog\Logger::addEmergency', | ||||
|         ) | ||||
|     ) | ||||
|         ] | ||||
|     ] | ||||
|  | ||||
| ); | ||||
|  | ||||
| ]; | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| <?php | ||||
|  | ||||
| return array( | ||||
| return [ | ||||
|     'view' => 'laravel-breadcrumbs::bootstrap3', | ||||
| ); | ||||
| ]; | ||||
|   | ||||
| @@ -1,134 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * This file is part of the TwigBridge package. | ||||
|  * | ||||
|  * @copyright Robert Crowe <hello@vivalacrowe.com> | ||||
|  * | ||||
|  * For the full copyright and license information, please view the LICENSE | ||||
|  * file that was distributed with this source code. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Configuration options for the built-in extensions. | ||||
|  */ | ||||
| return [ | ||||
|  | ||||
|     /* | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | Extensions | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | | ||||
|     | Enabled extensions. | ||||
|     | | ||||
|     | `Twig_Extension_Debug` is enabled automatically if twig.debug is TRUE. | ||||
|     | | ||||
|     */ | ||||
|     'enabled' => [ | ||||
|         'TwigBridge\Extension\Loader\Facades', | ||||
|         'TwigBridge\Extension\Loader\Filters', | ||||
|         'TwigBridge\Extension\Loader\Functions', | ||||
|  | ||||
|         'TwigBridge\Extension\Laravel\Auth', | ||||
|         'TwigBridge\Extension\Laravel\Config', | ||||
|         'TwigBridge\Extension\Laravel\Form', | ||||
|         'TwigBridge\Extension\Laravel\Html', | ||||
|         'TwigBridge\Extension\Laravel\Input', | ||||
|         'TwigBridge\Extension\Laravel\Session', | ||||
|         'TwigBridge\Extension\Laravel\String', | ||||
|         'TwigBridge\Extension\Laravel\Translator', | ||||
|         'TwigBridge\Extension\Laravel\Url', | ||||
|  | ||||
|         // 'TwigBridge\Extension\Laravel\Legacy\Facades', | ||||
|     ], | ||||
|  | ||||
|     /* | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | Facades | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | | ||||
|     | Available facades. Access like `{{ Config.get('foo.bar') }}`. | ||||
|     | | ||||
|     | Each facade can take an optional array of options. To mark the whole facade | ||||
|     | as safe you can set the option `'is_safe' => true`. Setting the facade as | ||||
|     | safe means that any HTML returned will not be escaped. | ||||
|     | | ||||
|     | It is advisable to not set the whole facade as safe and instead mark the | ||||
|     | each appropriate method as safe for security reasons. You can do that with | ||||
|     | the following syntax: | ||||
|     | | ||||
|     | <code> | ||||
|     |     'Form' => [ | ||||
|     |         'is_safe' => [ | ||||
|     |             'open' | ||||
|     |         ] | ||||
|     |     ] | ||||
|     | </code> | ||||
|     | | ||||
|     | The values of the `is_safe` array must match the called method on the facade | ||||
|     | in order to be marked as safe. | ||||
|     | | ||||
|     */ | ||||
|     'facades' => [], | ||||
|  | ||||
|     /* | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | Functions | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | | ||||
|     | Available functions. Access like `{{ secure_url(...) }}`. | ||||
|     | | ||||
|     | Each function can take an optional array of options. These options are | ||||
|     | passed directly to `Twig_SimpleFunction`. | ||||
|     | | ||||
|     | So for example, to mark a function as safe you can do the following: | ||||
|     | | ||||
|     | <code> | ||||
|     |     'link_to' => [ | ||||
|     |         'is_safe' => ['html'] | ||||
|     |     ] | ||||
|     | </code> | ||||
|     | | ||||
|     | The options array also takes a `callback` that allows you to name the | ||||
|     | function differently in your Twig templates than what it's actually called. | ||||
|     | | ||||
|     | <code> | ||||
|     |     'link' => [ | ||||
|     |         'callback' => 'link_to' | ||||
|     |     ] | ||||
|     | </code> | ||||
|     | | ||||
|     */ | ||||
|     'functions' => [], | ||||
|  | ||||
|     /* | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | Filters | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | | ||||
|     | Available filters. Access like `{{ variable|filter }}`. | ||||
|     | | ||||
|     | Each filter can take an optional array of options. These options are | ||||
|     | passed directly to `Twig_SimpleFilter`. | ||||
|     | | ||||
|     | So for example, to mark a filter as safe you can do the following: | ||||
|     | | ||||
|     | <code> | ||||
|     |     'studly_case' => [ | ||||
|     |         'is_safe' => ['html'] | ||||
|     |     ] | ||||
|     | </code> | ||||
|     | | ||||
|     | The options array also takes a `callback` that allows you to name the | ||||
|     | filter differently in your Twig templates than what is actually called. | ||||
|     | | ||||
|     | <code> | ||||
|     |     'snake' => [ | ||||
|     |         'callback' => 'snake_case' | ||||
|     |     ] | ||||
|     | </code> | ||||
|     | | ||||
|     */ | ||||
|     'filters' => [], | ||||
|  | ||||
| ]; | ||||
| @@ -1,88 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * This file is part of the TwigBridge package. | ||||
|  * | ||||
|  * @copyright Robert Crowe <hello@vivalacrowe.com> | ||||
|  * | ||||
|  * For the full copyright and license information, please view the LICENSE | ||||
|  * file that was distributed with this source code. | ||||
|  */ | ||||
|  | ||||
| use Illuminate\Support\Facades\Config; | ||||
|  | ||||
| /** | ||||
|  * Configuration options for Twig. | ||||
|  */ | ||||
| return [ | ||||
|  | ||||
|     /* | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | Extension | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | | ||||
|     | File extension for Twig view files. | ||||
|     | | ||||
|     */ | ||||
|     'extension' => 'twig', | ||||
|  | ||||
|     /* | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | Accepts all Twig environment configuration options | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | | ||||
|     | http://twig.sensiolabs.org/doc/api.html#environment-options | ||||
|     | | ||||
|     */ | ||||
|     'environment' => [ | ||||
|  | ||||
|         // When set to true, the generated templates have a __toString() method | ||||
|         // that you can use to display the generated nodes. | ||||
|         // default: false | ||||
|         'debug' => Config::get('app.debug', false), | ||||
|  | ||||
|         // The charset used by the templates. | ||||
|         // default: utf-8 | ||||
|         'charset' => 'utf-8', | ||||
|  | ||||
|         // The base template class to use for generated templates. | ||||
|         // default: TwigBridge\Twig\Template | ||||
|         'base_template_class' => 'TwigBridge\Twig\Template', | ||||
|  | ||||
|         // An absolute path where to store the compiled templates, or false to disable caching. If null | ||||
|         // then the cache file path is used. | ||||
|         // default: cache file storage path | ||||
|         'cache' => null, | ||||
|  | ||||
|         // When developing with Twig, it's useful to recompile the template | ||||
|         // whenever the source code changes. If you don't provide a value | ||||
|         // for the auto_reload option, it will be determined automatically based on the debug value. | ||||
|         'auto_reload' => true, | ||||
|  | ||||
|         // If set to false, Twig will silently ignore invalid variables | ||||
|         // (variables and or attributes/methods that do not exist) and | ||||
|         // replace them with a null value. When set to true, Twig throws an exception instead. | ||||
|         // default: false | ||||
|         'strict_variables' => false, | ||||
|  | ||||
|         // If set to true, auto-escaping will be enabled by default for all templates. | ||||
|         // default: true | ||||
|         'autoescape' => true, | ||||
|  | ||||
|         // A flag that indicates which optimizations to apply | ||||
|         // (default to -1 -- all optimizations are enabled; set it to 0 to disable) | ||||
|         'optimizations' => -1, | ||||
|     ], | ||||
|  | ||||
|     /* | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | Global variables | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | | ||||
|     | These will always be passed in and can be accessed as Twig variables. | ||||
|     | NOTE: these will be overwritten if you pass data into the view with the same key. | ||||
|     | | ||||
|     */ | ||||
|     'globals' => [], | ||||
|  | ||||
| ]; | ||||
							
								
								
									
										0
									
								
								app/config/queue.php
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								app/config/queue.php
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										2
									
								
								app/config/testing/app.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								app/config/testing/app.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| <?php | ||||
| return ['log_level' => 'debug',]; | ||||
| @@ -1,20 +1,3 @@ | ||||
| <?php | ||||
|  | ||||
| return array( | ||||
|  | ||||
| 	/* | ||||
| 	|-------------------------------------------------------------------------- | ||||
| 	| Default Cache Driver | ||||
| 	|-------------------------------------------------------------------------- | ||||
| 	| | ||||
| 	| This option controls the default cache "driver" that will be used when | ||||
| 	| using the Caching library. Of course, you may use other drivers any | ||||
| 	| time you wish. This is the default when another is not specified. | ||||
| 	| | ||||
| 	| Supported: "file", "database", "apc", "memcached", "redis", "array" | ||||
| 	| | ||||
| 	*/ | ||||
|  | ||||
| 	'driver' => 'array', | ||||
|  | ||||
| ); | ||||
| return ['driver' => 'array',]; | ||||
|   | ||||
| @@ -4,8 +4,9 @@ return [ | ||||
|     'connections' => [ | ||||
|         'sqlite' => [ | ||||
|             'driver'   => 'sqlite', | ||||
|             'database' => ':memory:', | ||||
|             'database' => realpath(__DIR__.'/../../../tests/_data/db.sqlite'), | ||||
|             'prefix'   => '' | ||||
|         ], | ||||
|         ] | ||||
|  | ||||
|     ] | ||||
| ]; | ||||
| ]; | ||||
|   | ||||
							
								
								
									
										13
									
								
								app/config/testing/mail.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								app/config/testing/mail.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| <?php | ||||
|  | ||||
| return [ | ||||
|     'driver'     => 'smtp', | ||||
|     'host'       => '', | ||||
|     'port'       => 587, | ||||
|     'from'       => ['address' => '', 'name' => 'Firefly III'], | ||||
|     'encryption' => 'tls', | ||||
|     'username'   => '', | ||||
|     'password'   => '', | ||||
|     'sendmail'   => '/usr/sbin/sendmail -bs', | ||||
|     'pretend'    => true, | ||||
| ]; | ||||
| @@ -1,21 +1,3 @@ | ||||
| <?php | ||||
|  | ||||
| return array( | ||||
|  | ||||
| 	/* | ||||
| 	|-------------------------------------------------------------------------- | ||||
| 	| Default Session Driver | ||||
| 	|-------------------------------------------------------------------------- | ||||
| 	| | ||||
| 	| This option controls the default session "driver" that will be used on | ||||
| 	| requests. By default, we will use the lightweight native driver but | ||||
| 	| you may specify any of the other wonderful drivers provided here. | ||||
| 	| | ||||
| 	| Supported: "native", "cookie", "database", "apc", | ||||
| 	|            "memcached", "redis", "array" | ||||
| 	| | ||||
| 	*/ | ||||
|  | ||||
| 	'driver' => 'array', | ||||
|  | ||||
| ); | ||||
| return ['driver' => 'array',]; | ||||
|   | ||||
							
								
								
									
										2
									
								
								app/config/testingInMemory/app.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								app/config/testingInMemory/app.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| <?php | ||||
| return ['log_level' => 'debug',]; | ||||
							
								
								
									
										8
									
								
								app/config/testingInMemory/auth.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								app/config/testingInMemory/auth.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| <?php | ||||
|  | ||||
| return [ | ||||
|     'verify_mail' => false, | ||||
|     'verify_reset' => true, | ||||
|     'allow_register' => true | ||||
|  | ||||
| ]; | ||||
							
								
								
									
										3
									
								
								app/config/testingInMemory/cache.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								app/config/testingInMemory/cache.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| <?php | ||||
|  | ||||
| return ['driver' => 'array',]; | ||||
							
								
								
									
										12
									
								
								app/config/testingInMemory/database.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								app/config/testingInMemory/database.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| <?php | ||||
| return [ | ||||
|     'default' => 'sqlite', | ||||
|     'connections' => [ | ||||
|         'sqlite' => [ | ||||
|             'driver'   => 'sqlite', | ||||
|             'database' => ':memory:', | ||||
|             'prefix'   => '' | ||||
|         ] | ||||
|  | ||||
|     ] | ||||
| ]; | ||||
							
								
								
									
										13
									
								
								app/config/testingInMemory/mail.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								app/config/testingInMemory/mail.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| <?php | ||||
|  | ||||
| return [ | ||||
|     'driver'     => 'smtp', | ||||
|     'host'       => '', | ||||
|     'port'       => 587, | ||||
|     'from'       => ['address' => '', 'name' => 'Firefly III'], | ||||
|     'encryption' => 'tls', | ||||
|     'username'   => '', | ||||
|     'password'   => '', | ||||
|     'sendmail'   => '/usr/sbin/sendmail -bs', | ||||
|     'pretend'    => true, | ||||
| ]; | ||||
							
								
								
									
										3
									
								
								app/config/testingInMemory/session.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								app/config/testingInMemory/session.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| <?php | ||||
|  | ||||
| return ['driver' => 'array',]; | ||||
| @@ -1,6 +1,6 @@ | ||||
| <?php | ||||
|  | ||||
| return [ | ||||
|     'paths'      => array(__DIR__ . '/../views'), | ||||
|     'paths'      => [__DIR__ . '/../views'], | ||||
|     'pagination' => 'pagination::slider-3', | ||||
| ]; | ||||
|   | ||||
| @@ -1,94 +1,78 @@ | ||||
| <?php | ||||
|  | ||||
| use Firefly\Helper\Controllers\AccountInterface as AI; | ||||
| use Firefly\Storage\Account\AccountRepositoryInterface as ARI; | ||||
| use FireflyIII\Database\Account\Account as AccountRepository; | ||||
| use FireflyIII\Exception\FireflyException; | ||||
|  | ||||
| /** | ||||
|  * Class AccountController | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CamelCasePropertyName) | ||||
|  */ | ||||
| class AccountController extends \BaseController | ||||
| class AccountController extends BaseController | ||||
| { | ||||
|  | ||||
|     /** @var array */ | ||||
|     protected $_accountTypesByIdentifier | ||||
|         = [ | ||||
|             'asset'   => ['Default account', 'Asset account'], | ||||
|             'expense' => ['Expense account', 'Beneficiary account'], | ||||
|             'revenue' => ['Revenue account'], | ||||
|         ]; | ||||
|  | ||||
|     /** @var AccountRepository */ | ||||
|     protected $_repository; | ||||
|     protected $_accounts; | ||||
|  | ||||
|     /** @var array */ | ||||
|     protected $_shortNamesByFullName | ||||
|         = [ | ||||
|             'Default account'     => 'asset', | ||||
|             'Asset account'       => 'asset', | ||||
|             'Expense account'     => 'expense', | ||||
|             'Beneficiary account' => 'expense', | ||||
|             'Revenue account'     => 'revenue', | ||||
|             'Cash account'        => 'cash', | ||||
|         ]; | ||||
|  | ||||
|     /** @var array */ | ||||
|     protected $_subIconsByIdentifier | ||||
|         = [ | ||||
|             'asset'               => 'fa-money', | ||||
|             'Asset account'       => 'fa-money', | ||||
|             'Default account'     => 'fa-money', | ||||
|             'Cash account'        => 'fa-money', | ||||
|             'expense'             => 'fa-shopping-cart', | ||||
|             'Expense account'     => 'fa-shopping-cart', | ||||
|             'Beneficiary account' => 'fa-shopping-cart', | ||||
|             'revenue'             => 'fa-download', | ||||
|             'Revenue account'     => 'fa-download', | ||||
|         ]; | ||||
|     /** @var array */ | ||||
|     protected $_subTitlesByIdentifier | ||||
|         = [ | ||||
|             'asset'   => 'Asset accounts', | ||||
|             'expense' => 'Expense accounts', | ||||
|             'revenue' => 'Revenue accounts', | ||||
|         ]; | ||||
|  | ||||
|     /** | ||||
|      * @param ARI $repository | ||||
|      * @param AI  $accounts | ||||
|      * @param AccountRepository $repository | ||||
|      */ | ||||
|     public function __construct(ARI $repository, AI $accounts) | ||||
|     public function __construct(AccountRepository $repository) | ||||
|     { | ||||
|         $this->_accounts   = $accounts; | ||||
|         $this->_repository = $repository; | ||||
|         View::share('mainTitleIcon', 'fa-credit-card'); | ||||
|         View::share('title', 'Accounts'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $what | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function create($what) | ||||
|     { | ||||
|         switch ($what) { | ||||
|             case 'asset': | ||||
|                 View::share('subTitleIcon', 'fa-money'); | ||||
|                 break; | ||||
|             case 'expense': | ||||
|                 View::share('subTitleIcon', 'fa-shopping-cart'); | ||||
|                 break; | ||||
|             case 'revenue': | ||||
|                 View::share('subTitleIcon', 'fa-download'); | ||||
|                 break; | ||||
|         } | ||||
|         $subTitleIcon = $this->_subIconsByIdentifier[$what]; | ||||
|         $subTitle     = 'Create a new ' . e($what) . ' account'; | ||||
|  | ||||
|  | ||||
|         return View::make('accounts.create')->with('subTitle', 'Create a new ' . $what . ' account')->with( | ||||
|             'what', $what | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function asset() | ||||
|     { | ||||
|         View::share('subTitleIcon', 'fa-money'); | ||||
|  | ||||
|         $accounts = $this->_repository->getOfTypes(['Asset account', 'Default account']); | ||||
|  | ||||
|         return View::make('accounts.asset')->with('subTitle', 'Asset accounts')->with( | ||||
|             'accounts', $accounts | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function expense() | ||||
|     { | ||||
|         View::share('subTitleIcon', 'fa-shopping-cart'); | ||||
|  | ||||
|         $accounts = $this->_repository->getOfTypes(['Expense account', 'Beneficiary account']); | ||||
|  | ||||
|         return View::make('accounts.expense')->with('subTitle', 'Expense accounts')->with( | ||||
|             'accounts', $accounts | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function revenue() | ||||
|     { | ||||
|         View::share('subTitleIcon', 'fa-download'); | ||||
|  | ||||
|         $accounts = $this->_repository->getOfTypes(['Revenue account']); | ||||
|  | ||||
|         return View::make('accounts.revenue')->with('subTitle', 'Revenue accounts')->with( | ||||
|             'accounts', $accounts | ||||
|         ); | ||||
|         return View::make('accounts.create', compact('subTitleIcon', 'what', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -98,10 +82,9 @@ class AccountController extends \BaseController | ||||
|      */ | ||||
|     public function delete(Account $account) | ||||
|     { | ||||
|         return View::make('accounts.delete')->with('account', $account) | ||||
|             ->with( | ||||
|                 'subTitle', 'Delete ' . strtolower($account->accountType->type) . ' "' . $account->name . '"' | ||||
|             ); | ||||
|         $subTitle = 'Delete ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"'; | ||||
|  | ||||
|         return View::make('accounts.delete', compact('account', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -111,24 +94,16 @@ class AccountController extends \BaseController | ||||
|      */ | ||||
|     public function destroy(Account $account) | ||||
|     { | ||||
|         $type = $account->accountType->type; | ||||
|  | ||||
|         $type     = $account->accountType->type; | ||||
|         $typeName = $this->_shortNamesByFullName[$type]; | ||||
|         $name     = $account->name; | ||||
|  | ||||
|         $this->_repository->destroy($account); | ||||
|         Session::flash('success', 'The account was deleted.'); | ||||
|         switch ($type) { | ||||
|             case 'Asset account': | ||||
|             case 'Default account': | ||||
|                 return Redirect::route('accounts.asset'); | ||||
|                 break; | ||||
|             case 'Expense account': | ||||
|             case 'Beneficiary account': | ||||
|                 return Redirect::route('accounts.expense'); | ||||
|                 break; | ||||
|             case 'Revenue account': | ||||
|                 return Redirect::route('accounts.revenue'); | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         Session::flash('success', 'The ' . e($typeName) . ' account "' . e($name) . '" was deleted.'); | ||||
|  | ||||
|         return Redirect::route('accounts.index', $typeName); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -139,138 +114,127 @@ class AccountController extends \BaseController | ||||
|     public function edit(Account $account) | ||||
|     { | ||||
|  | ||||
|         switch ($account->accountType->type) { | ||||
|             case 'Asset account': | ||||
|             case 'Default account': | ||||
|                 View::share('subTitleIcon', 'fa-money'); | ||||
|                 break; | ||||
|             case 'Expense account': | ||||
|             case 'Beneficiary account': | ||||
|                 View::share('subTitleIcon', 'fa-shopping-cart'); | ||||
|                 break; | ||||
|             case 'Revenue account': | ||||
|                 View::share('subTitleIcon', 'fa-download'); | ||||
|                 break; | ||||
|         } | ||||
|         $openingBalance = $this->_repository->openingBalanceTransaction($account); | ||||
|         $subTitleIcon   = $this->_subIconsByIdentifier[$account->accountType->type]; | ||||
|         $subTitle       = 'Edit ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"'; | ||||
|  | ||||
|         $openingBalance = $this->_accounts->openingBalanceTransaction($account); | ||||
|         return View::make('accounts.edit')->with('account', $account)->with('openingBalance', $openingBalance) | ||||
|         // pre fill some useful values. | ||||
|         $preFilled = [ | ||||
|             'account_role'       => $account->getMeta('accountRole'), | ||||
|             'openingBalanceDate' => $openingBalance ? $openingBalance->date->format('Y-m-d') : null, | ||||
|             'openingBalance'     => $openingBalance ? $openingBalance->getAmount($account) : null | ||||
|         ]; | ||||
|         Session::flash('preFilled', $preFilled); | ||||
|  | ||||
|             ->with('subTitle', 'Edit ' . strtolower($account->accountType->type) . ' "' . $account->name . '"'); | ||||
|         return View::make('accounts.edit', compact('account', 'subTitle', 'openingBalance', 'subTitleIcon')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      * | ||||
|      * @param string $what | ||||
|      * | ||||
|      * @return View | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function index() | ||||
|     public function index($what = 'default') | ||||
|     { | ||||
|         return View::make('error')->with('message', 'This view has been disabled'); | ||||
|         $subTitle     = $this->_subTitlesByIdentifier[$what]; | ||||
|         $subTitleIcon = $this->_subIconsByIdentifier[$what]; | ||||
|  | ||||
|         $accounts = $this->_repository->getAccountsByType($this->_accountTypesByIdentifier[$what]); | ||||
|  | ||||
|         return View::make('accounts.index', compact('what', 'subTitleIcon', 'subTitle', 'accounts')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param string  $range | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function show(Account $account) | ||||
|     public function show(Account $account, $range = 'session') | ||||
|     { | ||||
|         switch ($account->accountType->type) { | ||||
|             case 'Asset account': | ||||
|             case 'Default account': | ||||
|                 View::share('subTitleIcon', 'fa-money'); | ||||
|                 break; | ||||
|             case 'Expense account': | ||||
|             case 'Beneficiary account': | ||||
|                 View::share('subTitleIcon', 'fa-shopping-cart'); | ||||
|                 break; | ||||
|             case 'Revenue account': | ||||
|                 View::share('subTitleIcon', 'fa-download'); | ||||
|                 break; | ||||
|         } | ||||
|         $subTitleIcon = $this->_subIconsByIdentifier[$account->accountType->type]; | ||||
|         $what         = $this->_shortNamesByFullName[$account->accountType->type]; | ||||
|         $journals     = $this->_repository->getTransactionJournals($account, 50, $range); | ||||
|         $subTitle     = 'Details for ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"'; | ||||
|  | ||||
|  | ||||
|         $data = $this->_accounts->show($account, 40); | ||||
|  | ||||
|         return View::make('accounts.show')->with('account', $account)->with('show', $data)->with( | ||||
|             'subTitle', | ||||
|             'Details for ' . strtolower($account->accountType->type) . ' "' . $account->name . '"' | ||||
|         ); | ||||
|         return View::make('accounts.show', compact('account', 'what', 'range', 'subTitleIcon', 'journals', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this|\Illuminate\Http\RedirectResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store() | ||||
|     { | ||||
|  | ||||
|         $data         = Input::all(); | ||||
|         $data['what'] = isset($data['what']) && $data['what'] != '' ? $data['what'] : 'asset'; | ||||
|         $data = Input::except('_token'); | ||||
|  | ||||
|         // always validate: | ||||
|         $messages = $this->_repository->validate($data); | ||||
|  | ||||
|         switch ($data['what']) { | ||||
|             default: | ||||
|             case 'asset': | ||||
|                 $data['account_type'] = 'Asset account'; | ||||
|                 break; | ||||
|             case 'expense': | ||||
|                 $data['account_type'] = 'Expense account'; | ||||
|                 break; | ||||
|             case 'revenue': | ||||
|                 $data['account_type'] = 'Revenue account'; | ||||
|                 break; | ||||
|  | ||||
|         // flash messages: | ||||
|         Session::flash('warnings', $messages['warnings']); | ||||
|         Session::flash('successes', $messages['successes']); | ||||
|         Session::flash('errors', $messages['errors']); | ||||
|         if ($messages['errors']->count() > 0) { | ||||
|             Session::flash('error', 'Could not store account: ' . $messages['errors']->first()); | ||||
|         } | ||||
|         $account = $this->_repository->store($data); | ||||
|  | ||||
|         if ($account->validate()) { | ||||
|             // saved! return to wherever. | ||||
|             Session::flash('success', 'Account "' . $account->name . '" created!'); | ||||
|             if (intval(Input::get('create')) === 1) { | ||||
|                 return Redirect::route('accounts.create', $data['what'])->withInput(); | ||||
|             } else { | ||||
|  | ||||
|                 return Redirect::route('accounts.' . e($data['what'])); | ||||
|             } | ||||
|         } else { | ||||
|             // did not save, return with error: | ||||
|             Session::flash('error', 'Could not save the new account: ' . $account->errors()->first()); | ||||
|  | ||||
|             return Redirect::route('accounts.create', $data['what'])->withErrors($account->errors())->withInput(); | ||||
|  | ||||
|         // return to create screen: | ||||
|         if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { | ||||
|             return Redirect::route('accounts.create', e($data['what']))->withInput(); | ||||
|         } | ||||
|  | ||||
|         // store | ||||
|         $this->_repository->store($data); | ||||
|         Session::flash('success', 'Account "' . e($data['name']) . '" stored.'); | ||||
|         if ($data['post_submit_action'] == 'store') { | ||||
|             return Redirect::route('accounts.index', e($data['what'])); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('accounts.create', e($data['what']))->withInput(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return $this|\Illuminate\Http\RedirectResponse | ||||
|      * @return $this | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function update(Account $account) | ||||
|     { | ||||
|         /** @var \Account $account */ | ||||
|         $account = $this->_repository->update($account, Input::all()); | ||||
|         if ($account->validate()) { | ||||
|             Session::flash('success', 'Account "' . $account->name . '" updated.'); | ||||
|             switch ($account->accountType->type) { | ||||
|                 case 'Asset account': | ||||
|                 case 'Default account': | ||||
|                     return Redirect::route('accounts.asset'); | ||||
|                     break; | ||||
|                 case 'Expense account': | ||||
|                 case 'Beneficiary account': | ||||
|                     return Redirect::route('accounts.expense'); | ||||
|                     break; | ||||
|                 case 'Revenue account': | ||||
|                     return Redirect::route('accounts.revenue'); | ||||
|                     break; | ||||
|             } | ||||
|         $data         = Input::except('_token'); | ||||
|         $data['what'] = $this->_shortNamesByFullName[$account->accountType->type]; | ||||
|  | ||||
|         } else { | ||||
|             Session::flash('error', 'Could not update account: ' . $account->errors()->first()); | ||||
|  | ||||
|             return Redirect::route('accounts.edit', $account->id)->withInput()->withErrors($account->errors()); | ||||
|         // always validate: | ||||
|         $messages = $this->_repository->validate($data); | ||||
|  | ||||
|         // flash messages: | ||||
|         Session::flash('warnings', $messages['warnings']); | ||||
|         Session::flash('successes', $messages['successes']); | ||||
|         Session::flash('errors', $messages['errors']); | ||||
|         if ($messages['errors']->count() > 0) { | ||||
|             Session::flash('error', 'Could not update account: ' . $messages['errors']->first()); | ||||
|         } | ||||
|  | ||||
|         // return to update screen: | ||||
|         if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { | ||||
|             return Redirect::route('accounts.edit', $account->id)->withInput(); | ||||
|         } | ||||
|  | ||||
|         // update | ||||
|         $this->_repository->update($account, $data); | ||||
|         Session::flash('success', 'Account "' . e($data['name']) . '" updated.'); | ||||
|  | ||||
|         // go back to list | ||||
|         if ($data['post_submit_action'] == 'update') { | ||||
|             return Redirect::route('accounts.index', e($data['what'])); | ||||
|         } | ||||
|  | ||||
|         // go back to update screen. | ||||
|         return Redirect::route('accounts.edit', $account->id)->withInput(['post_submit_action' => 'return_to_edit']); | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
							
								
								
									
										212
									
								
								app/controllers/BillController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										212
									
								
								app/controllers/BillController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,212 @@ | ||||
| <?php | ||||
| use FireflyIII\Database\Bill\Bill as Repository; | ||||
| use FireflyIII\Exception\FireflyException; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @SuppressWarnings("CamelCase") // I'm fine with this. | ||||
|  * @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok. | ||||
|  * @SuppressWarnings("NPathComplexity") | ||||
|  * Class BillController | ||||
|  * | ||||
|  */ | ||||
| class BillController extends BaseController | ||||
| { | ||||
|  | ||||
|     /** @var  Repository */ | ||||
|     protected $_repository; | ||||
|  | ||||
|     /** | ||||
|      * @param Repository $repository | ||||
|      */ | ||||
|     public function __construct(Repository $repository) | ||||
|     { | ||||
|         $this->_repository = $repository; | ||||
|  | ||||
|         View::share('title', 'Bills'); | ||||
|         View::share('mainTitleIcon', 'fa-calendar-o'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function create() | ||||
|     { | ||||
|         $periods = \Config::get('firefly.periods_to_text'); | ||||
|  | ||||
|         return View::make('bills.create')->with('periods', $periods)->with('subTitle', 'Create new'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function delete(Bill $bill) | ||||
|     { | ||||
|         return View::make('bills.delete')->with('bill', $bill)->with( | ||||
|             'subTitle', 'Delete "' . e($bill->name) . '"' | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function destroy(Bill $bill) | ||||
|     { | ||||
|         $this->_repository->destroy($bill); | ||||
|         Session::flash('success', 'The bill was deleted.'); | ||||
|  | ||||
|         return Redirect::route('bills.index'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function edit(Bill $bill) | ||||
|     { | ||||
|         $periods = \Config::get('firefly.periods_to_text'); | ||||
|  | ||||
|         return View::make('bills.edit')->with('periods', $periods)->with('bill', $bill)->with( | ||||
|             'subTitle', 'Edit "' . e($bill->name) . '"' | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         $bills = $this->_repository->get(); | ||||
|         $bills->each( | ||||
|             function (Bill $bill) { | ||||
|                 $bill->nextExpectedMatch = $this->_repository->nextExpectedMatch($bill); | ||||
|                 $bill->lastFoundMatch    = $this->_repository->lastFoundMatch($bill); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return View::make('bills.index', compact('bills')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function rescan(Bill $bill) | ||||
|     { | ||||
|         if (intval($bill->active) == 0) { | ||||
|             Session::flash('warning', 'Inactive bills cannot be scanned.'); | ||||
|  | ||||
|             return Redirect::intended('/'); | ||||
|         } | ||||
|  | ||||
|         $this->_repository->scanEverything($bill); | ||||
|  | ||||
|         Session::flash('success', 'Rescanned everything.'); | ||||
|  | ||||
|         return Redirect::intended('/'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function show(Bill $bill) | ||||
|     { | ||||
|         $journals = $bill->transactionjournals()->withRelevantData()->orderBy('date', 'DESC')->get(); | ||||
|         $bill->nextExpectedMatch = $this->_repository->nextExpectedMatch($bill); | ||||
|         $hideBill = true; | ||||
|  | ||||
|  | ||||
|         return View::make('bills.show', compact('journals', 'hideBill', 'bill'))->with( | ||||
|             'subTitle', e($bill->name) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store() | ||||
|     { | ||||
|         $data            = Input::all(); | ||||
|         $data['user_id'] = Auth::user()->id; | ||||
|  | ||||
|  | ||||
|         // always validate: | ||||
|         $messages = $this->_repository->validate($data); | ||||
|  | ||||
|         // flash messages: | ||||
|         Session::flash('warnings', $messages['warnings']); | ||||
|         Session::flash('successes', $messages['successes']); | ||||
|         Session::flash('errors', $messages['errors']); | ||||
|         if ($messages['errors']->count() > 0) { | ||||
|             Session::flash('error', 'Could not store bill: ' . $messages['errors']->first()); | ||||
|         } | ||||
|  | ||||
|         // return to create screen: | ||||
|         if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { | ||||
|             return Redirect::route('bills.create')->withInput(); | ||||
|         } | ||||
|  | ||||
|         // store | ||||
|         $this->_repository->store($data); | ||||
|         Session::flash('success', 'Bill "' . e($data['name']) . '" stored.'); | ||||
|         if ($data['post_submit_action'] == 'store') { | ||||
|             return Redirect::route('bills.index'); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('bills.create')->withInput(); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      * | ||||
|      * @return $this | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function update(Bill $bill) | ||||
|     { | ||||
|         $data              = Input::except('_token'); | ||||
|         $data['active']    = isset($data['active']) ? 1 : 0; | ||||
|         $data['automatch'] = isset($data['automatch']) ? 1 : 0; | ||||
|         $data['user_id']   = Auth::user()->id; | ||||
|  | ||||
|         // always validate: | ||||
|         $messages = $this->_repository->validate($data); | ||||
|  | ||||
|         // flash messages: | ||||
|         Session::flash('warnings', $messages['warnings']); | ||||
|         Session::flash('successes', $messages['successes']); | ||||
|         Session::flash('errors', $messages['errors']); | ||||
|         if ($messages['errors']->count() > 0) { | ||||
|             Session::flash('error', 'Could not update bill: ' . $messages['errors']->first()); | ||||
|         } | ||||
|  | ||||
|         // return to update screen: | ||||
|         if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { | ||||
|             return Redirect::route('bills.edit', $bill->id)->withInput(); | ||||
|         } | ||||
|  | ||||
|         // update | ||||
|         $this->_repository->update($bill, $data); | ||||
|         Session::flash('success', 'Bill "' . e($data['name']) . '" updated.'); | ||||
|  | ||||
|         // go back to list | ||||
|         if ($data['post_submit_action'] == 'update') { | ||||
|             return Redirect::route('bills.index'); | ||||
|         } | ||||
|  | ||||
|         // go back to update screen. | ||||
|         return Redirect::route('bills.edit', $bill->id)->withInput(['post_submit_action' => 'return_to_edit']); | ||||
|  | ||||
|     } | ||||
| } | ||||
| @@ -1,75 +1,60 @@ | ||||
| <?php | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Firefly\Exception\FireflyException; | ||||
| use Firefly\Helper\Controllers\BudgetInterface as BI; | ||||
| use Firefly\Storage\Budget\BudgetRepositoryInterface as BRI; | ||||
| use FireflyIII\Database\Budget\Budget as BudgetRepository; | ||||
| use FireflyIII\Shared\Preferences\PreferencesInterface as Pref; | ||||
|  | ||||
| /** | ||||
|  * Class BudgetController | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CamelCasePropertyName) | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  * @SuppressWarnings("CamelCase") // I'm fine with this. | ||||
|  * @SuppressWarnings("TooManyMethods") // I'm also fine with this. | ||||
|  * @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok. | ||||
|  * @SuppressWarnings("CouplingBetweenObjects") // There's only so much I can remove. | ||||
|  * | ||||
|  */ | ||||
| class BudgetController extends BaseController | ||||
| { | ||||
|  | ||||
|     protected $_budgets; | ||||
|     /** @var Pref */ | ||||
|     protected $_preferences; | ||||
|     /** @var BudgetRepository */ | ||||
|     protected $_repository; | ||||
|  | ||||
|     /** | ||||
|      * @param BI  $budgets | ||||
|      * @param BRI $repository | ||||
|      * @param BudgetRepository $repository | ||||
|      * @param Pref             $preferences | ||||
|      */ | ||||
|     public function __construct(BI $budgets, BRI $repository) | ||||
|     public function __construct(BudgetRepository $repository, Pref $preferences) | ||||
|     { | ||||
|         $this->_budgets    = $budgets; | ||||
|         $this->_repository = $repository; | ||||
|         $this->_repository  = $repository; | ||||
|         $this->_preferences = $preferences; | ||||
|         View::share('title', 'Budgets'); | ||||
|         View::share('mainTitleIcon', 'fa-tasks'); | ||||
|     } | ||||
|  | ||||
|     public function nobudget($view = 'session') { | ||||
|         switch($view) { | ||||
|             default: | ||||
|                 throw new FireflyException('Cannot show transactions without a budget for view "'.$view.'".'); | ||||
|                 break; | ||||
|             case 'session': | ||||
|                 $start = Session::get('start'); | ||||
|                 $end   = Session::get('end'); | ||||
|                 break; | ||||
|         } | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function amount(Budget $budget) | ||||
|     { | ||||
|         $amount          = intval(Input::get('amount')); | ||||
|         $date            = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $limitRepetition = $this->_repository->updateLimitAmount($budget, $date, $amount); | ||||
|  | ||||
|         // Add expenses that have no budget: | ||||
|         $set = \Auth::user()->transactionjournals()->whereNotIn( | ||||
|             'transaction_journals.id', function ($query) use ($start, $end) { | ||||
|                 $query->select('transaction_journals.id')->from('transaction_journals') | ||||
|                       ->leftJoin( | ||||
|                           'component_transaction_journal', 'component_transaction_journal.transaction_journal_id', '=', | ||||
|                           'transaction_journals.id' | ||||
|                       ) | ||||
|                       ->leftJoin('components', 'components.id', '=', 'component_transaction_journal.component_id') | ||||
|                       ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) | ||||
|                       ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) | ||||
|                       ->where('components.class', 'Budget'); | ||||
|             } | ||||
|         )->before($end)->after($start)->get(); | ||||
|         return Response::json(['name' => $budget->name, 'repetition' => $limitRepetition->id]); | ||||
|  | ||||
|         return View::make('budgets.nobudget') | ||||
|                    ->with('view', $view) | ||||
|                    ->with('transactions',$set) | ||||
|                    ->with('subTitle', 'Transactions without a budget'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this|\Illuminate\View\View | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function create() | ||||
|     { | ||||
|         $periods = \Config::get('firefly.periods_to_text'); | ||||
|  | ||||
|         return View::make('budgets.create')->with('periods', $periods)->with('subTitle', 'Create a new budget'); | ||||
|         return View::make('budgets.create')->with('subTitle', 'Create a new budget'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -79,8 +64,9 @@ class BudgetController extends BaseController | ||||
|      */ | ||||
|     public function delete(Budget $budget) | ||||
|     { | ||||
|         return View::make('budgets.delete')->with('budget', $budget) | ||||
|             ->with('subTitle', 'Delete budget "' . $budget->name . '"'); | ||||
|         $subTitle = 'Delete budget "' . e($budget->name) . '"'; | ||||
|  | ||||
|         return View::make('budgets.delete', compact('budget', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -90,16 +76,11 @@ class BudgetController extends BaseController | ||||
|      */ | ||||
|     public function destroy(Budget $budget) | ||||
|     { | ||||
|         // remove budget | ||||
|         Event::fire('budgets.destroy', [$budget]); // just before deletion. | ||||
|         Session::flash('success', 'Budget "' . e($budget->name) . '" was deleted.'); | ||||
|         $this->_repository->destroy($budget); | ||||
|         Session::flash('success', 'The budget was deleted.'); | ||||
|  | ||||
|         // redirect: | ||||
|         if (Input::get('from') == 'date') { | ||||
|             return Redirect::route('budgets.index'); | ||||
|         } | ||||
|         return Redirect::route('budgets.index.budget'); | ||||
|  | ||||
|         return Redirect::route('budgets.index'); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -110,116 +91,115 @@ class BudgetController extends BaseController | ||||
|      */ | ||||
|     public function edit(Budget $budget) | ||||
|     { | ||||
|         return View::make('budgets.edit')->with('budget', $budget) | ||||
|             ->with('subTitle', 'Edit budget "' . $budget->name . '"'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this|\Illuminate\View\View | ||||
|      */ | ||||
|     public function indexByBudget() | ||||
|     { | ||||
|         View::share('subTitleIcon', 'fa-folder-open'); | ||||
|  | ||||
|         $budgets = $this->_repository->get(); | ||||
|  | ||||
|         return View::make('budgets.indexByBudget')->with('budgets', $budgets)->with('today', new Carbon) | ||||
|             ->with('subTitle', 'Grouped by budget'); | ||||
|         $subTitle = 'Edit budget "' . e($budget->name) . '"'; | ||||
|  | ||||
|         return View::make('budgets.edit', compact('budget', 'subTitle')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The index of the budget controller contains all budgets and the current relevant limit repetition. | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function indexByDate() | ||||
|     public function index() | ||||
|     { | ||||
|         View::share('subTitleIcon', 'fa-calendar'); | ||||
|         $budgets = $this->_repository->get(); | ||||
|  | ||||
|         // get a list of dates by getting all repetitions: | ||||
|         $set     = $this->_repository->get(); | ||||
|         $budgets = $this->_budgets->organizeByDate($set); | ||||
|  | ||||
|         return View::make('budgets.indexByDate')->with('budgets', $budgets) | ||||
|             ->with('subTitle', 'Grouped by date'); | ||||
|         // loop the budgets: | ||||
|         $budgets->each( | ||||
|             function (Budget $budget) { | ||||
|                 $budget->spent      = $this->_repository->spentInMonth($budget, \Session::get('start', Carbon::now()->startOfMonth())); | ||||
|                 $budget->currentRep = $this->_repository->getRepetitionByDate($budget, \Session::get('start', Carbon::now()->startOfMonth())); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         $spent         = $budgets->sum('spent'); | ||||
|         $amount        = $this->_preferences->get('budgetIncomeTotal' . \Session::get('start', Carbon::now()->startOfMonth())->format('FY'), 1000)->data; | ||||
|         $overspent     = $spent > $amount; | ||||
|         $spentPCT      = $overspent ? ceil($amount / $spent * 100) : ceil($spent / $amount * 100); | ||||
|         $budgetMax     = $this->_preferences->get('budgetMaximum', 1000); | ||||
|         $budgetMaximum = $budgetMax->data; | ||||
|  | ||||
|         return View::make('budgets.index', compact('budgetMaximum', 'budgets', 'spent', 'spentPCT', 'overspent', 'amount')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Three use cases for this view: | ||||
|      * | ||||
|      * - Show everything. | ||||
|      * - Show a specific repetition. | ||||
|      * - Show everything shows NO repetition. | ||||
|      * | ||||
|      * @param Budget          $budget | ||||
|      * @param LimitRepetition $repetition | ||||
|      * | ||||
|      * @return int | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function show(Budget $budget, \LimitRepetition $repetition = null) | ||||
|     public function noBudget() | ||||
|     { | ||||
|         $useSessionDates = Input::get('useSession') == 'true' ? true : false; | ||||
|         $view            = null; | ||||
|         $title           = null; | ||||
|         \Log::debug('Is envelope true? ' . (Input::get('noenvelope') == 'true')); | ||||
|         switch (true) { | ||||
|             case (!is_null($repetition)): | ||||
|                 $data  = $this->_budgets->organizeRepetition($repetition); | ||||
|                 $view  = 1; | ||||
|                 $title = $budget->name . ', ' . $repetition->periodShow() . ', ' . mf( | ||||
|                         $repetition->limit->amount, | ||||
|                         false | ||||
|                     ); | ||||
|                 break; | ||||
|             case (Input::get('noenvelope') == 'true'): | ||||
|                 $data  = $this->_budgets->outsideRepetitions($budget); | ||||
|                 $view  = 2; | ||||
|                 $title = $budget->name . ', transactions outside an envelope'; | ||||
|                 break; | ||||
|             default: | ||||
|                 $data  = $this->_budgets->organizeRepetitions($budget, $useSessionDates); | ||||
|                 $view  = $useSessionDates ? 3 : 4; | ||||
|                 $title = $useSessionDates ? $budget->name . ' in session period' : $budget->name; | ||||
|                 break; | ||||
|         } | ||||
|         $start    = \Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end      = \Session::get('end', Carbon::now()->startOfMonth()); | ||||
|         $list     = $this->_repository->journalsNoBudget($start, $end); | ||||
|         $subTitle = 'Transactions without a budget in ' . $start->format('F Y'); | ||||
|  | ||||
|         return View::make('budgets.show') | ||||
|             ->with('budget', $budget) | ||||
|             ->with('repetitions', $data) | ||||
|             ->with('view', $view) | ||||
|             ->with('highlight', Input::get('highlight')) | ||||
|             ->with('useSessionDates', $useSessionDates) | ||||
|             ->with('subTitle', 'Overview for ' . $title); | ||||
|         return View::make('budgets.noBudget', compact('list', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function store() | ||||
|     public function postUpdateIncome() | ||||
|     { | ||||
|         $this->_preferences->set('budgetIncomeTotal' . Session::get('start', Carbon::now()->startOfMonth())->format('FY'), intval(Input::get('amount'))); | ||||
|  | ||||
|         $budget = $this->_repository->store(Input::all()); | ||||
|         if ($budget->validate()) { | ||||
|             Event::fire('budgets.store', [$budget]); | ||||
|             Session::flash('success', 'Budget created!'); | ||||
|         return Redirect::route('budgets.index'); | ||||
|     } | ||||
|  | ||||
|             if (Input::get('create') == '1') { | ||||
|                 return Redirect::route('budgets.create', ['from' => Input::get('from')]); | ||||
|             } | ||||
|  | ||||
|             if (Input::get('from') == 'date') { | ||||
|                 return Redirect::route('budgets.index'); | ||||
|             } else { | ||||
|                 return Redirect::route('budgets.index.budget'); | ||||
|             } | ||||
|         } else { | ||||
|             Session::flash('error', 'Could not save the new budget'); | ||||
|  | ||||
|             return Redirect::route('budgets.create')->withInput()->withErrors($budget->errors()); | ||||
|     /** | ||||
|      * @param Budget          $budget | ||||
|      * @param LimitRepetition $repetition | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function show(Budget $budget, LimitRepetition $repetition = null) | ||||
|     { | ||||
|         if (!is_null($repetition) && $repetition->budgetLimit->budget->id != $budget->id) { | ||||
|             return View::make('error')->with('message', 'Invalid selection.'); | ||||
|         } | ||||
|  | ||||
|         $hideBudget = true; // used in transaction list. | ||||
|         $journals   = $this->_repository->getJournals($budget, $repetition); | ||||
|         $limits     = $repetition ? [$repetition->budgetLimit] : $budget->budgetLimits()->orderBy('startdate', 'DESC')->get(); | ||||
|         $subTitle   = $repetition ? e($budget->name) . ' in ' . $repetition->startdate->format('F Y') : e($budget->name); | ||||
|  | ||||
|         return View::make('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle', 'hideBudget')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this|\Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function store() | ||||
|     { | ||||
|         $data            = Input::except('_token'); | ||||
|         $data['user_id'] = Auth::user()->id; | ||||
|  | ||||
|         // always validate: | ||||
|         $messages = $this->_repository->validate($data); | ||||
|  | ||||
|         // flash messages: | ||||
|         Session::flash('warnings', $messages['warnings']); | ||||
|         Session::flash('successes', $messages['successes']); | ||||
|         Session::flash('errors', $messages['errors']); | ||||
|         if ($messages['errors']->count() > 0) { | ||||
|             Session::flash('error', 'Could not validate budget: ' . $messages['errors']->first()); | ||||
|         } | ||||
|  | ||||
|         // return to create screen: | ||||
|         if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { | ||||
|             return Redirect::route('budgets.create')->withInput(); | ||||
|         } | ||||
|  | ||||
|         // store | ||||
|         $this->_repository->store($data); | ||||
|         Session::flash('success', 'Budget "' . e($data['name']) . '" stored.'); | ||||
|         if ($data['post_submit_action'] == 'store') { | ||||
|             return Redirect::route('budgets.index'); | ||||
|         } | ||||
|  | ||||
|         // create another. | ||||
|         return Redirect::route('budgets.create')->withInput(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -229,23 +209,45 @@ class BudgetController extends BaseController | ||||
|      */ | ||||
|     public function update(Budget $budget) | ||||
|     { | ||||
|         $budget = $this->_repository->update($budget, Input::all()); | ||||
|         if ($budget->validate()) { | ||||
|             Event::fire('budgets.update', [$budget]); | ||||
|             Session::flash('success', 'Budget "' . $budget->name . '" updated.'); | ||||
|  | ||||
|             if (Input::get('from') == 'date') { | ||||
|                 return Redirect::route('budgets.index'); | ||||
|             } else { | ||||
|                 return Redirect::route('budgets.index.budget'); | ||||
|             } | ||||
|         } else { | ||||
|             Session::flash('error', 'Could not update budget: ' . $budget->errors()->first()); | ||||
|         $data            = Input::except('_token'); | ||||
|         $data['user_id'] = Auth::user()->id; | ||||
|  | ||||
|             return Redirect::route('budgets.edit', $budget->id)->withInput()->withErrors($budget->errors()); | ||||
|         // always validate: | ||||
|         $messages = $this->_repository->validate($data); | ||||
|  | ||||
|         // flash messages: | ||||
|         Session::flash('warnings', $messages['warnings']); | ||||
|         Session::flash('successes', $messages['successes']); | ||||
|         Session::flash('errors', $messages['errors']); | ||||
|         if ($messages['errors']->count() > 0) { | ||||
|             Session::flash('error', 'Could not update budget: ' . $messages['errors']->first()); | ||||
|         } | ||||
|  | ||||
|         // return to update screen: | ||||
|         if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { | ||||
|             return Redirect::route('budgets.edit', $budget->id)->withInput(); | ||||
|         } | ||||
|  | ||||
|         // update | ||||
|         $this->_repository->update($budget, $data); | ||||
|         Session::flash('success', 'Budget "' . e($data['name']) . '" updated.'); | ||||
|  | ||||
|         // go back to list | ||||
|         if ($data['post_submit_action'] == 'update') { | ||||
|             return Redirect::route('budgets.index'); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('budgets.edit', $budget->id)->withInput(['post_submit_action' => 'return_to_edit']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function updateIncome() | ||||
|     { | ||||
|         $budgetAmount = $this->_preferences->get('budgetIncomeTotal' . Session::get('start', Carbon::now()->startOfMonth())->format('FY'), 1000); | ||||
|  | ||||
| }  | ||||
|         return View::make('budgets.income')->with('amount', $budgetAmount); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,28 +1,30 @@ | ||||
| <?php | ||||
|  | ||||
| use Firefly\Helper\Controllers\CategoryInterface as CI; | ||||
| use Firefly\Storage\Category\CategoryRepositoryInterface as CRI; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Database\Category\Category as CategoryRepository; | ||||
| use FireflyIII\Exception\FireflyException; | ||||
|  | ||||
| /** | ||||
|  * Class CategoryController | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CamelCasePropertyName) | ||||
|  * @SuppressWarnings("CamelCase") // I'm fine with this. | ||||
|  * @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok. | ||||
|  * | ||||
|  * Class CategoryController | ||||
|  */ | ||||
| class CategoryController extends BaseController | ||||
| { | ||||
|  | ||||
|     /** @var CategoryRepository */ | ||||
|     protected $_repository; | ||||
|     protected $_category; | ||||
|  | ||||
|     /** | ||||
|      * @param CRI $repository | ||||
|      * @param CI  $category | ||||
|      * @param CategoryRepository $repository | ||||
|      */ | ||||
|     public function __construct(CRI $repository, CI $category) | ||||
|     public function __construct(CategoryRepository $repository) | ||||
|     { | ||||
|         $this->_repository = $repository; | ||||
|         $this->_category   = $category; | ||||
|         View::share('title','Categories'); | ||||
|         View::share('title', 'Categories'); | ||||
|         View::share('mainTitleIcon', 'fa-bar-chart'); | ||||
|  | ||||
|         $this->_repository = $repository; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -33,6 +35,19 @@ class CategoryController extends BaseController | ||||
|         return View::make('categories.create')->with('subTitle', 'Create a new category'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function noCategory() | ||||
|     { | ||||
|         $start    = \Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end      = \Session::get('end', Carbon::now()->startOfMonth()); | ||||
|         $list     = $this->_repository->journalsNoCategory($start, $end); | ||||
|         $subTitle = 'Transactions without a category in ' . $start->format('F Y'); | ||||
|  | ||||
|         return View::make('categories.noCategory', compact('list', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
| @@ -40,8 +55,7 @@ class CategoryController extends BaseController | ||||
|      */ | ||||
|     public function delete(Category $category) | ||||
|     { | ||||
|         return View::make('categories.delete')->with('category', $category) | ||||
|             ->with('subTitle', 'Delete category "' . $category->name . '"'); | ||||
|         return View::make('categories.delete')->with('category', $category)->with('subTitle', 'Delete category "' . e($category->name) . '"'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -51,8 +65,10 @@ class CategoryController extends BaseController | ||||
|      */ | ||||
|     public function destroy(Category $category) | ||||
|     { | ||||
|         Session::flash('success', 'Category "' . e($category->name) . '" was deleted.'); | ||||
|         $this->_repository->destroy($category); | ||||
|         Session::flash('success', 'The category was deleted.'); | ||||
|  | ||||
|  | ||||
|         return Redirect::route('categories.index'); | ||||
|     } | ||||
|  | ||||
| @@ -63,8 +79,7 @@ class CategoryController extends BaseController | ||||
|      */ | ||||
|     public function edit(Category $category) | ||||
|     { | ||||
|         return View::make('categories.edit')->with('category', $category) | ||||
|             ->with('subTitle', 'Edit category "' . $category->name . '"'); | ||||
|         return View::make('categories.edit')->with('category', $category)->with('subTitle', 'Edit category "' . e($category->name) . '"'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -74,8 +89,7 @@ class CategoryController extends BaseController | ||||
|     { | ||||
|         $categories = $this->_repository->get(); | ||||
|  | ||||
|         return View::make('categories.index')->with('categories', $categories) | ||||
|             ->with('subTitle', 'All your categories'); | ||||
|         return View::make('categories.index', compact('categories')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -85,58 +99,88 @@ class CategoryController extends BaseController | ||||
|      */ | ||||
|     public function show(Category $category) | ||||
|     { | ||||
|         $start = \Session::get('start'); | ||||
|         $end   = \Session::get('end'); | ||||
|         $hideCategory = true; // used in list. | ||||
|         $journals     = $this->_repository->getTransactionJournals($category, 50); | ||||
|  | ||||
|  | ||||
|         $journals = $this->_category->journalsInRange($category, $start, $end); | ||||
|  | ||||
|         return View::make('categories.show')->with('category', $category)->with('journals', $journals)->with( | ||||
|             'highlight', Input::get('highlight') | ||||
|         )->with('subTitle', 'Overview for category "' . $category->name . '"'); | ||||
|         return View::make('categories.show', compact('category', 'journals', 'hideCategory')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this|\Illuminate\Http\RedirectResponse | ||||
|      * @return $this | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store() | ||||
|     { | ||||
|         $category = $this->_repository->store(Input::all()); | ||||
|         if ($category->validate()) { | ||||
|             Session::flash('success', 'Category "' . $category->name . '" created!'); | ||||
|         $data            = Input::except('_token'); | ||||
|         $data['user_id'] = Auth::user()->id; | ||||
|  | ||||
|             if (Input::get('create') == '1') { | ||||
|                 return Redirect::route('categories.create'); | ||||
|             } | ||||
|         // always validate: | ||||
|         $messages = $this->_repository->validate($data); | ||||
|  | ||||
|             return Redirect::route('categories.index'); | ||||
|         } else { | ||||
|             Session::flash('error', 'Could not save the new category!'); | ||||
|         // flash messages: | ||||
|         Session::flash('warnings', $messages['warnings']); | ||||
|         Session::flash('successes', $messages['successes']); | ||||
|         Session::flash('errors', $messages['errors']); | ||||
|         if ($messages['errors']->count() > 0) { | ||||
|             Session::flash('error', 'Could not store category: ' . $messages['errors']->first()); | ||||
|         } | ||||
|  | ||||
|         // return to create screen: | ||||
|         if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { | ||||
|             return Redirect::route('categories.create')->withInput(); | ||||
|         } | ||||
|  | ||||
|         // store | ||||
|         $this->_repository->store($data); | ||||
|         Session::flash('success', 'Category "' . e($data['name']) . '" stored.'); | ||||
|         if ($data['post_submit_action'] == 'store') { | ||||
|             return Redirect::route('categories.index'); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('categories.create')->withInput(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return $this|\Illuminate\Http\RedirectResponse | ||||
|      * @return $this | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function update(Category $category) | ||||
|     { | ||||
|         $category = $this->_repository->update($category, Input::all()); | ||||
|         if ($category->validate()) { | ||||
|             Session::flash('success', 'Category "' . $category->name . '" updated.'); | ||||
|         $data            = Input::except('_token'); | ||||
|         $data['user_id'] = Auth::user()->id; | ||||
|  | ||||
|             return Redirect::route('categories.index'); | ||||
|         } else { | ||||
|             Session::flash('success', 'Could not update category "' . $category->name . '".'); | ||||
|         // always validate: | ||||
|         $messages = $this->_repository->validate($data); | ||||
|  | ||||
|             return Redirect::route('categories.edit')->withErrors($category->errors())->withInput(); | ||||
|         // flash messages: | ||||
|         Session::flash('warnings', $messages['warnings']); | ||||
|         Session::flash('successes', $messages['successes']); | ||||
|         Session::flash('errors', $messages['errors']); | ||||
|         if ($messages['errors']->count() > 0) { | ||||
|             Session::flash('error', 'Could not update category: ' . $messages['errors']->first()); | ||||
|         } | ||||
|  | ||||
|         // return to update screen: | ||||
|         if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { | ||||
|             return Redirect::route('categories.edit', $category->id)->withInput(); | ||||
|         } | ||||
|  | ||||
|         // update | ||||
|         $this->_repository->update($category, $data); | ||||
|         Session::flash('success', 'Category "' . e($data['name']) . '" updated.'); | ||||
|  | ||||
|         // go back to list | ||||
|         if ($data['post_submit_action'] == 'update') { | ||||
|             return Redirect::route('categories.index'); | ||||
|         } | ||||
|  | ||||
|         // go back to update screen. | ||||
|         return Redirect::route('categories.edit', $category->id)->withInput(['post_submit_action' => 'return_to_edit']); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -1,485 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Firefly\Helper\Controllers\ChartInterface; | ||||
| use Firefly\Storage\Account\AccountRepositoryInterface; | ||||
|  | ||||
| /** | ||||
|  * Class ChartController | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CamelCasePropertyName) | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class ChartController extends BaseController | ||||
| { | ||||
|  | ||||
|     protected $_chart; | ||||
|     protected $_accounts; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param ChartInterface             $chart | ||||
|      * @param AccountRepositoryInterface $accounts | ||||
|      */ | ||||
|     public function __construct(ChartInterface $chart, AccountRepositoryInterface $accounts) | ||||
|     { | ||||
|         $this->_chart    = $chart; | ||||
|         $this->_accounts = $accounts; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method takes a budget, all limits and all their repetitions and displays three numbers per repetition: | ||||
|      * the amount of money in the repetition (represented as "an envelope"), the amount spent and the spent percentage. | ||||
|      * | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function budgetDefault(\Budget $budget) | ||||
|     { | ||||
|         $expense  = []; | ||||
|         $left     = []; | ||||
|         $envelope = []; | ||||
|         // get all limit repetitions for this budget. | ||||
|         /** @var \Limit $limit */ | ||||
|         foreach ($budget->limits as $limit) { | ||||
|             /** @var \LimitRepetition $rep */ | ||||
|             foreach ($limit->limitrepetitions as $rep) { | ||||
|                 // get the amount of money spent in this period on this budget. | ||||
|                 $spentInRep = $rep->amount - $rep->leftInRepetition(); | ||||
|                 $pct        = round((floatval($spentInRep) / floatval($limit->amount)) * 100, 2); | ||||
|                 $name       = $rep->periodShow(); | ||||
|                 $envelope[] = [$name, floatval($limit->amount)]; | ||||
|                 $expense[]  = [$name, floatval($spentInRep)]; | ||||
|                 $left[]     = [$name, $pct]; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $return = [ | ||||
|             'chart_title' => 'Overview for budget ' . $budget->name, | ||||
|             'subtitle'    => 'All envelopes', | ||||
|             'series'      => [ | ||||
|                 [ | ||||
|                     'type'  => 'line', | ||||
|                     'yAxis' => 1, | ||||
|                     'name'  => 'Amount in envelope', | ||||
|                     'data'  => $envelope | ||||
|                 ], | ||||
|                 [ | ||||
|                     'type' => 'column', | ||||
|                     'name' => 'Expenses in envelope', | ||||
|                     'data' => $expense | ||||
|                 ], | ||||
|                 [ | ||||
|                     'type'  => 'line', | ||||
|                     'yAxis' => 1, | ||||
|                     'name'  => 'Spent percentage for envelope', | ||||
|                     'data'  => $left | ||||
|                 ] | ||||
|  | ||||
|  | ||||
|             ] | ||||
|         ]; | ||||
|  | ||||
|         return Response::json($return); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method takes a single limit repetition (so a single "envelope") and displays the amount of money spent | ||||
|      * per day and subsequently how much money is left. | ||||
|      * | ||||
|      * @param LimitRepetition $rep | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function budgetLimit(\LimitRepetition $rep) | ||||
|     { | ||||
|         $budget             = $rep->limit->budget; | ||||
|         $current            = clone $rep->startdate; | ||||
|         $expense            = []; | ||||
|         $leftInLimit        = []; | ||||
|         $currentLeftInLimit = floatval($rep->limit->amount); | ||||
|         while ($current <= $rep->enddate) { | ||||
|             $spent              = $this->_chart->spentOnDay($budget, $current); | ||||
|             $spent              = floatval($spent) == 0 ? null : floatval($spent); | ||||
|             $entry              = [$current->timestamp * 1000, $spent]; | ||||
|             $expense[]          = $entry; | ||||
|             $currentLeftInLimit = $currentLeftInLimit - $spent; | ||||
|             $leftInLimit[]      = [$current->timestamp * 1000, $currentLeftInLimit]; | ||||
|             $current->addDay(); | ||||
|         } | ||||
|  | ||||
|         $return = [ | ||||
|             'chart_title' => 'Overview for budget ' . $budget->name, | ||||
|             'subtitle'    => | ||||
|                 'Between ' . $rep->startdate->format('M jS, Y') . ' and ' . $rep->enddate->format('M jS, Y'), | ||||
|             'series'      => [ | ||||
|                 [ | ||||
|                     'type'  => 'column', | ||||
|                     'name'  => 'Expenses per day', | ||||
|                     'yAxis' => 1, | ||||
|                     'data'  => $expense | ||||
|                 ], | ||||
|                 [ | ||||
|                     'type' => 'line', | ||||
|                     'name' => 'Left in envelope', | ||||
|                     'data' => $leftInLimit | ||||
|                 ] | ||||
|  | ||||
|             ] | ||||
|         ]; | ||||
|  | ||||
|         return Response::json($return); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method takes a budget and gets all transactions in it which haven't got an envelope (limit). | ||||
|      * | ||||
|      * Usually this means that very old and unorganized or very NEW transactions get displayed; there was never an | ||||
|      * envelope or it hasn't been created (yet). | ||||
|      * | ||||
|      * | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function budgetNoLimits(\Budget $budget) | ||||
|     { | ||||
|         /* | ||||
|          * Firefly can go about this two ways. Either it finds all transactions which definitely are IN an envelope | ||||
|          * and exclude them or it searches for transactions outside of the range of any of the envelopes there are. | ||||
|          * | ||||
|          * Since either is kinda shitty Firefly uses the first one because it's easier to build. | ||||
|          */ | ||||
|         $inRepetitions = $this->_chart->allJournalsInBudgetEnvelope($budget); | ||||
|  | ||||
|         /* | ||||
|          * With this set of id's, Firefly can search for all journals NOT in that set. | ||||
|          * BUT they have to be in the budget (duh). | ||||
|          */ | ||||
|         $set = $this->_chart->journalsNotInSet($budget, $inRepetitions); | ||||
|         /* | ||||
|          * Next step: get all transactions for those journals. | ||||
|          */ | ||||
|         $transactions = $this->_chart->transactionsByJournals($set); | ||||
|  | ||||
|  | ||||
|         /* | ||||
|          *  this set builds the chart: | ||||
|          */ | ||||
|         $expense = []; | ||||
|  | ||||
|         foreach ($transactions as $t) { | ||||
|             $date      = new Carbon($t->date); | ||||
|             $expense[] = [$date->timestamp * 1000, floatval($t->aggregate)]; | ||||
|         } | ||||
|         $return = [ | ||||
|             'chart_title' => 'Overview for ' . $budget->name, | ||||
|             'subtitle'    => 'Not organized by an envelope', | ||||
|             'series'      => [ | ||||
|                 [ | ||||
|                     'type' => 'column', | ||||
|                     'name' => 'Expenses per day', | ||||
|                     'data' => $expense | ||||
|                 ] | ||||
|  | ||||
|             ] | ||||
|         ]; | ||||
|         return Response::json($return); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method gets all transactions within a budget within the period set by the current session | ||||
|      * start and end date. It also includes any envelopes which might exist within this period. | ||||
|      * | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function budgetSession(\Budget $budget) | ||||
|     { | ||||
|         $series = []; | ||||
|         $end    = clone Session::get('end'); | ||||
|         $start  = clone Session::get('start'); | ||||
|  | ||||
|  | ||||
|         /* | ||||
|          * Expenses per day in the session's period. That's easy. | ||||
|          */ | ||||
|         $expense = []; | ||||
|         $current = clone Session::get('start'); | ||||
|         while ($current <= $end) { | ||||
|             $spent     = $this->_chart->spentOnDay($budget, $current); | ||||
|             $spent     = floatval($spent) == 0 ? null : floatval($spent); | ||||
|             $expense[] = [$current->timestamp * 1000, $spent]; | ||||
|             $current->addDay(); | ||||
|         } | ||||
|  | ||||
|         $series[] = [ | ||||
|             'type' => 'column', | ||||
|             'name' => 'Expenses per day', | ||||
|             'data' => $expense | ||||
|         ]; | ||||
|         unset($expense, $spent, $current); | ||||
|  | ||||
|         /* | ||||
|          * Find all limit repetitions (for this budget) between start and end. This is | ||||
|          * quite a complex query. | ||||
|          */ | ||||
|         $reps = $this->_chart->limitsInRange($budget, $start, $end); | ||||
|  | ||||
|         /* | ||||
|          * For each limitrepetition Firefly creates a serie that contains the amount left in | ||||
|          * the limitrepetition for its entire date-range. Entries are only actually included when they | ||||
|          * fall into the charts date range. | ||||
|          * | ||||
|          * So example: the user has a session date from Jan 15 to Jan 30. The limitrepetition | ||||
|          * starts at 1 Jan until 1 Feb. | ||||
|          * | ||||
|          * Firefly loops from 1 Jan to 1 Feb but only includes Jan 15 / Jan 30. | ||||
|          * But it does keep count of the amount outside of these dates because otherwise the line might be wrong. | ||||
|          */ | ||||
|         /** @var \LimitRepetition $repetition */ | ||||
|         foreach ($reps as $repetition) { | ||||
|             $limitAmount = $repetition->limit->amount; | ||||
|  | ||||
|             // create a serie for the repetition. | ||||
|             $currentSerie = [ | ||||
|                 'type'  => 'spline', | ||||
|                 'id'    => 'rep-' . $repetition->id, | ||||
|                 'yAxis' => 1, | ||||
|                 'name'  => 'Envelope #' . $repetition->id . ' in ' . $repetition->periodShow(), | ||||
|                 'data'  => [] | ||||
|             ]; | ||||
|             $current      = clone $repetition->startdate; | ||||
|             while ($current <= $repetition->enddate) { | ||||
|                 if ($current >= $start && $current <= $end) { | ||||
|                     // spent on limit: | ||||
|                     $spentSoFar  = $this->_chart->spentOnLimitRepetitionBetweenDates( | ||||
|                         $repetition, $repetition->startdate, $current | ||||
|                     ); | ||||
|                     $leftInLimit = floatval($limitAmount) - floatval($spentSoFar); | ||||
|  | ||||
|                     $currentSerie['data'][] = [$current->timestamp * 1000, $leftInLimit]; | ||||
|                 } | ||||
|                 $current->addDay(); | ||||
|             } | ||||
|  | ||||
|             // do something here. | ||||
|             $series[] = $currentSerie; | ||||
|         } | ||||
|  | ||||
|         $return = [ | ||||
|             'chart_title' => 'Overview for budget ' . $budget->name, | ||||
|             'subtitle'    => | ||||
|                 'Between ' . Session::get('start')->format('M jS, Y') . ' and ' . Session::get('end')->format( | ||||
|                     'M jS, Y' | ||||
|                 ), | ||||
|             'series'      => $series | ||||
|         ]; | ||||
|  | ||||
|         return Response::json($return); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function categoryShowChart(Category $category) | ||||
|     { | ||||
|         $start = Session::get('start'); | ||||
|         $end   = Session::get('end'); | ||||
|         $range = Session::get('range'); | ||||
|  | ||||
|         $serie = $this->_chart->categoryShowChart($category, $range, $start, $end); | ||||
|         $data  = [ | ||||
|             'chart_title' => $category->name, | ||||
|             'subtitle'    => '<a href="' . route('categories.show', [$category->id]) . '">View more</a>', | ||||
|             'series'      => $serie | ||||
|         ]; | ||||
|  | ||||
|         return Response::json($data); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function homeAccount(Account $account = null) | ||||
|     { | ||||
|         // get preferences and accounts (if necessary): | ||||
|         $start = Session::get('start'); | ||||
|         $end   = Session::get('end'); | ||||
|  | ||||
|         if (is_null($account)) { | ||||
|             // get, depending on preferences: | ||||
|             /** @var  \Firefly\Helper\Preferences\PreferencesHelperInterface $prefs */ | ||||
|             $prefs = \App::make('Firefly\Helper\Preferences\PreferencesHelperInterface'); | ||||
|             $pref  = $prefs->get('frontpageAccounts', []); | ||||
|  | ||||
|             /** @var \Firefly\Storage\Account\AccountRepositoryInterface $acct */ | ||||
|             $acct     = \App::make('Firefly\Storage\Account\AccountRepositoryInterface'); | ||||
|             $accounts = $acct->getByIds($pref->data); | ||||
|         } else { | ||||
|             $accounts = [$account]; | ||||
|         } | ||||
|         // loop and get array data. | ||||
|  | ||||
|         $url  = count($accounts) == 1 && is_array($accounts) | ||||
|             ? '<a href="' . route('accounts.show', [$account->id]) . '">View more</a>' | ||||
|             : | ||||
|             '<a href="' . route('accounts.index') . '">View more</a>'; | ||||
|         $data = [ | ||||
|             'chart_title' => count($accounts) == 1 ? $accounts[0]->name : 'All accounts', | ||||
|             'subtitle'    => $url, | ||||
|             'series'      => [] | ||||
|         ]; | ||||
|  | ||||
|         foreach ($accounts as $account) { | ||||
|             $data['series'][] = $this->_chart->account($account, $start, $end); | ||||
|         } | ||||
|  | ||||
|         return Response::json($data); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $name | ||||
|      * @param $day | ||||
|      * @param $month | ||||
|      * @param $year | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function homeAccountInfo($name, $day, $month, $year) | ||||
|     { | ||||
|         $account = $this->_accounts->findByName($name); | ||||
|  | ||||
|         $date   = Carbon::createFromDate($year, $month, $day); | ||||
|         $result = $this->_chart->accountDailySummary($account, $date); | ||||
|  | ||||
|         return View::make('charts.info')->with('rows', $result['rows'])->with('sum', $result['sum'])->with( | ||||
|             'account', $account | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function homeBudgets() | ||||
|     { | ||||
|         $start = Session::get('start'); | ||||
|         $end   = Session::get('end'); | ||||
|         $data  = [ | ||||
|             'labels' => [], | ||||
|             'series' => [ | ||||
|                 [ | ||||
|                     'name' => 'Limit', | ||||
|                     'data' => [] | ||||
|                 ], | ||||
|                 [ | ||||
|                     'name' => 'Spent', | ||||
|                     'data' => [] | ||||
|                 ], | ||||
|             ] | ||||
|         ]; | ||||
|  | ||||
|         // Get all budgets. | ||||
|         $budgets   = \Auth::user()->budgets()->orderBy('name', 'ASC')->get(); | ||||
|         $budgetIds = []; | ||||
|         /** @var \Budget $budget */ | ||||
|         foreach ($budgets as $budget) { | ||||
|             $budgetIds[] = $budget->id; | ||||
|  | ||||
|             // Does the budget have a limit starting on $start? | ||||
|             $rep = \LimitRepetition:: | ||||
|             leftJoin('limits', 'limit_repetitions.limit_id', '=', 'limits.id')->leftJoin( | ||||
|                 'components', 'limits.component_id', '=', 'components.id' | ||||
|             )->where('limit_repetitions.startdate', $start->format('Y-m-d'))->where( | ||||
|                 'components.id', $budget->id | ||||
|             )->first(['limit_repetitions.*']); | ||||
|  | ||||
|             if (is_null($rep)) { | ||||
|                 $limit     = 0.0; | ||||
|                 $id        = null; | ||||
|                 $parameter = 'useSession=true'; | ||||
|             } else { | ||||
|                 $limit     = floatval($rep->amount); | ||||
|                 $id        = $rep->id; | ||||
|                 $parameter = ''; | ||||
|             } | ||||
|  | ||||
|             // Date range to check for expenses made? | ||||
|             if (is_null($rep)) { | ||||
|                 // use the session start and end for our search query | ||||
|                 $expenseStart = Session::get('start'); | ||||
|                 $expenseEnd   = Session::get('end'); | ||||
|  | ||||
|             } else { | ||||
|                 // use the limit's start and end for our search query | ||||
|                 $expenseStart = $rep->startdate; | ||||
|                 $expenseEnd   = $rep->enddate; | ||||
|             } | ||||
|             // How much have we spent on this budget? | ||||
|             $expenses = floatval($budget->transactionjournals()->before($expenseEnd)->after($expenseStart)->lessThan(0)->sum('amount')) * -1; | ||||
|  | ||||
|             // Append to chart: | ||||
|             if ($limit > 0 || $expenses > 0) { | ||||
|                 $data['labels'][]            = $budget->name; | ||||
|                 $data['series'][0]['data'][] = [ | ||||
|                     'y'   => $limit, | ||||
|                     'url' => route('budgets.show', [$budget->id, $id]) . '?' . $parameter | ||||
|                 ]; | ||||
|                 $data['series'][1]['data'][] = [ | ||||
|                     'y'   => $expenses, | ||||
|                     'url' => route('budgets.show', [$budget->id, $id]) . '?' . $parameter | ||||
|                 ]; | ||||
|             } | ||||
|         } | ||||
|         // Add expenses that have no budget: | ||||
|         $set = \Auth::user()->transactionjournals()->whereNotIn( | ||||
|             'transaction_journals.id', function ($query) use ($start, $end) { | ||||
|                 $query->select('transaction_journals.id')->from('transaction_journals') | ||||
|                     ->leftJoin( | ||||
|                         'component_transaction_journal', 'component_transaction_journal.transaction_journal_id', '=', | ||||
|                         'transaction_journals.id' | ||||
|                     ) | ||||
|                     ->leftJoin('components', 'components.id', '=', 'component_transaction_journal.component_id') | ||||
|                     ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) | ||||
|                     ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) | ||||
|                     ->where('components.class', 'Budget'); | ||||
|             } | ||||
|         )->before($end)->after($start)->lessThan(0)->transactionTypes(['Withdrawal'])->sum('amount'); | ||||
|  | ||||
|         // This can be debugged by using get(['transaction_journals.*','transactions.amount']); | ||||
|         $data['labels'][]            = 'No budget'; | ||||
|         $data['series'][0]['data'][] = [ | ||||
|             'y'   => 0, | ||||
|             'url' => route('budgets.nobudget','session') | ||||
|         ]; | ||||
|         $data['series'][1]['data'][] = [ | ||||
|             'y'   => floatval($set) * -1, | ||||
|             'url' => route('budgets.nobudget','session') | ||||
|         ]; | ||||
|  | ||||
|         return Response::json($data); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function homeCategories() | ||||
|     { | ||||
|         $start = Session::get('start'); | ||||
|         $end   = Session::get('end'); | ||||
|  | ||||
|         return Response::json($this->_chart->categories($start, $end)); | ||||
|  | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										197
									
								
								app/controllers/CurrencyController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								app/controllers/CurrencyController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,197 @@ | ||||
| <?php | ||||
| use FireflyIII\Database\TransactionCurrency\TransactionCurrency as Repository; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @SuppressWarnings("CamelCase") // I'm fine with this. | ||||
|  * @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok. | ||||
|  * | ||||
|  * Class CurrencyController | ||||
|  */ | ||||
| class CurrencyController extends BaseController | ||||
| { | ||||
|  | ||||
|     /** @var Repository */ | ||||
|     protected $_repository; | ||||
|  | ||||
|     /** | ||||
|      * @param Repository $repository | ||||
|      */ | ||||
|     public function __construct(Repository $repository) | ||||
|     { | ||||
|         $this->_repository = $repository; | ||||
|  | ||||
|  | ||||
|         View::share('title', 'Currencies'); | ||||
|         View::share('mainTitleIcon', 'fa-usd'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function create() | ||||
|     { | ||||
|         $subTitleIcon = 'fa-plus'; | ||||
|         $subTitle     = 'Create a new currency'; | ||||
|  | ||||
|         return View::make('currency.create', compact('subTitleIcon', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function defaultCurrency(TransactionCurrency $currency) | ||||
|     { | ||||
|         /** @var \FireflyIII\Shared\Preferences\Preferences $preferences */ | ||||
|         $preferences = App::make('FireflyIII\Shared\Preferences\Preferences'); | ||||
|  | ||||
|         $currencyPreference       = $preferences->get('currencyPreference', 'EUR'); | ||||
|         $currencyPreference->data = $currency->code; | ||||
|         $currencyPreference->save(); | ||||
|  | ||||
|         Session::flash('success', $currency->name.' is now the default currency.'); | ||||
|         Cache::forget('FFCURRENCYSYMBOL'); | ||||
|         Cache::forget('FFCURRENCYCODE'); | ||||
|  | ||||
|         return Redirect::route('currency.index'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View | ||||
|      */ | ||||
|     public function delete(TransactionCurrency $currency) | ||||
|     { | ||||
|         if ($currency->transactionJournals()->count() > 0) { | ||||
|             Session::flash('error', 'Cannot delete ' . e($currency->name) . ' because there are still transactions attached to it.'); | ||||
|  | ||||
|             return Redirect::route('currency.index'); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         return View::make('currency.delete', compact('currency')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function destroy(TransactionCurrency $currency) | ||||
|     { | ||||
|         Session::flash('success', 'Currency "' . e($currency->name) . '" deleted'); | ||||
|  | ||||
|         $this->_repository->destroy($currency); | ||||
|  | ||||
|         return Redirect::route('currency.index'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function edit(TransactionCurrency $currency) | ||||
|     { | ||||
|         $subTitleIcon     = 'fa-pencil'; | ||||
|         $subTitle         = 'Edit currency "' . e($currency->name) . '"'; | ||||
|         $currency->symbol = htmlentities($currency->symbol); | ||||
|  | ||||
|         return View::make('currency.edit', compact('currency', 'subTitle', 'subTitleIcon')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         $currencies = $this->_repository->get(); | ||||
|  | ||||
|         /** @var \FireflyIII\Shared\Preferences\Preferences $preferences */ | ||||
|         $preferences = App::make('FireflyIII\Shared\Preferences\Preferences'); | ||||
|  | ||||
|         $currencyPreference = $preferences->get('currencyPreference', 'EUR'); | ||||
|         $defaultCurrency    = $this->_repository->findByCode($currencyPreference->data); | ||||
|  | ||||
|  | ||||
|         return View::make('currency.index', compact('currencies', 'defaultCurrency')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this|\Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function store() | ||||
|     { | ||||
|         $data = Input::except('_token'); | ||||
|  | ||||
|         // always validate: | ||||
|         $messages = $this->_repository->validate($data); | ||||
|  | ||||
|         // flash messages: | ||||
|         Session::flash('warnings', $messages['warnings']); | ||||
|         Session::flash('successes', $messages['successes']); | ||||
|         Session::flash('errors', $messages['errors']); | ||||
|         if ($messages['errors']->count() > 0) { | ||||
|             Session::flash('error', 'Could not store currency: ' . $messages['errors']->first()); | ||||
|         } | ||||
|  | ||||
|         // return to create screen: | ||||
|         if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { | ||||
|             return Redirect::route('currency.create')->withInput(); | ||||
|         } | ||||
|  | ||||
|         // store | ||||
|         $this->_repository->store($data); | ||||
|         Session::flash('success', 'Currency "' . e($data['name']) . '" stored.'); | ||||
|         if ($data['post_submit_action'] == 'store') { | ||||
|             return Redirect::route('currency.index'); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('currency.create')->withInput(); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return $this|\Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function update(TransactionCurrency $currency) | ||||
|     { | ||||
|         $data = Input::except('_token'); | ||||
|  | ||||
|         // always validate: | ||||
|         $messages = $this->_repository->validate($data); | ||||
|  | ||||
|         // flash messages: | ||||
|         Session::flash('warnings', $messages['warnings']); | ||||
|         Session::flash('successes', $messages['successes']); | ||||
|         Session::flash('errors', $messages['errors']); | ||||
|         if ($messages['errors']->count() > 0) { | ||||
|             Session::flash('error', 'Could not update currency: ' . $messages['errors']->first()); | ||||
|         } | ||||
|  | ||||
|         // return to update screen: | ||||
|         if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { | ||||
|             return Redirect::route('currency.edit', $currency->id)->withInput(); | ||||
|         } | ||||
|  | ||||
|         // update | ||||
|         $this->_repository->update($currency, $data); | ||||
|         Session::flash('success', 'Currency "' . e($data['name']) . '" updated.'); | ||||
|  | ||||
|         // go back to list | ||||
|         if ($data['post_submit_action'] == 'update') { | ||||
|             return Redirect::route('currency.index'); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('currency.edit', $currency->id)->withInput(['post_submit_action' => 'return_to_edit']); | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										488
									
								
								app/controllers/GoogleChartController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										488
									
								
								app/controllers/GoogleChartController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,488 @@ | ||||
| <?php | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Chart\ChartInterface; | ||||
| use Grumpydictator\Gchart\GChart as GChart; | ||||
|  | ||||
| /** | ||||
|  * Class GoogleChartController | ||||
|  * @SuppressWarnings("CamelCase") // I'm fine with this. | ||||
|  * @SuppressWarnings("TooManyMethods") // I'm also fine with this. | ||||
|  * @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok. | ||||
|  * @SuppressWarnings("MethodLength") // There is one with 45 lines and im gonna move it. | ||||
|  * @SuppressWarnings("CouplingBetweenObjects") // There's only so much I can remove. | ||||
|  */ | ||||
| class GoogleChartController extends BaseController | ||||
| { | ||||
|  | ||||
|     /** @var GChart */ | ||||
|     protected $_chart; | ||||
|     /** @var  Carbon */ | ||||
|     protected $_end; | ||||
|     /** @var ChartInterface */ | ||||
|     protected $_repository; | ||||
|     /** @var  Carbon */ | ||||
|     protected $_start; | ||||
|  | ||||
|     /** | ||||
|      * @param GChart         $chart | ||||
|      * @param ChartInterface $repository | ||||
|      */ | ||||
|     public function __construct(GChart $chart, ChartInterface $repository) | ||||
|     { | ||||
|         $this->_chart      = $chart; | ||||
|         $this->_repository = $repository; | ||||
|         $this->_start      = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $this->_end        = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param string  $view | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function accountBalanceChart(Account $account, $view = 'session') | ||||
|     { | ||||
|         $this->_chart->addColumn('Day of month', 'date'); | ||||
|         $this->_chart->addColumn('Balance for ' . $account->name, 'number'); | ||||
|  | ||||
|         $start = $this->_start; | ||||
|         $end   = $this->_end; | ||||
|         $count = $account->transactions()->count(); | ||||
|  | ||||
|         if ($view == 'all' && $count > 0) { | ||||
|             $first = $account->transactions()->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')->orderBy( | ||||
|                 'date', 'ASC' | ||||
|             )->first(['transaction_journals.date']); | ||||
|             $last  = $account->transactions()->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')->orderBy( | ||||
|                 'date', 'DESC' | ||||
|             )->first(['transaction_journals.date']); | ||||
|             $start = new Carbon($first->date); | ||||
|             $end   = new Carbon($last->date); | ||||
|         } | ||||
|  | ||||
|         $current = clone $start; | ||||
|  | ||||
|         while ($end >= $current) { | ||||
|             $this->_chart->addRow(clone $current, Steam::balance($account, $current)); | ||||
|             $current->addDay(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $this->_chart->generate(); | ||||
|  | ||||
|         return Response::json($this->_chart->getData()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method renders the b | ||||
|      */ | ||||
|     public function allAccountsBalanceChart() | ||||
|     { | ||||
|         $this->_chart->addColumn('Day of the month', 'date'); | ||||
|  | ||||
|         /** @var \FireflyIII\Shared\Preferences\Preferences $preferences */ | ||||
|         $preferences = App::make('FireflyIII\Shared\Preferences\Preferences'); | ||||
|         $pref        = $preferences->get('frontPageAccounts', []); | ||||
|  | ||||
|         /** @var \FireflyIII\Database\Account\Account $acct */ | ||||
|         $acct     = App::make('FireflyIII\Database\Account\Account'); | ||||
|         $accounts = count($pref->data) > 0 ? $acct->getByIds($pref->data) : $acct->getAssetAccounts(); | ||||
|  | ||||
|         /** @var Account $account */ | ||||
|         foreach ($accounts as $account) { | ||||
|             $this->_chart->addColumn('Balance for ' . $account->name, 'number'); | ||||
|         } | ||||
|         $current = clone $this->_start; | ||||
|         $current->subDay(); | ||||
|  | ||||
|         while ($this->_end >= $current) { | ||||
|             $row = [clone $current]; | ||||
|             foreach ($accounts as $account) { | ||||
|                 $row[] = Steam::balance($account, $current); | ||||
|             } | ||||
|             $this->_chart->addRowArray($row); | ||||
|             $current->addDay(); | ||||
|         } | ||||
|  | ||||
|         $this->_chart->generate(); | ||||
|  | ||||
|         return Response::json($this->_chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function allBudgetsHomeChart() | ||||
|     { | ||||
|         $this->_chart->addColumn('Budget', 'string'); | ||||
|         $this->_chart->addColumn('Budgeted', 'number'); | ||||
|         $this->_chart->addColumn('Spent', 'number'); | ||||
|  | ||||
|         Log::debug('Now in allBudgetsHomeChart()'); | ||||
|  | ||||
|         /** @var \FireflyIII\Database\Budget\Budget $bdt */ | ||||
|         $bdt     = App::make('FireflyIII\Database\Budget\Budget'); | ||||
|         $budgets = $bdt->get(); | ||||
|  | ||||
|         /** @var Budget $budget */ | ||||
|         foreach ($budgets as $budget) { | ||||
|  | ||||
|             Log::debug('Now working budget #' . $budget->id . ', ' . $budget->name); | ||||
|  | ||||
|             /** @var \LimitRepetition $repetition */ | ||||
|             $repetition = $bdt->repetitionOnStartingOnDate($budget, $this->_start); | ||||
|             if (is_null($repetition)) { | ||||
|                 \Log::debug('Budget #' . $budget->id . ' has no repetition on ' . $this->_start->format('Y-m-d')); | ||||
|                 // use the session start and end for our search query | ||||
|                 $searchStart = $this->_start; | ||||
|                 $searchEnd   = $this->_end; | ||||
|                 $limit       = 0; // the limit is zero: | ||||
|             } else { | ||||
|                 \Log::debug('Budget #' . $budget->id . ' has a repetition on ' . $this->_start->format('Y-m-d') . '!'); | ||||
|                 // use the limit's start and end for our search query | ||||
|                 $searchStart = $repetition->startdate; | ||||
|                 $searchEnd   = $repetition->enddate; | ||||
|                 $limit       = floatval($repetition->amount); // the limit is the repetitions limit: | ||||
|             } | ||||
|  | ||||
|             $expenses = floatval($budget->transactionjournals()->before($searchEnd)->after($searchStart)->lessThan(0)->sum('amount')) * -1; | ||||
|             \Log::debug('Expenses in budget ' . $budget->name . ' before ' . $searchEnd->format('Y-m-d') . ' and after ' . $searchStart . ' are: ' . $expenses); | ||||
|             if ($expenses > 0) { | ||||
|                 $this->_chart->addRow($budget->name, $limit, $expenses); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $noBudgetSet = $bdt->expenseNoBudget($this->_start, $this->_end); | ||||
|         $sum         = $noBudgetSet->sum('amount') * -1; | ||||
|         $this->_chart->addRow('No budget', 0, $sum); | ||||
|         $this->_chart->generate(); | ||||
|  | ||||
|         return Response::json($this->_chart->getData()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function allCategoriesHomeChart() | ||||
|     { | ||||
|         $this->_chart->addColumn('Category', 'string'); | ||||
|         $this->_chart->addColumn('Spent', 'number'); | ||||
|  | ||||
|         // query! | ||||
|         $set = $this->_repository->getCategorySummary($this->_start, $this->_end); | ||||
|  | ||||
|         foreach ($set as $entry) { | ||||
|             $entry->name = strlen($entry->name) == 0 ? '(no category)' : $entry->name; | ||||
|             $this->_chart->addRow($entry->name, floatval($entry->sum)); | ||||
|         } | ||||
|  | ||||
|         $this->_chart->generate(); | ||||
|  | ||||
|         return Response::json($this->_chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Bill $bill | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function billOverview(Bill $bill) | ||||
|     { | ||||
|  | ||||
|         $this->_chart->addColumn('Date', 'date'); | ||||
|         $this->_chart->addColumn('Max amount', 'number'); | ||||
|         $this->_chart->addColumn('Min amount', 'number'); | ||||
|         $this->_chart->addColumn('Current entry', 'number'); | ||||
|  | ||||
|         // get first transaction or today for start: | ||||
|         $first = $bill->transactionjournals()->orderBy('date', 'ASC')->first(); | ||||
|         if ($first) { | ||||
|             $start = $first->date; | ||||
|         } else { | ||||
|             $start = new Carbon; | ||||
|         } | ||||
|         $end = new Carbon; | ||||
|         while ($start <= $end) { | ||||
|             $result = $bill->transactionjournals()->before($end)->after($start)->first(); | ||||
|             if ($result) { | ||||
|                 $amount = $result->getAmount(); | ||||
|             } else { | ||||
|                 $amount = 0; | ||||
|             } | ||||
|             unset($result); | ||||
|             $this->_chart->addRow(clone $start, $bill->amount_max, $bill->amount_min, $amount); | ||||
|             $start = DateKit::addPeriod($start, $bill->repeat_freq, 0); | ||||
|         } | ||||
|  | ||||
|         $this->_chart->generate(); | ||||
|  | ||||
|         return Response::json($this->_chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      * @throws \FireflyIII\Exception\FireflyException | ||||
|      */ | ||||
|     public function billsOverview() | ||||
|     { | ||||
|         $paid   = ['items' => [], 'amount' => 0]; | ||||
|         $unpaid = ['items' => [], 'amount' => 0]; | ||||
|         $this->_chart->addColumn('Name', 'string'); | ||||
|         $this->_chart->addColumn('Amount', 'number'); | ||||
|  | ||||
|         $set = $this->_repository->getBillsSummary($this->_start, $this->_end); | ||||
|  | ||||
|         foreach ($set as $entry) { | ||||
|             if (intval($entry->journalId) == 0) { | ||||
|                 $unpaid['items'][] = $entry->name; | ||||
|                 $unpaid['amount'] += floatval($entry->averageAmount); | ||||
|             } else { | ||||
|                 $paid['items'][] = $entry->description; | ||||
|                 $paid['amount'] += floatval($entry->actualAmount); | ||||
|             } | ||||
|         } | ||||
|         $this->_chart->addRow('Unpaid: ' . join(', ', $unpaid['items']), $unpaid['amount']); | ||||
|         $this->_chart->addRow('Paid: ' . join(', ', $paid['items']), $paid['amount']); | ||||
|         $this->_chart->generate(); | ||||
|  | ||||
|         return Response::json($this->_chart->getData()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @param Budget          $budget | ||||
|      * @param LimitRepetition $repetition | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function budgetLimitSpending(\Budget $budget, \LimitRepetition $repetition) | ||||
|     { | ||||
|         $start = clone $repetition->startdate; | ||||
|         $end   = $repetition->enddate; | ||||
|  | ||||
|         $this->_chart->addColumn('Day', 'date'); | ||||
|         $this->_chart->addColumn('Left', 'number'); | ||||
|  | ||||
|  | ||||
|         $amount = $repetition->amount; | ||||
|  | ||||
|         while ($start <= $end) { | ||||
|             /* | ||||
|              * Sum of expenses on this day: | ||||
|              */ | ||||
|             $sum = floatval($budget->transactionjournals()->lessThan(0)->transactionTypes(['Withdrawal'])->onDate($start)->sum('amount')); | ||||
|             $amount += $sum; | ||||
|             $this->_chart->addRow(clone $start, $amount); | ||||
|             $start->addDay(); | ||||
|         } | ||||
|         $this->_chart->generate(); | ||||
|  | ||||
|         return Response::json($this->_chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @param Budget    $budget | ||||
|      * @param           $year | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function budgetsAndSpending(Budget $budget, $year) | ||||
|     { | ||||
|         try { | ||||
|             new Carbon('01-01-' . $year); | ||||
|         } catch (Exception $e) { | ||||
|             return View::make('error')->with('message', 'Invalid year.'); | ||||
|         } | ||||
|  | ||||
|         /** @var \FireflyIII\Database\Budget\Budget $budgetRepository */ | ||||
|         $budgetRepository = App::make('FireflyIII\Database\Budget\Budget'); | ||||
|  | ||||
|         $this->_chart->addColumn('Month', 'date'); | ||||
|         $this->_chart->addColumn('Budgeted', 'number'); | ||||
|         $this->_chart->addColumn('Spent', 'number'); | ||||
|  | ||||
|         $start = new Carbon('01-01-' . $year); | ||||
|         $end   = clone $start; | ||||
|         $end->endOfYear(); | ||||
|         while ($start <= $end) { | ||||
|             $spent      = $budgetRepository->spentInMonth($budget, $start); | ||||
|             $repetition = $budgetRepository->repetitionOnStartingOnDate($budget, $start); | ||||
|  | ||||
|             if ($repetition) { | ||||
|                 $budgeted = floatval($repetition->amount); | ||||
|                 \Log::debug('Found a repetition on ' . $start->format('Y-m-d'). ' for budget ' . $budget->name.'!'); | ||||
|             } else { | ||||
|                 \Log::debug('No repetition on ' . $start->format('Y-m-d'). ' for budget ' . $budget->name); | ||||
|                 $budgeted = null; | ||||
|             } | ||||
|  | ||||
|             $this->_chart->addRow(clone $start, $budgeted, $spent); | ||||
|  | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $this->_chart->generate(); | ||||
|  | ||||
|         return Response::json($this->_chart->getData()); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @param Category  $component | ||||
|      * @param           $year | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function categoriesAndSpending(Category $component, $year) | ||||
|     { | ||||
|         try { | ||||
|             new Carbon('01-01-' . $year); | ||||
|         } catch (Exception $e) { | ||||
|             return View::make('error')->with('message', 'Invalid year.'); | ||||
|         } | ||||
|  | ||||
|         /** @var \FireflyIII\Database\Category\Category $categoryRepository */ | ||||
|         $categoryRepository = App::make('FireflyIII\Database\Category\Category'); | ||||
|  | ||||
|         $this->_chart->addColumn('Month', 'date'); | ||||
|         $this->_chart->addColumn('Budgeted', 'number'); | ||||
|         $this->_chart->addColumn('Spent', 'number'); | ||||
|  | ||||
|         $start = new Carbon('01-01-' . $year); | ||||
|         $end   = clone $start; | ||||
|         $end->endOfYear(); | ||||
|         while ($start <= $end) { | ||||
|  | ||||
|             $spent    = $categoryRepository->spentInMonth($component, $start); | ||||
|             $budgeted = null; | ||||
|  | ||||
|             $this->_chart->addRow(clone $start, $budgeted, $spent); | ||||
|  | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $this->_chart->generate(); | ||||
|  | ||||
|         return Response::json($this->_chart->getData()); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function piggyBankHistory(\PiggyBank $piggyBank) | ||||
|     { | ||||
|         $this->_chart->addColumn('Date', 'date'); | ||||
|         $this->_chart->addColumn('Balance', 'number'); | ||||
|  | ||||
|         $set = \DB::table('piggy_bank_events')->where('piggy_bank_id', $piggyBank->id)->groupBy('date')->get(['date', DB::Raw('SUM(`amount`) AS `sum`')]); | ||||
|  | ||||
|         foreach ($set as $entry) { | ||||
|             $this->_chart->addRow(new Carbon($entry->date), floatval($entry->sum)); | ||||
|         } | ||||
|  | ||||
|         $this->_chart->generate(); | ||||
|  | ||||
|         return Response::json($this->_chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @param $year | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function yearInExp($year) | ||||
|     { | ||||
|         try { | ||||
|             $start = new Carbon('01-01-' . $year); | ||||
|         } catch (Exception $e) { | ||||
|             return View::make('error')->with('message', 'Invalid year.'); | ||||
|         } | ||||
|         $this->_chart->addColumn('Month', 'date'); | ||||
|         $this->_chart->addColumn('Income', 'number'); | ||||
|         $this->_chart->addColumn('Expenses', 'number'); | ||||
|  | ||||
|         /** @var \FireflyIII\Database\TransactionJournal\TransactionJournal $repository */ | ||||
|         $repository = App::make('FireflyIII\Database\TransactionJournal\TransactionJournal'); | ||||
|  | ||||
|         $end = clone $start; | ||||
|         $end->endOfYear(); | ||||
|         while ($start < $end) { | ||||
|  | ||||
|             // total income: | ||||
|             $income  = $repository->getSumOfIncomesByMonth($start); | ||||
|             $expense = $repository->getSumOfExpensesByMonth($start); | ||||
|  | ||||
|             $this->_chart->addRow(clone $start, $income, $expense); | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $this->_chart->generate(); | ||||
|  | ||||
|         return Response::json($this->_chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @param $year | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function yearInExpSum($year) | ||||
|     { | ||||
|         try { | ||||
|             $start = new Carbon('01-01-' . $year); | ||||
|         } catch (Exception $e) { | ||||
|             return View::make('error')->with('message', 'Invalid year.'); | ||||
|         } | ||||
|         $this->_chart->addColumn('Summary', 'string'); | ||||
|         $this->_chart->addColumn('Income', 'number'); | ||||
|         $this->_chart->addColumn('Expenses', 'number'); | ||||
|  | ||||
|         /** @var \FireflyIII\Database\TransactionJournal\TransactionJournal $repository */ | ||||
|         $repository = App::make('FireflyIII\Database\TransactionJournal\TransactionJournal'); | ||||
|  | ||||
|         $end = clone $start; | ||||
|         $end->endOfYear(); | ||||
|         $income  = 0; | ||||
|         $expense = 0; | ||||
|         $count   = 0; | ||||
|         while ($start < $end) { | ||||
|  | ||||
|             // total income: | ||||
|             $income += $repository->getSumOfIncomesByMonth($start); | ||||
|             $expense += $repository->getSumOfExpensesByMonth($start); | ||||
|             $count++; | ||||
|  | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|         $this->_chart->addRow('Sum', $income, $expense); | ||||
|         $count = $count > 0 ? $count : 1; | ||||
|         $this->_chart->addRow('Average', ($income / $count), ($expense / $count)); | ||||
|  | ||||
|  | ||||
|         $this->_chart->generate(); | ||||
|  | ||||
|         return Response::json($this->_chart->getData()); | ||||
|  | ||||
|     } | ||||
| }  | ||||
							
								
								
									
										54
									
								
								app/controllers/HelpController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								app/controllers/HelpController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok. | ||||
|  * | ||||
|  * Class HelpController | ||||
|  */ | ||||
| class HelpController extends BaseController | ||||
| { | ||||
|     /** | ||||
|      * @param $route | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function show($route) | ||||
|     { | ||||
|         $helpText  = '<p>There is no help for this route!</p>'; | ||||
|         $helpTitle = 'Help'; | ||||
|         if (!Route::has($route)) { | ||||
|             \Log::error('No such route: ' . $route); | ||||
|  | ||||
|             return Response::json(['title' => $helpTitle, 'text' => $helpText]); | ||||
|         } | ||||
|         if (Cache::has('help.' . $route . '.title') && Cache::has('help.' . $route . '.text')) { | ||||
|             $helpText  = Cache::get('help.' . $route . '.text'); | ||||
|             $helpTitle = Cache::get('help.' . $route . '.title'); | ||||
|  | ||||
|             return Response::json(['title' => $helpTitle, 'text' => $helpText]); | ||||
|         } | ||||
|  | ||||
|         $uri = 'https://raw.githubusercontent.com/JC5/firefly-iii-help/master/' . e($route) . '.md'; | ||||
|         \Log::debug('URL is: ' . $uri); | ||||
|         try { | ||||
|             $helpText = file_get_contents($uri); | ||||
|         } catch (ErrorException $e) { | ||||
|             \Log::error(trim($e->getMessage())); | ||||
|         } | ||||
|         \Log::debug('Found help for ' . $route); | ||||
|         \Log::debug('Help text length for route ' . $route . ' is ' . strlen($helpText)); | ||||
|         \Log::debug('Help text IS: "' . $helpText . '".'); | ||||
|         if (strlen(trim($helpText)) == 0) { | ||||
|             $helpText = '<p>There is no help for this route.</p>'; | ||||
|         } | ||||
|  | ||||
|         $helpText  = \Michelf\Markdown::defaultTransform($helpText); | ||||
|         $helpTitle = $route; | ||||
|  | ||||
|         Cache::put('help.' . $route . '.text', $helpText, 10080); // a week. | ||||
|         Cache::put('help.' . $route . '.title', $helpTitle, 10080); | ||||
|  | ||||
|         return Response::json(['title' => $helpTitle, 'text' => $helpText]); | ||||
|  | ||||
|     } | ||||
| }  | ||||
| @@ -1,63 +1,12 @@ | ||||
| <?php | ||||
| use Firefly\Helper\Preferences\PreferencesHelperInterface as PHI; | ||||
| use Firefly\Storage\Account\AccountRepositoryInterface as ARI; | ||||
| use Firefly\Storage\Reminder\ReminderRepositoryInterface as RRI; | ||||
| use Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface as TJRI; | ||||
| use Carbon\Carbon; | ||||
|  | ||||
| /** | ||||
|  * Class HomeController | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CamelCasePropertyName) | ||||
|  */ | ||||
| class HomeController extends BaseController | ||||
| { | ||||
|     protected $_accounts; | ||||
|     protected $_preferences; | ||||
|     protected $_journal; | ||||
|     protected $_reminders; | ||||
|  | ||||
|     /** | ||||
|      * @param ARI  $accounts | ||||
|      * @param PHI  $preferences | ||||
|      * @param TJRI $journal | ||||
|      * @param RRI  $reminders | ||||
|      */ | ||||
|     public function __construct(ARI $accounts, PHI $preferences, TJRI $journal, RRI $reminders) | ||||
|     { | ||||
|         $this->_accounts    = $accounts; | ||||
|         $this->_preferences = $preferences; | ||||
|         $this->_journal     = $journal; | ||||
|         $this->_reminders   = $reminders; | ||||
|     } | ||||
|  | ||||
|     public function jobDev() { | ||||
|         $fullName = storage_path().DIRECTORY_SEPARATOR.'firefly-export-2014-07-23.json'; | ||||
|         \Log::notice('Pushed start job.'); | ||||
|         Queue::push('Firefly\Queue\Import@start', ['file' => $fullName, 'user' => 1]); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      * | ||||
|      */ | ||||
|     public function sessionPrev() { | ||||
|         /** @var \Firefly\Helper\Toolkit\ToolkitInterface $toolkit */ | ||||
|         $toolkit = App::make('Firefly\Helper\Toolkit\ToolkitInterface'); | ||||
|         $toolkit->prev(); | ||||
|         return Redirect::back(); | ||||
|         //return Redirect::route('index'); | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      * | ||||
|      */ | ||||
|     public function sessionNext() { | ||||
|         /** @var \Firefly\Helper\Toolkit\ToolkitInterface $toolkit */ | ||||
|         $toolkit = App::make('Firefly\Helper\Toolkit\ToolkitInterface'); | ||||
|         $toolkit->next(); | ||||
|         return Redirect::back(); | ||||
|         //return Redirect::route('index'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
| @@ -74,34 +23,81 @@ class HomeController extends BaseController | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         Event::fire('limits.check'); | ||||
|         Event::fire('piggybanks.check'); | ||||
|         Event::fire('recurring.check'); | ||||
|  | ||||
|         // count, maybe Firefly needs some introducing text to show: | ||||
|         $count = $this->_accounts->count(); | ||||
|         $start = Session::get('start'); | ||||
|         $end   = Session::get('end'); | ||||
|         /** @var \FireflyIII\Database\Account\Account $acct */ | ||||
|         $acct = App::make('FireflyIII\Database\Account\Account'); | ||||
|  | ||||
|         /** @var \FireflyIII\Database\TransactionJournal\TransactionJournal $journalRepository */ | ||||
|         $journalRepository = App::make('FireflyIII\Database\TransactionJournal\TransactionJournal'); | ||||
|  | ||||
|         /** @var \FireflyIII\Shared\Preferences\PreferencesInterface $preferences */ | ||||
|         $preferences = App::make('FireflyIII\Shared\Preferences\PreferencesInterface'); | ||||
|  | ||||
|         $count = $acct->countAssetAccounts(); | ||||
|  | ||||
|         $start = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end   = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|  | ||||
|  | ||||
|         // get the preference for the home accounts to show: | ||||
|         $frontpage = $this->_preferences->get('frontpageAccounts', []); | ||||
|         if ($frontpage->data == []) { | ||||
|             $accounts = $this->_accounts->getActiveDefault(); | ||||
|         $frontPage = $preferences->get('frontPageAccounts', []); | ||||
|         if ($frontPage->data == []) { | ||||
|             $accounts = $acct->getAssetAccounts(); | ||||
|         } else { | ||||
|             $accounts = $this->_accounts->getByIds($frontpage->data); | ||||
|             $accounts = $acct->getByIds($frontPage->data); | ||||
|         } | ||||
|  | ||||
|         $transactions = []; | ||||
|         foreach ($accounts as $account) { | ||||
|             $set = $this->_journal->getByAccountInDateRange($account, 10, $start, $end); | ||||
|             $set = $journalRepository->getInDateRangeAccount($account, $start, $end, 10); | ||||
|             if (count($set) > 0) { | ||||
|                 $transactions[] = [$set, $account]; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // build the home screen: | ||||
|         return View::make('index')->with('count', $count)->with('transactions', $transactions)->with('title', 'Firefly') | ||||
|             ->with('subTitle', 'What\'s playing?')->with('mainTitleIcon','fa-fire'); | ||||
|         return View::make('index')->with('count', $count)->with('transactions', $transactions)->with('title', 'Firefly')->with('subTitle', 'What\'s playing?') | ||||
|                    ->with('mainTitleIcon', 'fa-fire'); | ||||
|     } | ||||
| } | ||||
|  | ||||
|     /** | ||||
|      * @param $range | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function rangeJump($range) | ||||
|     { | ||||
|  | ||||
|         $valid = ['1D', '1W', '1M', '3M', '6M', '1Y',]; | ||||
|  | ||||
|         /** @var \FireflyIII\Shared\Preferences\PreferencesInterface $preferences */ | ||||
|         $preferences = App::make('FireflyIII\Shared\Preferences\PreferencesInterface'); | ||||
|  | ||||
|         if (in_array($range, $valid)) { | ||||
|             $preferences->set('viewRange', $range); | ||||
|             Session::forget('range'); | ||||
|         } | ||||
|  | ||||
|         return Redirect::intended('/'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function sessionNext() | ||||
|     { | ||||
|         Navigation::next(); | ||||
|  | ||||
|         return Redirect::intended('/'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function sessionPrev() | ||||
|     { | ||||
|         Navigation::prev(); | ||||
|  | ||||
|         return Redirect::intended('/'); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,26 +1,11 @@ | ||||
| <?php | ||||
|  | ||||
| use Firefly\Helper\Controllers\JsonInterface as JI; | ||||
| use Illuminate\Support\Collection; | ||||
| use LaravelBook\Ardent\Builder; | ||||
|  | ||||
| /** | ||||
|  * Class JsonController | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CamelCasePropertyName) | ||||
|  */ | ||||
| class JsonController extends BaseController | ||||
| { | ||||
|     /** @var \Firefly\Helper\Controllers\JsonInterface $helper */ | ||||
|     protected $helper; | ||||
|  | ||||
|     public function __construct(JI $helper) | ||||
|     { | ||||
|         $this->helper = $helper; | ||||
|  | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a list of categories. | ||||
| @@ -29,8 +14,8 @@ class JsonController extends BaseController | ||||
|      */ | ||||
|     public function categories() | ||||
|     { | ||||
|         /** @var \Firefly\Storage\Category\EloquentCategoryRepository $categories */ | ||||
|         $categories = App::make('Firefly\Storage\Category\CategoryRepositoryInterface'); | ||||
|         /** @var \FireflyIII\Database\Category\Category $categories */ | ||||
|         $categories = App::make('FireflyIII\Database\Category\Category'); | ||||
|         $list       = $categories->get(); | ||||
|         $return     = []; | ||||
|         foreach ($list as $entry) { | ||||
| @@ -49,9 +34,9 @@ class JsonController extends BaseController | ||||
|      */ | ||||
|     public function expenseAccounts() | ||||
|     { | ||||
|         /** @var \Firefly\Storage\Account\EloquentAccountRepository $accounts */ | ||||
|         $accounts = App::make('Firefly\Storage\Account\AccountRepositoryInterface'); | ||||
|         $list     = $accounts->getOfTypes(['Expense account', 'Beneficiary account']); | ||||
|         /** @var \FireflyIII\Database\Account\Account $accounts */ | ||||
|         $accounts = App::make('FireflyIII\Database\Account\Account'); | ||||
|         $list     = $accounts->getExpenseAccounts(); | ||||
|         $return   = []; | ||||
|         foreach ($list as $entry) { | ||||
|             $return[] = $entry->name; | ||||
| @@ -62,78 +47,13 @@ class JsonController extends BaseController | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a list of transactions, expenses only, using the given parameters. | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function expenses() | ||||
|     { | ||||
|  | ||||
|         /* | ||||
|          * Gets most parameters from the Input::all() array: | ||||
|          */ | ||||
|         $parameters = $this->helper->dataTableParameters(); | ||||
|  | ||||
|         /* | ||||
|          * Add some more parameters to fine tune the query: | ||||
|          */ | ||||
|         $parameters['transactionTypes'] = ['Withdrawal']; | ||||
|         $parameters['amount']           = 'negative'; | ||||
|  | ||||
|         /* | ||||
|          * Get the query: | ||||
|          */ | ||||
|         $query = $this->helper->journalQuery($parameters); | ||||
|  | ||||
|         /* | ||||
|          * Build result set: | ||||
|          */ | ||||
|         $resultSet = $this->helper->journalDataset($parameters, $query); | ||||
|  | ||||
|  | ||||
|         /* | ||||
|          * Build return data: | ||||
|          */ | ||||
|         return Response::json($resultSet); | ||||
|     } | ||||
|  | ||||
|     public function recurring() | ||||
|     { | ||||
|         $parameters = $this->helper->dataTableParameters(); | ||||
|         $query = $this->helper->recurringTransactionsQuery($parameters); | ||||
|         $resultSet = $this->helper->recurringTransactionsDataset($parameters, $query); | ||||
|         return Response::json($resultSet); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Http\JsonResponse|string | ||||
|      */ | ||||
|     public function revenue() | ||||
|     { | ||||
|         $parameters                     = $this->helper->dataTableParameters(); | ||||
|         $parameters['transactionTypes'] = ['Deposit']; | ||||
|         $parameters['amount']           = 'positive'; | ||||
|  | ||||
|         $query     = $this->helper->journalQuery($parameters); | ||||
|         $resultSet = $this->helper->journalDataset($parameters, $query); | ||||
|  | ||||
|  | ||||
|         /* | ||||
|          * Build return data: | ||||
|          */ | ||||
|         return Response::json($resultSet); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a JSON list of all revenue accounts. | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function revenueAccounts() | ||||
|     { | ||||
|         /** @var \Firefly\Storage\Account\EloquentAccountRepository $accounts */ | ||||
|         $accounts = App::make('Firefly\Storage\Account\AccountRepositoryInterface'); | ||||
|         $list     = $accounts->getOfTypes(['Revenue account']); | ||||
|         /** @var \FireflyIII\Database\Account\Account $accounts */ | ||||
|         $accounts = App::make('FireflyIII\Database\Account\Account'); | ||||
|         $list     = $accounts->getRevenueAccounts(); | ||||
|         $return   = []; | ||||
|         foreach ($list as $entry) { | ||||
|             $return[] = $entry->name; | ||||
| @@ -142,25 +62,4 @@ class JsonController extends BaseController | ||||
|         return Response::json($return); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a list of all transfers. | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function transfers() | ||||
|     { | ||||
|         $parameters                     = $this->helper->dataTableParameters(); | ||||
|         $parameters['transactionTypes'] = ['Transfer']; | ||||
|         $parameters['amount']           = 'positive'; | ||||
|  | ||||
|         $query     = $this->helper->journalQuery($parameters); | ||||
|         $resultSet = $this->helper->journalDataset($parameters, $query); | ||||
|  | ||||
|  | ||||
|         /* | ||||
|          * Build return data: | ||||
|          */ | ||||
|         return Response::json($resultSet); | ||||
|     } | ||||
| }  | ||||
| } | ||||
|   | ||||
| @@ -1,162 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| use Firefly\Storage\Budget\BudgetRepositoryInterface as BRI; | ||||
| use Firefly\Storage\Limit\LimitRepositoryInterface as LRI; | ||||
|  | ||||
| /** | ||||
|  * Class LimitController | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CamelCasePropertyName) | ||||
|  */ | ||||
| class LimitController extends BaseController | ||||
| { | ||||
|  | ||||
|     protected $_budgets; | ||||
|     protected $_limits; | ||||
|  | ||||
|     /** | ||||
|      * @param BRI $budgets | ||||
|      * @param LRI $limits | ||||
|      */ | ||||
|     public function __construct(BRI $budgets, LRI $limits) | ||||
|     { | ||||
|         $this->_budgets = $budgets; | ||||
|         $this->_limits  = $limits; | ||||
|  | ||||
|         View::share('title','Envelopes'); | ||||
|         View::share('mainTitleIcon', 'fa-tasks'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function create(\Budget $budget = null) | ||||
|     { | ||||
|         $periods   = \Config::get('firefly.periods_to_text'); | ||||
|         $prefilled = [ | ||||
|             'startdate'   => \Input::get('startdate') ? : date('Y-m-d'), | ||||
|             'repeat_freq' => \Input::get('repeat_freq') ? : 'monthly', | ||||
|             'budget_id'   => $budget ? $budget->id : null | ||||
|         ]; | ||||
|  | ||||
|         /** @var \Firefly\Helper\Toolkit\Toolkit $toolkit */ | ||||
|         $toolkit = App::make('Firefly\Helper\Toolkit\Toolkit'); | ||||
|         $budgets = $toolkit->makeSelectList($this->_budgets->get()); | ||||
|  | ||||
|         return View::make('limits.create')->with('budgets', $budgets)->with( | ||||
|             'periods', $periods | ||||
|         )->with('prefilled', $prefilled)->with('subTitle','New envelope'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Limit $limit | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function delete(\Limit $limit) | ||||
|     { | ||||
|         return View::make('limits.delete')->with('limit', $limit)->with('subTitle','Delete envelope'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Limit $limit | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function destroy(\Limit $limit) | ||||
|     { | ||||
|         Event::fire('limits.destroy', [$limit]); // before | ||||
|         $success = $this->_limits->destroy($limit); | ||||
|  | ||||
|         if ($success) { | ||||
|             Session::flash('success', 'The envelope was deleted.'); | ||||
|         } else { | ||||
|             Session::flash('error', 'Could not delete the envelope. Check the logs to be sure.'); | ||||
|         } | ||||
|         if (Input::get('from') == 'date') { | ||||
|             return Redirect::route('budgets.index'); | ||||
|         } else { | ||||
|             return Redirect::route('budgets.index.budget'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Limit $limit | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function edit(Limit $limit) | ||||
|     { | ||||
|         /** @var \Firefly\Helper\Toolkit\Toolkit $toolkit */ | ||||
|         $toolkit = App::make('Firefly\Helper\Toolkit\Toolkit'); | ||||
|  | ||||
|         $budgets    = $toolkit->makeSelectList($this->_budgets->get()); | ||||
|         $periods = \Config::get('firefly.periods_to_text'); | ||||
|  | ||||
|         return View::make('limits.edit')->with('limit', $limit)->with('budgets', $budgets)->with( | ||||
|             'periods', $periods | ||||
|         )->with('subTitle','Edit envelope'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return $this|\Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function store(Budget $budget = null) | ||||
|     { | ||||
|  | ||||
|         // find a limit with these properties, as Firefly might already have one: | ||||
|         $limit = $this->_limits->store(Input::all()); | ||||
|         if ($limit->validate()) { | ||||
|             Session::flash('success', 'Envelope created!'); | ||||
|             Event::fire('limits.store', [$limit]); | ||||
|             if (Input::get('from') == 'date') { | ||||
|                 return Redirect::route('budgets.index'); | ||||
|             } else { | ||||
|                 return Redirect::route('budgets.index.budget'); | ||||
|             } | ||||
|         } else { | ||||
|             Session::flash('error', 'Could not save new envelope.'); | ||||
|             $budgetId   = $budget ? $budget->id : null; | ||||
|             $parameters = [$budgetId, 'from' => Input::get('from')]; | ||||
|  | ||||
|             return Redirect::route('budgets.limits.create', $parameters)->withInput() | ||||
|                 ->withErrors($limit->errors()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Limit $limit | ||||
|      * | ||||
|      * @return $this|\Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function update(\Limit $limit) | ||||
|     { | ||||
|  | ||||
|  | ||||
|         $limit = $this->_limits->update($limit, Input::all()); | ||||
|  | ||||
|         if ($limit->validate()) { | ||||
|             Event::fire('limits.update', [$limit]); | ||||
|             Session::flash('success', 'Limit saved!'); | ||||
|             if (Input::get('from') == 'date') { | ||||
|                 return Redirect::route('budgets.index'); | ||||
|             } else { | ||||
|                 return Redirect::route('budgets.index.budget'); | ||||
|             } | ||||
|  | ||||
|  | ||||
|         } else { | ||||
|             Session::flash('error', 'Could not save new limit: ' . $limit->errors()->first()); | ||||
|  | ||||
|             return Redirect::route('budgets.limits.edit', [$limit->id, 'from' => Input::get('from')])->withInput() | ||||
|                 ->withErrors($limit->errors()); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
| }  | ||||
| @@ -1,52 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * Class MigrateController | ||||
|  */ | ||||
| class MigrateController extends BaseController | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         return View::make('migrate.index')->with('index', 'Migration')->with('title','Migrate')-> | ||||
|             with('subTitle','From Firefly II to Firefly III'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function upload() | ||||
|     { | ||||
|         if (Input::hasFile('file') && Input::file('file')->isValid()) { | ||||
|             $path     = storage_path(); | ||||
|             $fileName = 'firefly-iii-import-' . date('Y-m-d-H-i') . '.json'; | ||||
|             $fullName = $path . DIRECTORY_SEPARATOR . $fileName; | ||||
|             if (Input::file('file')->move($path, $fileName)) { | ||||
|                 // so now Firefly pushes something in a queue and does something with it! Yay! | ||||
|                 \Log::debug('Pushed a job to start the import.'); | ||||
|                 Queue::push('Firefly\Queue\Import@start', ['file' => $fullName, 'user' => \Auth::user()->id]); | ||||
|                 if (Config::get('queue.default') == 'sync') { | ||||
|                     Session::flash('success', 'Your data has been imported!'); | ||||
|                 } else { | ||||
|                     Session::flash( | ||||
|                         'success', | ||||
|                         'The import job has been queued. Please be patient. Data will appear slowly. Please be patient.' | ||||
|                     ); | ||||
|                 } | ||||
|  | ||||
|                 return Redirect::route('index'); | ||||
|             } | ||||
|             Session::flash('error', 'Could not save file to storage.'); | ||||
|             return Redirect::route('migrate.index'); | ||||
|  | ||||
|         } else { | ||||
|             Session::flash('error', 'Please upload a file.'); | ||||
|             return Redirect::route('migrate.index'); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
| }  | ||||
| @@ -1,404 +1,358 @@ | ||||
| <?php | ||||
|  | ||||
| use Firefly\Exception\FireflyException; | ||||
| use Firefly\Storage\Account\AccountRepositoryInterface as ARI; | ||||
| use Firefly\Storage\Piggybank\PiggybankRepositoryInterface as PRI; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Database\PiggyBank\PiggyBank as Repository; | ||||
| use FireflyIII\Exception\FireflyException; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class PiggybankController | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CamelCasePropertyName) | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  * @SuppressWarnings(PHPMD.TooManyMethods) | ||||
|  * @SuppressWarnings("CamelCase") // I'm fine with this. | ||||
|  * @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok. | ||||
|  * @SuppressWarnings("TooManyMethods") // I'm also fine with this. | ||||
|  * @SuppressWarnings("CouplingBetweenObjects") // There's only so much I can remove. | ||||
|  * | ||||
|  * | ||||
|  * Class PiggyBankController | ||||
|  * | ||||
|  */ | ||||
| class PiggybankController extends BaseController | ||||
| class PiggyBankController extends BaseController | ||||
| { | ||||
|  | ||||
|     protected $_accounts; | ||||
|     /** @var Repository */ | ||||
|     protected $_repository; | ||||
|  | ||||
|     /** | ||||
|      * @param PRI $repository | ||||
|      * @param ARI $accounts | ||||
|      * @param Repository $repository | ||||
|      */ | ||||
|     public function __construct(PRI $repository, ARI $accounts) | ||||
|     public function __construct(Repository $repository) | ||||
|     { | ||||
|         $this->_repository = $repository; | ||||
|         $this->_accounts   = $accounts; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Piggybank $piggyBank | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function addMoney(Piggybank $piggyBank) | ||||
|     { | ||||
|         $what      = 'add'; | ||||
|         $maxAdd    = $this->_repository->leftOnAccount($piggyBank->account); | ||||
|         $maxRemove = null; | ||||
|  | ||||
|         return View::make('piggybanks.modifyAmount')->with('what', $what)->with('maxAdd', $maxAdd)->with( | ||||
|             'maxRemove', $maxRemove | ||||
|         )->with('piggybank', $piggyBank); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function createPiggybank() | ||||
|     { | ||||
|         /** @var \Firefly\Helper\Toolkit\Toolkit $toolkit */ | ||||
|         $toolkit = App::make('Firefly\Helper\Toolkit\Toolkit'); | ||||
|  | ||||
|  | ||||
|         $periods  = Config::get('firefly.piggybank_periods'); | ||||
|         $list     = $this->_accounts->getActiveDefault(); | ||||
|         $accounts = $toolkit->makeSelectList($list); | ||||
|  | ||||
|         View::share('title', 'Piggy banks'); | ||||
|         View::share('subTitle', 'Create new'); | ||||
|         View::share('mainTitleIcon', 'fa-sort-amount-asc'); | ||||
|  | ||||
|         return View::make('piggybanks.create-piggybank')->with('accounts', $accounts) | ||||
|             ->with('periods', $periods); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function createRepeated() | ||||
|     { | ||||
|         /** @var \Firefly\Helper\Toolkit\Toolkit $toolkit */ | ||||
|         $toolkit = App::make('Firefly\Helper\Toolkit\Toolkit'); | ||||
|  | ||||
|         $periods  = Config::get('firefly.piggybank_periods'); | ||||
|         $list     = $this->_accounts->getActiveDefault(); | ||||
|         $accounts = $toolkit->makeSelectList($list); | ||||
|  | ||||
|         View::share('title', 'Repeated expenses'); | ||||
|         View::share('subTitle', 'Create new'); | ||||
|         View::share('mainTitleIcon', 'fa-rotate-right'); | ||||
|  | ||||
|         return View::make('piggybanks.create-repeated')->with('accounts', $accounts)->with('periods', $periods); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Piggybank $piggyBank | ||||
|      * Add money to piggy bank | ||||
|      * | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function delete(Piggybank $piggyBank) | ||||
|     { | ||||
|         View::share('subTitle', 'Delete "' . $piggyBank->name . '"'); | ||||
|         if ($piggyBank->repeats == 1) { | ||||
|             View::share('title', 'Repeated expenses'); | ||||
|             View::share('mainTitleIcon', 'fa-rotate-right'); | ||||
|         } else { | ||||
|             View::share('title', 'Piggy banks'); | ||||
|             View::share('mainTitleIcon', 'fa-sort-amount-asc'); | ||||
|         } | ||||
|  | ||||
|         return View::make('piggybanks.delete')->with('piggybank', $piggyBank); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Piggybank $piggyBank | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function destroy(Piggybank $piggyBank) | ||||
|     { | ||||
|         Event::fire('piggybanks.destroy', [$piggyBank]); | ||||
|         if ($piggyBank->repeats == 1) { | ||||
|             $route   = 'piggybanks.index.repeated'; | ||||
|             $message = 'Repeated expense'; | ||||
|         } else { | ||||
|             $route   = 'piggybanks.index.piggybanks'; | ||||
|             $message = 'Piggybank'; | ||||
|         } | ||||
|         $this->_repository->destroy($piggyBank); | ||||
|  | ||||
|         Session::flash('success', $message . ' deleted.'); | ||||
|  | ||||
|         return Redirect::route($route); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Piggybank $piggyBank | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function edit(Piggybank $piggyBank) | ||||
|     { | ||||
|         /** @var \Firefly\Helper\Toolkit\Toolkit $toolkit */ | ||||
|         $toolkit = App::make('Firefly\Helper\Toolkit\Toolkit'); | ||||
|  | ||||
|         $list     = $this->_accounts->getActiveDefault(); | ||||
|         $accounts = $toolkit->makeSelectList($list); | ||||
|         $periods  = Config::get('firefly.piggybank_periods'); | ||||
|  | ||||
|  | ||||
|         View::share('subTitle', 'Edit "' . $piggyBank->name . '"'); | ||||
|  | ||||
|  | ||||
|         if ($piggyBank->repeats == 1) { | ||||
|             View::share('title', 'Repeated expenses'); | ||||
|             View::share('mainTitleIcon', 'fa-rotate-left'); | ||||
|  | ||||
|             return View::make('piggybanks.edit-repeated')->with('piggybank', $piggyBank)->with('accounts', $accounts) | ||||
|                 ->with('periods', $periods); | ||||
|         } else { | ||||
|             // piggy bank. | ||||
|             View::share('title', 'Piggy banks'); | ||||
|             View::share('mainTitleIcon', 'fa-sort-amount-asc'); | ||||
|  | ||||
|             return View::make('piggybanks.edit-piggybank')->with('piggybank', $piggyBank)->with('accounts', $accounts) | ||||
|                 ->with('periods', $periods); | ||||
|         } | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Piggybank $piggyBank | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      * @throws Firefly\Exception\FireflyException | ||||
|      */ | ||||
|     public function modMoney(Piggybank $piggyBank) | ||||
|     { | ||||
|         $amount = floatval(Input::get('amount')); | ||||
|         switch (Input::get('what')) { | ||||
|             default: | ||||
|                 throw new FireflyException('No such action'); | ||||
|                 break; | ||||
|             case 'add': | ||||
|                 $maxAdd = $this->_repository->leftOnAccount($piggyBank->account); | ||||
|                 if (round($amount, 2) <= round(min($maxAdd, $piggyBank->targetamount), 2)) { | ||||
|                     Session::flash('success', 'Amount updated!'); | ||||
|                     $this->_repository->modifyAmount($piggyBank, $amount); | ||||
|                     Event::fire('piggybanks.modifyAmountAdd', [$piggyBank, $amount]); | ||||
|                 } else { | ||||
|                     Session::flash('warning', 'Could not!'); | ||||
|                 } | ||||
|                 break; | ||||
|             case 'remove': | ||||
|                 $rep       = $piggyBank->currentRelevantRep(); | ||||
|                 $maxRemove = $rep->currentamount; | ||||
|                 if (round($amount, 2) <= round($maxRemove, 2)) { | ||||
|                     Session::flash('success', 'Amount updated!'); | ||||
|                     $this->_repository->modifyAmount($piggyBank, ($amount * -1)); | ||||
|                     Event::fire('piggybanks.modifyAmountRemove', [$piggyBank, ($amount * -1)]); | ||||
|                 } else { | ||||
|                     Session::flash('warning', 'Could not!'); | ||||
|                 } | ||||
|                 break; | ||||
|         } | ||||
|         if($piggyBank->repeats == 1) { | ||||
|             $route   = 'piggybanks.index.repeated'; | ||||
|  | ||||
|         } else { | ||||
|             $route   = 'piggybanks.index.piggybanks'; | ||||
|         } | ||||
|         return Redirect::route($route); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function piggybanks() | ||||
|     { | ||||
|         $countRepeating    = $this->_repository->countRepeating(); | ||||
|         $countNonRepeating = $this->_repository->countNonrepeating(); | ||||
|  | ||||
|         $piggybanks = $this->_repository->get(); | ||||
|  | ||||
|         // get the accounts with each piggy bank and check their balance; Fireflyy might needs to | ||||
|         // show the user a correction. | ||||
|  | ||||
|         $accounts = []; | ||||
|         /** @var \Piggybank $piggybank */ | ||||
|         foreach ($piggybanks as $piggybank) { | ||||
|             $account = $piggybank->account; | ||||
|             $id      = $account->id; | ||||
|             if (!isset($accounts[$id])) { | ||||
|                 $account->leftOnAccount = $this->_repository->leftOnAccount($account); | ||||
|                 $accounts[$id]          = ['account' => $account, 'left' => $this->_repository->leftOnAccount($account)]; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         View::share('title', 'Piggy banks'); | ||||
|         View::share('subTitle', 'Save for big expenses'); | ||||
|         View::share('mainTitleIcon', 'fa-sort-amount-asc'); | ||||
|  | ||||
|         return View::make('piggybanks.index')->with('piggybanks', $piggybanks) | ||||
|             ->with('countRepeating', $countRepeating) | ||||
|             ->with('countNonRepeating', $countNonRepeating) | ||||
|             ->with('accounts', $accounts); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Piggybank $piggyBank | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function removeMoney(Piggybank $piggyBank) | ||||
|     { | ||||
|         $what      = 'remove'; | ||||
|         $maxAdd    = $this->_repository->leftOnAccount($piggyBank->account); | ||||
|         $maxRemove = $piggyBank->currentRelevantRep()->currentamount; | ||||
|  | ||||
|         return View::make('piggybanks.modifyAmount')->with('what', $what)->with('maxAdd', $maxAdd)->with( | ||||
|             'maxRemove', $maxRemove | ||||
|         )->with('piggybank', $piggyBank); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function repeated() | ||||
|     { | ||||
|         $countRepeating    = $this->_repository->countRepeating(); | ||||
|         $countNonRepeating = $this->_repository->countNonrepeating(); | ||||
|  | ||||
|         $piggybanks = $this->_repository->get(); | ||||
|  | ||||
|         // get the accounts with each piggy bank and check their balance; Fireflyy might needs to | ||||
|         // show the user a correction. | ||||
|  | ||||
|         $accounts = []; | ||||
|         /** @var \Piggybank $piggybank */ | ||||
|         foreach ($piggybanks as $piggybank) { | ||||
|             $account = $piggybank->account; | ||||
|             $id      = $account->id; | ||||
|             if (!isset($accounts[$id])) { | ||||
|                 $account->leftOnAccount = $this->_repository->leftOnAccount($account); | ||||
|                 $accounts[$id]          = ['account' => $account, 'left' => $this->_repository->leftOnAccount($account)]; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         View::share('title', 'Repeated expenses'); | ||||
|         View::share('subTitle', 'Save for returning bills'); | ||||
|         View::share('mainTitleIcon', 'fa-rotate-left'); | ||||
|  | ||||
|  | ||||
|         return View::make('piggybanks.index')->with('piggybanks', $piggybanks) | ||||
|             ->with('countRepeating', $countRepeating) | ||||
|             ->with('countNonRepeating', $countNonRepeating) | ||||
|             ->with('accounts', $accounts); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function show(Piggybank $piggyBank) | ||||
|     public function add(PiggyBank $piggyBank) | ||||
|     { | ||||
|         $leftOnAccount = $this->_repository->leftOnAccount($piggyBank->account); | ||||
|         $balance       = $piggyBank->account->balance(); | ||||
|         $savedSoFar    = $piggyBank->currentRelevantRep()->currentamount; | ||||
|         $leftToSave    = $piggyBank->targetamount - $savedSoFar; | ||||
|         $maxAmount     = min($leftOnAccount, $leftToSave); | ||||
|  | ||||
|         View::share('subTitle', $piggyBank->name); | ||||
|  | ||||
|         if ($piggyBank->repeats == 1) { | ||||
|             // repeated expense. | ||||
|             View::share('title', 'Repeated expenses'); | ||||
|             View::share('mainTitleIcon', 'fa-rotate-left'); | ||||
|         } else { | ||||
|             // piggy bank. | ||||
|             View::share('title', 'Piggy banks'); | ||||
|             View::share('mainTitleIcon', 'fa-sort-amount-asc'); | ||||
|         } | ||||
|         \Log::debug('Now going to view for piggy bank #' . $piggyBank->id . ' (' . $piggyBank->name . ')'); | ||||
|  | ||||
|         return View::make('piggybanks.show')->with('piggyBank', $piggyBank)->with('leftOnAccount', $leftOnAccount) | ||||
|             ->with('balance', $balance); | ||||
|         return View::make('piggy_banks.add', compact('piggyBank', 'maxAmount')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this|\Illuminate\Http\RedirectResponse | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function storePiggybank() | ||||
|     { | ||||
|         $data = Input::all(); | ||||
|         unset($data['_token']); | ||||
|  | ||||
|         // extend the data array with the settings needed to create a piggy bank: | ||||
|         $data['repeats']   = 0; | ||||
|         $data['rep_times'] = 1; | ||||
|         $data['rep_every'] = 1; | ||||
|         $data['order']     = 0; | ||||
|  | ||||
|         $piggyBank = $this->_repository->store($data); | ||||
|         if (!is_null($piggyBank->id)) { | ||||
|             Session::flash('success', 'New piggy bank "' . $piggyBank->name . '" created!'); | ||||
|             Event::fire('piggybanks.store', [$piggyBank]); | ||||
|  | ||||
|             return Redirect::route('piggybanks.index.piggybanks'); | ||||
|  | ||||
|  | ||||
|         } else { | ||||
|             Session::flash('error', 'Could not save piggy bank: ' . $piggyBank->errors()->first()); | ||||
|  | ||||
|             return Redirect::route('piggybanks.create.piggybank')->withInput()->withErrors($piggyBank->errors()); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this|\Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function storeRepeated() | ||||
|     public function create() | ||||
|     { | ||||
|  | ||||
|         $data = Input::all(); | ||||
|         unset($data['_token']); | ||||
|         /** @var \FireflyIII\Database\Account\Account $acct */ | ||||
|         $acct = App::make('FireflyIII\Database\Account\Account'); | ||||
|  | ||||
|         // extend the data array with the settings needed to create a repeated: | ||||
|         $data['repeats'] = 1; | ||||
|         $data['order']   = 0; | ||||
|  | ||||
|         $piggyBank = $this->_repository->store($data); | ||||
|         if ($piggyBank->id) { | ||||
|             Session::flash('success', 'New piggy bank "' . $piggyBank->name . '" created!'); | ||||
|             Event::fire('piggybanks.store', [$piggyBank]); | ||||
|             return Redirect::route('piggybanks.index.repeated'); | ||||
|  | ||||
|         } else { | ||||
|             Session::flash('error', 'Could not save piggy bank: ' . $piggyBank->errors()->first()); | ||||
|  | ||||
|             return Redirect::route('piggybanks.create.repeated')->withInput()->withErrors($piggyBank->errors()); | ||||
|         } | ||||
|         $periods      = Config::get('firefly.piggy_bank_periods'); | ||||
|         $accounts     = FFForm::makeSelectList($acct->getAssetAccounts()); | ||||
|         $subTitle     = 'Create new piggy bank'; | ||||
|         $subTitleIcon = 'fa-plus'; | ||||
|  | ||||
|         return View::make('piggy_banks.create', compact('accounts', 'periods', 'subTitle', 'subTitleIcon')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Piggybank $piggyBank | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return $this|\Illuminate\Http\RedirectResponse | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function update(Piggybank $piggyBank) | ||||
|     public function delete(PiggyBank $piggyBank) | ||||
|     { | ||||
|         $piggyBank = $this->_repository->update($piggyBank, Input::all()); | ||||
|         if ($piggyBank->validate()) { | ||||
|             if ($piggyBank->repeats == 1) { | ||||
|                 $route   = 'piggybanks.index.repeated'; | ||||
|                 $message = 'Repeated expense'; | ||||
|             } else { | ||||
|                 $route   = 'piggybanks.index.piggybanks'; | ||||
|                 $message = 'Piggy bank'; | ||||
|             } | ||||
|         $subTitle = 'Delete "' . e($piggyBank->name) . '"'; | ||||
|  | ||||
|         return View::make('piggy_banks.delete', compact('piggyBank', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|             Session::flash('success', $message . ' "' . $piggyBank->name . '" updated.'); | ||||
|             Event::fire('piggybanks.update', [$piggyBank]); | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function destroy(PiggyBank $piggyBank) | ||||
|     { | ||||
|  | ||||
|             return Redirect::route($route); | ||||
|         Session::flash('success', 'Piggy bank "' . e($piggyBank->name) . '" deleted.'); | ||||
|         $this->_repository->destroy($piggyBank); | ||||
|  | ||||
|         return Redirect::route('piggy_banks.index'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function edit(PiggyBank $piggyBank) | ||||
|     { | ||||
|  | ||||
|         /** @var \FireflyIII\Database\Account\Account $acct */ | ||||
|         $acct = App::make('FireflyIII\Database\Account\Account'); | ||||
|  | ||||
|         $periods      = Config::get('firefly.piggy_bank_periods'); | ||||
|         $accounts     = FFForm::makeSelectList($acct->getAssetAccounts()); | ||||
|         $subTitle     = 'Edit piggy bank "' . e($piggyBank->name) . '"'; | ||||
|         $subTitleIcon = 'fa-pencil'; | ||||
|  | ||||
|         /* | ||||
|          * Flash some data to fill the form. | ||||
|          */ | ||||
|         if (is_null($piggyBank->targetdate) || $piggyBank->targetdate == '') { | ||||
|             $targetDate = null; | ||||
|         } else { | ||||
|             Session::flash('error', 'Could not update piggy bank: ' . $piggyBank->errors()->first()); | ||||
|             $targetDate = new Carbon($piggyBank->targetdate); | ||||
|             $targetDate = $targetDate->format('Y-m-d'); | ||||
|         } | ||||
|         $preFilled = ['name'         => $piggyBank->name, | ||||
|                       'account_id'   => $piggyBank->account_id, | ||||
|                       'targetamount' => $piggyBank->targetamount, | ||||
|                       'targetdate'   => $targetDate, | ||||
|                       'reminder'     => $piggyBank->reminder, | ||||
|                       'remind_me'    => intval($piggyBank->remind_me) == 1 || !is_null($piggyBank->reminder) ? true : false | ||||
|         ]; | ||||
|         Session::flash('preFilled', $preFilled); | ||||
|  | ||||
|             return Redirect::route('piggybanks.edit', $piggyBank->id)->withErrors($piggyBank->errors())->withInput(); | ||||
|         return View::make('piggy_banks.edit', compact('subTitle', 'subTitleIcon', 'piggyBank', 'accounts', 'periods', 'preFilled')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         /** @var Collection $piggyBanks */ | ||||
|         $piggyBanks = $this->_repository->get(); | ||||
|  | ||||
|         $accounts = []; | ||||
|         /** @var PiggyBank $piggyBank */ | ||||
|         foreach ($piggyBanks as $piggyBank) { | ||||
|             $piggyBank->savedSoFar = floatval($piggyBank->currentRelevantRep()->currentamount); | ||||
|             $piggyBank->percentage = intval($piggyBank->savedSoFar / $piggyBank->targetamount * 100); | ||||
|             $piggyBank->leftToSave = $piggyBank->targetamount - $piggyBank->savedSoFar; | ||||
|  | ||||
|             /* | ||||
|              * Fill account information: | ||||
|              */ | ||||
|             $account = $piggyBank->account; | ||||
|             if (!isset($accounts[$account->id])) { | ||||
|                 $accounts[$account->id] = [ | ||||
|                     'name'              => $account->name, | ||||
|                     'balance'           => Steam::balance($account), | ||||
|                     'leftForPiggyBanks' => $this->_repository->leftOnAccount($account), | ||||
|                     'sumOfSaved'        => $piggyBank->savedSoFar, | ||||
|                     'sumOfTargets'      => floatval($piggyBank->targetamount), | ||||
|                     'leftToSave'        => $piggyBank->leftToSave | ||||
|                 ]; | ||||
|             } else { | ||||
|                 $accounts[$account->id]['sumOfSaved'] += $piggyBank->savedSoFar; | ||||
|                 $accounts[$account->id]['sumOfTargets'] += floatval($piggyBank->targetamount); | ||||
|                 $accounts[$account->id]['leftToSave'] += $piggyBank->leftToSave; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return View::make('piggy_banks.index', compact('piggyBanks', 'accounts')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * POST add money to piggy bank | ||||
|      * | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function postAdd(PiggyBank $piggyBank) | ||||
|     { | ||||
|         $amount = round(floatval(Input::get('amount')), 2); | ||||
|  | ||||
|         /** @var \FireflyIII\Database\PiggyBank\PiggyBank $acct */ | ||||
|         $piggyRepository = App::make('FireflyIII\Database\PiggyBank\PiggyBank'); | ||||
|  | ||||
|         $leftOnAccount = $piggyRepository->leftOnAccount($piggyBank->account); | ||||
|         $savedSoFar    = $piggyBank->currentRelevantRep()->currentamount; | ||||
|         $leftToSave    = $piggyBank->targetamount - $savedSoFar; | ||||
|         $maxAmount     = round(min($leftOnAccount, $leftToSave), 2); | ||||
|  | ||||
|         if ($amount <= $maxAmount) { | ||||
|             $repetition = $piggyBank->currentRelevantRep(); | ||||
|             $repetition->currentamount += $amount; | ||||
|             $repetition->save(); | ||||
|  | ||||
|             /* | ||||
|              * Create event! | ||||
|              */ | ||||
|             Event::fire('piggy_bank.addMoney', [$piggyBank, $amount]); // new and used. | ||||
|  | ||||
|             Session::flash('success', 'Added ' . Amount::format($amount, false) . ' to "' . e($piggyBank->name) . '".'); | ||||
|         } else { | ||||
|             Session::flash('error', 'Could not add ' . Amount::format($amount, false) . ' to "' . e($piggyBank->name) . '".'); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('piggy_banks.index'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function postRemove(PiggyBank $piggyBank) | ||||
|     { | ||||
|         $amount = floatval(Input::get('amount')); | ||||
|  | ||||
|         $savedSoFar = $piggyBank->currentRelevantRep()->currentamount; | ||||
|  | ||||
|         if ($amount <= $savedSoFar) { | ||||
|             $repetition = $piggyBank->currentRelevantRep(); | ||||
|             $repetition->currentamount -= $amount; | ||||
|             $repetition->save(); | ||||
|  | ||||
|             /* | ||||
|              * Create event! | ||||
|              */ | ||||
|             Event::fire('piggy_bank.removeMoney', [$piggyBank, $amount]); // new and used. | ||||
|  | ||||
|             Session::flash('success', 'Removed ' . Amount::format($amount, false) . ' from "' . e($piggyBank->name) . '".'); | ||||
|         } else { | ||||
|             Session::flash('error', 'Could not remove ' . Amount::format($amount, false) . ' from "' . e($piggyBank->name) . '".'); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('piggy_banks.index'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @SuppressWarnings("Unused") | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function remove(PiggyBank $piggyBank) | ||||
|     { | ||||
|         return View::make('piggy_banks.remove', compact('piggyBank')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function show(PiggyBank $piggyBank) | ||||
|     { | ||||
|  | ||||
|         $events = $piggyBank->piggyBankEvents()->orderBy('date', 'DESC')->orderBy('id', 'DESC')->get(); | ||||
|  | ||||
|         /* | ||||
|          * Number of reminders: | ||||
|          */ | ||||
|  | ||||
|         $subTitle = e($piggyBank->name); | ||||
|  | ||||
|         return View::make('piggy_banks.show', compact('piggyBank', 'events', 'subTitle')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function store() | ||||
|     { | ||||
|         $data                  = Input::all(); | ||||
|         $data['repeats']       = 0; | ||||
|         $data['user_id']       = Auth::user()->id; | ||||
|         $data['rep_every']     = 0; | ||||
|         $data['reminder_skip'] = 0; | ||||
|         $data['remind_me']     = intval(Input::get('remind_me')); | ||||
|         $data['order']         = 0; | ||||
|  | ||||
|  | ||||
|         // always validate: | ||||
|         $messages = $this->_repository->validate($data); | ||||
|  | ||||
|         // flash messages: | ||||
|         Session::flash('warnings', $messages['warnings']); | ||||
|         Session::flash('successes', $messages['successes']); | ||||
|         Session::flash('errors', $messages['errors']); | ||||
|         if ($messages['errors']->count() > 0) { | ||||
|             Session::flash('error', 'Could not store piggy bank: ' . $messages['errors']->first()); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         // return to create screen: | ||||
|         if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { | ||||
|             return Redirect::route('piggy_banks.create')->withInput(); | ||||
|         } | ||||
|  | ||||
|         // store | ||||
|         $piggyBank = $this->_repository->store($data); | ||||
|         Event::fire('piggy_bank.store', [$piggyBank]); // new and used. | ||||
|         Session::flash('success', 'Piggy bank "' . e($data['name']) . '" stored.'); | ||||
|         if ($data['post_submit_action'] == 'store') { | ||||
|             return Redirect::route('piggy_banks.index'); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('piggy_banks.create')->withInput(); | ||||
|     } | ||||
| } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return $this | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function update(PiggyBank $piggyBank) | ||||
|     { | ||||
|  | ||||
|         $data                  = Input::except('_token'); | ||||
|         $data['rep_every']     = 0; | ||||
|         $data['reminder_skip'] = 0; | ||||
|         $data['order']         = 0; | ||||
|         $data['remind_me']     = isset($data['remind_me']) ? 1 : 0; | ||||
|         $data['user_id']       = Auth::user()->id; | ||||
|         $data['repeats']       = 0; | ||||
|  | ||||
|         // always validate: | ||||
|         $messages = $this->_repository->validate($data); | ||||
|  | ||||
|         Session::flash('warnings', $messages['warnings']); | ||||
|         Session::flash('successes', $messages['successes']); | ||||
|         Session::flash('errors', $messages['errors']); | ||||
|         if ($messages['errors']->count() > 0) { | ||||
|             Session::flash('error', 'Could not update piggy bank: ' . $messages['errors']->first()); | ||||
|         } | ||||
|  | ||||
|         // return to update screen: | ||||
|         if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { | ||||
|             return Redirect::route('piggy_banks.edit', $piggyBank->id)->withInput(); | ||||
|         } | ||||
|  | ||||
|         // update | ||||
|         $this->_repository->update($piggyBank, $data); | ||||
|         Session::flash('success', 'Piggy bank "' . e($data['name']) . '" updated.'); | ||||
|  | ||||
|         // go back to list | ||||
|         if ($data['post_submit_action'] == 'update') { | ||||
|             return Redirect::route('piggy_banks.index'); | ||||
|         } | ||||
|  | ||||
|         // go back to update screen. | ||||
|         return Redirect::route('piggy_banks.edit', $piggyBank->id)->withInput(['post_submit_action' => 'return_to_edit']); | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,29 +1,21 @@ | ||||
| <?php | ||||
|  | ||||
| use Firefly\Helper\Preferences\PreferencesHelperInterface as PHI; | ||||
| use Firefly\Storage\Account\AccountRepositoryInterface as ARI; | ||||
|  | ||||
| /** | ||||
|  * Class PreferencesController | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CamelCasePropertyName) | ||||
|  * @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok. | ||||
|  * | ||||
|  */ | ||||
| class PreferencesController extends BaseController | ||||
| { | ||||
|     protected $_accounts; | ||||
|     protected $_preferences; | ||||
|  | ||||
|     /** | ||||
|      * @param ARI $accounts | ||||
|      * @param PHI $preferences | ||||
|      * | ||||
|      */ | ||||
|     public function __construct(ARI $accounts, PHI $preferences) | ||||
|     public function __construct() | ||||
|     { | ||||
|  | ||||
|         $this->_accounts    = $accounts; | ||||
|         $this->_preferences = $preferences; | ||||
|         View::share('title','Preferences'); | ||||
|         View::share('mainTitleIcon','fa-gear'); | ||||
|         View::share('title', 'Preferences'); | ||||
|         View::share('mainTitleIcon', 'fa-gear'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -31,16 +23,22 @@ class PreferencesController extends BaseController | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         $accounts = $this->_accounts->getDefault(); | ||||
|         /** @var \FireflyIII\Database\Account\Account $acct */ | ||||
|         $acct = App::make('FireflyIII\Database\Account\Account'); | ||||
|  | ||||
|         $viewRange      = $this->_preferences->get('viewRange', '1M'); | ||||
|         /** @var \FireflyIII\Shared\Preferences\Preferences $preferences */ | ||||
|         $preferences = App::make('FireflyIII\Shared\Preferences\Preferences'); | ||||
|  | ||||
|         $accounts       = $acct->getAssetAccounts(); | ||||
|         $viewRange      = $preferences->get('viewRange', '1M'); | ||||
|         $viewRangeValue = $viewRange->data; | ||||
|         $frontPage      = $preferences->get('frontPageAccounts', []); | ||||
|         $budgetMax      = $preferences->get('budgetMaximum', 1000); | ||||
|         $budgetMaximum  = $budgetMax->data; | ||||
|  | ||||
|         // pref: | ||||
|         $frontpage = $this->_preferences->get('frontpageAccounts', []); | ||||
|  | ||||
|         return View::make('preferences.index')->with('accounts', $accounts)->with('frontpageAccounts', $frontpage) | ||||
|             ->with('viewRange', $viewRangeValue); | ||||
|         return View::make('preferences.index', compact('budgetMaximum'))->with('accounts', $accounts)->with('frontPageAccounts', $frontPage)->with( | ||||
|             'viewRange', $viewRangeValue | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -48,24 +46,31 @@ class PreferencesController extends BaseController | ||||
|      */ | ||||
|     public function postIndex() | ||||
|     { | ||||
|         /** @var \FireflyIII\Shared\Preferences\Preferences $preferences */ | ||||
|         $preferences = App::make('FireflyIII\Shared\Preferences\Preferences'); | ||||
|  | ||||
|         // frontpage accounts | ||||
|         $frontpageAccounts = []; | ||||
|         foreach (Input::get('frontpageAccounts') as $id) { | ||||
|             $frontpageAccounts[] = intval($id); | ||||
|         // front page accounts | ||||
|         $frontPageAccounts = []; | ||||
|         foreach (Input::get('frontPageAccounts') as $id) { | ||||
|             $frontPageAccounts[] = intval($id); | ||||
|         } | ||||
|         $this->_preferences->set('frontpageAccounts', $frontpageAccounts); | ||||
|         $preferences->set('frontPageAccounts', $frontPageAccounts); | ||||
|  | ||||
|         // view range: | ||||
|         $this->_preferences->set('viewRange', Input::get('viewRange')); | ||||
|         $preferences->set('viewRange', Input::get('viewRange')); | ||||
|         // forget session values: | ||||
|         Session::forget('start'); | ||||
|         Session::forget('end'); | ||||
|         Session::forget('range'); | ||||
|  | ||||
|         // budget maximum: | ||||
|         $budgetMaximum = intval(Input::get('budgetMaximum')); | ||||
|         $preferences->set('budgetMaximum', $budgetMaximum); | ||||
|  | ||||
|  | ||||
|         Session::flash('success', 'Preferences saved!'); | ||||
|  | ||||
|         return Redirect::route('preferences'); | ||||
|     } | ||||
|  | ||||
| }  | ||||
| }  | ||||
|   | ||||
| @@ -1,19 +1,21 @@ | ||||
| <?php | ||||
|  | ||||
| use Firefly\Storage\User\UserRepositoryInterface as URI; | ||||
|  | ||||
| /** | ||||
|  * @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok. | ||||
|  * | ||||
|  * Class ProfileController | ||||
|  */ | ||||
| class ProfileController extends BaseController | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param URI $user | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function __construct(URI $user) | ||||
|     public function changePassword() | ||||
|     { | ||||
|         $this->user = $user; | ||||
|         return View::make('profile.change-password')->with('title', Auth::user()->email)->with('subTitle', 'Change your password')->with( | ||||
|             'mainTitleIcon', 'fa-user' | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -22,21 +24,7 @@ class ProfileController extends BaseController | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         View::share('title','Profile'); | ||||
|         View::share('subTitle',Auth::user()->email); | ||||
|         View::share('mainTitleIcon','fa-user'); | ||||
|         return View::make('profile.index'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function changePassword() | ||||
|     { | ||||
|         View::share('title',Auth::user()->email); | ||||
|         View::share('subTitle','Change your password'); | ||||
|         View::share('mainTitleIcon','fa-user'); | ||||
|         return View::make('profile.change-password'); | ||||
|         return View::make('profile.index')->with('title', 'Profile')->with('subTitle', Auth::user()->email)->with('mainTitleIcon', 'fa-user'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -46,7 +34,6 @@ class ProfileController extends BaseController | ||||
|     { | ||||
|  | ||||
|         // old, new1, new2 | ||||
|         /** @noinspection PhpUndefinedFieldInspection */ | ||||
|         if (!Hash::check(Input::get('old'), Auth::user()->password)) { | ||||
|             Session::flash('error', 'Invalid current password!'); | ||||
|  | ||||
| @@ -70,12 +57,13 @@ class ProfileController extends BaseController | ||||
|         } | ||||
|  | ||||
|         // update the user with the new password. | ||||
|         /** @noinspection PhpParamsInspection */ | ||||
|         $this->user->updatePassword(Auth::user(), Input::get('new1')); | ||||
|         /** @var \FireflyIII\Database\User\User $repository */ | ||||
|         $repository = \App::make('FireflyIII\Database\User\User'); | ||||
|         $repository->updatePassword(Auth::user(), Input::get('new1')); | ||||
|  | ||||
|         Session::flash('success', 'Password changed!'); | ||||
|  | ||||
|         return Redirect::route('profile'); | ||||
|     } | ||||
|  | ||||
| }  | ||||
| }  | ||||
|   | ||||
| @@ -1,213 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| use Firefly\Exception\FireflyException; | ||||
| use Firefly\Storage\RecurringTransaction\RecurringTransactionRepositoryInterface as RTR; | ||||
| use Firefly\Helper\Controllers\RecurringInterface as RI; | ||||
|  | ||||
| /** | ||||
|  * Class RecurringController | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CamelCasePropertyName) | ||||
|  */ | ||||
| class RecurringController extends BaseController | ||||
| { | ||||
|     protected $_repository; | ||||
|     protected $_helper; | ||||
|  | ||||
|     /** | ||||
|      * @param RTR $repository | ||||
|      * @param RI $helper | ||||
|      */ | ||||
|     public function __construct(RTR $repository, RI $helper) | ||||
|     { | ||||
|         $this->_repository = $repository; | ||||
|         $this->_helper = $helper; | ||||
|  | ||||
|         View::share('title', 'Recurring transactions'); | ||||
|         View::share('mainTitleIcon', 'fa-rotate-right'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function create() | ||||
|     { | ||||
|         View::share('subTitle', 'Create new'); | ||||
|         $periods = \Config::get('firefly.periods_to_text'); | ||||
|  | ||||
|         return View::make('recurring.create')->with('periods', $periods); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param RecurringTransaction $recurringTransaction | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function delete(RecurringTransaction $recurringTransaction) | ||||
|     { | ||||
|         View::share('subTitle', 'Delete "' . $recurringTransaction->name . '"'); | ||||
|         return View::make('recurring.delete')->with('recurringTransaction', $recurringTransaction); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param RecurringTransaction $recurringTransaction | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function destroy(RecurringTransaction $recurringTransaction) | ||||
|     { | ||||
|         //Event::fire('recurring.destroy', [$recurringTransaction]); | ||||
|         $result = $this->_repository->destroy($recurringTransaction); | ||||
|         if ($result === true) { | ||||
|             Session::flash('success', 'The recurring transaction was deleted.'); | ||||
|         } else { | ||||
|             Session::flash('error', 'Could not delete the recurring transaction. Check the logs to be sure.'); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('recurring.index'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param RecurringTransaction $recurringTransaction | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function edit(RecurringTransaction $recurringTransaction) | ||||
|     { | ||||
|         $periods = \Config::get('firefly.periods_to_text'); | ||||
|  | ||||
|         View::share('subTitle', 'Edit "' . $recurringTransaction->name . '"'); | ||||
|  | ||||
|         return View::make('recurring.edit')->with('periods', $periods)->with( | ||||
|             'recurringTransaction', $recurringTransaction | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         return View::make('recurring.index'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function show(RecurringTransaction $recurringTransaction) | ||||
|     { | ||||
|         View::share('subTitle', $recurringTransaction->name); | ||||
|         return View::make('recurring.show')->with('recurring', $recurringTransaction); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public function store() | ||||
|     { | ||||
|         $data = Input::except(['_token', 'post_submit_action']); | ||||
|         switch (Input::get('post_submit_action')) { | ||||
|             default: | ||||
|                 throw new FireflyException('Method ' . Input::get('post_submit_action') . ' not implemented yet.'); | ||||
|                 break; | ||||
|             case 'store': | ||||
|             case 'create_another': | ||||
|                 /* | ||||
|                  * Try to store: | ||||
|                  */ | ||||
|                 $messageBag = $this->_repository->store($data); | ||||
|  | ||||
|                 /* | ||||
|                  * Failure! | ||||
|                  */ | ||||
|                 if ($messageBag->count() > 0) { | ||||
|                     Session::flash('error', 'Could not save recurring transaction: ' . $messageBag->first()); | ||||
|                     return Redirect::route('recurring.create')->withInput()->withErrors($messageBag); | ||||
|                 } | ||||
|  | ||||
|                 /* | ||||
|                  * Success! | ||||
|                  */ | ||||
|                 Session::flash('success', 'Recurring transaction "' . e(Input::get('name')) . '" saved!'); | ||||
|  | ||||
|                 /* | ||||
|                  * Redirect to original location or back to the form. | ||||
|                  */ | ||||
|                 if (Input::get('post_submit_action') == 'create_another') { | ||||
|                     return Redirect::route('recurring.create')->withInput(); | ||||
|                 } else { | ||||
|                     return Redirect::route('recurring.index'); | ||||
|                 } | ||||
|                 break; | ||||
|             case 'validate_only': | ||||
|                 $messageBags = $this->_helper->validate($data); | ||||
|  | ||||
|                 Session::flash('warnings', $messageBags['warnings']); | ||||
|                 Session::flash('successes', $messageBags['successes']); | ||||
|                 Session::flash('errors', $messageBags['errors']); | ||||
|                 return Redirect::route('recurring.create')->withInput(); | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public function update(RecurringTransaction $recurringTransaction) | ||||
|     { | ||||
|         $data = Input::except(['_token', 'post_submit_action']); | ||||
|         switch (Input::get('post_submit_action')) { | ||||
|             case 'update': | ||||
|             case 'return_to_edit': | ||||
|                 $messageBag = $this->_repository->update($recurringTransaction, $data); | ||||
|                 if ($messageBag->count() == 0) { | ||||
|                     // has been saved, return to index: | ||||
|                     Session::flash('success', 'Recurring transaction updated!'); | ||||
|  | ||||
|                     if (Input::get('post_submit_action') == 'return_to_edit') { | ||||
|                         return Redirect::route('recurring.edit', $recurringTransaction->id)->withInput(); | ||||
|                     } else { | ||||
|                         return Redirect::route('recurring.index'); | ||||
|                     } | ||||
|                 } else { | ||||
|                     Session::flash('error', 'Could not update recurring transaction: ' . $messageBag->first()); | ||||
|  | ||||
|                     return Redirect::route('transactions.edit', $recurringTransaction->id)->withInput() | ||||
|                         ->withErrors($messageBag); | ||||
|                 } | ||||
|  | ||||
|  | ||||
|                 break; | ||||
|             case 'validate_only': | ||||
|                 $data = Input::all(); | ||||
|                 $data['id'] = $recurringTransaction->id; | ||||
|                 $messageBags = $this->_helper->validate($data); | ||||
|  | ||||
|                 Session::flash('warnings', $messageBags['warnings']); | ||||
|                 Session::flash('successes', $messageBags['successes']); | ||||
|                 Session::flash('errors', $messageBags['errors']); | ||||
|                 return Redirect::route('recurring.edit', $recurringTransaction->id)->withInput(); | ||||
|  | ||||
|                 break; | ||||
|             // update | ||||
|             default: | ||||
|                 throw new FireflyException('Method ' . Input::get('post_submit_action') . ' not implemented yet.'); | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|  | ||||
| //        /** @var \RecurringTransaction $recurringTransaction */ | ||||
| //        $recurringTransaction = $this->_repository->update($recurringTransaction, Input::all()); | ||||
| //        if ($recurringTransaction->errors()->count() == 0) { | ||||
| //            Session::flash('success', 'The recurring transaction has been updated.'); | ||||
| //            //Event::fire('recurring.update', [$recurringTransaction]); | ||||
| // | ||||
| //            return Redirect::route('recurring.index'); | ||||
| //        } else { | ||||
| //            Session::flash( | ||||
| //                'error', 'Could not update the recurring transaction: ' . $recurringTransaction->errors()->first() | ||||
| //            ); | ||||
| // | ||||
| //            return Redirect::route('recurring.edit', $recurringTransaction->id)->withInput()->withErrors( | ||||
| //                $recurringTransaction->errors() | ||||
| //            ); | ||||
| //        } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										139
									
								
								app/controllers/RelatedController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								app/controllers/RelatedController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,139 @@ | ||||
| <?php | ||||
| use FireflyIII\Helper\Related\RelatedInterface; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class RelatedController | ||||
|  */ | ||||
| class RelatedController extends BaseController | ||||
| { | ||||
|  | ||||
|     protected $_repository; | ||||
|  | ||||
|     public function __construct(RelatedInterface $repository) | ||||
|     { | ||||
|         $this->_repository = $repository; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function alreadyRelated(TransactionJournal $journal) | ||||
|     { | ||||
|         $ids = []; | ||||
|         /** @var TransactionGroup $group */ | ||||
|         foreach ($journal->transactiongroups()->get() as $group) { | ||||
|             /** @var TransactionJournal $loopJournal */ | ||||
|             foreach ($group->transactionjournals()->get() as $loopJournal) { | ||||
|                 if ($loopJournal->id != $journal->id) { | ||||
|                     $ids[] = $loopJournal->id; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         $unique = array_unique($ids); | ||||
|         if (count($unique) > 0) { | ||||
|  | ||||
|             $set = $this->_repository->getJournalsByIds($unique); | ||||
|             $set->each( | ||||
|                 function (TransactionJournal $journal) { | ||||
|                     $journal->amount = Amount::format($journal->getAmount()); | ||||
|                 } | ||||
|             ); | ||||
|  | ||||
|             return Response::json($set->toArray()); | ||||
|         } else { | ||||
|             return Response::json((new Collection)->toArray()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $parentJournal | ||||
|      * @param TransactionJournal $childJournal | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function relate(TransactionJournal $parentJournal, TransactionJournal $childJournal) | ||||
|     { | ||||
|         $group           = new TransactionGroup; | ||||
|         $group->relation = 'balance'; | ||||
|         $group->user_id  = $this->_repository->getUser()->id; | ||||
|         $group->save(); | ||||
|         $group->transactionjournals()->save($parentJournal); | ||||
|         $group->transactionjournals()->save($childJournal); | ||||
|  | ||||
|         return Response::json(true); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function related(TransactionJournal $journal) | ||||
|     { | ||||
|         $groups  = $journal->transactiongroups()->get(); | ||||
|         $members = new Collection; | ||||
|         /** @var TransactionGroup $group */ | ||||
|         foreach ($groups as $group) { | ||||
|             /** @var TransactionJournal $loopJournal */ | ||||
|             foreach ($group->transactionjournals()->get() as $loopJournal) { | ||||
|                 if ($loopJournal->id != $journal->id) { | ||||
|                     $members->push($loopJournal); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return View::make('related.relate', compact('journal', 'members')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $parentJournal | ||||
|      * @param TransactionJournal $childJournal | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function removeRelation(TransactionJournal $parentJournal, TransactionJournal $childJournal) | ||||
|     { | ||||
|         $groups = $parentJournal->transactiongroups()->get(); | ||||
|         /** @var TransactionGroup $group */ | ||||
|         foreach ($groups as $group) { | ||||
|             foreach ($group->transactionjournals()->get() as $loopJournal) { | ||||
|                 if ($loopJournal->id == $childJournal->id) { | ||||
|                     // remove from group: | ||||
|                     $group->transactionjournals()->detach($childJournal); | ||||
|                 } | ||||
|             } | ||||
|             if ($group->transactionjournals()->count() == 1) { | ||||
|                 $group->delete(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return Response::json(true); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function search(TransactionJournal $journal) | ||||
|     { | ||||
|  | ||||
|         $search = e(trim(Input::get('searchValue'))); | ||||
|  | ||||
|         $result = $this->_repository->search($search, $journal); | ||||
|         $result->each( | ||||
|             function (TransactionJournal $j) { | ||||
|                 $j->amount = Amount::format($j->getAmount()); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return Response::json($result->toArray()); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -1,97 +1,93 @@ | ||||
| <?php | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Firefly\Storage\Reminder\ReminderRepositoryInterface as RRI; | ||||
| use FireflyIII\Exception\FireflyException; | ||||
|  | ||||
| /** | ||||
|  * Class ReminderController | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CamelCasePropertyName) | ||||
|  */ | ||||
| class ReminderController extends BaseController | ||||
| { | ||||
|  | ||||
|     protected $_repository; | ||||
|  | ||||
|     /** | ||||
|      * @param RRI $repository | ||||
|      * | ||||
|      */ | ||||
|     public function __construct(RRI $repository) | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->_repository = $repository; | ||||
|         View::share('title', 'Reminders'); | ||||
|         View::share('mainTitleIcon', 'fa-lightbulb-o'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Reminder $reminder | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function dismiss(\Reminder $reminder) | ||||
|     public function act(Reminder $reminder) | ||||
|     { | ||||
|         $reminder = $this->_repository->deactivate($reminder); | ||||
|  | ||||
|         return Response::json($reminder->id); | ||||
|     } | ||||
|         $class = get_class($reminder->remindersable); | ||||
|  | ||||
|     /** | ||||
|      * Returns the reminders currently active for the modal dialog. | ||||
|      */ | ||||
|     public function modalDialog() | ||||
|     { | ||||
|         $today     = new Carbon; | ||||
|         $reminders = $this->_repository->getPiggybankReminders(); | ||||
|  | ||||
|         /** @var \Reminder $reminder */ | ||||
|         foreach ($reminders as $index => $reminder) { | ||||
|             if (\Session::has('dismissal-' . $reminder->id)) { | ||||
|                 $time = \Session::get('dismissal-' . $reminder->id); | ||||
|                 if ($time >= $today) { | ||||
|                     unset($reminders[$index]); | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return View::make('reminders.popup')->with('reminders', $reminders); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Reminder $reminder | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function postpone(\Reminder $reminder) | ||||
|     { | ||||
|         $now = new Carbon; | ||||
|         $now->addDay(); | ||||
|         Session::put('dismissal-' . $reminder->id, $now); | ||||
|  | ||||
|         return Response::json($reminder->id); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Reminder $reminder | ||||
|      * | ||||
|      * @return $this|\Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function redirect(\Reminder $reminder) | ||||
|     { | ||||
|         if ($reminder instanceof PiggybankReminder) { | ||||
|             // fields to prefill: | ||||
|             $parameters = [ | ||||
|                 'account_to_id' => $reminder->piggybank->account->id, | ||||
|                 'amount'        => round($reminder->amountToSave(), 2), | ||||
|                 'description'   => 'Money for ' . $reminder->piggybank->name, | ||||
|                 'piggybank_id'  => $reminder->piggybank->id, | ||||
|                 'reminder_id'   => $reminder->id | ||||
|         if ($class == 'PiggyBank') { | ||||
|             $amount    = Reminders::amountForReminder($reminder); | ||||
|             $preFilled = [ | ||||
|                 'amount'        => round($amount, 2), | ||||
|                 'description'   => 'Money for ' . $reminder->remindersable->name, | ||||
|                 'piggy_bank_id' => $reminder->remindersable_id, | ||||
|                 'account_to_id' => $reminder->remindersable->account_id | ||||
|             ]; | ||||
|             Session::flash('preFilled', $preFilled); | ||||
|  | ||||
|             return Redirect::to( | ||||
|                 route('transactions.create', ['what' => 'transfer']) . '?' . http_build_query($parameters) | ||||
|             ); | ||||
|             return Redirect::route('transactions.create', 'transfer'); | ||||
|         } | ||||
|         return View::make('error')->with('message', 'No such reminder.'); | ||||
|  | ||||
|         return View::make('error')->with('message', 'This reminder has an invalid class connected to it.'); | ||||
|     } | ||||
|  | ||||
| }  | ||||
|     /** | ||||
|      * @param Reminder $reminder | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function dismiss(Reminder $reminder) | ||||
|     { | ||||
|         $reminder->active = 0; | ||||
|         $reminder->save(); | ||||
|         Session::flash('success', 'Reminder dismissed'); | ||||
|  | ||||
|         return Redirect::route('index'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Reminder $reminder | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function notNow(Reminder $reminder) | ||||
|     { | ||||
|         $reminder->active = 0; | ||||
|         $reminder->notnow = 1; | ||||
|         $reminder->save(); | ||||
|         Session::flash('success', 'Reminder dismissed'); | ||||
|  | ||||
|         return Redirect::route('index'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Reminder $reminder | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function show(Reminder $reminder) | ||||
|     { | ||||
|  | ||||
|         $amount = null; | ||||
|         if (get_class($reminder->remindersable) == 'PiggyBank') { | ||||
|  | ||||
|             $amount = Reminders::amountForReminder($reminder); | ||||
|         } | ||||
|  | ||||
|         return View::make('reminders.show', compact('reminder', 'amount')); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
							
								
								
									
										227
									
								
								app/controllers/RepeatedExpenseController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										227
									
								
								app/controllers/RepeatedExpenseController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,227 @@ | ||||
| <?php | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Database\PiggyBank\RepeatedExpense as Repository; | ||||
| use FireflyIII\Exception\FireflyException; | ||||
|  | ||||
| /** | ||||
|  * @SuppressWarnings("CamelCase") // I'm fine with this. | ||||
|  * @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok. | ||||
|  * @SuppressWarnings("CouplingBetweenObjects") // There's only so much I can remove. | ||||
|  * | ||||
|  * Class RepeatedExpenseController | ||||
|  */ | ||||
| class RepeatedExpenseController extends BaseController | ||||
| { | ||||
|     /** @var  Repository */ | ||||
|     protected $_repository; | ||||
|  | ||||
|     /** | ||||
|      * @param Repository $repository | ||||
|      */ | ||||
|     public function __construct(Repository $repository) | ||||
|     { | ||||
|         View::share('title', 'Repeated expenses'); | ||||
|         View::share('mainTitleIcon', 'fa-rotate-left'); | ||||
|         $this->_repository = $repository; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function create() | ||||
|     { | ||||
|         /** @var \FireflyIII\Database\Account\Account $acct */ | ||||
|         $acct     = App::make('FireflyIII\Database\Account\Account'); | ||||
|         $periods  = Config::get('firefly.piggy_bank_periods'); | ||||
|         $accounts = FFForm::makeSelectList($acct->getAssetAccounts()); | ||||
|  | ||||
|         return View::make('repeatedExpense.create', compact('accounts', 'periods'))->with('subTitle', 'Create new repeated expense')->with( | ||||
|             'subTitleIcon', 'fa-plus' | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $repeatedExpense | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function delete(PiggyBank $repeatedExpense) | ||||
|     { | ||||
|         $subTitle = 'Delete "' . e($repeatedExpense->name) . '"'; | ||||
|  | ||||
|         return View::make('repeatedExpense.delete', compact('repeatedExpense', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $repeatedExpense | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function destroy(PiggyBank $repeatedExpense) | ||||
|     { | ||||
|  | ||||
|         Session::flash('success', 'Repeated expense "' . e($repeatedExpense->name) . '" deleted.'); | ||||
|         $this->_repository->destroy($repeatedExpense); | ||||
|  | ||||
|         return Redirect::route('repeated.index'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $repeatedExpense | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function edit(PiggyBank $repeatedExpense) | ||||
|     { | ||||
|  | ||||
|         /** @var \FireflyIII\Database\Account\Account $acct */ | ||||
|         $acct = App::make('FireflyIII\Database\Account\Account'); | ||||
|  | ||||
|         $periods      = Config::get('firefly.piggy_bank_periods'); | ||||
|         $accounts     = FFForm::makeSelectList($acct->getAssetAccounts()); | ||||
|         $subTitle     = 'Edit repeated expense "' . e($repeatedExpense->name) . '"'; | ||||
|         $subTitleIcon = 'fa-pencil'; | ||||
|  | ||||
|         /* | ||||
|          * Flash some data to fill the form. | ||||
|          */ | ||||
|         $preFilled = ['name'         => $repeatedExpense->name, | ||||
|                       'account_id'   => $repeatedExpense->account_id, | ||||
|                       'targetamount' => $repeatedExpense->targetamount, | ||||
|                       'targetdate'   => $repeatedExpense->targetdate->format('Y-m-d'), | ||||
|                       'reminder'     => $repeatedExpense->reminder, | ||||
|                       'remind_me'    => intval($repeatedExpense->remind_me) == 1 || !is_null($repeatedExpense->reminder) ? true : false | ||||
|         ]; | ||||
|         Session::flash('preFilled', $preFilled); | ||||
|  | ||||
|         return View::make('repeatedExpense.edit', compact('subTitle', 'subTitleIcon', 'repeatedExpense', 'accounts', 'periods', 'preFilled')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|  | ||||
|         $subTitle = 'Overview'; | ||||
|  | ||||
|         $expenses = $this->_repository->get(); | ||||
|         $expenses->each( | ||||
|             function (PiggyBank $piggyBank) { | ||||
|                 $piggyBank->currentRelevantRep(); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return View::make('repeatedExpense.index', compact('expenses', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $repeatedExpense | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function show(PiggyBank $repeatedExpense) | ||||
|     { | ||||
|         $subTitle    = $repeatedExpense->name; | ||||
|         $today       = Carbon::now(); | ||||
|         $repetitions = $repeatedExpense->piggyBankRepetitions()->get(); | ||||
|  | ||||
|         $repetitions->each( | ||||
|             function (PiggyBankRepetition $repetition) { | ||||
|                 $repetition->bars = $this->_repository->calculateParts($repetition); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return View::make('repeatedExpense.show', compact('repetitions', 'repeatedExpense', 'today', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function store() | ||||
|     { | ||||
|         $data                  = Input::all(); | ||||
|         $data['repeats']       = 1; | ||||
|         $data['user_id']       = Auth::user()->id; | ||||
|         $targetDate            = new Carbon($data['targetdate']); | ||||
|         $startDate             = \DateKit::subtractPeriod($targetDate, $data['rep_length']); | ||||
|         $data['startdate']     = $startDate->format('Y-m-d'); | ||||
|         $data['targetdate']    = $targetDate->format('Y-m-d'); | ||||
|         $data['reminder_skip'] = 0; | ||||
|         $data['remind_me']     = isset($data['remind_me']) ? 1 : 0; | ||||
|         $data['order']         = 0; | ||||
|  | ||||
|         // always validate: | ||||
|         $messages = $this->_repository->validate($data); | ||||
|  | ||||
|         Session::flash('warnings', $messages['warnings']); | ||||
|         Session::flash('successes', $messages['successes']); | ||||
|         Session::flash('errors', $messages['errors']); | ||||
|         if ($messages['errors']->count() > 0) { | ||||
|             Session::flash('error', 'Could not store repeated expense: ' . $messages['errors']->first()); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         // return to create screen: | ||||
|         if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { | ||||
|             return Redirect::route('repeated.create')->withInput(); | ||||
|         } | ||||
|  | ||||
|         // store | ||||
|         $piggyBank = $this->_repository->store($data); | ||||
|         Event::fire('piggy_bank.store', [$piggyBank]); // new and used. | ||||
|         Session::flash('success', 'Piggy bank "' . e($data['name']) . '" stored.'); | ||||
|         if ($data['post_submit_action'] == 'store') { | ||||
|             return Redirect::route('repeated.index'); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('repeated.create')->withInput(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $repeatedExpense | ||||
|      * | ||||
|      * @return $this | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function update(PiggyBank $repeatedExpense) | ||||
|     { | ||||
|  | ||||
|         $data                  = Input::except('_token'); | ||||
|         $data['rep_every']     = 0; | ||||
|         $data['reminder_skip'] = 0; | ||||
|         $data['order']         = 0; | ||||
|         $data['repeats']       = 1; | ||||
|         $data['remind_me']     = isset($data['remind_me']) ? 1 : 0; | ||||
|         $data['user_id']       = Auth::user()->id; | ||||
|  | ||||
|         // always validate: | ||||
|         $messages = $this->_repository->validate($data); | ||||
|  | ||||
|         Session::flash('warnings', $messages['warnings']); | ||||
|         Session::flash('successes', $messages['successes']); | ||||
|         Session::flash('errors', $messages['errors']); | ||||
|         if ($messages['errors']->count() > 0) { | ||||
|             Session::flash('error', 'Could not update repeated expense: ' . $messages['errors']->first()); | ||||
|         } | ||||
|  | ||||
|         // return to update screen: | ||||
|         if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { | ||||
|             return Redirect::route('repeated.edit', $repeatedExpense->id)->withInput(); | ||||
|         } | ||||
|  | ||||
|         // update | ||||
|         $this->_repository->update($repeatedExpense, $data); | ||||
|         Session::flash('success', 'Repeated expense "' . e($data['name']) . '" updated.'); | ||||
|  | ||||
|         // go back to list | ||||
|         if ($data['post_submit_action'] == 'update') { | ||||
|             return Redirect::route('repeated.index'); | ||||
|         } | ||||
|  | ||||
|         // go back to update screen. | ||||
|         return Redirect::route('repeated.edit', $repeatedExpense->id)->withInput(['post_submit_action' => 'return_to_edit']); | ||||
|  | ||||
|     } | ||||
| }  | ||||
| @@ -1,18 +1,133 @@ | ||||
| <?php | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Database\TransactionJournal\TransactionJournal as TransactionJournalRepository; | ||||
| use FireflyIII\Report\ReportInterface as Report; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @SuppressWarnings("CamelCase") // I'm fine with this. | ||||
|  * | ||||
|  * Class ReportController | ||||
|  */ | ||||
| class ReportController extends BaseController | ||||
| { | ||||
|     /** @var \FireflyIII\Database\Budget\Budget */ | ||||
|     protected $_budgets; | ||||
|     /** @var TransactionJournalRepository */ | ||||
|     protected $_journals; | ||||
|     /** @var Report */ | ||||
|     protected $_repository; | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournalRepository $journals | ||||
|      * @param Report                       $repository | ||||
|      */ | ||||
|     public function __construct(TransactionJournalRepository $journals, Report $repository) | ||||
|     { | ||||
|         $this->_journals   = $journals; | ||||
|         $this->_repository = $repository; | ||||
|         /** @var \FireflyIII\Database\Budget\Budget _budgets */ | ||||
|         $this->_budgets = App::make('FireflyIII\Database\Budget\Budget'); | ||||
|  | ||||
|  | ||||
|         View::share('title', 'Reports'); | ||||
|         View::share('mainTitleIcon', 'fa-line-chart'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $year | ||||
|      * @param string $month | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function budget($year = '2014', $month = '1') | ||||
|     { | ||||
|         try { | ||||
|             new Carbon($year . '-' . $month . '-01'); | ||||
|         } catch (Exception $e) { | ||||
|             return View::make('error')->with('message', 'Invalid date'); | ||||
|         } | ||||
|         $date     = new Carbon($year . '-' . $month . '-01'); | ||||
|         $dayEarly = clone $date; | ||||
|         $dayEarly = $dayEarly->subDay(); | ||||
|         $accounts = $this->_repository->getAccountListBudgetOverview($date); | ||||
|         $budgets  = $this->_repository->getBudgetsForMonth($date); | ||||
|  | ||||
|         return View::make('reports.budget', compact('date', 'accounts', 'budgets', 'dayEarly')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|         return View::make('reports.index')->with('title','Reports')->with('mainTitleIcon','fa-line-chart'); | ||||
|         $start         = $this->_journals->firstDate(); | ||||
|         $months        = $this->_repository->listOfMonths(clone $start); | ||||
|         $years         = $this->_repository->listOfYears(clone $start); | ||||
|         $title         = 'Reports'; | ||||
|         $mainTitleIcon = 'fa-line-chart'; | ||||
|  | ||||
|         return View::make('reports.index', compact('years', 'months', 'title', 'mainTitleIcon')); | ||||
|     } | ||||
|  | ||||
| } | ||||
|     /** | ||||
|      * @param string $year | ||||
|      * @param string $month | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function month($year = '2014', $month = '1') | ||||
|     { | ||||
|         try { | ||||
|             new Carbon($year . '-' . $month . '-01'); | ||||
|         } catch (Exception $e) { | ||||
|             return View::make('error')->with('message', 'Invalid date.'); | ||||
|         } | ||||
|         $date         = new Carbon($year . '-' . $month . '-01'); | ||||
|         $subTitle     = 'Report for ' . $date->format('F Y'); | ||||
|         $subTitleIcon = 'fa-calendar'; | ||||
|         $displaySum   = true; // to show sums in report. | ||||
|         $income       = $this->_repository->getIncomeForMonth($date); | ||||
|         $expenses     = $this->_repository->getExpenseGroupedForMonth($date, 10); | ||||
|         $budgets      = $this->_repository->getBudgetsForMonth($date); | ||||
|         $categories   = $this->_repository->getCategoriesForMonth($date, 10); | ||||
|         $accounts     = $this->_repository->getAccountsForMonth($date); | ||||
|  | ||||
|         return View::make( | ||||
|             'reports.month', | ||||
|             compact('date', 'accounts', 'categories', 'budgets', 'expenses', 'subTitle', 'displaySum', 'subTitleIcon', 'income') | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $year | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function year($year) | ||||
|     { | ||||
|         try { | ||||
|             new Carbon('01-01-' . $year); | ||||
|         } catch (Exception $e) { | ||||
|             return View::make('error')->with('message', 'Invalid date.'); | ||||
|         } | ||||
|         $date = new Carbon('01-01-' . $year); | ||||
|         $end  = clone $date; | ||||
|         $end->endOfYear(); | ||||
|         $title         = 'Reports'; | ||||
|         $subTitle      = $year; | ||||
|         $subTitleIcon  = 'fa-bar-chart'; | ||||
|         $mainTitleIcon = 'fa-line-chart'; | ||||
|  | ||||
|         $balances        = $this->_repository->yearBalanceReport($date); | ||||
|         $groupedIncomes  = $this->_repository->revenueGroupedByAccount($date, $end, 15); | ||||
|         $groupedExpenses = $this->_repository->expensesGroupedByAccount($date, $end, 15); | ||||
|  | ||||
|         return View::make( | ||||
|             'reports.year', compact('date', 'groupedIncomes', 'groupedExpenses', 'year', 'balances', 'title', 'subTitle', 'subTitleIcon', 'mainTitleIcon') | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,50 +1,38 @@ | ||||
| <?php | ||||
|  | ||||
| use Firefly\Helper\Controllers\SearchInterface as SI; | ||||
|  | ||||
| /** | ||||
|  * Class SearchController | ||||
|  */ | ||||
| class SearchController extends BaseController | ||||
| { | ||||
|     protected $_helper; | ||||
|  | ||||
|     public function __construct(SI $helper) | ||||
|     { | ||||
|         $this->_helper = $helper; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Results always come in the form of an array [results, count, fullCount] | ||||
|      */ | ||||
|     public function index() | ||||
|     { | ||||
|  | ||||
|         /** @var \FireflyIII\Search\Search $searcher */ | ||||
|         $searcher = App::make('FireflyIII\Search\Search'); | ||||
|  | ||||
|         $subTitle = null; | ||||
|         $rawQuery = null; | ||||
|         $result = []; | ||||
|         if (!is_null(Input::get('q'))) { | ||||
|         $result   = []; | ||||
|         if (!is_null(Input::get('q')) && strlen(Input::get('q')) > 0) { | ||||
|             $rawQuery = trim(Input::get('q')); | ||||
|             $words    = explode(' ', $rawQuery); | ||||
|             $subTitle = 'Results for "' . e($rawQuery) . '"'; | ||||
|  | ||||
|             $transactions = $this->_helper->searchTransactions($words); | ||||
|             $accounts     = $this->_helper->searchAccounts($words); | ||||
|             $categories   = $this->_helper->searchCategories($words); | ||||
|             $budgets      = $this->_helper->searchBudgets($words); | ||||
|             $tags         = $this->_helper->searchTags($words); | ||||
|             $result = [ | ||||
|                 'transactions' => $transactions, | ||||
|                 'accounts' => $accounts, | ||||
|                 'categories' => $categories, | ||||
|                 'budgets' => $budgets, | ||||
|                 'tags' => $tags | ||||
|             ]; | ||||
|             $transactions = $searcher->searchTransactions($words); | ||||
|             $accounts     = $searcher->searchAccounts($words); | ||||
|             $categories   = $searcher->searchCategories($words); | ||||
|             $budgets      = $searcher->searchBudgets($words); | ||||
|             $tags         = $searcher->searchTags($words); | ||||
|             $result       = ['transactions' => $transactions, 'accounts' => $accounts, 'categories' => $categories, 'budgets' => $budgets, 'tags' => $tags]; | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return View::make('search.index')->with('title', 'Search')->with('subTitle', $subTitle)->with( | ||||
|             'mainTitleIcon', 'fa-search' | ||||
|         )->with('query', $rawQuery)->with('result',$result); | ||||
|         )->with('query', $rawQuery)->with('result', $result); | ||||
|     } | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -1,37 +1,46 @@ | ||||
| <?php | ||||
|  | ||||
|  | ||||
| use Firefly\Exception\FireflyException; | ||||
| use Firefly\Helper\Controllers\TransactionInterface as TI; | ||||
| use Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface as TJRI; | ||||
| use Illuminate\Support\MessageBag; | ||||
| use FireflyIII\Database\TransactionJournal\TransactionJournal as Repository; | ||||
| use FireflyIII\Exception\FireflyException; | ||||
| use FireflyIII\Helper\TransactionJournal\HelperInterface as Helper; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class TransactionController | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CamelCasePropertyName) | ||||
|  * @SuppressWarnings("CamelCase") // I'm fine with this. | ||||
|  * @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok. | ||||
|  * @SuppressWarnings("CouplingBetweenObjects") // There's only so much I can remove. | ||||
|  * @SuppressWarnings("TooManyMethods") // I'm also fine with this. | ||||
|  * @SuppressWarnings("ExcessiveClassComplexity") | ||||
|  * | ||||
|  * Class TransactionController | ||||
|  * | ||||
|  */ | ||||
| class TransactionController extends BaseController | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** @var Helper */ | ||||
|     protected $_helper; | ||||
|     /** @var Repository */ | ||||
|     protected $_repository; | ||||
|  | ||||
|     /** | ||||
|      * Construct a new transaction controller with two of the most often used helpers. | ||||
|      * | ||||
|      * @param TJRI $repository | ||||
|      * @param TI   $helper | ||||
|      * @param Repository $repository | ||||
|      * @param Helper     $helper | ||||
|      */ | ||||
|     public function __construct(TJRI $repository, TI $helper) | ||||
|     public function __construct(Repository $repository, Helper $helper) | ||||
|     { | ||||
|         $this->_repository = $repository; | ||||
|         $this->_helper = $helper; | ||||
|         $this->_helper     = $helper; | ||||
|         View::share('title', 'Transactions'); | ||||
|         View::share('mainTitleIcon', 'fa-repeat'); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Shows the view helping the user to create a new transaction journal. | ||||
|      * | ||||
| @@ -41,68 +50,48 @@ class TransactionController extends BaseController | ||||
|      */ | ||||
|     public function create($what = 'deposit') | ||||
|     { | ||||
|         /* | ||||
|          * The repositories we need: | ||||
|          */ | ||||
|         /** @var \Firefly\Helper\Toolkit\Toolkit $toolkit */ | ||||
|         $toolkit = App::make('Firefly\Helper\Toolkit\Toolkit'); | ||||
|         $accounts         = FFForm::makeSelectList($this->_helper->getAssetAccounts()); | ||||
|         $budgets          = FFForm::makeSelectList($this->_helper->getBudgets()); | ||||
|         $budgets[0]       = '(no budget)'; | ||||
|         $piggyBanks       = $this->_helper->getPiggyBanks(); | ||||
|         $repeatedExpenses = $this->_helper->getRepeatedExpenses(); | ||||
|         $list             = $piggyBanks->merge($repeatedExpenses); | ||||
|         $piggies          = FFForm::makeSelectList($list); | ||||
|         $piggies[0]       = '(no piggy bank)'; | ||||
|         $preFilled        = Session::has('preFilled') ? Session::get('preFilled') : []; | ||||
|         $respondTo        = ['account_id', 'account_from_id']; | ||||
|         $subTitle         = 'Add a new ' . e($what); | ||||
|  | ||||
|         /** @var \Firefly\Storage\Account\AccountRepositoryInterface $accountRepository */ | ||||
|         $accountRepository = App::make('Firefly\Storage\Account\AccountRepositoryInterface'); | ||||
|  | ||||
|         /** @var \Firefly\Storage\Budget\BudgetRepositoryInterface $budgetRepository */ | ||||
|         $budgetRepository = App::make('Firefly\Storage\Budget\BudgetRepositoryInterface'); | ||||
|  | ||||
|         /** @var \Firefly\Storage\Piggybank\PiggybankRepositoryInterface $piggyRepository */ | ||||
|         $piggyRepository = App::make('Firefly\Storage\Piggybank\PiggybankRepositoryInterface'); | ||||
|  | ||||
|         // get asset accounts with names and id's. | ||||
|         $assetAccounts = $toolkit->makeSelectList($accountRepository->getActiveDefault()); | ||||
|  | ||||
|         // get budgets as a select list. | ||||
|         $budgets = $toolkit->makeSelectList($budgetRepository->get()); | ||||
|         $budgets[0] = '(no budget)'; | ||||
|  | ||||
|         // get the piggy banks. | ||||
|         $piggies = $toolkit->makeSelectList($piggyRepository->get()); | ||||
|         $piggies[0] = '(no piggy bank)'; | ||||
|  | ||||
|         /* | ||||
|          * respond to a possible given values in the URL. | ||||
|          */ | ||||
|         $prefilled = Session::has('prefilled') ? Session::get('prefilled') : []; | ||||
|         $respondTo = ['account_id', 'account_from_id']; | ||||
|         foreach ($respondTo as $r) { | ||||
|             if (!is_null(Input::get($r))) { | ||||
|                 $prefilled[$r] = Input::get($r); | ||||
|                 $preFilled[$r] = Input::get($r); | ||||
|             } | ||||
|         } | ||||
|         Session::put('prefilled', $prefilled); | ||||
|         Session::put('preFilled', $preFilled); | ||||
|  | ||||
|         return View::make('transactions.create')->with('accounts', $assetAccounts)->with('budgets', $budgets)->with( | ||||
|             'what', $what | ||||
|         )->with('piggies', $piggies)->with('subTitle', 'Add a new ' . $what); | ||||
|         asort($piggies); | ||||
|  | ||||
|  | ||||
|         return View::make('transactions.create', compact('accounts', 'budgets', 'what', 'piggies', 'subTitle')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Shows the form that allows a user to delete a transaction journal. | ||||
|      * | ||||
|      * @param TransactionJournal $transactionJournal | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function delete(TransactionJournal $transactionJournal) | ||||
|     public function delete(TransactionJournal $journal) | ||||
|     { | ||||
|         $type = strtolower($transactionJournal->transactionType->type); | ||||
|         $type     = strtolower($journal->transactionType->type); | ||||
|         $subTitle = 'Delete ' . e($type) . ' "' . e($journal->description) . '"'; | ||||
|  | ||||
|         return View::make('transactions.delete')->with('journal', $transactionJournal)->with( | ||||
|             'subTitle', 'Delete ' . $type . ' "' . $transactionJournal->description . '"' | ||||
|         ); | ||||
|         return View::make('transactions.delete', compact('journal', 'subTitle')); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $transactionJournal | ||||
|      * | ||||
| @@ -110,20 +99,23 @@ class TransactionController extends BaseController | ||||
|      */ | ||||
|     public function destroy(TransactionJournal $transactionJournal) | ||||
|     { | ||||
|         $type = $transactionJournal->transactionType->type; | ||||
|         $transactionJournal->delete(); | ||||
|         $type   = $transactionJournal->transactionType->type; | ||||
|         $return = 'withdrawal'; | ||||
|  | ||||
|         Session::flash('success', 'Transaction "' . e($transactionJournal->description) . '" destroyed.'); | ||||
|  | ||||
|         $this->_repository->destroy($transactionJournal); | ||||
|  | ||||
|         switch ($type) { | ||||
|             case 'Withdrawal': | ||||
|                 return Redirect::route('transactions.expenses'); | ||||
|                 break; | ||||
|             case 'Deposit': | ||||
|                 return Redirect::route('transactions.revenue'); | ||||
|                 $return = 'deposit'; | ||||
|                 break; | ||||
|             case 'Transfer': | ||||
|                 return Redirect::route('transactions.transfers'); | ||||
|                 $return = 'transfers'; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('transactions.index', $return); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -135,118 +127,77 @@ class TransactionController extends BaseController | ||||
|      */ | ||||
|     public function edit(TransactionJournal $journal) | ||||
|     { | ||||
|         /* | ||||
|          * All the repositories we need: | ||||
|          */ | ||||
|         /** @var \Firefly\Helper\Toolkit\Toolkit $toolkit */ | ||||
|         $toolkit = App::make('Firefly\Helper\Toolkit\Toolkit'); | ||||
|  | ||||
|         /** @var \Firefly\Storage\Account\AccountRepositoryInterface $accountRepository */ | ||||
|         $accountRepository = App::make('Firefly\Storage\Account\AccountRepositoryInterface'); | ||||
|  | ||||
|         /** @var \Firefly\Storage\Budget\BudgetRepositoryInterface $budgetRepository */ | ||||
|         $budgetRepository = App::make('Firefly\Storage\Budget\BudgetRepositoryInterface'); | ||||
|  | ||||
|         /** @var \Firefly\Storage\Piggybank\PiggybankRepositoryInterface $piggyRepository */ | ||||
|         $piggyRepository = App::make('Firefly\Storage\Piggybank\PiggybankRepositoryInterface'); | ||||
|  | ||||
|         // type is useful for display: | ||||
|         $what = strtolower($journal->transactiontype->type); | ||||
|  | ||||
|         // get asset accounts with names and id's. | ||||
|         $accounts = $toolkit->makeSelectList($accountRepository->getActiveDefault()); | ||||
|  | ||||
|         // get budgets as a select list. | ||||
|         $budgets = $toolkit->makeSelectList($budgetRepository->get()); | ||||
|         $budgets[0] = '(no budget)'; | ||||
|  | ||||
|         /* | ||||
|          * Get all piggy banks plus (if any) the relevant piggy bank. Since just one | ||||
|          * of the transactions in the journal has this field, it should all fill in nicely. | ||||
|          */ | ||||
|         // get the piggy banks. | ||||
|         $piggies = $toolkit->makeSelectList($piggyRepository->get()); | ||||
|         $piggies[0] = '(no piggy bank)'; | ||||
|         $piggyBankId = 0; | ||||
|         foreach ($journal->transactions as $t) { | ||||
|             if (!is_null($t->piggybank_id)) { | ||||
|                 $piggyBankId = $t->piggybank_id; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /* | ||||
|          * Data to properly display the edit form. | ||||
|          */ | ||||
|         $prefilled = [ | ||||
|             'date'         => $journal->date->format('Y-m-d'), | ||||
|             'category'     => '', | ||||
|             'budget_id'    => 0, | ||||
|             'piggybank_id' => $piggyBankId | ||||
|         $what         = strtolower($journal->transactiontype->type); | ||||
|         $subTitle     = 'Edit ' . e($what) . ' "' . e($journal->description) . '"'; | ||||
|         $budgets      = FFForm::makeSelectList($this->_helper->getBudgets(), true); | ||||
|         $accounts     = FFForm::makeSelectList($this->_helper->getAssetAccounts()); | ||||
|         $piggies      = FFForm::makeSelectList($this->_helper->getPiggyBanks(), true); | ||||
|         $transactions = $journal->transactions()->orderBy('amount', 'DESC')->get(); | ||||
|         $preFilled    = [ | ||||
|             'date'          => $journal->date->format('Y-m-d'), | ||||
|             'category'      => '', | ||||
|             'budget_id'     => 0, | ||||
|             'piggy_bank_id' => 0 | ||||
|         ]; | ||||
|  | ||||
|         /* | ||||
|          * Fill in the category. | ||||
|          */ | ||||
|         $category = $journal->categories()->first(); | ||||
|         if (!is_null($category)) { | ||||
|             $prefilled['category'] = $category->name; | ||||
|             $preFilled['category'] = $category->name; | ||||
|         } | ||||
|  | ||||
|         /* | ||||
|          * Switch on the type of transaction edited by the user and fill in other | ||||
|          * relevant fields: | ||||
|          */ | ||||
|         $budget = $journal->budgets()->first(); | ||||
|         if (!is_null($budget)) { | ||||
|             $preFilled['budget_id'] = $budget->id; | ||||
|         } | ||||
|  | ||||
|         if ($journal->piggyBankEvents()->count() > 0) { | ||||
|             $preFilled['piggy_bank_id'] = $journal->piggyBankEvents()->first()->piggy_bank_id; | ||||
|         } | ||||
|  | ||||
|         $preFilled['amount']          = $journal->getAmount(); | ||||
|         $preFilled['account_id']      = $this->_helper->getAssetAccount($what, $transactions); | ||||
|         $preFilled['expense_account'] = $transactions[0]->account->name; | ||||
|         $preFilled['revenue_account'] = $transactions[1]->account->name; | ||||
|         $preFilled['account_from_id'] = $transactions[1]->account->id; | ||||
|         $preFilled['account_to_id']   = $transactions[0]->account->id; | ||||
|  | ||||
|  | ||||
|         return View::make('transactions.edit', compact('journal', 'accounts', 'what', 'budgets', 'piggies', 'subTitle'))->with('data', $preFilled); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $what | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function index($what) | ||||
|     { | ||||
|         switch ($what) { | ||||
|             case 'expenses': | ||||
|             case 'withdrawal': | ||||
|                 $prefilled['account_id'] = $journal->transactions[0]->account->id; | ||||
|                 $prefilled['expense_account'] = $journal->transactions[1]->account->name; | ||||
|                 $prefilled['amount'] = floatval($journal->transactions[1]->amount); | ||||
|                 $budget = $journal->budgets()->first(); | ||||
|                 if (!is_null($budget)) { | ||||
|                     $prefilled['budget_id'] = $budget->id; | ||||
|                 } | ||||
|                 $subTitleIcon = 'fa-long-arrow-left'; | ||||
|                 $subTitle     = 'Expenses'; | ||||
|                 $journals     = $this->_repository->getWithdrawalsPaginated(50); | ||||
|                 break; | ||||
|             case 'revenue': | ||||
|             case 'deposit': | ||||
|                 $prefilled['account_id'] = $journal->transactions[1]->account->id; | ||||
|                 $prefilled['revenue_account'] = $journal->transactions[0]->account->name; | ||||
|                 $prefilled['amount'] = floatval($journal->transactions[1]->amount); | ||||
|                 $subTitleIcon = 'fa-long-arrow-right'; | ||||
|                 $subTitle     = 'Revenue, income and deposits'; | ||||
|                 $journals     = $this->_repository->getDepositsPaginated(50); | ||||
|                 break; | ||||
|             case 'transfer': | ||||
|                 $prefilled['account_from_id'] = $journal->transactions[1]->account->id; | ||||
|                 $prefilled['account_to_id'] = $journal->transactions[0]->account->id; | ||||
|                 $prefilled['amount'] = floatval($journal->transactions[1]->amount); | ||||
|             case 'transfers': | ||||
|                 $subTitleIcon = 'fa-arrows-h'; | ||||
|                 $subTitle     = 'Transfers'; | ||||
|                 $journals     = $this->_repository->getTransfersPaginated(50); | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         /* | ||||
|          * Show the view. | ||||
|          */ | ||||
|         return View::make('transactions.edit')->with('journal', $journal)->with('accounts', $accounts)->with( | ||||
|             'what', $what | ||||
|         )->with('budgets', $budgets)->with('data', $prefilled)->with('piggies', $piggies)->with( | ||||
|             'subTitle', 'Edit ' . $what . ' "' . $journal->description . '"' | ||||
|         ); | ||||
|         return View::make('transactions.index', compact('subTitle', 'what', 'subTitleIcon', 'journals')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function expenses() | ||||
|     { | ||||
|         return View::make('transactions.list')->with('subTitle', 'Expenses')->with( | ||||
|             'subTitleIcon', 'fa-long-arrow-left' | ||||
|         )->with('what', 'expenses'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function revenue() | ||||
|     { | ||||
|         return View::make('transactions.list')->with('subTitle', 'Revenue')->with( | ||||
|             'subTitleIcon', 'fa-long-arrow-right' | ||||
|         )->with('what', 'revenue'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $journal | ||||
| @@ -255,8 +206,31 @@ class TransactionController extends BaseController | ||||
|      */ | ||||
|     public function show(TransactionJournal $journal) | ||||
|     { | ||||
|         return View::make('transactions.show')->with('journal', $journal)->with( | ||||
|             'subTitle', $journal->transactionType->type . ' "' . $journal->description . '"' | ||||
|         $journal->transactions->each( | ||||
|             function (\Transaction $t) use ($journal) { | ||||
|                 $t->before = floatval( | ||||
|                     $t->account->transactions()->leftJoin( | ||||
|                         'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id' | ||||
|                     )->where('transaction_journals.date', '<=', $journal->date->format('Y-m-d'))->where( | ||||
|                         'transaction_journals.created_at', '<=', $journal->created_at->format('Y-m-d H:i:s') | ||||
|                     )->where('transaction_journals.id', '!=', $journal->id)->sum('transactions.amount') | ||||
|                 ); | ||||
|                 $t->after  = $t->before + $t->amount; | ||||
|             } | ||||
|         ); | ||||
|         $members = new Collection; | ||||
|         /** @var TransactionGroup $group */ | ||||
|         foreach ($journal->transactiongroups()->get() as $group) { | ||||
|             /** @var TransactionJournal $loopJournal */ | ||||
|             foreach ($group->transactionjournals()->get() as $loopJournal) { | ||||
|                 if ($loopJournal->id != $journal->id) { | ||||
|                     $members->push($loopJournal); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return View::make('transactions.show', compact('journal', 'members'))->with( | ||||
|             'subTitle', e($journal->transactionType->type) . ' "' . e($journal->description) . '"' | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| @@ -268,112 +242,90 @@ class TransactionController extends BaseController | ||||
|      */ | ||||
|     public function store($what) | ||||
|     { | ||||
|         /* | ||||
|          * Collect data to process: | ||||
|          */ | ||||
|         $data = Input::except(['_token']); | ||||
|         $data['what'] = $what; | ||||
|         $data                            = Input::except('_token'); | ||||
|         $transactionType                 = $this->_repository->getJournalType($what); | ||||
|         $transactionCurrency             = $this->_repository->getJournalCurrency('EUR'); | ||||
|         $data['transaction_type_id']     = $transactionType->id; | ||||
|         $data['transaction_currency_id'] = $transactionCurrency->id; | ||||
|         $data['completed']               = 0; | ||||
|         $data['what']                    = $what; | ||||
|         $data['currency']                = 'EUR'; | ||||
|  | ||||
|         switch (Input::get('post_submit_action')) { | ||||
|             case 'store': | ||||
|             case 'create_another': | ||||
|                 /* | ||||
|                  * Try to store: | ||||
|                  */ | ||||
|                 $messageBag = $this->_helper->store($data); | ||||
|         // always validate: | ||||
|         $messages = $this->_repository->validate($data); | ||||
|  | ||||
|                 /* | ||||
|                  * Failure! | ||||
|                  */ | ||||
|                 if ($messageBag->count() > 0) { | ||||
|                     Session::flash('error', 'Could not save transaction: ' . $messageBag->first()); | ||||
|                     return Redirect::route('transactions.create', [$what])->withInput()->withErrors($messageBag); | ||||
|                 } | ||||
|  | ||||
|                 /* | ||||
|                  * Success! | ||||
|                  */ | ||||
|                 Session::flash('success', 'Transaction "' . e(Input::get('description')) . '" saved!'); | ||||
|  | ||||
|                 /* | ||||
|                  * Redirect to original location or back to the form. | ||||
|                  */ | ||||
|                 if (Input::get('post_submit_action') == 'create_another') { | ||||
|                     return Redirect::route('transactions.create', $what)->withInput(); | ||||
|                 } else { | ||||
|                     return Redirect::route('transactions.index.' . $what); | ||||
|                 } | ||||
|  | ||||
|                 break; | ||||
|             case 'validate_only': | ||||
|                 $messageBags = $this->_helper->validate($data); | ||||
|  | ||||
|                 Session::flash('warnings', $messageBags['warnings']); | ||||
|                 Session::flash('successes', $messageBags['successes']); | ||||
|                 Session::flash('errors', $messageBags['errors']); | ||||
|                 return Redirect::route('transactions.create', [$what])->withInput(); | ||||
|                 break; | ||||
|             default: | ||||
|                 throw new FireflyException('Method ' . Input::get('post_submit_action') . ' not implemented yet.'); | ||||
|                 break; | ||||
|         Session::flash('warnings', $messages['warnings']); | ||||
|         Session::flash('successes', $messages['successes']); | ||||
|         Session::flash('errors', $messages['errors']); | ||||
|         if ($messages['errors']->count() > 0) { | ||||
|             Session::flash('error', 'Could not store transaction: ' . $messages['errors']->first()); | ||||
|         } | ||||
|  | ||||
|         // return to create screen: | ||||
|         if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { | ||||
|             return Redirect::route('transactions.create', $data['what'])->withInput(); | ||||
|         } | ||||
|  | ||||
|         // store | ||||
|         $journal = $this->_repository->store($data); | ||||
|         Event::fire('transactionJournal.store', [$journal, Input::get('piggy_bank_id')]); // new and used. | ||||
|         /* | ||||
|          * Also trigger on both transactions. | ||||
|          */ | ||||
|         /** @var Transaction $transaction */ | ||||
|         foreach ($journal->transactions as $transaction) { | ||||
|             Event::fire('transaction.store', [$transaction]); | ||||
|         } | ||||
|  | ||||
|         Session::flash('success', 'Transaction "' . e($data['description']) . '" stored.'); | ||||
|         if ($data['post_submit_action'] == 'store') { | ||||
|             return Redirect::route('transactions.index', $data['what']); | ||||
|         } | ||||
|  | ||||
|         return Redirect::route('transactions.create', $data['what'])->withInput(); | ||||
|     } | ||||
|  | ||||
|     public function transfers() | ||||
|     { | ||||
|         return View::make('transactions.list')->with('subTitle', 'Transfers')->with( | ||||
|             'subTitleIcon', 'fa-arrows-h' | ||||
|         )->with('what', 'transfers'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $journal | ||||
|      * | ||||
|      * @return $this | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function update(TransactionJournal $journal) | ||||
|     { | ||||
|         switch (Input::get('post_submit_action')) { | ||||
|             case 'update': | ||||
|             case 'return_to_edit': | ||||
|                 $what = strtolower($journal->transactionType->type); | ||||
|                 $messageBag = $this->_helper->update($journal, Input::all()); | ||||
|                 if ($messageBag->count() == 0) { | ||||
|                     // has been saved, return to index: | ||||
|                     Session::flash('success', 'Transaction updated!'); | ||||
|                     Event::fire('journals.update', [$journal]); | ||||
|         $data                            = Input::except('_token'); | ||||
|         $data['currency']                = 'EUR'; | ||||
|         $data['what']                    = strtolower($journal->transactionType->type); | ||||
|         $data['transaction_type_id']     = $journal->transaction_type_id; | ||||
|         $data['transaction_currency_id'] = $journal->transaction_currency_id; | ||||
|         $data['completed']               = 1; | ||||
|         $messages                        = $this->_repository->validate($data); | ||||
|  | ||||
|                     if (Input::get('post_submit_action') == 'return_to_edit') { | ||||
|                         return Redirect::route('transactions.edit', $journal->id)->withInput(); | ||||
|                     } else { | ||||
|                         return Redirect::route('transactions.index.' . $what); | ||||
|                     } | ||||
|                 } else { | ||||
|                     Session::flash('error', 'Could not update transaction: ' . $journal->errors()->first()); | ||||
|  | ||||
|                     return Redirect::route('transactions.edit', $journal->id)->withInput()->withErrors( | ||||
|                         $journal->errors() | ||||
|                     ); | ||||
|                 } | ||||
|  | ||||
|                 break; | ||||
|             case 'validate_only': | ||||
|                 $data = Input::all(); | ||||
|                 $data['what'] = strtolower($journal->transactionType->type); | ||||
|                 $messageBags = $this->_helper->validate($data); | ||||
|  | ||||
|                 Session::flash('warnings', $messageBags['warnings']); | ||||
|                 Session::flash('successes', $messageBags['successes']); | ||||
|                 Session::flash('errors', $messageBags['errors']); | ||||
|                 return Redirect::route('transactions.edit', $journal->id)->withInput(); | ||||
|                 break; | ||||
|             default: | ||||
|                 throw new FireflyException('Method ' . Input::get('post_submit_action') . ' not implemented yet.'); | ||||
|                 break; | ||||
|         Session::flash('warnings', $messages['warnings']); | ||||
|         Session::flash('successes', $messages['successes']); | ||||
|         Session::flash('errors', $messages['errors']); | ||||
|         if ($messages['errors']->count() > 0) { | ||||
|             Session::flash('error', 'Could not update transaction: ' . $messages['errors']->first()); | ||||
|         } | ||||
|         if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { | ||||
|             return Redirect::route('transactions.edit', $journal->id)->withInput(); | ||||
|         } | ||||
|         $this->_repository->update($journal, $data); | ||||
|         Session::flash('success', 'Transaction "' . e($data['description']) . '" updated.'); | ||||
|         Event::fire('transactionJournal.update', [$journal]); // new and used. | ||||
|         /** @var Transaction $transaction */ | ||||
|         foreach ($journal->transactions()->get() as $transaction) { | ||||
|             Event::fire('transaction.update', [$transaction]); | ||||
|         } | ||||
|         if ($data['post_submit_action'] == 'update') { | ||||
|             return Redirect::route('transactions.index', $data['what']); | ||||
|         } | ||||
|  | ||||
|         // go back to update screen. | ||||
|         return Redirect::route('transactions.edit', $journal->id)->withInput(['post_submit_action' => 'return_to_edit']); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
| }  | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,5 @@ | ||||
| <?php | ||||
|  | ||||
| use Firefly\Helper\Email\EmailHelperInterface as EHI; | ||||
| use Firefly\Storage\User\UserRepositoryInterface as URI; | ||||
|  | ||||
| /** | ||||
|  * Class UserController | ||||
|  */ | ||||
| @@ -11,15 +8,9 @@ class UserController extends BaseController | ||||
|  | ||||
|     /** | ||||
|      * Constructor. | ||||
|      * | ||||
|      * @param URI $user | ||||
|      * @param EHI $email | ||||
|      */ | ||||
|     public function __construct(URI $user, EHI $email) | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->user  = $user; | ||||
|         $this->email = $email; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -32,6 +23,18 @@ class UserController extends BaseController | ||||
|         return View::make('user.login'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Logout user. | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function logout() | ||||
|     { | ||||
|         Auth::logout(); | ||||
|         Session::flush(); | ||||
|  | ||||
|         return Redirect::route('login'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Login. | ||||
| @@ -41,10 +44,7 @@ class UserController extends BaseController | ||||
|     public function postLogin() | ||||
|     { | ||||
|         $rememberMe = Input::get('remember_me') == '1'; | ||||
|         $data       = [ | ||||
|             'email'    => Input::get('email'), | ||||
|             'password' => Input::get('password') | ||||
|         ]; | ||||
|         $data       = ['email' => Input::get('email'), 'password' => Input::get('password')]; | ||||
|         $result     = Auth::attempt($data, $rememberMe); | ||||
|         if ($result) { | ||||
|             return Redirect::route('index'); | ||||
| @@ -55,20 +55,6 @@ class UserController extends BaseController | ||||
|         return View::make('user.login'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * If allowed, show the register form. | ||||
|      * | ||||
|      * @return $this|\Illuminate\View\View | ||||
|      */ | ||||
|     public function register() | ||||
|     { | ||||
|         if (Config::get('auth.allow_register') !== true) { | ||||
|             return View::make('error')->with('message', 'Not possible'); | ||||
|         } | ||||
|  | ||||
|         return View::make('user.register'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * If allowed, register the user. | ||||
|      * | ||||
| @@ -81,70 +67,72 @@ class UserController extends BaseController | ||||
|      */ | ||||
|     public function postRegister() | ||||
|     { | ||||
|         if (Config::get('auth.allow_register') !== true) { | ||||
|             return View::make('error')->with('message', 'Not possible'); | ||||
|         } | ||||
|         $user = $this->user->register(Input::all()); | ||||
|  | ||||
|         /** @var \FireflyIII\Database\User\User $repository */ | ||||
|         $repository = App::make('FireflyIII\Database\User\User'); | ||||
|  | ||||
|         /** @var \FireflyIII\Shared\Mail\RegistrationInterface $email */ | ||||
|         $email = App::make('FireflyIII\Shared\Mail\RegistrationInterface'); | ||||
|  | ||||
|         $user = $repository->register(Input::all()); | ||||
|  | ||||
|         if ($user) { | ||||
|             if (Config::get('auth.verify_mail') === true) { | ||||
|                 $this->email->sendVerificationMail($user); | ||||
|             $email->sendVerificationMail($user); | ||||
|  | ||||
|                 return View::make('user.verification-pending'); | ||||
|             } | ||||
|             $this->email->sendPasswordMail($user); | ||||
|  | ||||
|             return View::make('user.registered'); | ||||
|             return View::make('user.verification-pending'); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         return View::make('user.register'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Logout user. | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function logout() | ||||
|     { | ||||
|         Auth::logout(); | ||||
|         Session::flush(); | ||||
|  | ||||
|         return Redirect::route('index'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show form to help user get a new password. | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function remindme() | ||||
|     { | ||||
|         return View::make('user.remindme'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * If need to verify, send new reset code. | ||||
|      * Otherwise, send new password. | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function postRemindme() | ||||
|     public function postRemindMe() | ||||
|     { | ||||
|         $user = $this->user->findByEmail(Input::get('email')); | ||||
|  | ||||
|         /** @var \FireflyIII\Database\User\User $repository */ | ||||
|         $repository = App::make('FireflyIII\Database\User\User'); | ||||
|  | ||||
|         /** @var \FireflyIII\Shared\Mail\RegistrationInterface $email */ | ||||
|         $email = App::make('FireflyIII\Shared\Mail\RegistrationInterface'); | ||||
|  | ||||
|  | ||||
|         $user = $repository->findByEmail(Input::get('email')); | ||||
|         if (!$user) { | ||||
|             Session::flash('error', 'No good!'); | ||||
|  | ||||
|             return View::make('user.remindme'); | ||||
|             return View::make('user.remindMe'); | ||||
|         } | ||||
|         if (Config::get('auth.verify_reset') === true) { | ||||
|             $this->email->sendResetVerification($user); | ||||
|         $email->sendResetVerification($user); | ||||
|  | ||||
|             return View::make('user.verification-pending'); | ||||
|         } | ||||
|         $this->email->sendPasswordMail($user); | ||||
|         return View::make('user.verification-pending'); | ||||
|  | ||||
|         return View::make('user.registered'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * If allowed, show the register form. | ||||
|      * | ||||
|      * @return $this|\Illuminate\View\View | ||||
|      */ | ||||
|     public function register() | ||||
|     { | ||||
|  | ||||
|         return View::make('user.register'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show form to help user get a new password. | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function remindMe() | ||||
|     { | ||||
|         return View::make('user.remindMe'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -156,14 +144,21 @@ class UserController extends BaseController | ||||
|      */ | ||||
|     public function reset($reset) | ||||
|     { | ||||
|         $user = $this->user->findByReset($reset); | ||||
|  | ||||
|         /** @var \FireflyIII\Database\User\User $repository */ | ||||
|         $repository = App::make('FireflyIII\Database\User\User'); | ||||
|  | ||||
|         /** @var \FireflyIII\Shared\Mail\RegistrationInterface $email */ | ||||
|         $email = App::make('FireflyIII\Shared\Mail\RegistrationInterface'); | ||||
|  | ||||
|         $user = $repository->findByReset($reset); | ||||
|         if ($user) { | ||||
|             $this->email->sendPasswordMail($user); | ||||
|             $email->sendPasswordMail($user); | ||||
|  | ||||
|             return View::make('user.registered'); | ||||
|         } | ||||
|  | ||||
|         return View::make('error')->with('message', 'Yo no hablo reset code!'); | ||||
|         return View::make('error')->with('message', 'No reset code found!'); | ||||
|     } | ||||
|  | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -5,12 +5,20 @@ use Illuminate\Database\Schema\Blueprint; | ||||
|  | ||||
| /** | ||||
|  * Class CreateUsersTable | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ShortMethodName) | ||||
|  */ | ||||
| class CreateUsersTable extends Migration | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('users'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
| @@ -26,21 +34,9 @@ class CreateUsersTable extends Migration | ||||
|                 $table->string('password', 60); | ||||
|                 $table->string('reset', 32)->nullable(); | ||||
|                 $table->string('remember_token', 255)->nullable(); | ||||
|                 $table->boolean('migrated'); | ||||
|  | ||||
|                 $table->unique('email'); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('users'); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -6,7 +6,6 @@ use Illuminate\Database\Schema\Blueprint; | ||||
| /** | ||||
|  * Class CreateAccountTypesTable | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ShortMethodName) | ||||
|  */ | ||||
| class CreateAccountTypesTable extends Migration | ||||
| { | ||||
| @@ -29,14 +28,14 @@ class CreateAccountTypesTable extends Migration | ||||
|     public function up() | ||||
|     { | ||||
|         Schema::create( | ||||
|               'account_types', function (Blueprint $table) { | ||||
|                       $table->increments('id'); | ||||
|                       $table->timestamps(); | ||||
|                       $table->string('type', 50); | ||||
|                       $table->boolean('editable'); | ||||
|             'account_types', function (Blueprint $table) { | ||||
|                 $table->increments('id'); | ||||
|                 $table->timestamps(); | ||||
|                 $table->string('type', 30); | ||||
|                 $table->boolean('editable'); | ||||
|  | ||||
|                       $table->unique('type'); | ||||
|                   } | ||||
|                 $table->unique('type'); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -6,11 +6,20 @@ use Illuminate\Database\Schema\Blueprint; | ||||
| /** | ||||
|  * Class CreateAccountsTable | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ShortMethodName) | ||||
|  */ | ||||
| class CreateAccountsTable extends Migration | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('accounts'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
| @@ -22,34 +31,22 @@ class CreateAccountsTable extends Migration | ||||
|             'accounts', function (Blueprint $table) { | ||||
|                 $table->increments('id'); | ||||
|                 $table->timestamps(); | ||||
|                 $table->softDeletes(); | ||||
|                 $table->integer('user_id')->unsigned(); | ||||
|                 $table->integer('account_type_id')->unsigned(); | ||||
|                 $table->string('name', 100); | ||||
|                 $table->boolean('active'); | ||||
|  | ||||
|                 // connect accounts to users | ||||
|                 $table->foreign('user_id') | ||||
|                     ->references('id')->on('users') | ||||
|                     ->onDelete('cascade'); | ||||
|                 $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); | ||||
|  | ||||
|                 // connect accounts to account_types | ||||
|                 $table->foreign('account_type_id') | ||||
|                     ->references('id')->on('account_types') | ||||
|                     ->onDelete('cascade'); | ||||
|                 $table->foreign('account_type_id')->references('id')->on('account_types')->onDelete('cascade'); | ||||
|  | ||||
|                 // for a user, the account name must be unique. | ||||
|                 $table->unique(['user_id', 'account_type_id', 'name']); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('accounts'); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -6,11 +6,20 @@ use Illuminate\Database\Schema\Blueprint; | ||||
| /** | ||||
|  * Class CreateComponentsTable | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ShortMethodName) | ||||
|  */ | ||||
| class CreateComponentsTable extends Migration | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('components'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
| @@ -22,29 +31,19 @@ class CreateComponentsTable extends Migration | ||||
|             'components', function (Blueprint $table) { | ||||
|                 $table->increments('id'); | ||||
|                 $table->timestamps(); | ||||
|                 $table->softDeletes(); | ||||
|                 $table->string('name', 50); | ||||
|                 $table->integer('user_id')->unsigned(); | ||||
|                 $table->string('class', 20); | ||||
|  | ||||
|                 // connect components to users | ||||
|                 $table->foreign('user_id') | ||||
|                     ->references('id')->on('users') | ||||
|                     ->onDelete('cascade'); | ||||
|                 $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); | ||||
|  | ||||
|                 // for a user, the component type & name must be unique. | ||||
|                 $table->unique(['user_id', 'class', 'name']); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('components'); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -6,11 +6,20 @@ use Illuminate\Database\Schema\Blueprint; | ||||
| /** | ||||
|  * Class CreatePiggybanksTable | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ShortMethodName) | ||||
|  */ | ||||
| class CreatePiggybanksTable extends Migration | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('piggybanks'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
| @@ -28,31 +37,22 @@ class CreatePiggybanksTable extends Migration | ||||
|                 $table->date('startdate')->nullable(); | ||||
|                 $table->date('targetdate')->nullable(); | ||||
|                 $table->boolean('repeats'); | ||||
|                 $table->enum('rep_length', ['day', 'week', 'month', 'year'])->nullable(); | ||||
|                 $table->enum('rep_length', ['day', 'week', 'quarter', 'month', 'year'])->nullable(); | ||||
|                 $table->smallInteger('rep_every')->unsigned(); | ||||
|                 $table->smallInteger('rep_times')->unsigned()->nullable(); | ||||
|                 $table->enum('reminder', ['day', 'week', 'month', 'year'])->nullable(); | ||||
|                 $table->enum('reminder', ['day', 'week', 'quarter', 'month', 'year'])->nullable(); | ||||
|                 $table->smallInteger('reminder_skip')->unsigned(); | ||||
|                 $table->boolean('remind_me'); | ||||
|                 $table->integer('order')->unsigned(); | ||||
|  | ||||
|                 // connect account to piggybank. | ||||
|                 $table->foreign('account_id') | ||||
|                     ->references('id')->on('accounts') | ||||
|                     ->onDelete('cascade'); | ||||
|                 // connect account to piggy bank. | ||||
|                 $table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade'); | ||||
|  | ||||
|                 // for an account, the name must be unique. | ||||
|                 $table->unique(['account_id', 'name']); | ||||
|  | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('piggybanks'); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -6,11 +6,20 @@ use Illuminate\Database\Schema\Blueprint; | ||||
| /** | ||||
|  * Class CreateTransactionCurrenciesTable | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ShortMethodName) | ||||
|  */ | ||||
| class CreateTransactionCurrenciesTable extends Migration | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('transaction_currencies'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
| @@ -22,19 +31,13 @@ class CreateTransactionCurrenciesTable extends Migration | ||||
|             'transaction_currencies', function (Blueprint $table) { | ||||
|                 $table->increments('id'); | ||||
|                 $table->timestamps(); | ||||
|                 $table->softDeletes(); | ||||
|                 $table->string('code', 3); | ||||
|  | ||||
|                 // code must be unique. | ||||
|                 $table->unique(['code']); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('transaction_currencies'); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -6,11 +6,20 @@ use Illuminate\Database\Schema\Blueprint; | ||||
| /** | ||||
|  * Class CreateTransactionTypesTable | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ShortMethodName) | ||||
|  */ | ||||
| class CreateTransactionTypesTable extends Migration | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('transaction_types'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
| @@ -22,19 +31,13 @@ class CreateTransactionTypesTable extends Migration | ||||
|             'transaction_types', function (Blueprint $table) { | ||||
|                 $table->increments('id'); | ||||
|                 $table->timestamps(); | ||||
|                 $table->softDeletes(); | ||||
|                 $table->string('type', 50); | ||||
|  | ||||
|                 // type must be unique. | ||||
|                 $table->unique(['type']); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('transaction_types'); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -6,11 +6,20 @@ use Illuminate\Database\Schema\Blueprint; | ||||
| /** | ||||
|  * Class CreateRecurringTransactionsTable | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ShortMethodName) | ||||
|  */ | ||||
| class CreateRecurringTransactionsTable extends Migration | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('recurring_transactions'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
| @@ -34,6 +43,10 @@ class CreateRecurringTransactionsTable extends Migration | ||||
|                 $table->enum('repeat_freq', ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly']); | ||||
|                 $table->smallInteger('skip')->unsigned(); | ||||
|  | ||||
|                 // connect user id to users | ||||
|                 $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); | ||||
|  | ||||
|                 // for a user, the name must be unique | ||||
|                 $table->unique(['user_id', 'name']); | ||||
|  | ||||
|  | ||||
| @@ -41,14 +54,4 @@ class CreateRecurringTransactionsTable extends Migration | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('recurring_transactions'); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -6,11 +6,20 @@ use Illuminate\Database\Schema\Blueprint; | ||||
| /** | ||||
|  * Class CreateTransactionJournalsTable | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ShortMethodName) | ||||
|  */ | ||||
| class CreateTransactionJournalsTable extends Migration | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('transaction_journals'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
| @@ -22,6 +31,7 @@ class CreateTransactionJournalsTable extends Migration | ||||
|             'transaction_journals', function (Blueprint $table) { | ||||
|                 $table->increments('id'); | ||||
|                 $table->timestamps(); | ||||
|                 $table->softDeletes(); | ||||
|                 $table->integer('user_id')->unsigned(); | ||||
|                 $table->integer('transaction_type_id')->unsigned(); | ||||
|                 $table->integer('recurring_transaction_id')->unsigned()->nullable(); | ||||
| @@ -30,37 +40,21 @@ class CreateTransactionJournalsTable extends Migration | ||||
|                 $table->boolean('completed'); | ||||
|                 $table->date('date'); | ||||
|  | ||||
|                 // connect users | ||||
|                 $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); | ||||
|  | ||||
|                 // connect transaction journals to transaction types | ||||
|                 $table->foreign('transaction_type_id') | ||||
|                     ->references('id')->on('transaction_types') | ||||
|                     ->onDelete('cascade'); | ||||
|                 $table->foreign('transaction_type_id')->references('id')->on('transaction_types')->onDelete('cascade'); | ||||
|  | ||||
|                 // connect transaction journals to recurring transactions | ||||
|                 $table->foreign('recurring_transaction_id') | ||||
|                     ->references('id')->on('recurring_transactions') | ||||
|                     ->onDelete('set null'); | ||||
|                 $table->foreign('recurring_transaction_id')->references('id')->on('recurring_transactions')->onDelete('set null'); | ||||
|  | ||||
|                 // connect transaction journals to transaction currencies | ||||
|                 $table->foreign('transaction_currency_id') | ||||
|                     ->references('id')->on('transaction_currencies') | ||||
|                     ->onDelete('cascade'); | ||||
|                 $table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('cascade'); | ||||
|  | ||||
|  | ||||
|                 // connect users | ||||
|                 $table->foreign('user_id') | ||||
|                     ->references('id')->on('users') | ||||
|                     ->onDelete('cascade'); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('transaction_journals'); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -6,7 +6,6 @@ use Illuminate\Database\Schema\Blueprint; | ||||
| /** | ||||
|  * Class CreateTransactionsTable | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ShortMethodName) | ||||
|  */ | ||||
| class CreateTransactionsTable extends Migration | ||||
| { | ||||
| @@ -32,26 +31,25 @@ class CreateTransactionsTable extends Migration | ||||
|             'transactions', function (Blueprint $table) { | ||||
|                 $table->increments('id'); | ||||
|                 $table->timestamps(); | ||||
|                 $table->softDeletes(); | ||||
|                 $table->integer('account_id')->unsigned(); | ||||
|                 $table->integer('piggybank_id')->nullable()->unsigned(); | ||||
|                 $table->integer('transaction_journal_id')->unsigned(); | ||||
|                 $table->string('description', 255)->nullable(); | ||||
|                 $table->decimal('amount', 10, 2); | ||||
|  | ||||
|                 // connect transactions to transaction journals | ||||
|                 $table->foreign('transaction_journal_id') | ||||
|                     ->references('id')->on('transaction_journals') | ||||
|                     ->onDelete('cascade'); | ||||
|                 // connect account id: | ||||
|                 $table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade'); | ||||
|  | ||||
|                 // connect piggy banks | ||||
|                 $table->foreign('piggybank_id') | ||||
|                     ->references('id')->on('piggybanks') | ||||
|                     ->onDelete('set null'); | ||||
|                 $table->foreign('piggybank_id')->references('id')->on('piggybanks')->onDelete('set null'); | ||||
|  | ||||
|                 // connect transactions to transaction journals | ||||
|                 $table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade'); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|                 // connect account id: | ||||
|                 $table->foreign('account_id') | ||||
|                     ->references('id')->on('accounts') | ||||
|                     ->onDelete('cascade'); | ||||
|  | ||||
|             } | ||||
|         ); | ||||
|   | ||||
| @@ -6,11 +6,20 @@ use Illuminate\Database\Schema\Blueprint; | ||||
| /** | ||||
|  * Class CreateComponentTransactionTable | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ShortMethodName) | ||||
|  */ | ||||
| class CreateComponentTransactionTable extends Migration | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::dropIfExists('component_transaction'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
| @@ -25,26 +34,15 @@ class CreateComponentTransactionTable extends Migration | ||||
|                 $table->integer('transaction_id')->unsigned(); | ||||
|  | ||||
|                 // connect to components | ||||
|                 $table->foreign('component_id') | ||||
|                     ->references('id')->on('components') | ||||
|                     ->onDelete('cascade'); | ||||
|                 $table->foreign('component_id')->references('id')->on('components')->onDelete('cascade'); | ||||
|  | ||||
|                 // connect to transactions | ||||
|                 $table->foreign('transaction_id') | ||||
|                     ->references('id')->on('transactions') | ||||
|                     ->onDelete('cascade'); | ||||
|                 $table->foreign('transaction_id')->references('id')->on('transactions')->onDelete('cascade'); | ||||
|  | ||||
|                 // combo must be unique: | ||||
|                 $table->unique(['component_id', 'transaction_id']); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('component_transaction'); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -6,37 +6,10 @@ use Illuminate\Database\Schema\Blueprint; | ||||
| /** | ||||
|  * Class CreateComponentTransactionJournalTable | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ShortMethodName) | ||||
|  */ | ||||
| class CreateComponentTransactionJournalTable extends Migration | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function up() | ||||
|     { | ||||
|         Schema::create( | ||||
|             'component_transaction_journal', function (Blueprint $table) { | ||||
|                 $table->increments('id'); | ||||
|                 $table->integer('component_id')->unsigned(); | ||||
|                 $table->integer('transaction_journal_id')->unsigned(); | ||||
|  | ||||
|                 // link components with component_id | ||||
|                 $table->foreign('component_id') | ||||
|                     ->references('id')->on('components') | ||||
|                     ->onDelete('cascade'); | ||||
|  | ||||
|                 // link transaction journals with transaction_journal_id | ||||
|                 $table->foreign('transaction_journal_id') | ||||
|                     ->references('id')->on('transaction_journals') | ||||
|                     ->onDelete('cascade'); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
| @@ -47,4 +20,29 @@ class CreateComponentTransactionJournalTable extends Migration | ||||
|         Schema::drop('component_transaction_journal'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function up() | ||||
|     { | ||||
|         Schema::create( | ||||
|             'component_transaction_journal', function (Blueprint $table) { | ||||
|             $table->increments('id'); | ||||
|             $table->integer('component_id')->unsigned(); | ||||
|             $table->integer('transaction_journal_id')->unsigned(); | ||||
|  | ||||
|             // link components with component_id | ||||
|             $table->foreign('component_id')->references('id')->on('components')->onDelete('cascade'); | ||||
|  | ||||
|             // link transaction journals with transaction_journal_id | ||||
|             $table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade'); | ||||
|  | ||||
|             // combo must be unique: | ||||
|             $table->unique(['component_id', 'transaction_journal_id'], 'cid_tjid_unique'); | ||||
|         } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -6,11 +6,20 @@ use Illuminate\Database\Schema\Blueprint; | ||||
| /** | ||||
|  * Class CreatePreferencesTable | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ShortMethodName) | ||||
|  */ | ||||
| class CreatePreferencesTable extends Migration | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('preferences'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
| @@ -27,21 +36,12 @@ class CreatePreferencesTable extends Migration | ||||
|                 $table->text('data'); | ||||
|  | ||||
|                 // connect preferences to users | ||||
|                 $table->foreign('user_id') | ||||
|                     ->references('id')->on('users') | ||||
|                     ->onDelete('cascade'); | ||||
|                 $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); | ||||
|  | ||||
|                 // only one preference per name per user | ||||
|                 $table->unique(['user_id', 'name']); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('preferences'); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,31 +1,15 @@ | ||||
| <?php | ||||
|  | ||||
| use Illuminate\Database\Migrations\Migration; | ||||
| use Illuminate\Database\Schema\Blueprint; | ||||
|  | ||||
| /** | ||||
|  * Class CreateSessionTable | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ShortMethodName) | ||||
|  */ | ||||
| class CreateSessionTable extends Migration | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function up() | ||||
|     { | ||||
|         Schema::create( | ||||
|             'sessions', function ($t) { | ||||
|                 $t->string('id')->unique(); | ||||
|                 $t->text('payload'); | ||||
|                 $t->integer('last_activity'); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
| @@ -36,4 +20,20 @@ class CreateSessionTable extends Migration | ||||
|         Schema::drop('sessions'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function up() | ||||
|     { | ||||
|         Schema::create( | ||||
|             'sessions', function (Blueprint $table) { | ||||
|             $table->string('id')->unique(); | ||||
|             $table->text('payload'); | ||||
|             $table->integer('last_activity'); | ||||
|         } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -6,38 +6,10 @@ use Illuminate\Database\Schema\Blueprint; | ||||
| /** | ||||
|  * Class CreateLimitsTable | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ShortMethodName) | ||||
|  */ | ||||
| class CreateLimitsTable extends Migration | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function up() | ||||
|     { | ||||
|         Schema::create( | ||||
|             'limits', function (Blueprint $table) { | ||||
|                 $table->increments('id'); | ||||
|                 $table->timestamps(); | ||||
|                 $table->integer('component_id')->unsigned(); | ||||
|                 $table->date('startdate'); | ||||
|                 $table->decimal('amount', 10, 2); | ||||
|                 $table->boolean('repeats'); | ||||
|                 $table->enum('repeat_freq', ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly']); | ||||
|  | ||||
|                 $table->unique(['component_id', 'startdate', 'repeat_freq']); | ||||
|  | ||||
|                 // connect component | ||||
|                 $table->foreign('component_id') | ||||
|                     ->references('id')->on('components') | ||||
|                     ->onDelete('cascade'); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
| @@ -48,4 +20,29 @@ class CreateLimitsTable extends Migration | ||||
|         Schema::drop('limits'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function up() | ||||
|     { | ||||
|         Schema::create( | ||||
|             'limits', function (Blueprint $table) { | ||||
|             $table->increments('id'); | ||||
|             $table->timestamps(); | ||||
|             $table->integer('component_id')->unsigned(); | ||||
|             $table->date('startdate'); | ||||
|             $table->decimal('amount', 10, 2); | ||||
|             $table->boolean('repeats'); | ||||
|             $table->enum('repeat_freq', ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly']); | ||||
|  | ||||
|             $table->unique(['component_id', 'startdate', 'repeat_freq'], 'unique_ci_combi'); | ||||
|  | ||||
|             // connect component | ||||
|             $table->foreign('component_id')->references('id')->on('components')->onDelete('cascade'); | ||||
|         } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -6,11 +6,20 @@ use Illuminate\Database\Schema\Blueprint; | ||||
| /** | ||||
|  * Class CreateLimitRepeatTable | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ShortMethodName) | ||||
|  */ | ||||
| class CreateLimitRepeatTable extends Migration | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('limit_repetitions'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
| @@ -30,21 +39,9 @@ class CreateLimitRepeatTable extends Migration | ||||
|                 $table->unique(['limit_id', 'startdate', 'enddate']); | ||||
|  | ||||
|                 // connect limit | ||||
|                 $table->foreign('limit_id') | ||||
|                     ->references('id')->on('limits') | ||||
|                     ->onDelete('cascade'); | ||||
|                 $table->foreign('limit_id')->references('id')->on('limits')->onDelete('cascade'); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('limit_repetitions'); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,50 @@ | ||||
| <?php | ||||
|  | ||||
| use Illuminate\Database\Migrations\Migration; | ||||
| use Illuminate\Database\Schema\Blueprint; | ||||
|  | ||||
| /** | ||||
|  * Class CreateComponentRecurringTransactionTable | ||||
|  * | ||||
|  */ | ||||
| class CreateComponentRecurringTransactionTable extends Migration | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::dropIfExists('component_recurring_transaction'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function up() | ||||
|     { | ||||
|         Schema::create( | ||||
|             'component_recurring_transaction', function (Blueprint $table) { | ||||
|             $table->increments('id'); | ||||
|             $table->integer('component_id')->unsigned(); | ||||
|             $table->integer('recurring_transaction_id')->unsigned(); | ||||
|             $table->boolean('optional'); | ||||
|  | ||||
|             // link components with component_id | ||||
|             $table->foreign('component_id')->references('id')->on('components')->onDelete('cascade'); | ||||
|  | ||||
|             // link transaction journals with transaction_journal_id | ||||
|             $table->foreign('recurring_transaction_id')->references('id')->on('recurring_transactions')->onDelete('cascade'); | ||||
|  | ||||
|             // component and recurring transaction must be unique. | ||||
|             $table->unique(['component_id', 'recurring_transaction_id'], 'cid_rtid_unique'); | ||||
|  | ||||
|         } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -1,51 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| use Illuminate\Database\Migrations\Migration; | ||||
| use Illuminate\Database\Schema\Blueprint; | ||||
|  | ||||
| /** | ||||
|  * Class RecurringTransactionsToComponents | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ShortMethodName) | ||||
|  */ | ||||
| class RecurringTransactionsToComponents extends Migration | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function up() | ||||
|     { | ||||
|         Schema::create( | ||||
|             'component_recurring_transaction', function (Blueprint $table) { | ||||
|                 $table->increments('id'); | ||||
|                 $table->integer('component_id')->unsigned(); | ||||
|                 $table->integer('recurring_transaction_id')->unsigned(); | ||||
|                 $table->boolean('optional'); | ||||
|  | ||||
|                 // link components with component_id | ||||
|                 $table->foreign('component_id') | ||||
|                     ->references('id')->on('components') | ||||
|                     ->onDelete('cascade'); | ||||
|  | ||||
|                 // link transaction journals with transaction_journal_id | ||||
|                 $table->foreign('recurring_transaction_id') | ||||
|                     ->references('id')->on('recurring_transactions') | ||||
|                     ->onDelete('cascade'); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('component_recurring_transaction'); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -3,9 +3,23 @@ | ||||
| use Illuminate\Database\Migrations\Migration; | ||||
| use Illuminate\Database\Schema\Blueprint; | ||||
| 
 | ||||
| class CreatePiggyInstance extends Migration | ||||
| /** | ||||
|  * Class CreatePiggyInstance | ||||
|  * | ||||
|  */ | ||||
| class CreatePiggybankRepetitionsTable extends Migration | ||||
| { | ||||
| 
 | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('piggybank_repetitions'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
| @@ -25,21 +39,9 @@ class CreatePiggyInstance extends Migration | ||||
|                 $table->unique(['piggybank_id', 'startdate', 'targetdate']); | ||||
| 
 | ||||
|                 // connect instance to piggybank.
 | ||||
|                 $table->foreign('piggybank_id') | ||||
|                     ->references('id')->on('piggybanks') | ||||
|                     ->onDelete('cascade'); | ||||
|                 $table->foreign('piggybank_id')->references('id')->on('piggybanks')->onDelete('cascade'); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('piggybank_repetitions'); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @@ -3,9 +3,23 @@ | ||||
| use Illuminate\Database\Migrations\Migration; | ||||
| use Illuminate\Database\Schema\Blueprint; | ||||
| 
 | ||||
| class CreatePiggyEvents extends Migration | ||||
| /** | ||||
|  * Class CreatePiggybankEventsTable | ||||
|  * | ||||
|  */ | ||||
| class CreatePiggybankEventsTable extends Migration | ||||
| { | ||||
| 
 | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('piggybank_events'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
| @@ -18,25 +32,18 @@ class CreatePiggyEvents extends Migration | ||||
|                 $table->increments('id'); | ||||
|                 $table->timestamps(); | ||||
|                 $table->integer('piggybank_id')->unsigned(); | ||||
|                 $table->integer('transaction_journal_id')->unsigned()->nullable(); | ||||
| 
 | ||||
|                 $table->date('date'); | ||||
|                 $table->decimal('amount', 10, 2); | ||||
| 
 | ||||
|                 // connect instance to piggybank.
 | ||||
|                 $table->foreign('piggybank_id') | ||||
|                     ->references('id')->on('piggybanks') | ||||
|                     ->onDelete('cascade'); | ||||
|                 $table->foreign('piggybank_id')->references('id')->on('piggybanks')->onDelete('cascade'); | ||||
| 
 | ||||
|                 // connect to journal:
 | ||||
|                 $table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('set null'); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('piggybank_events'); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @@ -3,6 +3,10 @@ | ||||
| use Illuminate\Database\Migrations\Migration; | ||||
| use Illuminate\Database\Schema\Blueprint; | ||||
|  | ||||
| /** | ||||
|  * Class CreateRemindersTable | ||||
|  * | ||||
|  */ | ||||
| class CreateRemindersTable extends Migration | ||||
| { | ||||
|  | ||||
| @@ -27,30 +31,16 @@ class CreateRemindersTable extends Migration | ||||
|             'reminders', function (Blueprint $table) { | ||||
|                 $table->increments('id'); | ||||
|                 $table->timestamps(); | ||||
|                 $table->string('class', 40); | ||||
|                 $table->integer('piggybank_id')->unsigned()->nullable(); | ||||
|                 $table->integer('recurring_transaction_id')->unsigned()->nullable(); | ||||
|                 $table->integer('user_id')->unsigned(); | ||||
|                 $table->date('startdate'); | ||||
|                 $table->date('enddate')->nullable(); | ||||
|                 $table->boolean('active'); | ||||
|  | ||||
|  | ||||
|                 // connect reminders to piggy banks. | ||||
|                 $table->foreign('piggybank_id') | ||||
|                     ->references('id')->on('piggybanks') | ||||
|                     ->onDelete('set null'); | ||||
|  | ||||
|                 // connect reminders to recurring transactions. | ||||
|                 $table->foreign('recurring_transaction_id') | ||||
|                     ->references('id')->on('recurring_transactions') | ||||
|                     ->onDelete('set null'); | ||||
|  | ||||
|                 $table->boolean('notnow')->default(0); | ||||
|                 $table->integer('remindersable_id')->unsigned()->nullable(); | ||||
|                 $table->string('remindersable_type')->nullable(); | ||||
|  | ||||
|                 // connect reminders to users | ||||
|                 $table->foreign('user_id') | ||||
|                     ->references('id')->on('users') | ||||
|                     ->onDelete('cascade'); | ||||
|                 $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|   | ||||
| @@ -1,41 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| use Illuminate\Database\Schema\Blueprint; | ||||
| use Illuminate\Database\Migrations\Migration; | ||||
|  | ||||
| class CreateImportmapsTable extends Migration { | ||||
|  | ||||
| 	/** | ||||
| 	 * Run the migrations. | ||||
| 	 * | ||||
| 	 * @return void | ||||
| 	 */ | ||||
| 	public function up() | ||||
| 	{ | ||||
| 		Schema::create('importmaps', function(Blueprint $table) | ||||
| 		{ | ||||
| 			$table->increments('id'); | ||||
| 			$table->timestamps(); | ||||
|             $table->integer('user_id')->unsigned(); | ||||
|             $table->string('file',500); | ||||
|             $table->integer('totaljobs')->unsigned(); | ||||
|             $table->integer('jobsdone')->unsigned(); | ||||
|  | ||||
|             // connect maps to users | ||||
|             $table->foreign('user_id') | ||||
|                   ->references('id')->on('users') | ||||
|                   ->onDelete('cascade'); | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Reverse the migrations. | ||||
| 	 * | ||||
| 	 * @return void | ||||
| 	 */ | ||||
| 	public function down() | ||||
| 	{ | ||||
| 		Schema::drop('importmaps'); | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -1,42 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| use Illuminate\Database\Schema\Blueprint; | ||||
| use Illuminate\Database\Migrations\Migration; | ||||
|  | ||||
| class CreateImportentriesTable extends Migration { | ||||
|  | ||||
| 	/** | ||||
| 	 * Run the migrations. | ||||
| 	 * | ||||
| 	 * @return void | ||||
| 	 */ | ||||
| 	public function up() | ||||
| 	{ | ||||
| 		Schema::create('importentries', function(Blueprint $table) | ||||
| 		{ | ||||
| 			$table->increments('id'); | ||||
| 			$table->timestamps(); | ||||
|             $table->string('class',200); | ||||
|             $table->integer('importmap_id')->unsigned(); | ||||
|             $table->integer('old')->unsigned(); | ||||
|             $table->integer('new')->unsigned(); | ||||
|  | ||||
|             // map import entries to import map. | ||||
|             // connect accounts to account_types | ||||
|             $table->foreign('importmap_id') | ||||
|                   ->references('id')->on('importmaps') | ||||
|                   ->onDelete('cascade'); | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Reverse the migrations. | ||||
| 	 * | ||||
| 	 * @return void | ||||
| 	 */ | ||||
| 	public function down() | ||||
| 	{ | ||||
| 		Schema::drop('importentries'); | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -1,35 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| use Illuminate\Database\Migrations\Migration; | ||||
| use Illuminate\Database\Schema\Blueprint; | ||||
|  | ||||
| class CreateFailedJobsTable extends Migration | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('failed_jobs'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function up() | ||||
|     { | ||||
|         Schema::create('failed_jobs', function (Blueprint $table) { | ||||
|             $table->increments('id'); | ||||
|             $table->text('connection'); | ||||
|             $table->text('queue'); | ||||
|             $table->text('payload'); | ||||
|             $table->timestamp('failed_at'); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,47 @@ | ||||
| <?php | ||||
|  | ||||
| use Illuminate\Database\Migrations\Migration; | ||||
| use Illuminate\Database\Schema\Blueprint; | ||||
|  | ||||
| /** | ||||
|  * Class CreateAccountMetaTable | ||||
|  * | ||||
|  */ | ||||
| class CreateAccountMetaTable extends Migration | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         // | ||||
|         Schema::drop('account_meta'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function up() | ||||
|     { | ||||
|         // | ||||
|         Schema::create( | ||||
|             'account_meta', function (Blueprint $table) { | ||||
|                 $table->increments('id'); | ||||
|                 $table->timestamps(); | ||||
|                 $table->integer('account_id')->unsigned(); | ||||
|                 $table->string('name'); | ||||
|                 $table->text('data'); | ||||
|  | ||||
|                 $table->unique(['account_id', 'name']); | ||||
|  | ||||
|  | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,46 @@ | ||||
| <?php | ||||
|  | ||||
| use Illuminate\Database\Migrations\Migration; | ||||
| use Illuminate\Database\Schema\Blueprint; | ||||
|  | ||||
| /** | ||||
|  * Class CreateTransactionGroupsTable | ||||
|  * | ||||
|  */ | ||||
| class CreateTransactionGroupsTable extends Migration | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::drop('transaction_groups'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function up() | ||||
|     { | ||||
|         Schema::create( | ||||
|             'transaction_groups', function (Blueprint $table) { | ||||
|                 $table->increments('id'); | ||||
|                 $table->timestamps(); | ||||
|                 $table->softDeletes(); | ||||
|                 $table->integer('user_id')->unsigned(); | ||||
|                 $table->enum('relation', ['balance']); | ||||
|  | ||||
|                 // connect reminders to users | ||||
|                 $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,49 @@ | ||||
| <?php | ||||
|  | ||||
| use Illuminate\Database\Migrations\Migration; | ||||
| use Illuminate\Database\Schema\Blueprint; | ||||
|  | ||||
| /** | ||||
|  * Class CreateTransactionGroupTransactionJournalTable | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ShortMethodName) | ||||
|  */ | ||||
| class CreateTransactionGroupTransactionJournalTable extends Migration | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         // | ||||
|         Schema::drop('transaction_group_transaction_journal'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function up() | ||||
|     { | ||||
|  | ||||
|         Schema::create( | ||||
|             'transaction_group_transaction_journal', function (Blueprint $table) { | ||||
|                 $table->increments('id'); | ||||
|                 $table->integer('transaction_group_id')->unsigned(); | ||||
|                 $table->integer('transaction_journal_id')->unsigned(); | ||||
|  | ||||
|                 // link to foreign tables. | ||||
|                 $table->foreign('transaction_group_id', 'tr_grp_id')->references('id')->on('transaction_groups')->onDelete('cascade'); | ||||
|                 $table->foreign('transaction_journal_id', 'tr_trj_id')->references('id')->on('transaction_journals')->onDelete('cascade'); | ||||
|  | ||||
|                 // add unique. | ||||
|                 $table->unique(['transaction_group_id', 'transaction_journal_id'], 'tt_joined'); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										494
									
								
								app/database/migrations/2014_12_13_190730_changes_for_v321.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										494
									
								
								app/database/migrations/2014_12_13_190730_changes_for_v321.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,494 @@ | ||||
| <?php | ||||
|  | ||||
| use Illuminate\Database\Migrations\Migration; | ||||
| use Illuminate\Database\Schema\Blueprint; | ||||
| use Illuminate\Support\Facades\Schema; | ||||
|  | ||||
| /** | ||||
|  * Down: | ||||
|  * 1. Create new Components based on Budgets. | ||||
|  * 2. Create new Components based on Categories | ||||
|  * 3. Recreate component_id in limits | ||||
|  * 4. Update all budget_limits entries (component_id). | ||||
|  * 5. Add the foreign key to component_id in budget_limits | ||||
|  * 6. Drop column 'budget_id' in budget_limits. | ||||
|  * 7. Create table journal_components. | ||||
|  * 8. create entries for budgets in journal_components. | ||||
|  * 9. create entries for categories in journal_components. | ||||
|  * 10. drop table budget_journals | ||||
|  * 11. drop table category_journals | ||||
|  * 12. drop table budgets | ||||
|  * 13. drop table categories. | ||||
|  * 14. rename budget_limits to limits. | ||||
|  * 15. Rename piggy_bank_events to piggybank_events | ||||
|  * 16. Rename field 'budget_limit_id' to 'limit_id' in 'limit_repetitions' | ||||
|  * 17. Do not recreate component_recurring_transaction | ||||
|  * 18. Do not recreate component_transaction | ||||
|  * 19. Do not recreate field 'piggybank_id' in 'transactions' | ||||
|  * 20. Drop fields from currency table. | ||||
|  * | ||||
|  * | ||||
|  * | ||||
|  * Up: | ||||
|  * | ||||
|  * 1. Create new budget table. | ||||
|  * 2. Create new category table. | ||||
|  * 3. Create journal_budget table. | ||||
|  * 4. Create journal_category table. | ||||
|  * 5. Move budgets to new budgets table AND move journal_components to budget_components. | ||||
|  * 6. Move categories to categories table AND move journal_components to category_components. | ||||
|  * 7. Rename limits to budget_limits. | ||||
|  * 8. Rename piggybank_events to piggy_bank_events | ||||
|  * 9. Rename field 'limit_id' to 'budget_limit_id' in 'limit_repetitions' | ||||
|  * 10. Create field budget_id in budget_limits. | ||||
|  * 11. Update budget_limits with budgets (instead of components). | ||||
|  * 12. drop table journal_components | ||||
|  * 13. Drop table component_recurring_transaction | ||||
|  * 14. Drop table component_transaction | ||||
|  * 15. Drop field 'piggybank_id' from 'transactions' | ||||
|  * 16. Drop field 'component_id' from 'budget_limits' | ||||
|  * 17. Expand currency table with new fields. | ||||
|  * | ||||
|  * Class ChangesForV321 | ||||
|  */ | ||||
| class ChangesForV321 extends Migration | ||||
| { | ||||
|     public function down() | ||||
|     { | ||||
|  | ||||
|         $this->moveBudgetsBack(); // 1. | ||||
|         $this->moveCategoriesBack(); // 2. | ||||
|         $this->createComponentId(); // 3. | ||||
|         $this->updateComponentInBudgetLimits(); // 4. | ||||
|         $this->createComponentIdForeignKey(); // 5. | ||||
|         $this->dropBudgetIdColumnInBudgetLimits(); // 6. | ||||
|         $createComponents = new CreateComponentTransactionJournalTable;  // 7. | ||||
|         $createComponents->up(); | ||||
|         $this->moveBackEntriesForBudgetsInJoinedTable(); // 8. | ||||
|         $this->moveBackEntriesForCategoriesInJoinedTable(); // 9. | ||||
|         $this->dropBudgetJournalTable(); // 10. | ||||
|         $this->dropCategoryJournalTable(); // 11. | ||||
|         $this->dropBudgetTable(); // 12. | ||||
|         $this->dropCategoryTable(); // 13. | ||||
|         $this->renameBudgetLimits(); // 14. | ||||
|         $this->renamePiggyBankEvents(); // 15. | ||||
|         $this->renameBudgetLimitToBudgetInRepetitions(); // 16. | ||||
|         // 17, 18, 19 | ||||
|         $this->dropFieldsFromCurrencyTable(); // 20. | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public function moveBudgetsBack() | ||||
|     { | ||||
|         Budget::get()->each( | ||||
|             function (Budget $budget) { | ||||
|                 Component::firstOrCreate( | ||||
|                     [ | ||||
|                         'name'    => $budget->name, | ||||
|                         'user_id' => $budget->user_id, | ||||
|                         'class'   => 'Budget' | ||||
|                     ] | ||||
|                 ); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function moveCategoriesBack() | ||||
|     { | ||||
|         Category::get()->each( | ||||
|             function (Category $category) { | ||||
|                 Component::firstOrCreate( | ||||
|                     [ | ||||
|                         'name'    => $category->name, | ||||
|                         'user_id' => $category->user_id, | ||||
|                         'class'   => 'Category' | ||||
|                     ] | ||||
|                 ); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function createComponentId() | ||||
|     { | ||||
|         Schema::table( | ||||
|             'budget_limits', function (Blueprint $table) { | ||||
|             $table->integer('component_id')->unsigned(); | ||||
|         } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function updateComponentInBudgetLimits() | ||||
|     { | ||||
|         BudgetLimit::get()->each( | ||||
|             function (BudgetLimit $bl) { | ||||
|                 $budgetId = $bl->budget_id; | ||||
|                 $budget   = Budget::find($budgetId); | ||||
|                 if ($budget) { | ||||
|                     $component = Component::where('class', 'Budget')->where('user_id', $budget->user_id)->where('name', $budget->name)->first(); | ||||
|                     if ($component) { | ||||
|                         $bl->component_id = $component->id; | ||||
|                         $bl->save(); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function createComponentIdForeignKey() | ||||
|     { | ||||
|         Schema::table( | ||||
|             'budget_limits', function (Blueprint $table) { | ||||
|             $table->foreign('component_id', 'limits_component_id_foreign')->references('id')->on('components')->onDelete('cascade'); | ||||
|         } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function dropBudgetIdColumnInBudgetLimits() | ||||
|     { | ||||
|         Schema::table( | ||||
|             'budget_limits', function (Blueprint $table) { | ||||
|             $table->dropForeign('bid_foreign'); | ||||
|             $table->dropColumn('budget_id'); // also drop foreign key! | ||||
|         } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function moveBackEntriesForBudgetsInJoinedTable() | ||||
|     { | ||||
|         $set = DB::table('budget_transaction_journal')->get(); | ||||
|         foreach ($set as $entry) { | ||||
|             $budget = Budget::find($entry->budget_id); | ||||
|             if ($budget) { | ||||
|                 $component = Component::where('class', 'Budget')->where('name', $budget->name)->where('user_id', $budget->user_id)->first(); | ||||
|                 if ($component) { | ||||
|                     DB::table('component_transaction_journal')->insert( | ||||
|                         [ | ||||
|                             'component_id'           => $component->id, | ||||
|                             'transaction_journal_id' => $entry->transaction_journal_id | ||||
|                         ] | ||||
|                     ); | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public function moveBackEntriesForCategoriesInJoinedTable() | ||||
|     { | ||||
|         $set = DB::table('category_transaction_journal')->get(); | ||||
|         foreach ($set as $entry) { | ||||
|             $category = Category::find($entry->category_id); | ||||
|             if ($category) { | ||||
|                 $component = Component::where('class', 'Category')->where('name', $category->name)->where('user_id', $category->user_id)->first(); | ||||
|                 if ($component) { | ||||
|                     DB::table('component_transaction_journal')->insert( | ||||
|                         [ | ||||
|                             'component_id'           => $component->id, | ||||
|                             'transaction_journal_id' => $entry->transaction_journal_id | ||||
|                         ] | ||||
|                     ); | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public function dropBudgetJournalTable() | ||||
|     { | ||||
|         Schema::dropIfExists('budget_transaction_journal'); | ||||
|     } | ||||
|  | ||||
|     public function dropCategoryJournalTable() | ||||
|     { | ||||
|         Schema::dropIfExists('category_transaction_journal'); | ||||
|     } | ||||
|  | ||||
|     public function dropBudgetTable() | ||||
|     { | ||||
|         Schema::dropIfExists('budgets'); | ||||
|     } | ||||
|  | ||||
|     public function dropCategoryTable() | ||||
|     { | ||||
|         Schema::dropIfExists('categories'); | ||||
|     } | ||||
|  | ||||
|     public function renameBudgetLimits() | ||||
|     { | ||||
|         Schema::rename('budget_limits', 'limits'); | ||||
|     } | ||||
|  | ||||
|     public function renamePiggyBankEvents() | ||||
|     { | ||||
|         Schema::rename('piggy_bank_events', 'piggybank_events'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public function renameBudgetLimitToBudgetInRepetitions() | ||||
|     { | ||||
|         Schema::table( | ||||
|             'limit_repetitions', function (Blueprint $table) { | ||||
|             $table->renameColumn('budget_limit_id', 'limit_id'); | ||||
|         } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function dropFieldsFromCurrencyTable() | ||||
|     { | ||||
|  | ||||
|         Schema::table( | ||||
|             'transaction_currencies', function (Blueprint $table) { | ||||
|             $table->dropColumn('symbol'); | ||||
|             $table->dropColumn('name'); | ||||
|         } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function up() | ||||
|     { | ||||
|         $this->createBudgetTable(); // 1. | ||||
|         $this->createCategoryTable(); // 2. | ||||
|         $this->createBudgetJournalTable(); // 3 | ||||
|         $this->createCategoryJournalTable(); // 4. | ||||
|         $this->moveBudgets(); // 5. | ||||
|         $this->moveCategories(); // 6. | ||||
|         $this->correctNameForBudgetLimits(); // 7. | ||||
|         $this->correctNameForPiggyBankEvents(); // 8. | ||||
|         $this->renameBudgetToBudgetLimitInRepetitions(); // 9. | ||||
|         $this->addBudgetIdFieldToBudgetLimits(); // 10. | ||||
|         $this->moveComponentIdToBudgetId(); // 11. | ||||
|         $this->dropComponentJournalTable(); // 12. | ||||
|         $this->dropComponentRecurringTransactionTable(); // 13. | ||||
|         $this->dropComponentTransactionTable(); // 14. | ||||
|         $this->dropPiggyBankIdFromTransactions(); // 15. | ||||
|         $this->dropComponentIdFromBudgetLimits(); // 16. | ||||
|         $this->expandCurrencyTable(); // 17. | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public function createBudgetTable() | ||||
|     { | ||||
|         Schema::create( | ||||
|             'budgets', function (Blueprint $table) { | ||||
|             $table->increments('id'); | ||||
|             $table->timestamps(); | ||||
|             $table->softDeletes(); | ||||
|             $table->string('name', 50); | ||||
|             $table->integer('user_id')->unsigned(); | ||||
|             $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); | ||||
|             $table->unique(['user_id', 'name']); | ||||
|         } | ||||
|         ); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public function createCategoryTable() | ||||
|     { | ||||
|         Schema::create( | ||||
|             'categories', function (Blueprint $table) { | ||||
|             $table->increments('id'); | ||||
|             $table->timestamps(); | ||||
|             $table->softDeletes(); | ||||
|             $table->string('name', 50); | ||||
|             $table->integer('user_id')->unsigned(); | ||||
|             $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); | ||||
|             $table->unique(['user_id', 'name']); | ||||
|         } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function createBudgetJournalTable() | ||||
|     { | ||||
|         Schema::create( | ||||
|             'budget_transaction_journal', function (Blueprint $table) { | ||||
|             $table->increments('id'); | ||||
|             $table->integer('budget_id')->unsigned(); | ||||
|             $table->integer('transaction_journal_id')->unsigned(); | ||||
|             $table->foreign('budget_id')->references('id')->on('budgets')->onDelete('cascade'); | ||||
|             $table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade'); | ||||
|             $table->unique(['budget_id', 'transaction_journal_id'], 'budid_tjid_unique'); | ||||
|         } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function createCategoryJournalTable() | ||||
|     { | ||||
|         Schema::create( | ||||
|             'category_transaction_journal', function (Blueprint $table) { | ||||
|             $table->increments('id'); | ||||
|             $table->integer('category_id')->unsigned(); | ||||
|             $table->integer('transaction_journal_id')->unsigned(); | ||||
|             $table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade'); | ||||
|             $table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade'); | ||||
|             $table->unique(['category_id', 'transaction_journal_id'], 'catid_tjid_unique'); | ||||
|         } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function moveBudgets() | ||||
|     { | ||||
|         Component::where('class', 'Budget')->get()->each( | ||||
|             function (Component $c) { | ||||
|                 $entry  = [ | ||||
|                     'user_id' => $c->user_id, | ||||
|                     'name'    => $c->name | ||||
|  | ||||
|                 ]; | ||||
|                 $budget = Budget::firstOrCreate($entry); | ||||
|                 Log::debug('Migrated budget #' . $budget->id . ': ' . $budget->name); | ||||
|                 // create entry in budget_transaction_journal | ||||
|                 $connections = DB::table('component_transaction_journal')->where('component_id', $c->id)->get(); | ||||
|                 foreach ($connections as $connection) { | ||||
|                     DB::table('budget_transaction_journal')->insert( | ||||
|                         [ | ||||
|                             'budget_id'              => $budget->id, | ||||
|                             'transaction_journal_id' => $connection->transaction_journal_id | ||||
|                         ] | ||||
|                     ); | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function moveCategories() | ||||
|     { | ||||
|         Component::where('class', 'Category')->get()->each( | ||||
|             function (Component $c) { | ||||
|                 $entry    = [ | ||||
|                     'user_id' => $c->user_id, | ||||
|                     'name'    => $c->name | ||||
|  | ||||
|                 ]; | ||||
|                 $category = Category::firstOrCreate($entry); | ||||
|                 Log::debug('Migrated category #' . $category->id . ': ' . $category->name); | ||||
|                 // create entry in category_transaction_journal | ||||
|                 $connections = DB::table('component_transaction_journal')->where('component_id', $c->id)->get(); | ||||
|                 foreach ($connections as $connection) { | ||||
|                     DB::table('category_transaction_journal')->insert( | ||||
|                         [ | ||||
|                             'category_id'            => $category->id, | ||||
|                             'transaction_journal_id' => $connection->transaction_journal_id | ||||
|                         ] | ||||
|                     ); | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function correctNameForBudgetLimits() | ||||
|     { | ||||
|         Schema::rename('limits', 'budget_limits'); | ||||
|     } | ||||
|  | ||||
|     public function correctNameForPiggyBankEvents() | ||||
|     { | ||||
|         Schema::rename('piggybank_events', 'piggy_bank_events'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public function renameBudgetToBudgetLimitInRepetitions() | ||||
|     { | ||||
|         Schema::table( | ||||
|             'limit_repetitions', function (Blueprint $table) { | ||||
|             $table->renameColumn('limit_id', 'budget_limit_id'); | ||||
|         } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function addBudgetIdFieldToBudgetLimits() | ||||
|     { | ||||
|         Schema::table( | ||||
|             'budget_limits', function (Blueprint $table) { | ||||
|             $table->integer('budget_id', false, true)->nullable()->after('updated_at'); | ||||
|             $table->foreign('budget_id', 'bid_foreign')->references('id')->on('budgets')->onDelete('cascade'); | ||||
|         } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function moveComponentIdToBudgetId() | ||||
|     { | ||||
|         \Log::debug('Now in moveComponentIdToBudgetId()'); | ||||
|         BudgetLimit::get()->each( | ||||
|             function (BudgetLimit $bl) { | ||||
|                 \Log::debug('Now at budgetLimit #' . $bl->id . ' with component_id: ' . $bl->component_id); | ||||
|                 $component = Component::find($bl->component_id); | ||||
|                 if ($component) { | ||||
|                     \Log::debug('Found component with id #' . $component->id . ' and name ' . $component->name); | ||||
|                     $budget = Budget::whereName($component->name)->whereUserId($component->user_id)->first(); | ||||
|                     if ($budget) { | ||||
|                         \Log::debug('Found a budget with ID #' . $budget->id . ' and name ' . $budget->name); | ||||
|                         $bl->budget_id = $budget->id; | ||||
|                         $bl->save(); | ||||
|                         \Log::debug('Connected budgetLimit #' . $bl->id . ' to budget_id' . $budget->id); | ||||
|                     } else { | ||||
|                         \Log::debug('Could not find a matching budget with name ' . $component->name); | ||||
|                     } | ||||
|                 } else { | ||||
|                     \Log::debug('Could not find a component with id ' . $bl->component_id); | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|         \Log::debug('Done with moveComponentIdToBudgetId()'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public function dropComponentJournalTable() | ||||
|     { | ||||
|         Schema::dropIfExists('component_transaction_journal'); | ||||
|     } | ||||
|  | ||||
|     public function dropComponentRecurringTransactionTable() | ||||
|     { | ||||
|         Schema::dropIfExists('component_recurring_transaction'); | ||||
|     } | ||||
|  | ||||
|     public function dropComponentTransactionTable() | ||||
|     { | ||||
|         Schema::dropIfExists('component_transaction'); | ||||
|     } | ||||
|  | ||||
|     public function dropPiggyBankIdFromTransactions() | ||||
|     { | ||||
|  | ||||
|         Schema::table( | ||||
|             'transactions', function (Blueprint $table) { | ||||
|             if (Schema::hasColumn('transactions', 'piggybank_id')) { | ||||
|                 $table->dropForeign('transactions_piggybank_id_foreign'); | ||||
|                 $table->dropColumn('piggybank_id'); | ||||
|             } | ||||
|         } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function dropComponentIdFromBudgetLimits() | ||||
|     { | ||||
|         Schema::table( | ||||
|             'budget_limits', function (Blueprint $table) { | ||||
|             $table->dropForeign('limits_component_id_foreign'); | ||||
|             $table->dropColumn('component_id'); | ||||
|         } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function expandCurrencyTable() | ||||
|     { | ||||
|         Schema::table( | ||||
|             'transaction_currencies', function (Blueprint $table) { | ||||
|             $table->string('name', 48)->nullable(); | ||||
|             $table->string('symbol', 8)->nullable(); | ||||
|         } | ||||
|         ); | ||||
|         \DB::update('UPDATE `transaction_currencies` SET `symbol` = "€", `name` = "Euro" WHERE `code` = "EUR";'); | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										168
									
								
								app/database/migrations/2014_12_24_191544_changes_for_v322.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								app/database/migrations/2014_12_24_191544_changes_for_v322.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,168 @@ | ||||
| <?php | ||||
|  | ||||
| use Illuminate\Database\Migrations\Migration; | ||||
| use Illuminate\Database\Schema\Blueprint; | ||||
|  | ||||
| /** | ||||
|  * Class ChangesForV322 | ||||
|  */ | ||||
| class ChangesForV322 extends Migration | ||||
| { | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         // rename tables: | ||||
|         Schema::rename('piggy_bank_repetitions', 'piggybank_repetitions'); | ||||
|         Schema::rename('piggy_banks', 'piggybanks'); | ||||
|  | ||||
|         // rename fields | ||||
|         Schema::table( | ||||
|             'piggy_bank_events', function (Blueprint $table) { | ||||
|             $table->renameColumn('piggy_bank_id', 'piggybank_id'); | ||||
|         } | ||||
|         ); | ||||
|  | ||||
|         Schema::table( | ||||
|             'piggybank_repetitions', function (Blueprint $table) { | ||||
|             $table->renameColumn('piggy_bank_id', 'piggybank_id'); | ||||
|         } | ||||
|         ); | ||||
|  | ||||
|         // remove soft delete to piggy banks | ||||
|         Schema::table( | ||||
|             'piggybanks', function (Blueprint $table) { | ||||
|             $table->dropSoftDeletes(); | ||||
|         } | ||||
|         ); | ||||
|  | ||||
|         // drop keys from bills (foreign bills_uid_for and unique uid_name_unique) | ||||
|         Schema::table( | ||||
|             'bills', function (Blueprint $table) { | ||||
|             $table->dropForeign('bills_uid_for'); | ||||
|             $table->dropUnique('uid_name_unique'); | ||||
|         } | ||||
|         ); | ||||
|         // drop foreign key from transaction_journals (bill_id_foreign) | ||||
|         Schema::table( | ||||
|             'transaction_journals', function (Blueprint $table) { | ||||
|             $table->dropForeign('bill_id_foreign'); | ||||
|  | ||||
|         } | ||||
|         ); | ||||
|  | ||||
|         // drop foreign key from budget_limits: | ||||
|         Schema::table( | ||||
|             'budget_limits', function (Blueprint $table) { | ||||
|             $table->dropForeign('bid_foreign'); | ||||
|             $table->dropUnique('unique_bl_combi'); | ||||
|         } | ||||
|         ); | ||||
|  | ||||
|         // rename bills to recurring_transactions | ||||
|         Schema::rename('bills', 'recurring_transactions'); | ||||
|         // recreate foreign key recurring_transactions_user_id_foreign in recurring_transactions | ||||
|         // recreate unique recurring_transactions_user_id_name_unique in recurring_transactions | ||||
|         Schema::table( | ||||
|             'recurring_transactions', function (Blueprint $table) { | ||||
|             $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); | ||||
|             $table->unique(['user_id', 'name']); | ||||
|         } | ||||
|         ); | ||||
|  | ||||
|         // rename bill_id to recurring_transaction_id | ||||
|         // recreate foreign transaction_journals_recurring_transaction_id_foreign in transaction_journals | ||||
|         Schema::table( | ||||
|             'transaction_journals', function (Blueprint $table) { | ||||
|             $table->renameColumn('bill_id', 'recurring_transaction_id'); | ||||
|             $table->foreign('recurring_transaction_id')->references('id')->on('recurring_transactions')->onDelete('set null'); | ||||
|         } | ||||
|         ); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function up() | ||||
|     { | ||||
|         // rename tables: | ||||
|         Schema::rename('piggybank_repetitions', 'piggy_bank_repetitions'); | ||||
|         Schema::rename('piggybanks', 'piggy_banks'); | ||||
|  | ||||
|         // recreate it the correct way: | ||||
|         Schema::table( | ||||
|             'budget_limits', function (Blueprint $table) { | ||||
|             $table->unique(['budget_id', 'startdate', 'repeat_freq'], 'unique_bl_combi'); | ||||
|         } | ||||
|         ); | ||||
|  | ||||
|         // rename fields | ||||
|         Schema::table( | ||||
|             'piggy_bank_events', function (Blueprint $table) { | ||||
|             $table->renameColumn('piggybank_id', 'piggy_bank_id'); | ||||
|         } | ||||
|         ); | ||||
|  | ||||
|         Schema::table( | ||||
|             'piggy_bank_repetitions', function (Blueprint $table) { | ||||
|             $table->renameColumn('piggybank_id', 'piggy_bank_id'); | ||||
|         } | ||||
|         ); | ||||
|  | ||||
|         // add soft delete to piggy banks | ||||
|         Schema::table( | ||||
|             'piggy_banks', function (Blueprint $table) { | ||||
|             $table->softDeletes(); | ||||
|         } | ||||
|         ); | ||||
|  | ||||
|         // rename everything related to recurring transactions, aka bills: | ||||
|         Schema::table( | ||||
|             'transaction_journals', function (Blueprint $table) { | ||||
|  | ||||
|  | ||||
|             // drop relation | ||||
|             $table->dropForeign('transaction_journals_recurring_transaction_id_foreign'); | ||||
|             // rename column | ||||
|             $table->renameColumn('recurring_transaction_id', 'bill_id'); | ||||
|  | ||||
|         } | ||||
|         ); | ||||
|  | ||||
|         Schema::table( | ||||
|             'recurring_transactions', function (Blueprint $table) { | ||||
|             $table->dropForeign('recurring_transactions_user_id_foreign'); | ||||
|             $table->dropUnique('recurring_transactions_user_id_name_unique'); | ||||
|         } | ||||
|         ); | ||||
|         // rename table: | ||||
|         Schema::rename('recurring_transactions', 'bills'); | ||||
|  | ||||
|         // recreate foreign relation: | ||||
|         Schema::table( | ||||
|             'transaction_journals', function (Blueprint $table) { | ||||
|             $table->foreign('bill_id', 'bill_id_foreign')->references('id')->on('bills')->onDelete('set null'); | ||||
|         } | ||||
|         ); | ||||
|  | ||||
|         // recreate more foreign relations. | ||||
|         Schema::table( | ||||
|             'bills', function (Blueprint $table) { | ||||
|             // connect user id to users | ||||
|             $table->foreign('user_id', 'bills_uid_for')->references('id')->on('users')->onDelete('cascade'); | ||||
|  | ||||
|             // for a user, the name must be unique | ||||
|             $table->unique(['user_id', 'name'], 'uid_name_unique'); | ||||
|         } | ||||
|         ); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -38,4 +38,4 @@ class AccountTypeSeeder extends Seeder | ||||
|     } | ||||
|  | ||||
|  | ||||
| }  | ||||
| }  | ||||
|   | ||||
| @@ -19,6 +19,7 @@ class DatabaseSeeder extends Seeder | ||||
|         $this->call('TransactionCurrencySeeder'); | ||||
|         $this->call('TransactionTypeSeeder'); | ||||
|         $this->call('DefaultUserSeeder'); | ||||
|         $this->call('TestContentSeeder'); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -8,17 +8,15 @@ class DefaultUserSeeder extends Seeder | ||||
|     public function run() | ||||
|     { | ||||
|         DB::table('users')->delete(); | ||||
|         if (App::environment() == 'testing' || App::environment() == 'homestead') { | ||||
|  | ||||
|         User::create( | ||||
|             [ | ||||
|                 'email'          => 's@nder.be', | ||||
|                 'password'       => 'sander', | ||||
|                 'reset'          => null, | ||||
|                 'remember_token' => null, | ||||
|                 'migrated'       => 0 | ||||
|             ] | ||||
|         ); | ||||
|             User::create(['email' => 'thegrumpydictator@gmail.com', 'password' => 'james', 'reset' => null, 'remember_token' => null]); | ||||
|             User::create(['email' => 'acceptance@example.com', 'password' => 'acceptance', 'reset' => null, 'remember_token' => null]); | ||||
|             User::create(['email' => 'functional@example.com', 'password' => 'functional', 'reset' => null, 'remember_token' => null]); | ||||
|             User::create(['email' => 'reset@example.com', 'password' => 'functional', 'reset' => 'okokokokokokokokokokokokokokokok', 'remember_token' => null]); | ||||
|  | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
| }  | ||||
| }  | ||||
|   | ||||
							
								
								
									
										561
									
								
								app/database/seeds/TestContentSeeder.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										561
									
								
								app/database/seeds/TestContentSeeder.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,561 @@ | ||||
| <?php | ||||
|  | ||||
| use Carbon\Carbon; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @SuppressWarnings("CamelCase") // I'm fine with this. | ||||
|  * | ||||
|  * Class TestContentSeeder | ||||
|  */ | ||||
| class TestContentSeeder extends Seeder | ||||
| { | ||||
|     /** @var  string */ | ||||
|     public $eom; | ||||
|     /** @var  string */ | ||||
|     public $neom; | ||||
|     /** @var  string */ | ||||
|     public $nsom; | ||||
|     /** @var  string */ | ||||
|     public $som; | ||||
|     /** @var  string */ | ||||
|     public $today; | ||||
|     /** @var  string */ | ||||
|     public $yaeom; | ||||
|     /** @var  string */ | ||||
|     public $yasom; | ||||
|     /** @var Carbon */ | ||||
|     protected $_endOfMonth; | ||||
|     /** @var Carbon */ | ||||
|     protected $_nextEndOfMonth; | ||||
|     /** @var Carbon */ | ||||
|     protected $_nextStartOfMonth; | ||||
|     /** @var Carbon */ | ||||
|     protected $_startOfMonth; | ||||
|     /** @var  Carbon */ | ||||
|     protected $_today; | ||||
|     /** @var  Carbon */ | ||||
|     protected $_yearAgoEndOfMonth; | ||||
|     /** @var  Carbon */ | ||||
|     protected $_yearAgoStartOfMonth; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->_startOfMonth = Carbon::now()->startOfMonth(); | ||||
|         $this->som           = $this->_startOfMonth->format('Y-m-d'); | ||||
|  | ||||
|         $this->_endOfMonth = Carbon::now()->endOfMonth(); | ||||
|         $this->eom         = $this->_endOfMonth->format('Y-m-d'); | ||||
|  | ||||
|         $this->_nextStartOfMonth = Carbon::now()->addMonth()->startOfMonth(); | ||||
|         $this->nsom              = $this->_nextStartOfMonth->format('Y-m-d'); | ||||
|  | ||||
|         $this->_nextEndOfMonth = Carbon::now()->addMonth()->endOfMonth(); | ||||
|         $this->neom            = $this->_nextEndOfMonth->format('Y-m-d'); | ||||
|  | ||||
|         $this->_yearAgoStartOfMonth = Carbon::now()->subYear()->startOfMonth(); | ||||
|         $this->yasom                = $this->_yearAgoStartOfMonth->format('Y-m-d'); | ||||
|  | ||||
|         $this->_yearAgoEndOfMonth = Carbon::now()->subYear()->startOfMonth(); | ||||
|         $this->yaeom              = $this->_yearAgoEndOfMonth->format('Y-m-d'); | ||||
|  | ||||
|  | ||||
|         $this->_today = Carbon::now(); | ||||
|         $this->today  = $this->_today->format('Y-m-d'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Dates are always this month, the start of this month or earlier. | ||||
|      */ | ||||
|     public function run() | ||||
|     { | ||||
|         if (App::environment() == 'testing' || App::environment() == 'homestead') { | ||||
|  | ||||
|             $user = User::whereEmail('thegrumpydictator@gmail.com')->first(); | ||||
|  | ||||
|             // create initial accounts and various other stuff: | ||||
|             $this->createAssetAccounts($user); | ||||
|             $this->createBudgets($user); | ||||
|             $this->createCategories($user); | ||||
|             $this->createPiggyBanks($user); | ||||
|             $this->createReminders($user); | ||||
|             $this->createRecurringTransactions($user); | ||||
|             $this->createBills($user); | ||||
|             $this->createExpenseAccounts($user); | ||||
|             $this->createRevenueAccounts($user); | ||||
|  | ||||
|             // get some objects from the database: | ||||
|             $checking   = Account::whereName('Checking account')->orderBy('id', 'DESC')->first(); | ||||
|             $savings    = Account::whereName('Savings account')->orderBy('id', 'DESC')->first(); | ||||
|             $landLord   = Account::whereName('Land lord')->orderBy('id', 'DESC')->first(); | ||||
|             $utilities  = Account::whereName('Utilities company')->orderBy('id', 'DESC')->first(); | ||||
|             $television = Account::whereName('TV company')->orderBy('id', 'DESC')->first(); | ||||
|             $phone      = Account::whereName('Phone agency')->orderBy('id', 'DESC')->first(); | ||||
|             $employer   = Account::whereName('Employer')->orderBy('id', 'DESC')->first(); | ||||
|  | ||||
|  | ||||
|             $bills     = Budget::whereName('Bills')->orderBy('id', 'DESC')->first(); | ||||
|             $groceries = Budget::whereName('Groceries')->orderBy('id', 'DESC')->first(); | ||||
|  | ||||
|             $house = Category::whereName('House')->orderBy('id', 'DESC')->first(); | ||||
|  | ||||
|  | ||||
|             $withdrawal = TransactionType::whereType('Withdrawal')->first(); | ||||
|             $deposit    = TransactionType::whereType('Deposit')->first(); | ||||
|             $transfer   = TransactionType::whereType('Transfer')->first(); | ||||
|  | ||||
|             $euro = TransactionCurrency::whereCode('EUR')->first(); | ||||
|  | ||||
|             $rentBill = Bill::where('name', 'Rent')->first(); | ||||
|  | ||||
|  | ||||
|             $current = clone $this->_yearAgoStartOfMonth; | ||||
|             while ($current <= $this->_startOfMonth) { | ||||
|                 $cur       = $current->format('Y-m-d'); | ||||
|                 $formatted = $current->format('F Y'); | ||||
|  | ||||
|                 // create expenses for rent, utilities, TV, phone on the 1st of the month. | ||||
|                 $this->createTransaction($checking, $landLord, 800, $withdrawal, 'Rent for ' . $formatted, $cur, $euro, $bills, $house, $rentBill); | ||||
|                 $this->createTransaction($checking, $utilities, 150, $withdrawal, 'Utilities for ' . $formatted, $cur, $euro, $bills, $house); | ||||
|                 $this->createTransaction($checking, $television, 50, $withdrawal, 'TV for ' . $formatted, $cur, $euro, $bills, $house); | ||||
|                 $this->createTransaction($checking, $phone, 50, $withdrawal, 'Phone bill for ' . $formatted, $cur, $euro, $bills, $house); | ||||
|  | ||||
|                 // two transactions. One without a budget, one without a category. | ||||
|                 $this->createTransaction($checking, $phone, 10, $withdrawal, 'Extra charges on phone bill for ' . $formatted, $cur, $euro, null, $house); | ||||
|                 $this->createTransaction($checking, $television, 5, $withdrawal, 'Extra charges on TV bill for ' . $formatted, $cur, $euro, $bills, null); | ||||
|  | ||||
|                 // income from job: | ||||
|                 $this->createTransaction($employer, $checking, rand(3500, 4000), $deposit, 'Salary for ' . $formatted, $cur, $euro); | ||||
|                 $this->createTransaction($checking, $savings, 2000, $transfer, 'Salary to savings account in ' . $formatted, $cur, $euro); | ||||
|  | ||||
|                 $this->createGroceries($current); | ||||
|                 $this->createBigExpense(clone $current); | ||||
|  | ||||
|                 echo 'Created test-content for ' . $current->format('F Y') . "\n"; | ||||
|                 $current->addMonth(); | ||||
|             } | ||||
|  | ||||
|  | ||||
|             // piggy bank event | ||||
|             // add money to this piggy bank | ||||
|             // create a piggy bank event to match: | ||||
|             $piggyBank = PiggyBank::whereName('New camera')->orderBy('id', 'DESC')->first(); | ||||
|             $intoPiggy = $this->createTransaction($checking, $savings, 100, $transfer, 'Money for piggy', $this->yaeom, $euro, $groceries, $house); | ||||
|             PiggyBankEvent::create( | ||||
|                 [ | ||||
|                     'piggy_bank_id'          => $piggyBank->id, | ||||
|                     'transaction_journal_id' => $intoPiggy->id, | ||||
|                     'date'                   => $this->yaeom, | ||||
|                     'amount'                 => 100 | ||||
|                 ] | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param User $user | ||||
|      */ | ||||
|     public function createAssetAccounts(User $user) | ||||
|     { | ||||
|         $assetType = AccountType::whereType('Asset account')->first(); | ||||
|         $ibType    = AccountType::whereType('Initial balance account')->first(); | ||||
|         $obType    = TransactionType::whereType('Opening balance')->first(); | ||||
|         $euro      = TransactionCurrency::whereCode('EUR')->first(); | ||||
|  | ||||
|  | ||||
|         $acc_a = Account::create(['user_id' => $user->id, 'account_type_id' => $assetType->id, 'name' => 'Checking account', 'active' => 1]); | ||||
|         $acc_b = Account::create(['user_id' => $user->id, 'account_type_id' => $assetType->id, 'name' => 'Savings account', 'active' => 1]); | ||||
|         $acc_c = Account::create(['user_id' => $user->id, 'account_type_id' => $assetType->id, 'name' => 'Delete me', 'active' => 1]); | ||||
|  | ||||
|         $acc_d = Account::create(['user_id' => $user->id, 'account_type_id' => $ibType->id, 'name' => 'Checking account initial balance', 'active' => 0]); | ||||
|         $acc_e = Account::create(['user_id' => $user->id, 'account_type_id' => $ibType->id, 'name' => 'Savings account initial balance', 'active' => 0]); | ||||
|         $acc_f = Account::create(['user_id' => $user->id, 'account_type_id' => $ibType->id, 'name' => 'Delete me initial balance', 'active' => 0]); | ||||
|  | ||||
|  | ||||
|         $this->createTransaction($acc_d, $acc_a, 4000, $obType, 'Initial Balance for Checking account', $this->yasom, $euro); | ||||
|         $this->createTransaction($acc_e, $acc_b, 10000, $obType, 'Initial Balance for Savings account', $this->yasom, $euro); | ||||
|         $this->createTransaction($acc_f, $acc_c, 100, $obType, 'Initial Balance for Delete me', $this->yasom, $euro); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account              $from | ||||
|      * @param Account              $to | ||||
|      * @param                      $amount | ||||
|      * @param TransactionType      $type | ||||
|      * @param                      $description | ||||
|      * @param                      $date | ||||
|      * @param TransactionCurrency  $currency | ||||
|      * | ||||
|      * @param Budget               $budget | ||||
|      * @param Category             $category | ||||
|      * @param Bill                 $bill | ||||
|      * | ||||
|      * @return TransactionJournal | ||||
|      */ | ||||
|     public function createTransaction( | ||||
|         Account $from, Account $to, $amount, TransactionType $type, $description, $date, TransactionCurrency $currency, Budget $budget = null, | ||||
|         Category $category = null, Bill $bill = null | ||||
|     ) { | ||||
|         $user = User::whereEmail('thegrumpydictator@gmail.com')->first(); | ||||
|  | ||||
|         $billID = is_null($bill) ? null : $bill->id; | ||||
|  | ||||
|  | ||||
|         /** @var TransactionJournal $journal */ | ||||
|         $journal = TransactionJournal::create( | ||||
|             [ | ||||
|                 'user_id'     => $user->id, 'transaction_type_id' => $type->id, 'transaction_currency_id' => $currency->id, 'bill_id' => $billID, | ||||
|                 'description' => $description, 'completed' => 1, 'date' => $date | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|         Transaction::create(['account_id' => $from->id, 'transaction_journal_id' => $journal->id, 'amount' => $amount * -1]); | ||||
|         Transaction::create(['account_id' => $to->id, 'transaction_journal_id' => $journal->id, 'amount' => $amount]); | ||||
|  | ||||
|         if (!is_null($budget)) { | ||||
|             $journal->budgets()->save($budget); | ||||
|         } | ||||
|         if (!is_null($category)) { | ||||
|             $journal->categories()->save($category); | ||||
|         } | ||||
|  | ||||
|         return $journal; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param User $user | ||||
|      */ | ||||
|     public function createBudgets(User $user) | ||||
|     { | ||||
|  | ||||
|         $groceries = Budget::create(['user_id' => $user->id, 'name' => 'Groceries']); | ||||
|         $bills     = Budget::create(['user_id' => $user->id, 'name' => 'Bills']); | ||||
|         $deleteMe  = Budget::create(['user_id' => $user->id, 'name' => 'Delete me']); | ||||
|         Budget::create(['user_id' => $user->id, 'name' => 'Budget without repetition']); | ||||
|         $groceriesLimit = BudgetLimit::create( | ||||
|             ['startdate' => $this->som, 'amount' => 201, 'repeats' => 0, 'repeat_freq' => 'monthly', 'budget_id' => $groceries->id] | ||||
|         ); | ||||
|         $billsLimit     = BudgetLimit::create( | ||||
|             ['startdate' => $this->som, 'amount' => 202, 'repeats' => 0, 'repeat_freq' => 'monthly', 'budget_id' => $bills->id] | ||||
|         ); | ||||
|         $deleteMeLimit  = BudgetLimit::create( | ||||
|             ['startdate' => $this->som, 'amount' => 203, 'repeats' => 0, 'repeat_freq' => 'monthly', 'budget_id' => $deleteMe->id] | ||||
|         ); | ||||
|  | ||||
|         // and because we have no filters, some repetitions: | ||||
|         LimitRepetition::create(['budget_limit_id' => $groceriesLimit->id, 'startdate' => $this->som, 'enddate' => $this->eom, 'amount' => 201]); | ||||
|         LimitRepetition::create(['budget_limit_id' => $billsLimit->id, 'startdate' => $this->som, 'enddate' => $this->eom, 'amount' => 202]); | ||||
|         LimitRepetition::create(['budget_limit_id' => $deleteMeLimit->id, 'startdate' => $this->som, 'enddate' => $this->eom, 'amount' => 203]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param User $user | ||||
|      */ | ||||
|     public function createCategories(User $user) | ||||
|     { | ||||
|         Category::create(['user_id' => $user->id, 'name' => 'DailyGroceries']); | ||||
|         Category::create(['user_id' => $user->id, 'name' => 'Lunch']); | ||||
|         Category::create(['user_id' => $user->id, 'name' => 'House']); | ||||
|         Category::create(['user_id' => $user->id, 'name' => 'Delete me']); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param User $user | ||||
|      */ | ||||
|     public function createPiggyBanks(User $user) | ||||
|     { | ||||
|         // account | ||||
|         $savings = Account::whereName('Savings account')->orderBy('id', 'DESC')->first(); | ||||
|  | ||||
|         // some dates | ||||
|         $endDate  = clone $this->_startOfMonth; | ||||
|         $nextYear = clone $this->_startOfMonth; | ||||
|  | ||||
|         $endDate->addMonths(4); | ||||
|         $nextYear->addYear()->subDay(); | ||||
|  | ||||
|         $next = $nextYear->format('Y-m-d'); | ||||
|         $end  = $endDate->format('Y-m-d'); | ||||
|  | ||||
|         // piggy bank | ||||
|         $newCamera = PiggyBank::create( | ||||
|             [ | ||||
|                 'account_id'    => $savings->id, | ||||
|                 'name'          => 'New camera', | ||||
|                 'targetamount'  => 2000, | ||||
|                 'startdate'     => $this->som, | ||||
|                 'targetdate'    => null, | ||||
|                 'repeats'       => 0, | ||||
|                 'rep_length'    => null, | ||||
|                 'rep_every'     => 0, | ||||
|                 'rep_times'     => null, | ||||
|                 'reminder'      => null, | ||||
|                 'reminder_skip' => 0, | ||||
|                 'remind_me'     => 0, | ||||
|                 'order'         => 0, | ||||
|             ] | ||||
|         ); | ||||
|         // and some events! | ||||
|         PiggyBankEvent::create(['piggy_bank_id' => $newCamera->id, 'date' => $this->som, 'amount' => 100]); | ||||
|         PiggyBankRepetition::create(['piggy_bank_id' => $newCamera->id, 'startdate' => $this->som, 'targetdate' => null, 'currentamount' => 100]); | ||||
|  | ||||
|  | ||||
|         $newClothes = PiggyBank::create( | ||||
|             [ | ||||
|                 'account_id'    => $savings->id, | ||||
|                 'name'          => 'New clothes', | ||||
|                 'targetamount'  => 2000, | ||||
|                 'startdate'     => $this->som, | ||||
|                 'targetdate'    => $end, | ||||
|                 'repeats'       => 0, | ||||
|                 'rep_length'    => null, | ||||
|                 'rep_every'     => 0, | ||||
|                 'rep_times'     => null, | ||||
|                 'reminder'      => null, | ||||
|                 'reminder_skip' => 0, | ||||
|                 'remind_me'     => 0, | ||||
|                 'order'         => 0, | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|         PiggyBankEvent::create(['piggy_bank_id' => $newClothes->id, 'date' => $this->som, 'amount' => 100]); | ||||
|         PiggyBankRepetition::create(['piggy_bank_id' => $newClothes->id, 'startdate' => $this->som, 'targetdate' => $end, 'currentamount' => 100]); | ||||
|  | ||||
|         // weekly reminder piggy bank | ||||
|         $weekly = PiggyBank::create( | ||||
|             [ | ||||
|                 'account_id'    => $savings->id, | ||||
|                 'name'          => 'Weekly reminder for clothes', | ||||
|                 'targetamount'  => 2000, | ||||
|                 'startdate'     => $this->som, | ||||
|                 'targetdate'    => $next, | ||||
|                 'repeats'       => 0, | ||||
|                 'rep_length'    => null, | ||||
|                 'rep_every'     => 0, | ||||
|                 'rep_times'     => null, | ||||
|                 'reminder'      => 'week', | ||||
|                 'reminder_skip' => 0, | ||||
|                 'remind_me'     => 1, | ||||
|                 'order'         => 0, | ||||
|             ] | ||||
|         ); | ||||
|         PiggyBankRepetition::create(['piggy_bank_id' => $weekly->id, 'startdate' => $this->som, 'targetdate' => $next, 'currentamount' => 0]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param User $user | ||||
|      */ | ||||
|     public function createReminders(User $user) | ||||
|     { | ||||
|         // for weekly piggy bank (clothes) | ||||
|         $nextWeek  = clone $this->_startOfMonth; | ||||
|         $piggyBank = PiggyBank::whereName('New clothes')->orderBy('id', 'DESC')->first(); | ||||
|         $nextWeek->addWeek(); | ||||
|         $week = $nextWeek->format('Y-m-d'); | ||||
|  | ||||
|         Reminder::create( | ||||
|             ['user_id'          => $user->id, 'startdate' => $this->som, 'enddate' => $week, 'active' => 1, 'notnow' => 0, | ||||
|              'remindersable_id' => $piggyBank->id, 'remindersable_type' => 'PiggyBank'] | ||||
|         ); | ||||
|  | ||||
|         // a fake reminder:: | ||||
|         Reminder::create( | ||||
|             ['user_id'            => $user->id, 'startdate' => $this->som, 'enddate' => $week, 'active' => 0, 'notnow' => 0, 'remindersable_id' => 40, | ||||
|              'remindersable_type' => 'Transaction'] | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param User $user | ||||
|      */ | ||||
|     public function createRecurringTransactions(User $user) | ||||
|     { | ||||
|         // account | ||||
|         $savings = Account::whereName('Savings account')->orderBy('id', 'DESC')->first(); | ||||
|  | ||||
|         $recurring = PiggyBank::create( | ||||
|             [ | ||||
|                 'account_id'    => $savings->id, | ||||
|                 'name'          => 'Nieuwe spullen', | ||||
|                 'targetamount'  => 1000, | ||||
|                 'startdate'     => $this->som, | ||||
|                 'targetdate'    => $this->eom, | ||||
|                 'repeats'       => 1, | ||||
|                 'rep_length'    => 'month', | ||||
|                 'rep_every'     => 0, | ||||
|                 'rep_times'     => 0, | ||||
|                 'reminder'      => 'month', | ||||
|                 'reminder_skip' => 0, | ||||
|                 'remind_me'     => 1, | ||||
|                 'order'         => 0, | ||||
|             ] | ||||
|         ); | ||||
|         PiggyBankRepetition::create(['piggy_bank_id' => $recurring->id, 'startdate' => $this->som, 'targetdate' => $this->eom, 'currentamount' => 0]); | ||||
|         PiggyBankRepetition::create( | ||||
|             ['piggy_bank_id' => $recurring->id, 'startdate' => $this->nsom, 'targetdate' => $this->neom, 'currentamount' => 0] | ||||
|         ); | ||||
|         Reminder::create( | ||||
|             ['user_id'          => $user->id, 'startdate' => $this->som, 'enddate' => $this->neom, 'active' => 1, 'notnow' => 0, | ||||
|              'remindersable_id' => $recurring->id, 'remindersable_type' => 'PiggyBank'] | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $user | ||||
|      */ | ||||
|     public function createBills($user) | ||||
|     { | ||||
|         // bill | ||||
|         Bill::create( | ||||
|             [ | ||||
|                 'user_id'     => $user->id, 'name' => 'Rent', 'match' => 'rent,landlord', | ||||
|                 'amount_min'  => 700, | ||||
|                 'amount_max'  => 900, | ||||
|                 'date'        => $this->som, | ||||
|                 'active'      => 1, | ||||
|                 'automatch'   => 1, | ||||
|                 'repeat_freq' => 'monthly', | ||||
|                 'skip'        => 0, | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|         // bill | ||||
|         Bill::create( | ||||
|             [ | ||||
|                 'user_id'     => $user->id, | ||||
|                 'name'        => 'Gas licht', | ||||
|                 'match'       => 'no,match', | ||||
|                 'amount_min'  => 500, | ||||
|                 'amount_max'  => 700, | ||||
|                 'date'        => $this->som, | ||||
|                 'active'      => 1, | ||||
|                 'automatch'   => 1, | ||||
|                 'repeat_freq' => 'monthly', | ||||
|                 'skip'        => 0, | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|         // bill | ||||
|         Bill::create( | ||||
|             [ | ||||
|                 'user_id'     => $user->id, | ||||
|                 'name'        => 'Something something', | ||||
|                 'match'       => 'mumble,mumble', | ||||
|                 'amount_min'  => 500, | ||||
|                 'amount_max'  => 700, | ||||
|                 'date'        => $this->som, | ||||
|                 'active'      => 0, | ||||
|                 'automatch'   => 1, | ||||
|                 'repeat_freq' => 'monthly', | ||||
|                 'skip'        => 0, | ||||
|             ] | ||||
|         ); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $user | ||||
|      */ | ||||
|     public function createExpenseAccounts($user) | ||||
|     { | ||||
|         //// create expenses for rent, utilities, water, TV, phone on the 1st of the month. | ||||
|         $expenseType = AccountType::whereType('Expense account')->first(); | ||||
|  | ||||
|         Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Land lord', 'active' => 1]); | ||||
|         Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Utilities company', 'active' => 1]); | ||||
|         Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Water company', 'active' => 1]); | ||||
|         Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'TV company', 'active' => 1]); | ||||
|         Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Phone agency', 'active' => 1]); | ||||
|         Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Super savers', 'active' => 1]); | ||||
|         Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Groceries House', 'active' => 1]); | ||||
|         Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Lunch House', 'active' => 1]); | ||||
|  | ||||
|  | ||||
|         Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Buy More', 'active' => 1]); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $user | ||||
|      */ | ||||
|     public function createRevenueAccounts($user) | ||||
|     { | ||||
|         $revenueType = AccountType::whereType('Revenue account')->first(); | ||||
|  | ||||
|         Account::create(['user_id' => $user->id, 'account_type_id' => $revenueType->id, 'name' => 'Employer', 'active' => 1]); | ||||
|         Account::create(['user_id' => $user->id, 'account_type_id' => $revenueType->id, 'name' => 'IRS', 'active' => 1]); | ||||
|         Account::create(['user_id' => $user->id, 'account_type_id' => $revenueType->id, 'name' => 'Second job employer', 'active' => 1]); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $date | ||||
|      */ | ||||
|     public function createGroceries(Carbon $date) | ||||
|     { | ||||
|         // variables we need: | ||||
|         $checking   = Account::whereName('Checking account')->orderBy('id', 'DESC')->first(); | ||||
|         $shopOne    = Account::whereName('Groceries House')->orderBy('id', 'DESC')->first(); | ||||
|         $shopTwo    = Account::whereName('Super savers')->orderBy('id', 'DESC')->first(); | ||||
|         $lunchHouse = Account::whereName('Lunch House')->orderBy('id', 'DESC')->first(); | ||||
|         $lunch      = Category::whereName('Lunch')->orderBy('id', 'DESC')->first(); | ||||
|         $daily      = Category::whereName('DailyGroceries')->orderBy('id', 'DESC')->first(); | ||||
|         $euro       = TransactionCurrency::whereCode('EUR')->first(); | ||||
|         $withdrawal = TransactionType::whereType('Withdrawal')->first(); | ||||
|         $groceries  = Budget::whereName('Groceries')->orderBy('id', 'DESC')->first(); | ||||
|  | ||||
|  | ||||
|         $shops = [$shopOne, $shopTwo]; | ||||
|  | ||||
|         // create groceries and lunch (daily, between 5 and 10 euro). | ||||
|         $mStart = clone $date; | ||||
|         $mEnd   = clone $date; | ||||
|         $mEnd->endOfMonth(); | ||||
|         while ($mStart <= $mEnd) { | ||||
|             $mFormat = $mStart->format('Y-m-d'); | ||||
|             $shop    = $shops[rand(0, 1)]; | ||||
|  | ||||
|             $this->createTransaction($checking, $shop, (rand(500, 1000) / 100), $withdrawal, 'Groceries', $mFormat, $euro, $groceries, $daily); | ||||
|             $this->createTransaction($checking, $lunchHouse, (rand(200, 600) / 100), $withdrawal, 'Lunch', $mFormat, $euro, $groceries, $lunch); | ||||
|  | ||||
|             $mStart->addDay(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $date | ||||
|      */ | ||||
|     public function createBigExpense($date) | ||||
|     { | ||||
|         $date->addDays(12); | ||||
|         $dollar     = TransactionCurrency::whereCode('USD')->first(); | ||||
|         $checking   = Account::whereName('Checking account')->orderBy('id', 'DESC')->first(); | ||||
|         $savings    = Account::whereName('Savings account')->orderBy('id', 'DESC')->first(); | ||||
|         $buyMore    = Account::whereName('Buy More')->orderBy('id', 'DESC')->first(); | ||||
|         $withdrawal = TransactionType::whereType('Withdrawal')->first(); | ||||
|         $transfer   = TransactionType::whereType('Transfer')->first(); | ||||
|         $user       = User::whereEmail('thegrumpydictator@gmail.com')->first(); | ||||
|  | ||||
|  | ||||
|         // create some big expenses, move some money around. | ||||
|         $amount = rand(500, 2000); | ||||
|         $one    = $this->createTransaction( | ||||
|             $savings, $checking, $amount, $transfer, 'Money for big expense in ' . $date->format('F Y'), $date->format('Y-m-d'), $dollar | ||||
|         ); | ||||
|         $two    = $this->createTransaction( | ||||
|             $checking, $buyMore, $amount, $withdrawal, 'Big expense in ' . $date->format('F Y'), $date->format('Y-m-d'), $dollar | ||||
|         ); | ||||
|         $group  = TransactionGroup::create( | ||||
|             [ | ||||
|                 'user_id'  => $user->id, | ||||
|                 'relation' => 'balance' | ||||
|             ] | ||||
|         ); | ||||
|         $group->transactionjournals()->save($one); | ||||
|         $group->transactionjournals()->save($two); | ||||
|     } | ||||
| }  | ||||
| @@ -10,9 +10,9 @@ class TransactionCurrencySeeder extends Seeder | ||||
|     { | ||||
|         DB::table('transaction_currencies')->delete(); | ||||
|  | ||||
|         TransactionCurrency::create( | ||||
|             ['code' => 'EUR'] | ||||
|         ); | ||||
|         TransactionCurrency::create(['code' => 'EUR','name' => 'Euro','symbol' => '€']); | ||||
|         TransactionCurrency::create(['code' => 'USD','name' => 'US Dollar','symbol' => '$']); | ||||
|         TransactionCurrency::create(['code' => 'HUF','name' => 'Hungarian forint','symbol' => 'Ft']); | ||||
|     } | ||||
|  | ||||
| }  | ||||
| }  | ||||
|   | ||||
| @@ -17,4 +17,4 @@ class TransactionTypeSeeder extends Seeder | ||||
|         TransactionType::create(['type' => 'Opening balance']); | ||||
|     } | ||||
|  | ||||
| }  | ||||
| }  | ||||
|   | ||||
| @@ -5,12 +5,17 @@ | ||||
| App::before( | ||||
|     function ($request) { | ||||
|  | ||||
|         // put IP in session if not already there. | ||||
|  | ||||
|         $reminders = []; | ||||
|  | ||||
|         if (Auth::check()) { | ||||
|             /** @var \Firefly\Helper\Toolkit\ToolkitInterface $toolkit */ | ||||
|             $toolkit = App::make('Firefly\Helper\Toolkit\ToolkitInterface'); | ||||
|             $toolkit->getDateRange(); | ||||
|             $toolkit->checkImportJobs(); | ||||
|             Filter::setSessionDateRange(); | ||||
|             Reminders::updateReminders(); | ||||
|             Steam::removeEmptyBudgetLimits(); | ||||
|             $reminders = Reminders::getReminders(); | ||||
|         } | ||||
|         View::share('reminders', $reminders); | ||||
|  | ||||
|     } | ||||
| ); | ||||
| @@ -67,6 +72,7 @@ Route::filter( | ||||
|         if (Auth::check()) { | ||||
|             return Redirect::to('/'); | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
| ); | ||||
|  | ||||
| @@ -88,3 +94,11 @@ Route::filter( | ||||
|         } | ||||
|     } | ||||
| ); | ||||
|  | ||||
| Route::filter( | ||||
|     'allow-register', function () { | ||||
|     if (Config::get('auth.allow_register') !== true) { | ||||
|         return View::make('error')->with('message', 'Not possible'); | ||||
|     } | ||||
| } | ||||
| ); | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| <?php | ||||
|  | ||||
| return array( | ||||
| return [ | ||||
|  | ||||
| 	/* | ||||
| 	|-------------------------------------------------------------------------- | ||||
| @@ -17,4 +17,4 @@ return array( | ||||
|  | ||||
| 	'next'     => 'Next »', | ||||
|  | ||||
| ); | ||||
| ]; | ||||
|   | ||||
| @@ -1,24 +1,24 @@ | ||||
| <?php | ||||
|  | ||||
| return array( | ||||
| return [ | ||||
|  | ||||
| 	/* | ||||
| 	|-------------------------------------------------------------------------- | ||||
| 	| Password Reminder Language Lines | ||||
| 	|-------------------------------------------------------------------------- | ||||
| 	| | ||||
| 	| The following language lines are the default lines which match reasons | ||||
| 	| that are given by the password broker for a password update attempt | ||||
| 	| has failed, such as for an invalid token or invalid new password. | ||||
| 	| | ||||
| 	*/ | ||||
|     /* | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | Password Reminder Language Lines | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | | ||||
|     | The following language lines are the default lines which match reasons | ||||
|     | that are given by the password broker for a password update attempt | ||||
|     | has failed, such as for an invalid token or invalid new password. | ||||
|     | | ||||
|     */ | ||||
|  | ||||
| 	"password" => "Passwords must be at least six characters and match the confirmation.", | ||||
|     "password" => "Passwords must be at least six characters and match the confirmation.", | ||||
|  | ||||
| 	"user" => "We can't find a user with that e-mail address.", | ||||
|     "user"     => "We can't find a user with that e-mail address.", | ||||
|  | ||||
| 	"token" => "This password reset token is invalid.", | ||||
|     "token"    => "This password reset token is invalid.", | ||||
|  | ||||
| 	"sent" => "Password reminder sent!", | ||||
|     "sent"     => "Password reminder sent!", | ||||
|  | ||||
| ); | ||||
| ]; | ||||
|   | ||||
| @@ -21,12 +21,12 @@ return [ | ||||
|     "alpha_num"            => "The :attribute may only contain letters and numbers.", | ||||
|     "array"                => "The :attribute must be an array.", | ||||
|     "before"               => "The :attribute must be a date before :date.", | ||||
|     "between"              => array( | ||||
|     "between"              => [ | ||||
|         "numeric" => "The :attribute must be between :min and :max.", | ||||
|         "file"    => "The :attribute must be between :min and :max kilobytes.", | ||||
|         "string"  => "The :attribute must be between :min and :max characters.", | ||||
|         "array"   => "The :attribute must have between :min and :max items.", | ||||
|     ), | ||||
|     ], | ||||
|     "confirmed"            => "The :attribute confirmation does not match.", | ||||
|     "date"                 => "The :attribute is not a valid date.", | ||||
|     "date_format"          => "The :attribute does not match the format :format.", | ||||
| @@ -39,19 +39,19 @@ return [ | ||||
|     "in"                   => "The selected :attribute is invalid.", | ||||
|     "integer"              => "The :attribute must be an integer.", | ||||
|     "ip"                   => "The :attribute must be a valid IP address.", | ||||
|     "max"                  => array( | ||||
|     "max"                  => [ | ||||
|         "numeric" => "The :attribute may not be greater than :max.", | ||||
|         "file"    => "The :attribute may not be greater than :max kilobytes.", | ||||
|         "string"  => "The :attribute may not be greater than :max characters.", | ||||
|         "array"   => "The :attribute may not have more than :max items.", | ||||
|     ), | ||||
|     ], | ||||
|     "mimes"                => "The :attribute must be a file of type: :values.", | ||||
|     "min"                  => array( | ||||
|     "min"                  => [ | ||||
|         "numeric" => "The :attribute must be at least :min.", | ||||
|         "file"    => "The :attribute must be at least :min kilobytes.", | ||||
|         "string"  => "The :attribute must be at least :min characters.", | ||||
|         "array"   => "The :attribute must have at least :min items.", | ||||
|     ), | ||||
|     ], | ||||
|     "not_in"               => "The selected :attribute is invalid.", | ||||
|     "numeric"              => "The :attribute must be a number.", | ||||
|     "regex"                => "The :attribute format is invalid.", | ||||
| @@ -62,12 +62,12 @@ return [ | ||||
|     "required_without"     => "The :attribute field is required when :values is not present.", | ||||
|     "required_without_all" => "The :attribute field is required when none of :values are present.", | ||||
|     "same"                 => "The :attribute and :other must match.", | ||||
|     "size"                 => array( | ||||
|     "size"                 => [ | ||||
|         "numeric" => "The :attribute must be :size.", | ||||
|         "file"    => "The :attribute must be :size kilobytes.", | ||||
|         "string"  => "The :attribute must be :size characters.", | ||||
|         "array"   => "The :attribute must contain :size items.", | ||||
|     ), | ||||
|     ], | ||||
|     "unique"               => "The :attribute has already been taken.", | ||||
|     "url"                  => "The :attribute format is invalid.", | ||||
|  | ||||
| @@ -82,11 +82,11 @@ return [ | ||||
|     | | ||||
|     */ | ||||
|  | ||||
|     'custom'               => array( | ||||
|         'attribute-name' => array( | ||||
|     'custom'               => [ | ||||
|         'attribute-name' => [ | ||||
|             'rule-name' => 'custom-message', | ||||
|         ), | ||||
|     ), | ||||
|         ], | ||||
|     ], | ||||
|     'alphabasic'                  => 'The :attribute field must consist of basic alphanumeric characters.', | ||||
|  | ||||
|     /* | ||||
| @@ -100,6 +100,6 @@ return [ | ||||
|     | | ||||
|     */ | ||||
|  | ||||
|     'attributes'           => array(), | ||||
|     'attributes'           => [], | ||||
|  | ||||
| ]; | ||||
|   | ||||
| @@ -1,121 +0,0 @@ | ||||
| <?php | ||||
| namespace Firefly\Database; | ||||
|  | ||||
| use LaravelBook\Ardent\Ardent; | ||||
|  | ||||
| /** | ||||
|  * Class SingleTableInheritanceEntity | ||||
|  * | ||||
|  * @package Firefly\Database | ||||
|  */ | ||||
| abstract class SingleTableInheritanceEntity extends Ardent | ||||
| { | ||||
|     /** | ||||
|      * The field that stores the subclass | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $subclassField = null; | ||||
|     /** | ||||
|      * must be overridden and set to true in subclasses | ||||
|      * | ||||
|      * @var bool | ||||
|      */ | ||||
|     protected $isSubclass = false; | ||||
|  | ||||
|     /** | ||||
|      * @param array $attributes | ||||
|      * | ||||
|      * @return \Illuminate\Database\Eloquent\Model|static | ||||
|      */ | ||||
|     public function newFromBuilder($attributes = []) | ||||
|     { | ||||
|         $instance = $this->mapData((array)$attributes)->newInstance([], true); | ||||
|         $instance->setRawAttributes((array)$attributes, true); | ||||
|  | ||||
|         return $instance; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * if no subclass is defined, function as normal | ||||
|      * | ||||
|      * @param array $attributes | ||||
|      * | ||||
|      * @return \Illuminate\Database\Eloquent\Model|static | ||||
|      */ | ||||
|     public function mapData(array $attributes) | ||||
|     { | ||||
|         if (!$this->subclassField) { | ||||
|             return $this->newInstance(); | ||||
|         } | ||||
|  | ||||
|         return new $attributes[$this->subclassField]; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * instead of using $this->newInstance(), call | ||||
|      * newInstance() on the object from mapData | ||||
|      * | ||||
|      * @param bool $excludeDeleted | ||||
|      * | ||||
|      * @return \Illuminate\Database\Eloquent\Builder|static | ||||
|      */ | ||||
|     public function newQuery($excludeDeleted = true) | ||||
|     { | ||||
|         // If using Laravel 4.0.x then use the following commented version of this command | ||||
|         // $builder = new Builder($this->newBaseQueryBuilder()); | ||||
|         // newEloquentBuilder() was added in 4.1 | ||||
|         $builder = $this->newEloquentBuilder($this->newBaseQueryBuilder()); | ||||
|  | ||||
|         // Once Firefly has the query builders, it will set the model instances so the | ||||
|         // builder can easily access any information it may need from the model | ||||
|         // while it is constructing and executing various queries against it. | ||||
|         $builder->setModel($this)->with($this->with); | ||||
|  | ||||
|         if ($excludeDeleted && $this->softDelete) { | ||||
|             $builder->whereNull($this->getQualifiedDeletedAtColumn()); | ||||
|         } | ||||
|  | ||||
|         if ($this->subclassField && $this->isSubclass()) { | ||||
|             $builder->where($this->subclassField, '=', get_class($this)); | ||||
|         } | ||||
|  | ||||
|         return $builder; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function isSubclass() | ||||
|     { | ||||
|         return $this->isSubclass; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * ensure that the subclass field is assigned on save | ||||
|      * | ||||
|      * @param array    $rules | ||||
|      * @param array    $customMessages | ||||
|      * @param array    $options | ||||
|      * @param callable $beforeSave | ||||
|      * @param callable $afterSave | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function save( | ||||
|         array $rules = [], | ||||
|         array $customMessages = [], | ||||
|         array $options = [], | ||||
|         \Closure $beforeSave = null, | ||||
|         \Closure $afterSave = null | ||||
|     ) { | ||||
|         if ($this->subclassField) { | ||||
|             $this->attributes[$this->subclassField] = get_class($this); | ||||
|         } | ||||
|  | ||||
|         return parent::save($rules, $customMessages, $options, $beforeSave, $afterSave); | ||||
|     } | ||||
| }  | ||||
| @@ -1,11 +0,0 @@ | ||||
| <?php | ||||
| namespace Firefly\Exception; | ||||
|  | ||||
| /** | ||||
|  * Class ValidationException | ||||
|  * | ||||
|  * @package Firefly\Exception | ||||
|  */ | ||||
| class ValidationException extends \Exception { | ||||
|  | ||||
| }  | ||||
| @@ -1,143 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Firefly\Helper\Controllers; | ||||
|  | ||||
| /** | ||||
|  * Class Account | ||||
|  * | ||||
|  * @package Firefly\Helper\Controllers | ||||
|  */ | ||||
| class Account implements AccountInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param \Account $account | ||||
|      * @return \TransactionJournal|null | ||||
|      */ | ||||
|     public function openingBalanceTransaction(\Account $account) | ||||
|     { | ||||
|         return \TransactionJournal::withRelevantData() | ||||
|                                   ->accountIs($account) | ||||
|                                   ->leftJoin('transaction_types', 'transaction_types.id', '=', | ||||
|                 'transaction_journals.transaction_type_id') | ||||
|                                   ->where('transaction_types.type', 'Opening balance') | ||||
|                                   ->first(['transaction_journals.*']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Since it is entirely possible the database is messed up somehow it might be that a transaction | ||||
|      * journal has only one transaction. This is mainly caused by wrong deletions and other artefacts from the past. | ||||
|      * | ||||
|      * If it is the case, Firefly removes $item and continues like nothing ever happened. This will however, | ||||
|      * mess up some statisics but it's decided everybody should learn to live with that. | ||||
|      * | ||||
|      * Firefly might be needing some cleanup routine in the future. | ||||
|      * | ||||
|      * For now, Firefly simply warns the user of this. | ||||
|      * | ||||
|      * @param \Account $account | ||||
|      * @param $perPage | ||||
|      * | ||||
|      * @return array|mixed | ||||
|      * @throws \Firefly\Exception\FireflyException | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      */ | ||||
|     public function show(\Account $account, $perPage) | ||||
|     { | ||||
|         $start = \Session::get('start'); | ||||
|         $end   = \Session::get('end'); | ||||
|         $stats = [ | ||||
|             'accounts' => [] | ||||
|         ]; | ||||
|         $items = []; | ||||
|  | ||||
|         // build a query: | ||||
|         $query = \TransactionJournal::withRelevantData() | ||||
|                                     ->defaultSorting() | ||||
|                                     ->accountIs($account) | ||||
|                                     ->after($start) | ||||
|                                     ->before($end); | ||||
|         // filter some: | ||||
|         switch (\Input::get('type')) { | ||||
|             case 'transactions': | ||||
|                 $query->transactionTypes(['Deposit', 'Withdrawal']); | ||||
|                 break; | ||||
|             case 'transfers': | ||||
|                 $query->transactionTypes(['Transfer']); | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         switch (\Input::get('show')) { | ||||
|             case 'expenses': | ||||
|             case 'out': | ||||
|                 $query->lessThan(0); | ||||
|                 break; | ||||
|             case 'income': | ||||
|             case 'in': | ||||
|                 $query->moreThan(0); | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         // build paginator: | ||||
|         $totalItems = $query->count(); | ||||
|         $page       = max(1, intval(\Input::get('page'))); | ||||
|         $skip       = ($page - 1) * $perPage; | ||||
|         $result     = $query->skip($skip)->take($perPage)->get(['transaction_journals.*']); | ||||
|  | ||||
|  | ||||
|         // get the relevant budgets, categories and accounts from this list: | ||||
|         /** @var $item \TransactionJournal */ | ||||
|         foreach ($result as $index => $item) { | ||||
|  | ||||
|             foreach ($item->components as $component) { | ||||
|                 $stats[$component->class][$component->id] = $component; | ||||
|             } | ||||
|  | ||||
|             if (count($item->transactions) < 2) { | ||||
|                 \Session::flash('warning', 'Some transactions are incomplete; they will not be shown.'); | ||||
|                 unset($result[$index]); | ||||
|                 continue; | ||||
|             } | ||||
|             $items[]                             = $item; | ||||
|             $fromAccount                         = $item->transactions[0]->account; | ||||
|             $toAccount                           = $item->transactions[1]->account; | ||||
|             $stats['accounts'][$fromAccount->id] = $fromAccount; | ||||
|             $stats['accounts'][$toAccount->id]   = $toAccount; | ||||
|         } | ||||
|         $paginator = \Paginator::make($items, $totalItems, $perPage); | ||||
|         unset($result, $page, $item, $fromAccount, $toAccount); | ||||
|  | ||||
|  | ||||
|         // statistics (transactions) | ||||
|         $trIn   = floatval(\Transaction::before($end)->after($start)->accountIs($account)->moreThan(0) | ||||
|                                        ->transactionTypes(['Deposit', 'Withdrawal'])->sum('transactions.amount')); | ||||
|         $trOut  = floatval(\Transaction::before($end)->after($start)->accountIs($account)->lessThan(0) | ||||
|                                        ->transactionTypes(['Deposit', 'Withdrawal'])->sum('transactions.amount')); | ||||
|         $trDiff = $trIn + $trOut; | ||||
|  | ||||
|         // statistics (transfers) | ||||
|         $trfIn   = floatval(\Transaction::before($end)->after($start)->accountIs($account)->moreThan(0) | ||||
|                                         ->transactionTypes(['Transfer'])->sum('transactions.amount')); | ||||
|         $trfOut  = floatval(\Transaction::before($end)->after($start)->accountIs($account)->lessThan(0) | ||||
|                                         ->transactionTypes(['Transfer'])->sum('transactions.amount')); | ||||
|         $trfDiff = $trfIn + $trfOut; | ||||
|  | ||||
|         $stats['period'] = [ | ||||
|             'in'     => $trIn, | ||||
|             'out'    => $trOut, | ||||
|             'diff'   => $trDiff, | ||||
|             't_in'   => $trfIn, | ||||
|             't_out'  => $trfOut, | ||||
|             't_diff' => $trfDiff | ||||
|  | ||||
|         ]; | ||||
|  | ||||
|         $return = [ | ||||
|             'journals'   => $paginator, | ||||
|             'statistics' => $stats | ||||
|         ]; | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
| }  | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user