mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-31 02:36:28 +00:00 
			
		
		
		
	Compare commits
	
		
			2156 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | e3de03e50d | ||
|  | d8b4af34e0 | ||
|  | 222d8e071a | ||
|  | 36c2f27d59 | ||
|  | 5d43faab96 | ||
|  | 07048cb5fb | ||
|  | 38c79c3dc4 | ||
|  | 7610d9e0db | ||
|  | e4f3d0a0ea | ||
|  | fdf147d9c6 | ||
|  | f7e418f517 | ||
|  | 738f6ed232 | ||
|  | 12217d9850 | ||
|  | 87c8b3d7c6 | ||
|  | fd571abbb0 | ||
|  | 64ae56757e | ||
|  | 7d75f00696 | ||
|  | 451c86e431 | ||
|  | c8c71da903 | ||
|  | 423f3a9296 | ||
|  | 7658b7d9a6 | ||
|  | 0d0906c5e2 | ||
|  | e0aa7f3ff5 | ||
|  | 59fdf5b77a | ||
|  | e28cfade8d | ||
|  | 19710c3eab | ||
|  | 0782354160 | ||
|  | 22bc6d507e | ||
|  | bf3c74e65f | ||
|  | 71fb9d8fa5 | ||
|  | 9a461fc7b7 | ||
|  | e0d87aa11e | ||
|  | b273af341c | ||
|  | 2117fc2a5a | ||
|  | 58e55dc789 | ||
|  | ac9b8b8c30 | ||
|  | 4dcc66238e | ||
|  | 90c0aa6360 | ||
|  | 1594335487 | ||
|  | 2517674849 | ||
|  | c00bc2a1f3 | ||
|  | f999be81c2 | ||
|  | e2530c5486 | ||
|  | 7526f13ca9 | ||
|  | ed08d299de | ||
|  | b6ea2f1c64 | ||
|  | 9ee14374bb | ||
|  | 925401682b | ||
|  | 53c71bb7a2 | ||
|  | 3c036ae021 | ||
|  | bf89d9956d | ||
|  | 71104f375c | ||
|  | 4c94820cf4 | ||
|  | 8998c9a672 | ||
|  | ccf60f4cdc | ||
|  | c5af1d363c | ||
|  | c6e3b54705 | ||
|  | 4f274a290e | ||
|  | 1774bcbabe | ||
|  | 492c11784b | ||
|  | 21ddbd220a | ||
|  | e4a95e55ed | ||
|  | 3a0eb5a428 | ||
|  | e55fd968cf | ||
|  | d41be08b48 | ||
|  | a18272513d | ||
|  | e88061199c | ||
|  | d0d7c437f2 | ||
|  | a1ac1a4a29 | ||
|  | 41d22876c4 | ||
|  | e1bb0298cb | ||
|  | 1ec2772255 | ||
|  | 40d77d82cd | ||
|  | 311d51464d | ||
|  | d63c9c9aea | ||
|  | f1e83f240e | ||
|  | b0f847959f | ||
|  | d3d4439b03 | ||
|  | 0e1da3f797 | ||
|  | def95df49e | ||
|  | 73c8c6de37 | ||
|  | 25b2b43a38 | ||
|  | 1fc2c998de | ||
|  | b7a577cc4c | ||
|  | 2cdedd9c29 | ||
|  | cf47daa2a0 | ||
|  | 926e2db1d6 | ||
|  | d092034ec5 | ||
|  | d13b9a0cc3 | ||
|  | bbbaf6c868 | ||
|  | 833add99a0 | ||
|  | b54e7f0d46 | ||
|  | a90981481f | ||
|  | edff3d7fb0 | ||
|  | 88d65b4784 | ||
|  | 6db869de23 | ||
|  | c645cb18e5 | ||
|  | 298132298b | ||
|  | 400b50a1f0 | ||
|  | 5b597e9b1f | ||
|  | e55de9c1d5 | ||
|  | 33ccf7c707 | ||
|  | 6b94210de5 | ||
|  | 745624f044 | ||
|  | 68956eabf2 | ||
|  | 87591f6868 | ||
|  | cc238a639e | ||
|  | de6758a972 | ||
|  | 49647eedae | ||
|  | f24e35236f | ||
|  | 6f200a423e | ||
|  | ef57c0601a | ||
|  | 9632e99bd3 | ||
|  | 93e18ea195 | ||
|  | f39676eedd | ||
|  | 1d73ff7c13 | ||
|  | 384e64d94d | ||
|  | 96bb880d1b | ||
|  | cf307a00e1 | ||
|  | 5a97bcb123 | ||
|  | 50f7620d7a | ||
|  | 78ec3ebe59 | ||
|  | 96f0faa546 | ||
|  | 4307bf3b83 | ||
|  | d56bd85328 | ||
|  | 9f2f258ad9 | ||
|  | 894b48df8e | ||
|  | 195fba5931 | ||
|  | 0556516524 | ||
|  | 5cad4e9d82 | ||
|  | 8607fd4997 | ||
|  | d905849b71 | ||
|  | 968505ac0e | ||
|  | e482b079df | ||
|  | 13cddd8f12 | ||
|  | 20b458f35d | ||
|  | cec8210d8b | ||
|  | e6ff895eff | ||
|  | 74ff17da7e | ||
|  | 7e1d430003 | ||
|  | eeff2895aa | ||
|  | f6d88521dd | ||
|  | c3e6e4f034 | ||
|  | 6c09330e74 | ||
|  | b100c02779 | ||
|  | ef6f00fcf5 | ||
|  | ad9405887a | ||
|  | 01e45de605 | ||
|  | aebefe8bcf | ||
|  | 5e41641d7c | ||
|  | 0f3b3a07d1 | ||
|  | 156d2fbaa4 | ||
|  | 4866b9dabb | ||
|  | 62ce9660b4 | ||
|  | 873c2ce10d | ||
|  | 2c2410e710 | ||
|  | 624eb0f958 | ||
|  | 770e44d1bd | ||
|  | 7144798377 | ||
|  | 606ff3ed00 | ||
|  | ca731adce7 | ||
|  | ca71f3008c | ||
|  | 7c56c14fa0 | ||
|  | e3433aa95b | ||
|  | 0df00556db | ||
|  | a55dd97d51 | ||
|  | b52959d41a | ||
|  | 163b0a2105 | ||
|  | d33c89a8ee | ||
|  | d0d73c5e3e | ||
|  | 799331b945 | ||
|  | 43073fa1fc | ||
|  | 7f91ff4b0c | ||
|  | ba778d4c60 | ||
|  | cddb3d82dd | ||
|  | a221f02393 | ||
|  | fa4959fc6a | ||
|  | bbd68e78c1 | ||
|  | 3c20938e0f | ||
|  | 94745cb3d5 | ||
|  | 602b328914 | ||
|  | 27802c930f | ||
|  | 3b4622a9ac | ||
|  | 18fb2e91b1 | ||
|  | 214cd9c262 | ||
|  | 337c289a74 | ||
|  | 0d560ec442 | ||
|  | a4d4bf3006 | ||
|  | 40028c8be7 | ||
|  | 961e7e92b3 | ||
|  | d3576c4151 | ||
|  | 1d51a0f396 | ||
|  | f62b7e4ae9 | ||
|  | 62135bc1cb | ||
|  | b245facdfe | ||
|  | 577f024310 | ||
|  | 1c2206cb9f | ||
|  | 16ba65c424 | ||
|  | 59cfaa20ab | ||
|  | ab0471c78e | ||
|  | 464642250b | ||
|  | d7bf9e234c | ||
|  | bf257574f9 | ||
|  | 92e42199b5 | ||
|  | 99b0b24a89 | ||
|  | d86383eba8 | ||
|  | 4fc12f232a | ||
|  | 729483102e | ||
|  | 7ac00935d5 | ||
|  | 639be5b104 | ||
|  | 17359c5e42 | ||
|  | 7aa5eee3aa | ||
|  | 98d6a7f32e | ||
|  | 0475b68817 | ||
|  | 2a89d49ba7 | ||
|  | aeab5f0333 | ||
|  | f80de95bb0 | ||
|  | e7bcc01fe8 | ||
|  | 9fcbce241e | ||
|  | 78a71fb7c6 | ||
|  | 3e25d66902 | ||
|  | 005e4ba4d1 | ||
|  | 0f83582fed | ||
|  | d736ffec8e | ||
|  | 27d6091e45 | ||
|  | 290405b987 | ||
|  | 7fa2fed147 | ||
|  | fd233510ee | ||
|  | 354be8dc88 | ||
|  | 9750bcba76 | ||
|  | 15d08ca17b | ||
|  | 1bc72fa49f | ||
|  | 68061fd292 | ||
|  | 2b77e9d96d | ||
|  | 5c48d2d56a | ||
|  | 11a0734009 | ||
|  | 2ccbfe45f2 | ||
|  | 3793b08d90 | ||
|  | 06b63209b1 | ||
|  | 02e318b3e6 | ||
|  | 3b78b26039 | ||
|  | f57fc06347 | ||
|  | 32a14ab8e0 | ||
|  | 5fafe6e4f4 | ||
|  | ee907aba34 | ||
|  | 2ae9a6f020 | ||
|  | 479841a609 | ||
|  | 10da45edce | ||
|  | 36c4a30fe3 | ||
|  | d4542cc3fc | ||
|  | dea02e374f | ||
|  | 91deac706c | ||
|  | 17e85ca2cf | ||
|  | 91593335ef | ||
|  | d27176c0b3 | ||
|  | 070e1e81ae | ||
|  | 2c7d94e5e9 | ||
|  | a5520d45e7 | ||
|  | 922c8703f5 | ||
|  | 75cc024e28 | ||
|  | 75c6da7730 | ||
|  | 35c8b2fce8 | ||
|  | 4f5d8f830e | ||
|  | 78cb6da21a | ||
|  | a7e1a51476 | ||
|  | a8ff77addd | ||
|  | 3c9c46d574 | ||
|  | 8ede404b8a | ||
|  | a7585e3040 | ||
|  | cd47b45fce | ||
|  | b6c23b8eb3 | ||
|  | 297e12f6e4 | ||
|  | 29b02fcac2 | ||
|  | 0c2218762c | ||
|  | 27bc03fc20 | ||
|  | 84b3195e9b | ||
|  | 6f54f41946 | ||
|  | c1ae0ab57d | ||
|  | 446ff81335 | ||
|  | 03b4a50317 | ||
|  | 06c3362332 | ||
|  | 5f059d02ad | ||
|  | 3e71a103a2 | ||
|  | e46561347d | ||
|  | a3f33ae888 | ||
|  | f71359e73d | ||
|  | a0b475d8ef | ||
|  | f3a597cd12 | ||
|  | 29f2ee93d1 | ||
|  | 454b3ebd97 | ||
|  | 89942ee49c | ||
|  | 746bd2ce92 | ||
|  | 747602a9cb | ||
|  | 8ce43a3fe1 | ||
|  | 1284f9cecc | ||
|  | c54541b839 | ||
|  | 4bd94e5450 | ||
|  | 2a30293905 | ||
|  | 159fffef2e | ||
|  | 5313652d7a | ||
|  | ae4612f134 | ||
|  | 97f6e68164 | ||
|  | 108d43f967 | ||
|  | b0e1c85c55 | ||
|  | 82e4055fa6 | ||
|  | 2a68ce6c90 | ||
|  | 05b0425929 | ||
|  | 3b15415a1b | ||
|  | 00fb809ab9 | ||
|  | 494aa15567 | ||
|  | 07450f9f23 | ||
|  | f0de469053 | ||
|  | 8e4092e7d7 | ||
|  | 9a2e5c36a1 | ||
|  | b782316cc0 | ||
|  | 3e84f9664f | ||
|  | 01e789f5ce | ||
|  | b2381f4657 | ||
|  | 64a3e46cbe | ||
|  | c0d6d0e28e | ||
|  | c13d0da9fa | ||
|  | 050334a648 | ||
|  | 0256337855 | ||
|  | bb073e4b6e | ||
|  | 40341ac14e | ||
|  | 4420df6e5d | ||
|  | 99cc7a9a60 | ||
|  | 7ec1b985d0 | ||
|  | 9f19d26a23 | ||
|  | e766614630 | ||
|  | ad49553b9c | ||
|  | 1b3b39d2ea | ||
|  | cb68505204 | ||
|  | a574dca0cc | ||
|  | c3fa1612d6 | ||
|  | 7a8f6d8660 | ||
|  | 9dda801fae | ||
|  | 344742c493 | ||
|  | 886d05d436 | ||
|  | baac2ad921 | ||
|  | c3337c9bac | ||
|  | 6a6ca22bf0 | ||
|  | f873f5488f | ||
|  | e18f843a57 | ||
|  | 56a92505bd | ||
|  | a8bc7dd7c1 | ||
|  | 94614550fc | ||
|  | b2052615e3 | ||
|  | f51b9217f5 | ||
|  | d892a87d1d | ||
|  | b7182f9462 | ||
|  | 79518753ad | ||
|  | 01634ed5e9 | ||
|  | f7abf8a02d | ||
|  | 3f7f1a50e7 | ||
|  | a5a770e750 | ||
|  | 9cd10f58ed | ||
|  | 5011531066 | ||
|  | d1c7a9767a | ||
|  | d78e11170b | ||
|  | 74f8dceb38 | ||
|  | 1fbf91c768 | ||
|  | edf764aaf4 | ||
|  | 7380c5096e | ||
|  | 45699f13fc | ||
|  | 1fd8c9adc2 | ||
|  | 5cc840e390 | ||
|  | e491dda229 | ||
|  | daa8aa5c9d | ||
|  | 0561554726 | ||
|  | 34abc6490c | ||
|  | 66f309f5ed | ||
|  | 2283f3e786 | ||
|  | d261c793ae | ||
|  | 31448a3add | ||
|  | d85ccb6ab2 | ||
|  | bd0be97137 | ||
|  | 81d70a57ca | ||
|  | b17f2f5d1f | ||
|  | 53ed5b2975 | ||
|  | 5626fee282 | ||
|  | cb9aefc489 | ||
|  | a9c83beb4f | ||
|  | 4a64a1bd46 | ||
|  | 4152179f10 | ||
|  | 400219a9fc | ||
|  | 933105a721 | ||
|  | bb39781848 | ||
|  | f90b7bed5e | ||
|  | 80bf94c009 | ||
|  | f46904c644 | ||
|  | 057619b157 | ||
|  | fd505b77b2 | ||
|  | 81a23b5b22 | ||
|  | c0ab0b5af5 | ||
|  | 970cc91938 | ||
|  | 749d373c95 | ||
|  | 3a427dd0f4 | ||
|  | e1402d5d8a | ||
|  | 864a6883d4 | ||
|  | 9b58c28be8 | ||
|  | 69fe6ecb7d | ||
|  | 321676c97f | ||
|  | d2e1493530 | ||
|  | 1c8375d0c2 | ||
|  | e164e22e13 | ||
|  | c1c4c96918 | ||
|  | 742e03944d | ||
|  | 60f2c19d9d | ||
|  | 21a8d9a109 | ||
|  | 9abedf3160 | ||
|  | 4e48961c2b | ||
|  | 78cd1629de | ||
|  | dd0cc2d173 | ||
|  | 8f00d2b616 | ||
|  | c26d98b308 | ||
|  | 913774850b | ||
|  | 43c9737e6e | ||
|  | 67cd3b6f81 | ||
|  | d0d2189d55 | ||
|  | b12773bc99 | ||
|  | da5a1fe264 | ||
|  | ea48c23535 | ||
|  | 8cd0d5e1ef | ||
|  | 9b46e62eb6 | ||
|  | 1653152dad | ||
|  | db7e3d725e | ||
|  | 329b34f7d1 | ||
|  | d624f20107 | ||
|  | 20bebeb7de | ||
|  | 4e9456b33b | ||
|  | 26c03552c6 | ||
|  | ac6c3496d4 | ||
|  | 2f1760f358 | ||
|  | 53db8912d6 | ||
|  | 91ef21a665 | ||
|  | 5b1153ab65 | ||
|  | 5196bb9281 | ||
|  | 8fd6f8177f | ||
|  | 7b68716a3d | ||
|  | d8ecc63e66 | ||
|  | 2575f61828 | ||
|  | c6370ebe48 | ||
|  | 3bc38570a2 | ||
|  | 0d36d43eda | ||
|  | a5a012738e | ||
|  | 7cce6504e3 | ||
|  | f696353e2c | ||
|  | cf11dfe73b | ||
|  | 940323c0b7 | ||
|  | 9f768396c2 | ||
|  | 160e57bfde | ||
|  | 429bec66f2 | ||
|  | 7f9b5e1e5e | ||
|  | 8088c28235 | ||
|  | 2ec310da18 | ||
|  | d8addc3175 | ||
|  | 7887655077 | ||
|  | 209c42b316 | ||
|  | 011d8a2b9a | ||
|  | 6f70791239 | ||
|  | 7ac439fd0e | ||
|  | 0cda098b4f | ||
|  | aaff40c4ad | ||
|  | 306e1081e3 | ||
|  | a1e2dac658 | ||
|  | 07382d5c6d | ||
|  | 56fdb57d24 | ||
|  | 336a9a97f9 | ||
|  | 88083c5b38 | ||
|  | 7e590fb6b3 | ||
|  | 4bb4ffbac4 | ||
|  | 7de3c7f80a | ||
|  | 84d0e44a08 | ||
|  | d7ca7e4cd8 | ||
|  | 3ba41d712f | ||
|  | ce917298ed | ||
|  | 91e0e33a04 | ||
|  | c32e9fabd9 | ||
|  | dc73db2a07 | ||
|  | 89cc01ce44 | ||
|  | efa3eb1981 | ||
|  | 50ab1fa3f0 | ||
|  | e50641e969 | ||
|  | d4c763df84 | ||
|  | c0669c158a | ||
|  | e33bbc6f16 | ||
|  | ea5ab54c3a | ||
|  | 3c18ea1e14 | ||
|  | 25ba86b5d8 | ||
|  | ecdf59ee3e | ||
|  | cc1f3bba7e | ||
|  | b501c47187 | ||
|  | 791b028dc4 | ||
|  | ab5b7f7893 | ||
|  | 4b1aa29269 | ||
|  | de34538d96 | ||
|  | 53eb93fc4d | ||
|  | a3841855e4 | ||
|  | b1e742c26c | ||
|  | 2c2814c998 | ||
|  | 214c7a6f3e | ||
|  | 6c4f967c39 | ||
|  | e0152d3df4 | ||
|  | 989ffc2f07 | ||
|  | f87a4c1e7c | ||
|  | fea5510700 | ||
|  | aa1ae18dbb | ||
|  | b5efd38ded | ||
|  | 2a457c40db | ||
|  | e38b64547f | ||
|  | bafa96b9c0 | ||
|  | d49a13b091 | ||
|  | 0bd818956f | ||
|  | c119b9cc7b | ||
|  | 958c7e7939 | ||
|  | 254a46b54c | ||
|  | 6ed31dc4c9 | ||
|  | fe8f5573d2 | ||
|  | 51dfb8ebf1 | ||
|  | 8fd64791d6 | ||
|  | 82e7202ad2 | ||
|  | 1f70782f7e | ||
|  | eefb1c4a47 | ||
|  | 069015c9b1 | ||
|  | c1583d19fb | ||
|  | 0556433ce4 | ||
|  | ec072cee23 | ||
|  | e29e6c147c | ||
|  | 972721b183 | ||
|  | 9bf43ce80d | ||
|  | 5941b5c07e | ||
|  | 3d91a186d5 | ||
|  | 744d45fb04 | ||
|  | f76fdedd25 | ||
|  | 93ca07d812 | ||
|  | d69042daee | ||
|  | d9f515900c | ||
|  | 57b4a5be08 | ||
|  | fa347f5f75 | ||
|  | 35e3404ced | ||
|  | f7344ec6c9 | ||
|  | 63a1e560ee | ||
|  | 98463f8258 | ||
|  | 2c95bfa701 | ||
|  | 2de3a2c98e | ||
|  | 314c0c9e3f | ||
|  | 4377627332 | ||
|  | 71d3f452ed | ||
|  | e117222dc2 | ||
|  | 6286daa881 | ||
|  | 0b3b9af623 | ||
|  | 1492f5611e | ||
|  | efeffaa49f | ||
|  | d77112955d | ||
|  | 9a34bb7e7a | ||
|  | b30445a5f3 | ||
|  | 0bf5c6ee3d | ||
|  | 155480b335 | ||
|  | 34202dea1d | ||
|  | 38d58f0354 | ||
|  | d4b82a33c5 | ||
|  | 06f3463dbc | ||
|  | 9df2d86ac2 | ||
|  | c83d93971f | ||
|  | 7e3ba3c27f | ||
|  | c7043dffc2 | ||
|  | d2c1e30979 | ||
|  | d5679c372f | ||
|  | b33f8b70d4 | ||
|  | d5773ab5d0 | ||
|  | 1903292202 | ||
|  | c3a9415208 | ||
|  | 9ece209c72 | ||
|  | 03956af88a | ||
|  | 013c8707ac | ||
|  | 32ed9c59ea | ||
|  | 4ef663669c | ||
|  | b855c54e81 | ||
|  | 8b65c8b909 | ||
|  | 28e7440726 | ||
|  | 7bca2298a0 | ||
|  | b1cc17d96e | ||
|  | 2afbef63aa | ||
|  | f0d2caec67 | ||
|  | ac2a317fd2 | ||
|  | bc4ac303e2 | ||
|  | 0e9fbecbe4 | ||
|  | 226b3cfdd8 | ||
|  | d43fa3790d | ||
|  | ca04113aa7 | ||
|  | 817c157db4 | ||
|  | 07edbe758a | ||
|  | 46ba0a5a5a | ||
|  | 480b636c7e | ||
|  | 20340dff7b | ||
|  | cfbabb500f | ||
|  | a4cb2c1cb1 | ||
|  | bd31b7e943 | ||
|  | b2e7c767df | ||
|  | bb9f763729 | ||
|  | fb61229bf3 | ||
|  | fc30d41ee5 | ||
|  | 7666147f3c | ||
|  | 52f8b24041 | ||
|  | eaf2667abb | ||
|  | de754ca4e0 | ||
|  | 96dd89fbeb | ||
|  | bae40e2cbc | ||
|  | 6a647dab8b | ||
|  | ebcf5b71d2 | ||
|  | 02370fb65d | ||
|  | 1e4f4907e3 | ||
|  | 13f72c73fb | ||
|  | 69b4632ef6 | ||
|  | ede8c293fc | ||
|  | 0cfe991482 | ||
|  | 6377459e2f | ||
|  | 33fe6dbfa3 | ||
|  | e158b9b64e | ||
|  | dfa9e537b3 | ||
|  | 6d28ece616 | ||
|  | 59f4ecdaa6 | ||
|  | 10d953f336 | ||
|  | 5b771f7def | ||
|  | 4a8e3ee845 | ||
|  | 9a1f559dd2 | ||
|  | 62321a03ca | ||
|  | 40ca72c656 | ||
|  | 34fcff7a9d | ||
|  | e1c829f4fa | ||
|  | 46136d94e9 | ||
|  | 0e2e8d1be5 | ||
|  | 1d1aa5dd3a | ||
|  | 0d82589916 | ||
|  | 4fc13037d2 | ||
|  | 3764499714 | ||
|  | c4bbbc49b4 | ||
|  | 503158ab97 | ||
|  | 8c1d1d1db0 | ||
|  | 7dc72a2894 | ||
|  | 07cfba1b3a | ||
|  | c55b80f467 | ||
|  | 2099da7142 | ||
|  | ea125936e7 | ||
|  | 5de01628a6 | ||
|  | 2834aca597 | ||
|  | 88bab888d8 | ||
|  | dfdbace298 | ||
|  | a9590d2bb6 | ||
|  | 29a81eb05e | ||
|  | 20490fcd80 | ||
|  | e775927f60 | ||
|  | 835a421909 | ||
|  | 850a0ae17e | ||
|  | 2b54363dd7 | ||
|  | b174a06b86 | ||
|  | d4096103cb | ||
|  | 3f493aceb2 | ||
|  | 05309da76d | ||
|  | 179f720806 | ||
|  | 7c34144ccd | ||
|  | cc234b594d | ||
|  | 024cf610a8 | ||
|  | a1896a6336 | ||
|  | d30da7bf5d | ||
|  | f8e914416d | ||
|  | 433da921bb | ||
|  | 4876053018 | ||
|  | 0c3a580b33 | ||
|  | 7689b7b4b0 | ||
|  | 21bff39e31 | ||
|  | ba09901228 | ||
|  | 90bf2e58b2 | ||
|  | 004807aa32 | ||
|  | 35bacf2ad0 | ||
|  | 81d17409d4 | ||
|  | a8080f55f0 | ||
|  | 379c540bd8 | ||
|  | f319005357 | ||
|  | df0e2dd2a2 | ||
|  | 219a0cd612 | ||
|  | 3ca3ce0726 | ||
|  | 566be8dc63 | ||
|  | 6bd4fa1c0a | ||
|  | c767ee04f4 | ||
|  | a5f89e0967 | ||
|  | 7355d14159 | ||
|  | efd5ceb405 | ||
|  | 035dc8ceb4 | ||
|  | 11be33e942 | ||
|  | e125254687 | ||
|  | a2b997ba20 | ||
|  | 7327941c77 | ||
|  | 6c9eb1b699 | ||
|  | 60e262dece | ||
|  | 9c5463e515 | ||
|  | 6941176519 | ||
|  | cb2c52cddb | ||
|  | dd95776144 | ||
|  | b95ca98be9 | ||
|  | 67b090b4d8 | ||
|  | 54b76a03ce | ||
|  | cd6c727730 | ||
|  | a35c6e29b6 | ||
|  | 95ce72fce7 | ||
|  | a803dfc7fa | ||
|  | c465d1c059 | ||
|  | 9914c0791e | ||
|  | 96baf5d3c7 | ||
|  | a205367b62 | ||
|  | 6218fa90de | ||
|  | 51a770cfdc | ||
|  | 16fba15b5c | ||
|  | ec2463a3ba | ||
|  | b605ede74e | ||
|  | b1b13d3696 | ||
|  | 51b11e5188 | ||
|  | eefa84a77b | ||
|  | 5908b4b000 | ||
|  | 2ed433c96d | ||
|  | 9865800e39 | ||
|  | 4f697e77d5 | ||
|  | c957aded98 | ||
|  | aa0758cd2b | ||
|  | 0c2093753d | ||
|  | 136f983353 | ||
|  | 7943164375 | ||
|  | 32e58d0a60 | ||
|  | bc807965ab | ||
|  | 477788658b | ||
|  | 723abf44bd | ||
|  | fd1298d4d2 | ||
|  | 42f39536a1 | ||
|  | 6f0ac91bd2 | ||
|  | 6dea9156ab | ||
|  | c5051b3e46 | ||
|  | 229d033e1a | ||
|  | f494ba7065 | ||
|  | 201bc7db53 | ||
|  | cd2a251f22 | ||
|  | ff44ad4994 | ||
|  | b496ca6a2c | ||
|  | 5908c0ce8c | ||
|  | f7eef25fed | ||
|  | 049c93465a | ||
|  | 33294dd9f0 | ||
|  | 0a89f4000d | ||
|  | 422e80530b | ||
|  | 07a8c69ba8 | ||
|  | 5449879a7d | ||
|  | 8dbc846314 | ||
|  | f0d3ca5d53 | ||
|  | 5af026674f | ||
|  | 2ebb4778cd | ||
|  | bf3c57d26b | ||
|  | cb9c87102f | ||
|  | c73b003de4 | ||
|  | 771d448a7b | ||
|  | de12db5f05 | ||
|  | dd49926cc2 | ||
|  | 7a9ab190eb | ||
|  | 2290fcde22 | ||
|  | ae85876965 | ||
|  | f07d8e958f | ||
|  | 610af45dee | ||
|  | 138a5bc3fe | ||
|  | 427e9c5637 | ||
|  | e3e8336602 | ||
|  | 194073e49a | ||
|  | 1af45aff73 | ||
|  | 56518ea028 | ||
|  | c1ac2bb156 | ||
|  | a004f27361 | ||
|  | 7843c55409 | ||
|  | 41da7d9f9a | ||
|  | 2add644706 | ||
|  | dfd9cf0874 | ||
|  | 7ad09da4e9 | ||
|  | 8efbeb14d2 | ||
|  | a1005d91df | ||
|  | a681f1ce3c | ||
|  | 5a0714ca1a | ||
|  | bd5c790043 | ||
|  | 2ae3cf79e4 | ||
|  | fb122ba097 | ||
|  | 0c104cd86c | ||
|  | a687f4ad68 | ||
|  | 228f42cf04 | ||
|  | 6d4956b574 | ||
|  | 0c7b652a70 | ||
|  | d35470a79e | ||
|  | 719d610be3 | ||
|  | 07ae64693e | ||
|  | 0ccc1271a6 | ||
|  | 26fa2b0b74 | ||
|  | 6f64c19c32 | ||
|  | e3e0e12fef | ||
|  | 0312ba8ad7 | ||
|  | 2ad8e7f343 | ||
|  | d6298d9f05 | ||
|  | 89be30c4b9 | ||
|  | 6bcfea1de4 | ||
|  | e8c9554dd6 | ||
|  | 02272f7db0 | ||
|  | 5a73e79475 | ||
|  | 7f4ecd40ce | ||
|  | 7c950c3022 | ||
|  | dbf019135a | ||
|  | e504ee82e5 | ||
|  | 780a15fe4f | ||
|  | abb249643f | ||
|  | 086eccaf4a | ||
|  | 871033501a | ||
|  | ccd727488f | ||
|  | aa59d0f082 | ||
|  | 5d12f53283 | ||
|  | 59c005875a | ||
|  | 06d22e843a | ||
|  | 4fa5f4e5a3 | ||
|  | 67ea825d4a | ||
|  | a616e06f9d | ||
|  | b7752928a4 | ||
|  | ca096852a5 | ||
|  | ea2c48bca5 | ||
|  | a722dc4235 | ||
|  | dbbf0ff5e4 | ||
|  | a941519db5 | ||
|  | d4ba014a8a | ||
|  | d193a6aec4 | ||
|  | 1f0fdf3da7 | ||
|  | b705240faa | ||
|  | 662b832274 | ||
|  | aed7e6d289 | ||
|  | f7a1201d02 | ||
|  | 4d5bdd25a8 | ||
|  | 4a90ce35f2 | ||
|  | 02f5eddd14 | ||
|  | 5ca4f1b181 | ||
|  | ec7ef3a813 | ||
|  | 49ff6febe5 | ||
|  | 2d66a9212f | ||
|  | 44fb307da4 | ||
|  | cfc2181a48 | ||
|  | cf4a846312 | ||
|  | 633b357d7b | ||
|  | b96d67a54e | ||
|  | 5b83931b01 | ||
|  | f22b54de30 | ||
|  | a3306bb26f | ||
|  | 0adacac269 | ||
|  | 7359ed2ba2 | ||
|  | 5a5f4e8161 | ||
|  | b886cc1333 | ||
|  | 9299efd086 | ||
|  | 1502aa3b20 | ||
|  | 73e32ecdcb | ||
|  | ac8776aea4 | ||
|  | 7b41c5b301 | ||
|  | 369839e012 | ||
|  | 8fde16422e | ||
|  | f1462dbd3d | ||
|  | 5dad569d62 | ||
|  | c424bb097d | ||
|  | e4b1760b20 | ||
|  | 780e365a78 | ||
|  | 3d1523a060 | ||
|  | ff403dfa2e | ||
|  | 89834baf01 | ||
|  | b8699422c8 | ||
|  | 6bc772d640 | ||
|  | 0712f30a51 | ||
|  | 9116796d90 | ||
|  | a95fdb903b | ||
|  | 2ca6421206 | ||
|  | cd076cc069 | ||
|  | 46482bdae1 | ||
|  | 5189c897be | ||
|  | 2c7d25d472 | ||
|  | 0da370c42d | ||
|  | 6f036d9120 | ||
|  | 260bbd79fd | ||
|  | 37ad6a3a62 | ||
|  | aa25007431 | ||
|  | 8b33ec1339 | ||
|  | cede11ecea | ||
|  | 2b4088c5f7 | ||
|  | d872484607 | ||
|  | f3f2160d96 | ||
|  | bcdb849b46 | ||
|  | 5846431b34 | ||
|  | 0217d9396a | ||
|  | c99e233026 | ||
|  | f670d930f3 | ||
|  | 0237d78f61 | ||
|  | 5665f127aa | ||
|  | 76386dad7d | ||
|  | 42072fdda4 | ||
|  | fc80f828be | ||
|  | d05a1e0260 | ||
|  | b315882f58 | ||
|  | 2f2f907ffe | ||
|  | 10492e3b2f | ||
|  | 8e08ff2d39 | ||
|  | e78a59a8a8 | ||
|  | cbe47a9dcc | ||
|  | a1056147d8 | ||
|  | 8692590600 | ||
|  | 57345113b5 | ||
|  | 52f02cb9eb | ||
|  | 5d4dcd7e4b | ||
|  | 7d1f4d8907 | ||
|  | a76241c7ba | ||
|  | bdc6678341 | ||
|  | c99b7e927d | ||
|  | 1675a0d442 | ||
|  | c0d2cd8962 | ||
|  | 146c9fd947 | ||
|  | 666e9897ea | ||
|  | 81d70bd811 | ||
|  | f6f8bb7fd1 | ||
|  | 7c3aaf7b7c | ||
|  | 32ea28f783 | ||
|  | 17f365941b | ||
|  | c2216843d8 | ||
|  | 339fb5099f | ||
|  | cf56707b02 | ||
|  | 19f38aa6ed | ||
|  | 9f69e112d0 | ||
|  | 8eb4259be0 | ||
|  | d3a1f43cbb | ||
|  | 18b06ff283 | ||
|  | 53addcf99a | ||
|  | 0fa4d75a47 | ||
|  | 2ef86c3339 | ||
|  | d48c3a6d2f | ||
|  | 2260ede559 | ||
|  | 5690a44c38 | ||
|  | e36a9fda1b | ||
|  | 10f195d334 | ||
|  | 54afc6ca8c | ||
|  | 2e67bd3b78 | ||
|  | f27eb084c7 | ||
|  | 7629dfd54a | ||
|  | f62fd18b72 | ||
|  | c6b60ff6b4 | ||
|  | e9655e6d86 | ||
|  | 3bca9b06f8 | ||
|  | d97fdc3393 | ||
|  | 7dc72f98bf | ||
|  | da00179066 | ||
|  | 89910031cd | ||
|  | 5676aeac80 | ||
|  | b0b9055e2e | ||
|  | c0aefed764 | ||
|  | e2ec9ca5fb | ||
|  | 8e38f5c2c0 | ||
|  | 99b2858863 | ||
|  | b43669e731 | ||
|  | 3bc9905715 | ||
|  | c55aebd005 | ||
|  | 55c331f536 | ||
|  | ce236284f4 | ||
|  | c24cac68f6 | ||
|  | db149ca6e1 | ||
|  | 0502f2a4a5 | ||
|  | f13df7e605 | ||
|  | 36a6981329 | ||
|  | 7abcdea816 | ||
|  | 0509e54a95 | ||
|  | b8893bcad7 | ||
|  | c9356c1237 | ||
|  | 2d7b7c2f3f | ||
|  | d0db1117f7 | ||
|  | e287e76db5 | ||
|  | 8c28c4b5ac | ||
|  | f048e943f8 | ||
|  | 12a84572e2 | ||
|  | c8de1d3372 | ||
|  | 234e3f4ca5 | ||
|  | 7749fb1a0b | ||
|  | f55d4e32c0 | ||
|  | cfd98a33fe | ||
|  | 7bdf20fee5 | ||
|  | e906fa3653 | ||
|  | 57cf7f6f0d | ||
|  | d378e7e897 | ||
|  | a8e666db34 | ||
|  | 7b46339a5d | ||
|  | 20aa6e429b | ||
|  | 7ba11a57a8 | ||
|  | 49de4f2200 | ||
|  | 5d01955133 | ||
|  | 7591f3fa29 | ||
|  | 89f8f9b45b | ||
|  | 59f5b38dca | ||
|  | 5b0e61033c | ||
|  | 096af00a72 | ||
|  | dca2dc4600 | ||
|  | 96b482dac5 | ||
|  | e05664f34f | ||
|  | 72cca5ccbf | ||
|  | 0b9be029ac | ||
|  | 91701473af | ||
|  | ad6a9a7df7 | ||
|  | 32b6ded008 | ||
|  | 4f2d0a0322 | ||
|  | 793cfcb2c5 | ||
|  | 3a71bd01fb | ||
|  | a1d99c1954 | ||
|  | 19a874b274 | ||
|  | b95dd5c238 | ||
|  | 7c84af2370 | ||
|  | db1c27d833 | ||
|  | 636cd84f4f | ||
|  | f2d4fae813 | ||
|  | 986c9ab20a | ||
|  | cd7e222b72 | ||
|  | 50b599b1a9 | ||
|  | 1d162edb59 | ||
|  | 7bdd4ddeab | ||
|  | ae6e5a5599 | ||
|  | 1222184b68 | ||
|  | 18f779c6de | ||
|  | 138f67581c | ||
|  | 597d6ac513 | ||
|  | 3ab25c2e8c | ||
|  | b11d97ba4e | ||
|  | 080c810131 | ||
|  | 56bc79d64e | ||
|  | 72d2c9d600 | ||
|  | 0374c32236 | ||
|  | d73cd4b515 | ||
|  | 54e3e3f051 | ||
|  | abf218fc21 | ||
|  | dcf90b6159 | ||
|  | 1cf91c78f8 | ||
|  | 968abd26e8 | ||
|  | aa05f7a2d2 | ||
|  | 181c23b07c | ||
|  | 955cde3ed9 | ||
|  | 477a3c7eb2 | ||
|  | f4b66b980b | ||
|  | 281de63e0d | ||
|  | c19a700662 | ||
|  | fc011ba1d9 | ||
|  | b941f590e0 | ||
|  | 8f4db78ff2 | ||
|  | 4b4dc2e298 | ||
|  | 2de19547ca | ||
|  | 5a058491b0 | ||
|  | 6743d99d9b | ||
|  | 35a5ec78c3 | ||
|  | 3440c3e77a | ||
|  | dd17f06362 | ||
|  | 8a15cb3a34 | ||
|  | 4a548ac282 | ||
|  | d22353b13d | ||
|  | c18046c25d | ||
|  | 4a12d4d156 | ||
|  | 20044427b4 | ||
|  | 073dedd483 | ||
|  | 06c25c913c | ||
|  | 08d06cf465 | ||
|  | 1e9eb843c0 | ||
|  | 78a5dae2a0 | ||
|  | 19443a5b34 | ||
|  | 74acc90702 | ||
|  | 349f580371 | ||
|  | f019d33a03 | ||
|  | c7af25ac38 | ||
|  | b52bd59cea | ||
|  | 332d32c319 | ||
|  | 2f824ba1a8 | ||
|  | a6b09acd5e | ||
|  | d4779c8c8f | ||
|  | ba01c4bbe8 | ||
|  | ddc1d81665 | ||
|  | 790aeb3c46 | ||
|  | 6ed5be10b1 | ||
|  | a7b8470d9e | ||
|  | 2a05cc382f | ||
|  | 1e10a6ce1b | ||
|  | 7645ef55c2 | ||
|  | 6ce200b60d | ||
|  | d782e28906 | ||
|  | da3bd31fb8 | ||
|  | aa3ed40430 | ||
|  | ad7e564f14 | ||
|  | f23ee2dac5 | ||
|  | 1962f74439 | ||
|  | 0064d060ea | ||
|  | e47e6b1958 | ||
|  | 4c04415e80 | ||
|  | 3654e75b8c | ||
|  | 66fa73aea4 | ||
|  | df87d03f32 | ||
|  | 3fbe851a0b | ||
|  | d1b2e63950 | ||
|  | 34fd8cf751 | ||
|  | f1fe90fce0 | ||
|  | 2ba6fa0dda | ||
|  | f2928e3d7d | ||
|  | 895ab9c5d8 | ||
|  | fb07c68132 | ||
|  | 68e7d45f63 | ||
|  | 49e302e1bc | ||
|  | b33ca786ae | ||
|  | dc77d8edda | ||
|  | c339a183b9 | ||
|  | f263795a99 | ||
|  | e9e771e57b | ||
|  | fbb9d7c6b4 | ||
|  | 10abd7b0ae | ||
|  | 3de36901b8 | ||
|  | 5b4967acb9 | ||
|  | 0a007b1e6e | ||
|  | 4ad68b7dfa | ||
|  | 73aef1b9a4 | ||
|  | dcfea20973 | ||
|  | 9b6766d3b2 | ||
|  | b8bc8e2c47 | ||
|  | 039e3aa34c | ||
|  | 551ff109c9 | ||
|  | 664451d0c6 | ||
|  | 4031057bc0 | ||
|  | fcf9b782c1 | ||
|  | d693d382b9 | ||
|  | 0a1b6c7793 | ||
|  | 5acba2bddf | ||
|  | 883b16fad1 | ||
|  | ef48b3e751 | ||
|  | 3c956e7e98 | ||
|  | 519ea271a9 | ||
|  | 09d5160404 | ||
|  | 97dcf03334 | ||
|  | 896a804a72 | ||
|  | 656bb5043d | ||
|  | e953becbae | ||
|  | 6c9901b919 | ||
|  | ff45c94106 | ||
|  | a8a3fbeef4 | ||
|  | dae8092ecd | ||
|  | 70110208fc | ||
|  | 217ca98933 | ||
|  | c2945c532e | ||
|  | ea750576b3 | ||
|  | 82538ba4fc | ||
|  | 2b2f37a8c9 | ||
|  | 4db2ec60e0 | ||
|  | 7d88d35556 | ||
|  | 3c3e91ff48 | ||
|  | 039e8d6e17 | ||
|  | 50bf79ab18 | ||
|  | 467c6762fa | ||
|  | 740f4e403f | ||
|  | 5664d51695 | ||
|  | b195a61498 | ||
|  | 94e6816bf6 | ||
|  | ebf97f710f | ||
|  | 714b54ed06 | ||
|  | 620c5f515e | ||
|  | c06fd12b07 | ||
|  | 2c206bba64 | ||
|  | 04953b5645 | ||
|  | 1732ce63f3 | ||
|  | 1e212c6da2 | ||
|  | 7d8fc54351 | ||
|  | dd44a1e517 | ||
|  | 9f26757e8a | ||
|  | a9c8c8384d | ||
|  | a826b0e0fb | ||
|  | 4aaec0e379 | ||
|  | 69019d5215 | ||
|  | 96411b17e9 | ||
|  | 5a093b58d8 | ||
|  | 470b3e0973 | ||
|  | dc251c216c | ||
|  | ae9ef61f80 | ||
|  | d9ca7b7277 | ||
|  | 0c99248deb | ||
|  | 1aae84a4d0 | ||
|  | 528da3f08e | ||
|  | 9c507f7f62 | ||
|  | 07da2fdda3 | ||
|  | ca3366544e | ||
|  | ccee7b483c | ||
|  | 5903133e3b | ||
|  | 5bf520b6ed | ||
|  | a47da92d81 | ||
|  | 63f84ae7b1 | ||
|  | 4d6bc55723 | ||
|  | 9bb4df4cc3 | ||
|  | c47a5379ae | ||
|  | cde9c4a2bc | ||
|  | 5a560b42ef | ||
|  | 50874c9cf7 | ||
|  | 6f984aa591 | ||
|  | 274162afcd | ||
|  | 6bd23d897f | ||
|  | 73f29ebf69 | ||
|  | cabcb9c6d0 | ||
|  | 116f7ed613 | ||
|  | 6ef0eb73d0 | ||
|  | 7f4feb0cfc | ||
|  | 626f7357bb | ||
|  | 690c9203c8 | ||
|  | 1209f3b39a | ||
|  | a4524b3c2c | ||
|  | a3cbdadb39 | ||
|  | 9e3c5fd984 | ||
|  | 7d80ac37a6 | ||
|  | f74b9ba7ab | ||
|  | 3ac240dc1c | ||
|  | d233b3f24f | ||
|  | 19fff681d2 | ||
|  | bc7c3bb9b3 | ||
|  | 57be7f2905 | ||
|  | 1c0da454db | ||
|  | b541f7b944 | ||
|  | 6e84326583 | ||
|  | ca14496e4e | ||
|  | 480d65fc1f | ||
|  | 6bddb63b45 | ||
|  | c5142aeba5 | ||
|  | 38d9f10672 | ||
|  | 937394af7a | ||
|  | fe10955eb9 | ||
|  | ccda71ff8e | ||
|  | cd75224cdd | ||
|  | 1c2089b8a3 | ||
|  | 3ead4d4587 | ||
|  | f2b71bc280 | ||
|  | f027d71136 | ||
|  | fa41d6df04 | ||
|  | d2bb65bf04 | ||
|  | b5be1b11d1 | ||
|  | 9fb049991f | ||
|  | fba847dd28 | ||
|  | b33883b334 | ||
|  | f74a6dffca | ||
|  | 7390e20218 | ||
|  | 9646dc439e | ||
|  | 554c63b9c7 | ||
|  | 24d8640e9b | ||
|  | ea151d069c | ||
|  | f140d2f37a | ||
|  | 4e163c4bda | ||
|  | ddcf8b892b | ||
|  | 49138eb03a | ||
|  | 71b63bd33b | ||
|  | 88348f59c2 | ||
|  | 7eb5643204 | ||
|  | 565cb6d79e | ||
|  | c0d715c78a | ||
|  | a3d0355ddd | ||
|  | bc4e06568d | ||
|  | 8acb9f4056 | ||
|  | 9cbbd581ee | ||
|  | fdc9467218 | ||
|  | 84ac3df580 | ||
|  | 7f459df9e9 | ||
|  | 3625f3293a | ||
|  | 0a2308592f | ||
|  | 8ef3f18da7 | ||
|  | e126427809 | ||
|  | 7b39828980 | ||
|  | d03de52735 | ||
|  | cabe90b2dd | ||
|  | 13b78bdc20 | ||
|  | 6f0e1c79ac | ||
|  | b66daad3d3 | ||
|  | 9c5523252d | ||
|  | bc8bcf7a1a | ||
|  | 85d655d3e2 | ||
|  | ac419e01d3 | ||
|  | 5d4467a6c0 | ||
|  | 81da7f3667 | ||
|  | 9734196eb9 | ||
|  | 7e0f9b9b8e | ||
|  | bb25132865 | ||
|  | 28bcff99f6 | ||
|  | 246cb36836 | ||
|  | 9a0c0f6d21 | ||
|  | a9dd8eb9e7 | ||
|  | 9026c9d6f1 | ||
|  | d5f7430723 | ||
|  | 5a53249fbb | ||
|  | d2848cf569 | ||
|  | 71f39f55f2 | ||
|  | 490c817fc1 | ||
|  | 2e1a777811 | ||
|  | 48357d1cc9 | ||
|  | 846df21764 | ||
|  | f78b8f9267 | ||
|  | 798d9ee876 | ||
|  | 1eea81e9dd | ||
|  | 4fcdfd41fa | ||
|  | 36a5f17af2 | ||
|  | 8032684ad0 | ||
|  | f7d3d4a010 | ||
|  | 9975e0b3f3 | ||
|  | ea484a7787 | ||
|  | c2e8a67330 | ||
|  | 8f3e4a2dee | ||
|  | 07768a43c8 | ||
|  | 01c10e320c | ||
|  | f16b2257c6 | ||
|  | e005fe7ce1 | ||
|  | c682e69ee7 | ||
|  | 49421f50ac | ||
|  | 529dd490b7 | ||
|  | 36329e596e | ||
|  | fb75e2ef02 | ||
|  | 352171e339 | ||
|  | 592901b143 | ||
|  | 769b4819b2 | ||
|  | 77fa2bcc39 | ||
|  | 1129001bc6 | ||
|  | 8dd765ee89 | ||
|  | 479648e7c1 | ||
|  | 45cd19d1e3 | ||
|  | f8718e0b7b | ||
|  | dcc45631da | ||
|  | c6d3a5bedc | ||
|  | 7cc8539298 | ||
|  | 900e8202e6 | ||
|  | eb6ac7d1d1 | ||
|  | 178f917a49 | ||
|  | 1a8293d9ef | ||
|  | ecdc00dcb7 | ||
|  | 147e04ecd2 | ||
|  | 49e48725a5 | ||
|  | b3af744041 | ||
|  | 58a6a95d90 | ||
|  | 1aa9461370 | ||
|  | 1f78b9d4bc | ||
|  | 6f974fe285 | ||
|  | f4f3c8798e | ||
|  | ce1614f4e7 | ||
|  | 91494584c2 | ||
|  | a85ebb49b2 | ||
|  | ae273f8320 | ||
|  | ef62e31b61 | ||
|  | 0c2c5d5344 | ||
|  | 11e93eac3d | ||
|  | dbe17debb4 | ||
|  | 6c12337317 | ||
|  | b2aa73b31e | ||
|  | 38b1fc7aa6 | ||
|  | f4afcb4d50 | ||
|  | 4b019fe38b | ||
|  | 191401f32b | ||
|  | 62b68c6a21 | ||
|  | 15a22f0bfc | ||
|  | 926c03986c | ||
|  | d8a00f4314 | ||
|  | 5862b832d9 | ||
|  | 67fa4a0fc7 | ||
|  | 90cf7a3bf5 | ||
|  | 0847040017 | ||
|  | 69b577048e | ||
|  | 3fbd2f93c8 | ||
|  | 8f0e36a8e4 | ||
|  | 7583698ee5 | ||
|  | b561e79a6c | ||
|  | 5850ad06b1 | ||
|  | e597f04b0d | ||
|  | 7b715925cf | ||
|  | d3701837e3 | ||
|  | 7af10aca9e | ||
|  | b54e99642b | ||
|  | b1ad0668cc | ||
|  | 6583d0f69b | ||
|  | cee6bbf134 | ||
|  | 43e49bf14a | ||
|  | 371b58a807 | ||
|  | 7812a1bb51 | ||
|  | 538e045e4c | ||
|  | 91fe1493a7 | ||
|  | 4650a2ea52 | ||
|  | 7cd51a7747 | ||
|  | b55545b959 | ||
|  | 2685256c93 | ||
|  | 3819de4e74 | ||
|  | 73fee4eb6b | ||
|  | 609c193b88 | ||
|  | 03a42976b1 | ||
|  | 6db0efdfbc | ||
|  | ebbbe1a620 | ||
|  | 5d1c77cb16 | ||
|  | d48fb3ba55 | ||
|  | 8c024a1ae9 | ||
|  | a3c34e6b3c | ||
|  | fa7ab45a40 | ||
|  | 379b104778 | ||
|  | d956c795a4 | ||
|  | 7d02d0f762 | ||
|  | f96f38b172 | ||
|  | 4cea5d65a6 | ||
|  | 40d94e7a62 | ||
|  | 66019fdbbf | ||
|  | 37b02e3d5b | ||
|  | 093bdd6090 | ||
|  | 52656b25da | ||
|  | 1386c9d915 | ||
|  | 02c9441727 | ||
|  | b1e926f2cb | ||
|  | df9dcb395b | ||
|  | ad59dad921 | ||
|  | 46e75968f5 | ||
|  | 0df5c5121d | ||
|  | 16f04b45ac | ||
|  | 5ce35a50c2 | ||
|  | 7110c1178a | ||
|  | 220f5e2913 | ||
|  | 9f8c75efc6 | ||
|  | 8f3e84df4d | ||
|  | 08ff3d8ad0 | ||
|  | 5c4d7734ac | ||
|  | 15f8cd49d3 | ||
|  | 62b3986fcd | ||
|  | 55b6d711f3 | ||
|  | 7e51d57d21 | ||
|  | 170d23d768 | ||
|  | 40266c6821 | ||
|  | 0a71077513 | ||
|  | be5c44af61 | ||
|  | 720dcb0fe5 | ||
|  | c86b207b1c | ||
|  | 413c1bc2fe | ||
|  | 5ca31ea3dd | ||
|  | dd5d2d1616 | ||
|  | 5f08790f12 | ||
|  | d5ef5ee5a7 | ||
|  | f641c70172 | ||
|  | 992657b942 | ||
|  | 41e468b507 | ||
|  | 6660306ac4 | ||
|  | dd9694890a | ||
|  | 0b8654d865 | ||
|  | f07dc7bd81 | ||
|  | 6a6482dc7f | ||
|  | 3c9b7c07af | ||
|  | 796ab4bf2c | ||
|  | 55602d632d | ||
|  | 310ed9f504 | ||
|  | dafddfa39a | ||
|  | 3e22c9860e | ||
|  | fb0a0c3fb5 | ||
|  | 3b735c7533 | ||
|  | 1645490f5c | ||
|  | aecffe10d9 | ||
|  | 4e69bc0e32 | ||
|  | 909f72e6be | ||
|  | 6a1d39d5f8 | ||
|  | c5d4ec17c3 | ||
|  | ed33a72945 | ||
|  | d8c0091680 | ||
|  | 6419d68626 | ||
|  | e2ecaf5bcf | ||
|  | 31146954d1 | ||
|  | 601ca9ec80 | ||
|  | 082b5ba895 | ||
|  | e06361d5d7 | ||
|  | 552a8e130c | ||
|  | 40787bc29a | ||
|  | 6ab03bb228 | ||
|  | 3fdb782321 | ||
|  | c8f52a1c40 | ||
|  | eb63090387 | ||
|  | 5bc8f31c31 | ||
|  | 5776de7745 | ||
|  | f45d0bb317 | ||
|  | 93aa5b7753 | ||
|  | dd6a6a565f | ||
|  | aba8025645 | ||
|  | b12872e5de | ||
|  | 5a7b1ba292 | ||
|  | 24715c72a2 | ||
|  | ed3a4e4663 | ||
|  | e97283b34b | ||
|  | c2dfbcba10 | ||
|  | a9870b35be | ||
|  | ed5cd2b9ca | ||
|  | a9356ca1e2 | ||
|  | cfba11e9ca | ||
|  | 4304a3c916 | ||
|  | 9e6194bfdc | ||
|  | 7d6c8aa9dc | ||
|  | aad0864018 | ||
|  | a55d18709c | ||
|  | dd2f3c861b | ||
|  | da1dc67e1c | ||
|  | 0c2b35e542 | ||
|  | 85dc1263ea | ||
|  | c8ecb3e0ee | ||
|  | ce10036a27 | ||
|  | 30e49846e0 | ||
|  | be97dd1c57 | ||
|  | 648a6dca42 | ||
|  | 0566d0d198 | ||
|  | dfc25722c9 | ||
|  | a436c55c50 | ||
|  | 0d58530f55 | ||
|  | 04b2eaf535 | ||
|  | ace2ed8bd0 | ||
|  | dff2d716a1 | ||
|  | ad18b9b81b | ||
|  | eabfe0769b | ||
|  | 19f7027718 | ||
|  | f537945351 | ||
|  | d02372ab90 | ||
|  | 1b020c522f | ||
|  | 79d0450c77 | ||
|  | bc32bc8831 | ||
|  | f68a307eeb | ||
|  | 82e7479cfe | ||
|  | 462fe5d89f | ||
|  | b0d8ac83ae | ||
|  | d8ac817c91 | ||
|  | 5105bc6f64 | ||
|  | 47c9f1e9b8 | ||
|  | 49d0ed0c1b | ||
|  | 99f5151aab | ||
|  | 0a056ad02d | ||
|  | c76b634d0b | ||
|  | a81698d50f | ||
|  | bae79063e1 | ||
|  | fb5323c283 | ||
|  | e2d1de94b7 | ||
|  | 7109fd8196 | ||
|  | a5fd821e0c | ||
|  | 6c63583e49 | ||
|  | dd16e1b784 | ||
|  | d52d8d7970 | ||
|  | f349aa47ce | ||
|  | ef4018934c | ||
|  | 951aa9535e | ||
|  | de1fe36226 | ||
|  | 64fd36d437 | ||
|  | 6f9ecc0ffa | ||
|  | a97bfc92e1 | ||
|  | 0d72fcdf02 | ||
|  | 0e84ca1df5 | ||
|  | b28bdda510 | ||
|  | 72314e2d9f | ||
|  | d22fb9f438 | ||
|  | 04b8552d27 | ||
|  | 5d6f44cd91 | ||
|  | afc8ad7ff5 | ||
|  | ae039bf1c7 | ||
|  | 8fa25e9d37 | ||
|  | 0daab491ec | ||
|  | 4f825bac1a | ||
|  | 39c8b79ebb | ||
|  | 7d66c90beb | ||
|  | 1b8b65582a | ||
|  | d25971cb44 | ||
|  | 89a56e661d | ||
|  | 3482746d7c | ||
|  | d5aeca6222 | ||
|  | 03f46638e1 | ||
|  | c2b000d910 | ||
|  | 88eb702d7b | ||
|  | b1d98f026f | ||
|  | 28dfe7b02c | ||
|  | 84f0ee183c | ||
|  | 7eedd6c2fc | ||
|  | e7b80c6d10 | ||
|  | d165609476 | ||
|  | 2f17521c06 | ||
|  | 8b52006959 | ||
|  | 8eb3d43123 | ||
|  | a511368229 | ||
|  | f0006a0743 | ||
|  | 7171e69715 | ||
|  | 2ab44fb33a | ||
|  | 7542175258 | ||
|  | 9dc4c50527 | ||
|  | 99d116f4ce | ||
|  | 9475fef8f6 | ||
|  | 60339a0f6a | ||
|  | 36113f84be | ||
|  | 139c2284b8 | ||
|  | 91909a70d7 | ||
|  | a23d97563f | ||
|  | bf538e2514 | ||
|  | 149b62f486 | ||
|  | 06dc8a499b | ||
|  | 5b8479f3a4 | ||
|  | e803a5e26e | ||
|  | 959f798a7f | ||
|  | 5b8adbfd0c | ||
|  | 54ba18975a | ||
|  | fdd2dedfc6 | ||
|  | 46f4fa1a7d | ||
|  | 28debb46be | ||
|  | 5f132be94d | ||
|  | 9f9feea159 | ||
|  | 3bd9e0bcd4 | ||
|  | c80a76f8c0 | ||
|  | c71f498587 | ||
|  | e658d447ca | ||
|  | 33def5b45d | ||
|  | 9fc26a8ee0 | ||
|  | 1b304bf85e | ||
|  | 99983a5c8f | ||
|  | d01b370cd7 | ||
|  | 1a643e2042 | ||
|  | 1aaf5fd288 | ||
|  | 8a758b8df0 | ||
|  | 211caa07dc | ||
|  | ac66e89edb | ||
|  | 6fe5b50410 | ||
|  | 166cdad58b | ||
|  | 1a721ac6b5 | ||
|  | 6591fa9fb4 | ||
|  | d804093f8b | ||
|  | 5261b784b0 | ||
|  | 5a188ceca3 | ||
|  | ce56cc538d | ||
|  | 269433bf00 | ||
|  | dae3371c69 | ||
|  | 38c1d332e2 | ||
|  | b627d42160 | ||
|  | 4e923057ae | ||
|  | 35d0bd1985 | ||
|  | 085eb650e7 | ||
|  | b4157e8ce0 | ||
|  | 81221038f0 | ||
|  | 9f37bf5875 | ||
|  | 140a5b20db | ||
|  | e9b6b45fc4 | ||
|  | f16760d607 | ||
|  | 9d457787f7 | ||
|  | 4e6afd5afc | ||
|  | 36354c3846 | ||
|  | 9f63dfb9cb | ||
|  | cae4faad0a | ||
|  | e389d0f7fa | ||
|  | 6b32213735 | ||
|  | b3fe24b713 | ||
|  | 5bb7530642 | ||
|  | 0b61c16eb0 | ||
|  | 77aced6734 | ||
|  | 94a7b6b9bd | ||
|  | f8bf6c163f | ||
|  | eb0da038fb | ||
|  | 6cda9f2900 | ||
|  | ecd4a862ff | ||
|  | 632d50a0d0 | ||
|  | 0f1cc46b71 | ||
|  | 60b225d61c | ||
|  | 23e540a57a | ||
|  | 1998412a3c | ||
|  | 7bbfb692de | ||
|  | c6da990748 | ||
|  | 049e57d578 | ||
|  | 78ba0f749c | ||
|  | 9cc1bfb4b5 | ||
|  | 278b7ac52b | ||
|  | 645a29e22b | ||
|  | b22d30bc65 | ||
|  | 2ee0490141 | ||
|  | 1fd783de69 | ||
|  | 8073896965 | ||
|  | 8a26e43c40 | ||
|  | a302aba3ab | ||
|  | 0458058cb1 | ||
|  | 999bb5ed49 | ||
|  | c9f4a1eb7b | ||
|  | 45aa76afce | ||
|  | e89a77efb1 | ||
|  | 8f930d6dd5 | ||
|  | 9d62b4c70d | ||
|  | 834032f58e | ||
|  | 33db99ffd3 | ||
|  | 28b00f6507 | ||
|  | 6559076c48 | ||
|  | 60f6311e00 | ||
|  | 574a5630e0 | ||
|  | d3294be1bc | ||
|  | 22fdc81de2 | ||
|  | 370e9b25d1 | ||
|  | 30f821af3e | ||
|  | 7a5aa1c39b | ||
|  | f674df4422 | ||
|  | c2da5931ec | ||
|  | 94f6bd34c7 | ||
|  | e066a6421c | ||
|  | ef338e2515 | ||
|  | dcf549261c | ||
|  | 8b868b426a | ||
|  | 2ef1022c92 | ||
|  | 9b3abd3b19 | ||
|  | db02fefcf4 | ||
|  | 523ae83811 | ||
|  | 4eb010f807 | ||
|  | 4958f28052 | ||
|  | 7e727b63ed | ||
|  | 138c38fbb5 | ||
|  | 2e61bb7375 | ||
|  | fce4c9174d | ||
|  | 2220963899 | ||
|  | e69e6c1ce8 | ||
|  | 0f09a9db4d | ||
|  | 53a6c10ada | ||
|  | 14772469ed | ||
|  | 55f13ef121 | ||
|  | 95648c37b3 | ||
|  | ac98822a55 | ||
|  | c460419166 | ||
|  | d2a8819dd4 | ||
|  | d393c693de | ||
|  | d4a84ed198 | ||
|  | e8c7986a58 | ||
|  | 809e40c5ce | ||
|  | f445a95c26 | ||
|  | 909dc212fb | ||
|  | eacc1da157 | ||
|  | 587ad1298d | ||
|  | fae7dabbc2 | ||
|  | 3a813c30b4 | ||
|  | 3de46f55fa | ||
|  | 3aa922341c | ||
|  | e94043edc2 | ||
|  | da91645ec0 | ||
|  | 178072d3af | ||
|  | 811d8e330f | ||
|  | d3c8d06114 | ||
|  | 82dc0045ba | ||
|  | 3d06f0ac14 | ||
|  | b5c0ef01d9 | ||
|  | 3a5d3016c7 | ||
|  | 20690b4d5b | ||
|  | 2816a4a325 | ||
|  | 2f4f37778c | ||
|  | c4507a7f75 | ||
|  | 9a0672e359 | ||
|  | f128db35c6 | ||
|  | a2cfaa0867 | ||
|  | 5850c5e20a | ||
|  | e77a1e403f | ||
|  | b72e8db7b1 | ||
|  | 07506784f4 | ||
|  | 0435e42b3d | ||
|  | 31884bbba6 | ||
|  | 6b38faf84e | ||
|  | 2f95f99890 | ||
|  | 9b78069f41 | ||
|  | 559c2042ac | ||
|  | ae3b369e9a | ||
|  | 31a6565e17 | ||
|  | f488bbde02 | ||
|  | e668b88fb5 | ||
|  | 2d0aa4af96 | ||
|  | 6e67416c83 | ||
|  | 1ef28cbc02 | ||
|  | 58bdf14f6b | ||
|  | 9f4ecb0963 | ||
|  | b1259a014f | ||
|  | 142d0b5af2 | ||
|  | 450e2bad1c | ||
|  | 089300d57e | ||
|  | 36f67793cb | ||
|  | c335a9bbc8 | ||
|  | 029688a594 | ||
|  | 6f2eb33fd0 | ||
|  | 8351020913 | ||
|  | 220efca8d7 | ||
|  | 28579f7b80 | ||
|  | f1d77bdb50 | ||
|  | ca8b4cb11a | ||
|  | 31dbb7b111 | ||
|  | 352cdf75c8 | ||
|  | d81c99bcda | ||
|  | 1e2c979341 | ||
|  | d8664096f9 | ||
|  | 0d9a221b00 | ||
|  | de85f17cac | ||
|  | e3d6f4f00f | ||
|  | d0e0054b00 | ||
|  | 735222a8ed | ||
|  | 66f299cd06 | ||
|  | e3c5268143 | ||
|  | df32493d77 | ||
|  | 86faf44153 | ||
|  | e2f3e4b555 | ||
|  | e57ed6015c | ||
|  | 9c34ca7fc4 | ||
|  | 7b94f4a441 | ||
|  | 693f8d0738 | ||
|  | d6ecbc06bf | ||
|  | c31674fffc | ||
|  | b08de8cc00 | ||
|  | 4c503e4c7c | ||
|  | dd4158c6b4 | ||
|  | 5fd7ea2b96 | ||
|  | b9ff80eb5a | ||
|  | afc725bbc8 | ||
|  | 0342c371cc | ||
|  | 2da4e6b048 | ||
|  | f50550d79c | ||
|  | 3fa39a6805 | ||
|  | 3dbe6d4870 | ||
|  | 59c48268ab | ||
|  | 1f83c5195d | ||
|  | 49a95a08fe | ||
|  | c86c5ccfe9 | ||
|  | 8a2497fc67 | ||
|  | 7c70732247 | ||
|  | 53fc4f2740 | ||
|  | f3ade5621e | ||
|  | ec2e08e33a | ||
|  | b9a26faa4d | ||
|  | 1a434d0c83 | ||
|  | 9a2c6c2967 | ||
|  | 602b35d589 | ||
|  | f42cd0c7c3 | ||
|  | cb81855a17 | ||
|  | 89cf351ad0 | ||
|  | 3f70a3f06c | ||
|  | 9df360f010 | ||
|  | 9a26d6d49f | ||
|  | bc4d801c12 | ||
|  | f2d8e13576 | ||
|  | ec0b5db973 | ||
|  | 46a0d1ce35 | ||
|  | cb81446ca6 | ||
|  | 9350b4939c | ||
|  | 33e8c8c415 | ||
|  | 48fa86cc54 | ||
|  | d5e6d1c578 | ||
|  | 0bc688795a | ||
|  | eb76ed5591 | ||
|  | 839cbaf37a | ||
|  | 788fc9204d | ||
|  | 3e3e304ef3 | ||
|  | 447d453fdc | ||
|  | 36fd7884f3 | ||
|  | 54da08b2f2 | ||
|  | 3f02072ae9 | ||
|  | a9c117703b | ||
|  | c137255155 | ||
|  | e7829ecc38 | ||
|  | 529bdafa31 | ||
|  | e2af0caa41 | ||
|  | 80f96abf08 | ||
|  | 70da38193f | ||
|  | 13df973873 | ||
|  | 3ccb791674 | ||
|  | ccf1a6c182 | ||
|  | 493543c1f5 | ||
|  | 5f5725e0e3 | ||
|  | 107dd42957 | ||
|  | a9f3fe4d3a | ||
|  | 3e62e17b9e | ||
|  | 57855b1930 | ||
|  | aa9e8227bb | ||
|  | a80f083b6e | ||
|  | 474e066d4a | ||
|  | 4428ccefbf | ||
|  | d568a6c8a9 | ||
|  | 97e9ad6cb2 | ||
|  | 00607d2a6d | ||
|  | c2a425121d | ||
|  | 435694e9ea | ||
|  | f59135a9ca | ||
|  | 102b106402 | ||
|  | 5c27c8e633 | ||
|  | edd5215b21 | ||
|  | 94b173ae6b | ||
|  | 7d96b281b6 | ||
|  | a5515ac89f | ||
|  | fb863b0bf2 | ||
|  | 50882f309b | ||
|  | ce854fbb43 | ||
|  | 6799268ec4 | ||
|  | 6fe5ce0485 | ||
|  | cbeaf8e16a | ||
|  | 04de4c9b36 | ||
|  | 517731cb59 | ||
|  | e34e43173c | ||
|  | 79d6055a78 | ||
|  | 7ac4d2a2f4 | ||
|  | 4984eda320 | ||
|  | 89e0791e2f | ||
|  | 922d487821 | ||
|  | 4b789979ac | ||
|  | 554b38ccff | ||
|  | 9614310208 | ||
|  | d9ec3ac354 | ||
|  | f326f08f7b | ||
|  | 0ae8418f32 | ||
|  | 309f9cd076 | ||
|  | 61f5ed3874 | ||
|  | 91178d2604 | ||
|  | 87dae6ea18 | ||
|  | 2e495c38d1 | ||
|  | c2987aaf4c | ||
|  | f4f4eecb7b | ||
|  | 84d9287251 | ||
|  | b71f334744 | ||
|  | ad306e4d01 | ||
|  | e40d4ef829 | ||
|  | 48c16c3dcc | ||
|  | c045193246 | ||
|  | a816e59a97 | ||
|  | 892074eaf2 | ||
|  | 3e501e429d | ||
|  | 0f40accb4c | ||
|  | 3dae6c99a4 | ||
|  | b185c83597 | ||
|  | ef6b4120f1 | ||
|  | a43eef01fc | ||
|  | 2cb9aa537f | ||
|  | 2edd49a8b4 | ||
|  | a57554d380 | ||
|  | c89486b6d9 | ||
|  | f737cb7235 | ||
|  | f1fe169553 | ||
|  | 2fc760780e | ||
|  | 8c3290bf6f | ||
|  | 495158b9c9 | ||
|  | f9fc9b1889 | ||
|  | 11ff2ab9d1 | ||
|  | 52b138e6b2 | ||
|  | 3562ec1f79 | ||
|  | 943b4de6dc | ||
|  | 4097f51f69 | ||
|  | cad5b2cae9 | ||
|  | 8bb4b0b9b2 | ||
|  | 9bcd1ed807 | ||
|  | d7b1892bda | ||
|  | ea0980ba83 | ||
|  | b479a3ef99 | ||
|  | 600e15d42f | ||
|  | 824959e71a | ||
|  | cfd8d231fb | ||
|  | 87c3dc2ecc | ||
|  | 590f0a83ea | ||
|  | 65e518856b | ||
|  | 469313eca7 | ||
|  | f13f378d7f | ||
|  | 76d8017be5 | ||
|  | af1bdc0c2c | ||
|  | 6ac1e05e60 | ||
|  | 7fa937e80b | ||
|  | ed0e14aee5 | ||
|  | e300c1aab4 | ||
|  | 9e1586878b | ||
|  | 5d54939bd4 | ||
|  | 3e9f98b43e | ||
|  | c329ffa545 | ||
|  | d3cad66b69 | ||
|  | 246af608d3 | ||
|  | e7debc5466 | ||
|  | 5866300ac1 | ||
|  | c1221aef4b | ||
|  | bc879a3872 | ||
|  | 2b4a3d463b | ||
|  | 6b59b6de6e | ||
|  | 3ce5ccb98a | ||
|  | a1b83def4f | ||
|  | 5177619301 | ||
|  | 4e0319bacc | ||
|  | 30f64af55f | ||
|  | cdeabaaf9a | ||
|  | fa676f60fb | ||
|  | 4ec123a19a | ||
|  | de35bde048 | ||
|  | 3f786856f3 | ||
|  | d49aecdf49 | ||
|  | 6713597621 | ||
|  | 09bd55675d | ||
|  | d87dda40ee | ||
|  | 06cfc391a1 | ||
|  | bea06a06a1 | ||
|  | 06fa2ab7a1 | ||
|  | 4926011f3f | ||
|  | 0455f8658d | ||
|  | 4773021ff0 | ||
|  | e2bd1f6544 | ||
|  | b73884160a | ||
|  | 8bcfa729b6 | ||
|  | f8dda5b4a6 | ||
|  | c0961d438d | ||
|  | d9dd00eb39 | ||
|  | 6d9baaa499 | ||
|  | b37ed5ab23 | ||
|  | 3fba741f1b | ||
|  | 73051d7d42 | ||
|  | 717e101b80 | ||
|  | 08f28d48af | ||
|  | ec2f693575 | ||
|  | 3cc1bf52cb | ||
|  | 5da9f0cfb6 | ||
|  | 64624bea1d | ||
|  | dc95395f42 | ||
|  | 273f188101 | ||
|  | a6b22b5156 | ||
|  | 9d8a4cd934 | ||
|  | c73dd5f664 | ||
|  | 7ff8c5e966 | ||
|  | 1c11aa13b8 | ||
|  | 0c2ec58366 | ||
|   | 2955d7148f | ||
|  | f9d87cb9f6 | ||
|  | 50fcc42e99 | ||
|  | 805456d032 | ||
|  | a9df7906eb | ||
|  | 59d732cba7 | ||
|  | 61099bef27 | ||
|  | dca44f1588 | ||
|  | 87174ddbb3 | ||
|  | c5cc101f4b | ||
|  | 071c4286a7 | ||
|  | 7603fc0436 | ||
|  | c7850f9f1a | ||
|  | c0eebb2b08 | ||
|  | 87147c37ae | ||
|  | 3815f9836f | ||
|  | cf66ae61e1 | ||
|  | 962324c3f7 | ||
|  | bd3e262273 | ||
|  | fa65035664 | ||
|  | ca1b6046f3 | ||
|  | 128085963f | ||
|  | 67cc03e4dd | ||
|  | ca4db81dbd | ||
|  | a10672a683 | ||
|  | 0977d8d631 | ||
|  | 42676746a2 | ||
|  | ae7933c8c9 | ||
|  | b65e1e022e | ||
|  | 9ab3848755 | ||
|  | 986d7de906 | ||
|  | eda1673518 | ||
|  | 97cde38d8f | ||
|  | 5ba03bd222 | ||
|  | a14ae02c27 | ||
|  | deebdef04d | ||
|  | e881bb55a7 | ||
|  | 9e3f31f2f0 | ||
|  | f7652e7f01 | ||
|  | 5289f3e4c2 | ||
|  | 01818af963 | ||
|  | 58eaf3bccc | ||
|  | a3ec741d67 | ||
|  | 5cb948d0f3 | ||
|  | 56ae279c96 | ||
|  | bf390b65d9 | ||
|  | 96ccce5db3 | ||
|  | d4aee258c4 | ||
|  | 7f8e736928 | ||
|  | f85bdcebaf | ||
|  | f6096339cb | ||
|  | f6bd17c70b | ||
|  | 6a05ec98f4 | ||
|  | c60ee14b86 | ||
|  | 26f196a067 | ||
|  | 93c463c349 | ||
|  | 59ea4a0364 | ||
|  | df406dd794 | ||
|  | 08b743ddcb | ||
|  | 8bd76d1ff0 | ||
|  | f13a93348f | ||
|  | b0ecdfe01d | ||
|  | 4b869f0d9e | ||
|  | 707af8bb4e | ||
|  | 840705f793 | ||
|  | 36c8275f5e | ||
|  | 62a4af8607 | ||
|  | 46f894c09b | ||
|  | e8f9796fc5 | ||
|  | a69aad878e | ||
|  | e21e339cb0 | ||
|  | 9ede6755c5 | ||
|  | 34fc9bc50a | ||
|  | 79f700c622 | ||
|  | ac04f77d94 | ||
|  | 9e8d7b18fa | ||
|  | 3f62cf512f | ||
|  | 51728efba1 | ||
|  | c7d4ff6f27 | ||
|  | c1e1da12c2 | ||
|  | 859b6fcea8 | ||
|  | 1f6e42afd9 | ||
|  | ef3bc07249 | ||
|  | 6c3204a8ce | ||
|  | 250da33fd7 | ||
|  | dfda29cec3 | ||
|  | 085876dd83 | ||
|  | ff9ad859b3 | ||
|  | 78335e5814 | ||
|  | b08af77c98 | ||
|  | 7d348f25ac | ||
|  | 22535c0e43 | ||
|  | 1d58d519a0 | ||
|  | 8176356509 | ||
|  | 9086259a65 | ||
|  | 66ee382da0 | ||
|  | 84b6708260 | ||
|  | 985cc100e2 | ||
|  | 3d0ecaa8d2 | ||
|  | 009c5a438c | ||
|  | c3af8fefde | ||
|  | 1b116e3a1d | ||
|  | 76632f5bae | ||
|  | ee6030bc62 | ||
|  | 2a000d432f | ||
|  | 7557d4d3cb | ||
|  | 54ecfac550 | ||
|  | 11b5a0294e | ||
|  | 9264f1e9b9 | ||
|  | 044af254f3 | ||
|  | e60bbc78e6 | ||
|  | 06ddfe3d41 | ||
|  | df458b3913 | ||
|  | fc4165b800 | ||
|  | 44496707fb | ||
|  | bad889d450 | ||
|  | 1b4edae4d9 | ||
|  | cacd889193 | ||
|  | 5a7cf04a7c | ||
|  | fd7a293f4b | ||
|  | f35aa6a035 | ||
|  | d1c8e54798 | ||
|  | 5d9e547d05 | ||
|  | c91bb5a565 | ||
|  | 1b5b79897a | ||
|  | d7f2b7cd63 | ||
|  | 12c15ea590 | ||
|  | d3a6ccacf0 | ||
|  | 6fed773cb8 | ||
|  | 4a1e4bb821 | ||
|  | 0c529cb7e7 | ||
|  | b1b6fe553a | ||
|  | 54c449f11b | ||
|  | b93a96db23 | ||
|  | 06683c57dd | ||
|  | 6ad90c7a87 | ||
|  | 2a87add745 | ||
|  | 089214709f | ||
|  | 9bf891f3fb | ||
|  | 583f376f11 | ||
|  | 4998eaeaf1 | ||
|  | 3cf6386bb6 | ||
|  | 2365fb69b4 | ||
|  | 1fec7d6271 | ||
|  | 17684a3ab3 | ||
|  | e488d7d84c | ||
|  | aa9500f5ad | ||
|  | 0774258516 | ||
|  | f231edaa6d | 
							
								
								
									
										177
									
								
								.deploy/docker/.env.docker
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								.deploy/docker/.env.docker
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,177 @@ | ||||
| # You can leave this on "local". If you change it to production most console commands will ask for extra confirmation. | ||||
| # Never set it to "testing". | ||||
| APP_ENV=${FF_APP_ENV} | ||||
|  | ||||
| # Set to true if you want to see debug information in error screens. | ||||
| APP_DEBUG=${APP_DEBUG} | ||||
|  | ||||
| # This should be your email address | ||||
| SITE_OWNER=${SITE_OWNER} | ||||
|  | ||||
| # The encryption key for your database and sessions. Keep this very secure. | ||||
| # If you generate a new one all existing data must be considered LOST. | ||||
| # Change it to a string of exactly 32 chars or use command `php artisan key:generate` to generate it | ||||
| APP_KEY=${FF_APP_KEY} | ||||
|  | ||||
| # Change this value to your preferred time zone. | ||||
| # Example: Europe/Amsterdam | ||||
| TZ=${TZ} | ||||
|  | ||||
| # This variable must match your installation's external address but keep in mind that | ||||
| # it's only used on the command line as a fallback value. | ||||
| APP_URL=${APP_URL} | ||||
|  | ||||
| # TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy. | ||||
| TRUSTED_PROXIES=${TRUSTED_PROXIES} | ||||
|  | ||||
| # The log channel defines where your log entries go to. | ||||
| # 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/. | ||||
| # Several other options exist. You can use 'single' for one big fat error log (not recommended). | ||||
| # Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself. | ||||
| LOG_CHANNEL=stdout | ||||
|  | ||||
| # Log level. You can set this from least severe to most severe: | ||||
| # debug, info, notice, warning, error, critical, alert, emergency | ||||
| # If you set it to debug your logs will grow large, and fast. If you set it to emergency probably | ||||
| # nothing will get logged, ever. | ||||
| APP_LOG_LEVEL=${APP_LOG_LEVEL} | ||||
|  | ||||
| # Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III | ||||
| # For other database types, please see the FAQ: http://firefly-iii.readthedocs.io/en/latest/support/faq.html | ||||
| DB_CONNECTION=${FF_DB_CONNECTION} | ||||
| DB_HOST=${FF_DB_HOST} | ||||
| DB_PORT=${FF_DB_PORT} | ||||
| DB_DATABASE=${FF_DB_NAME} | ||||
| DB_USERNAME=${FF_DB_USER} | ||||
| DB_PASSWORD="${FF_DB_PASSWORD}" | ||||
|  | ||||
| # If you're looking for performance improvements, you could install memcached. | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
|  | ||||
| # You can configure another file storage backend if you cannot use the local storage option. | ||||
| # To set this up, fill in the following variables. The upload path is used to store uploaded | ||||
| # files and the export path is to store exported data (before download). | ||||
| SFTP_HOST=${SFTP_HOST} | ||||
| SFTP_PORT=${SFTP_PORT} | ||||
| SFTP_UPLOAD_PATH=${SFTP_UPLOAD_PATH} | ||||
| SFTP_EXPORT_PATH=${SFTP_EXPORT_PATH} | ||||
|  | ||||
| # SFTP uses either the username/password combination or the private key to authenticate. | ||||
| SFTP_USERNAME=${SFTP_USERNAME} | ||||
| SFTP_PASSWORD="${SFTP_PASSWORD}" | ||||
| SFTP_PRIV_KEY=${SFTP_PRIV_KEY} | ||||
|  | ||||
| # Cookie settings. Should not be necessary to change these. | ||||
| COOKIE_PATH="/" | ||||
| COOKIE_DOMAIN= | ||||
| COOKIE_SECURE=false | ||||
|  | ||||
| # If you want Firefly III to mail you, update these settings | ||||
| # For instructions, see: https://firefly-iii.readthedocs.io/en/latest/installation/mail.html | ||||
| MAIL_DRIVER=${MAIL_DRIVER} | ||||
| MAIL_HOST=${MAIL_HOST} | ||||
| MAIL_PORT=${MAIL_PORT} | ||||
| MAIL_FROM=${MAIL_FROM} | ||||
| MAIL_USERNAME=${MAIL_USERNAME} | ||||
| MAIL_PASSWORD="${MAIL_PASSWORD}" | ||||
| MAIL_ENCRYPTION=${MAIL_ENCRYPTION} | ||||
|  | ||||
| # Other mail drivers: | ||||
| MAILGUN_DOMAIN=${MAILGUN_DOMAIN} | ||||
| MAILGUN_SECRET=${MAILGUN_SECRET} | ||||
| MANDRILL_SECRET=${MANDRILL_SECRET} | ||||
| SPARKPOST_SECRET=${SPARKPOST_SECRET} | ||||
|  | ||||
| # Firefly III can send you the following messages | ||||
| SEND_REGISTRATION_MAIL=true | ||||
| SEND_ERROR_MESSAGE=false | ||||
|  | ||||
| # These messages contain (sensitive) transaction information: | ||||
| SEND_REPORT_JOURNALS=${SEND_REPORT_JOURNALS} | ||||
|  | ||||
| # Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places. | ||||
| MAPBOX_API_KEY=${MAPBOX_API_KEY} | ||||
|  | ||||
| # Firefly III currently supports two provider for live Currency Exchange Rates: | ||||
| # "fixer" is the default (for backward compatibility), and "ratesapi" is the new one. | ||||
| # RatesApi.IO (see https://ratesapi.io) is a FREE and OPEN SOURCE live currency exchange rates, | ||||
| # built compatible with Fixer.IO, based on data published by European Central Bank, and don't require API key. | ||||
| CER_PROVIDER=${CER_PROVIDER} | ||||
| # If you have select "fixer" as default currency exchange rates, | ||||
| # set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates. | ||||
| # Please note that this WILL ONLY WORK FOR PAID fixer.io accounts because they severely limited | ||||
| # the free API up to the point where you might as well offer nothing. | ||||
| FIXER_API_KEY=${FIXER_API_KEY} | ||||
|  | ||||
| # If you wish to track your own behavior over Firefly III, set a valid analytics tracker ID here. | ||||
| ANALYTICS_ID=${ANALYTICS_ID} | ||||
|  | ||||
| # Most parts of the database are encrypted by default, but you can turn this off if you want to. | ||||
| # This makes it easier to migrate your database. Not that some fields will never be decrypted. | ||||
| USE_ENCRYPTION=true | ||||
|  | ||||
| # Firefly III has two options for user authentication. "eloquent" is the default, | ||||
| # and "ldap" for LDAP servers. | ||||
| # For full instructions on these settings please visit: | ||||
| # https://firefly-iii.readthedocs.io/en/latest/installation/authentication.html | ||||
| LOGIN_PROVIDER=${LOGIN_PROVIDER} | ||||
|  | ||||
| # LDAP connection configuration | ||||
| ADLDAP_CONNECTION_SCHEME=${ADLDAP_CONNECTION_SCHEME} | ||||
| ADLDAP_AUTO_CONNECT=${ADLDAP_AUTO_CONNECT} | ||||
|  | ||||
| # LDAP connection settings | ||||
| ADLDAP_CONTROLLERS=${ADLDAP_CONTROLLERS} | ||||
| ADLDAP_PORT=${ADLDAP_PORT} | ||||
| ADLDAP_TIMEOUT=${ADLDAP_TIMEOUT} | ||||
| ADLDAP_BASEDN="${ADLDAP_BASEDN}" | ||||
| ADLDAP_FOLLOW_REFFERALS=${ADLDAP_FOLLOW_REFFERALS} | ||||
| ADLDAP_USE_SSL=${ADLDAP_USE_SSL} | ||||
| ADLDAP_USE_TLS=${ADLDAP_USE_TLS} | ||||
|  | ||||
| ADLDAP_ADMIN_USERNAME=${ADLDAP_ADMIN_USERNAME} | ||||
| ADLDAP_ADMIN_PASSWORD="${ADLDAP_ADMIN_PASSWORD}" | ||||
|  | ||||
| ADLDAP_ACCOUNT_PREFIX="${ADLDAP_ACCOUNT_PREFIX}" | ||||
| ADLDAP_ACCOUNT_SUFFIX="${ADLDAP_ACCOUNT_SUFFIX}" | ||||
|  | ||||
| # LDAP authentication settings. | ||||
| ADLDAP_PASSWORD_SYNC=${ADLDAP_PASSWORD_SYNC} | ||||
| ADLDAP_LOGIN_FALLBACK=${ADLDAP_LOGIN_FALLBACK} | ||||
|  | ||||
| ADLDAP_DISCOVER_FIELD=${ADLDAP_DISCOVER_FIELD} | ||||
| ADLDAP_AUTH_FIELD=${ADLDAP_AUTH_FIELD} | ||||
|  | ||||
| # Will allow SSO if your server provides an AUTH_USER field. | ||||
| WINDOWS_SSO_DISCOVER=${WINDOWS_SSO_DISCOVER} | ||||
| WINDOWS_SSO_KEY=${WINDOWS_SSO_KEY} | ||||
|  | ||||
| # field to sync as local username. | ||||
| ADLDAP_SYNC_FIELD=${ADLDAP_SYNC_FIELD} | ||||
|  | ||||
| # You can disable the X-Frame-Options header if it interfears with tools like | ||||
| # Organizr. This is at your own risk. | ||||
| DISABLE_FRAME_HEADER=${DISABLE_FRAME_HEADER} | ||||
|  | ||||
| # Leave the following configuration vars as is. | ||||
| # Unless you like to tinker and know what you're doing. | ||||
| APP_NAME=FireflyIII | ||||
| ADLDAP_CONNECTION=default | ||||
| BROADCAST_DRIVER=log | ||||
| QUEUE_DRIVER=sync | ||||
| REDIS_HOST=127.0.0.1 | ||||
| REDIS_PASSWORD=null | ||||
| REDIS_PORT=6379 | ||||
| CACHE_PREFIX=firefly | ||||
| SEARCH_RESULT_LIMIT=50 | ||||
| PUSHER_KEY= | ||||
| PUSHER_SECRET= | ||||
| PUSHER_ID= | ||||
| DEMO_USERNAME= | ||||
| DEMO_PASSWORD= | ||||
| IS_DOCKER=true | ||||
| IS_SANDSTORM=false | ||||
| IS_HEROKU=false | ||||
| BUNQ_USE_SANDBOX=false | ||||
| FFIII_LAYOUT=v1 | ||||
| @@ -1,73 +1,3 @@ | ||||
| # This is the main Apache server configuration file.  It contains the | ||||
| # configuration directives that give the server its instructions. | ||||
| # See http://httpd.apache.org/docs/2.4/ for detailed information about | ||||
| # the directives and /usr/share/doc/apache2/README.Debian about Debian specific | ||||
| # hints. | ||||
| # | ||||
| # | ||||
| # Summary of how the Apache 2 configuration works in Debian: | ||||
| # The Apache 2 web server configuration in Debian is quite different to | ||||
| # upstream's suggested way to configure the web server. This is because Debian's | ||||
| # default Apache2 installation attempts to make adding and removing modules, | ||||
| # virtual hosts, and extra configuration directives as flexible as possible, in | ||||
| # order to make automating the changes and administering the server as easy as | ||||
| # possible. | ||||
| 
 | ||||
| # It is split into several files forming the configuration hierarchy outlined | ||||
| # below, all located in the /etc/apache2/ directory: | ||||
| # | ||||
| #	/etc/apache2/ | ||||
| #	|-- apache2.conf | ||||
| #	|	`--  ports.conf | ||||
| #	|-- mods-enabled | ||||
| #	|	|-- *.load | ||||
| #	|	`-- *.conf | ||||
| #	|-- conf-enabled | ||||
| #	|	`-- *.conf | ||||
| # 	`-- sites-enabled | ||||
| #	 	`-- *.conf | ||||
| # | ||||
| # | ||||
| # * apache2.conf is the main configuration file (this file). It puts the pieces | ||||
| #   together by including all remaining configuration files when starting up the | ||||
| #   web server. | ||||
| # | ||||
| # * ports.conf is always included from the main configuration file. It is | ||||
| #   supposed to determine listening ports for incoming connections which can be | ||||
| #   customized anytime. | ||||
| # | ||||
| # * Configuration files in the mods-enabled/, conf-enabled/ and sites-enabled/ | ||||
| #   directories contain particular configuration snippets which manage modules, | ||||
| #   global configuration fragments, or virtual host configurations, | ||||
| #   respectively. | ||||
| # | ||||
| #   They are activated by symlinking available configuration files from their | ||||
| #   respective *-available/ counterparts. These should be managed by using our | ||||
| #   helpers a2enmod/a2dismod, a2ensite/a2dissite and a2enconf/a2disconf. See | ||||
| #   their respective man pages for detailed information. | ||||
| # | ||||
| # * The binary is called apache2. Due to the use of environment variables, in | ||||
| #   the default configuration, apache2 needs to be started/stopped with | ||||
| #   /etc/init.d/apache2 or apache2ctl. Calling /usr/bin/apache2 directly will not | ||||
| #   work with the default configuration. | ||||
| 
 | ||||
| 
 | ||||
| # Global configuration | ||||
| # | ||||
| 
 | ||||
| # | ||||
| # ServerRoot: The top of the directory tree under which the server's | ||||
| # configuration, error, and log files are kept. | ||||
| # | ||||
| # NOTE!  If you intend to place this on an NFS (or otherwise network) | ||||
| # mounted filesystem then please read the Mutex documentation (available | ||||
| # at <URL:http://httpd.apache.org/docs/2.4/mod/core.html#mutex>); | ||||
| # you will save yourself a lot of trouble. | ||||
| # | ||||
| # Do NOT add a slash at the end of the directory path. | ||||
| # | ||||
| #ServerRoot "/etc/apache2" | ||||
| 
 | ||||
| # | ||||
| # The accept serialization lock file MUST BE STORED ON A LOCAL DISK. | ||||
| # | ||||
							
								
								
									
										22
									
								
								.deploy/docker/build-amd64.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										22
									
								
								.deploy/docker/build-amd64.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| # build image | ||||
| echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin | ||||
|  | ||||
|  | ||||
|  | ||||
| if [ "$TRAVIS_BRANCH" == "develop" ]; then | ||||
|     echo "Build develop amd64" | ||||
|     docker build -t jc5x/firefly-iii:develop-amd64 -f Dockerfile.amd64 . | ||||
|     docker tag jc5x/firefly-iii:develop-amd64 jc5x/firefly-iii:develop-$VERSION-amd64 | ||||
|     docker push jc5x/firefly-iii:develop-amd64 | ||||
|     docker push jc5x/firefly-iii:develop-$VERSION-amd64 | ||||
| fi | ||||
|  | ||||
| if [ "$TRAVIS_BRANCH" == "master" ]; then | ||||
|     echo "Build master amd64" | ||||
|     docker build -t jc5x/firefly-iii:latest-amd64 -f Dockerfile.amd64 . | ||||
|     docker tag jc5x/firefly-iii:latest-amd64 jc5x/firefly-iii:release-$VERSION-amd64 | ||||
|     docker push jc5x/firefly-iii:latest-amd64 | ||||
|     docker push jc5x/firefly-iii:release-$VERSION-amd64 | ||||
| fi | ||||
							
								
								
									
										30
									
								
								.deploy/docker/build-arm.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										30
									
								
								.deploy/docker/build-arm.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| docker run --rm --privileged multiarch/qemu-user-static:register --reset | ||||
|  | ||||
|  | ||||
| # get qemu-arm-static binary | ||||
| mkdir tmp | ||||
| pushd tmp && \ | ||||
| curl -L -o qemu-arm-static.tar.gz https://github.com/multiarch/qemu-user-static/releases/download/v2.6.0/qemu-arm-static.tar.gz && \ | ||||
| tar xzf qemu-arm-static.tar.gz && \ | ||||
| popd | ||||
|  | ||||
| # build image | ||||
| echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin | ||||
|  | ||||
| if [ "$TRAVIS_BRANCH" == "develop" ]; then | ||||
|     echo "Build develop arm" | ||||
|     docker build --tag jc5x/firefly-iii:develop-arm --file Dockerfile.arm . | ||||
|     docker tag jc5x/firefly-iii:develop-arm jc5x/firefly-iii:develop-$VERSION-arm | ||||
|     docker push jc5x/firefly-iii:develop-arm | ||||
|     docker push jc5x/firefly-iii:develop-$VERSION-arm | ||||
| fi | ||||
|  | ||||
| if [ "$TRAVIS_BRANCH" == "master" ]; then | ||||
|     echo "Build master arm" | ||||
|     docker build --tag jc5x/firefly-iii:latest-arm --file Dockerfile.arm . | ||||
|     docker tag jc5x/firefly-iii:latest-arm jc5x/firefly-iii:release-$VERSION-arm | ||||
|     docker push jc5x/firefly-iii:latest-arm | ||||
|     docker push jc5x/firefly-iii:release-$VERSION-arm | ||||
| fi | ||||
							
								
								
									
										3314
									
								
								.deploy/docker/cacert.pem
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3314
									
								
								.deploy/docker/cacert.pem
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										64
									
								
								.deploy/docker/entrypoint.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										64
									
								
								.deploy/docker/entrypoint.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| echo "Now in entrypoint.sh for Firefly III" | ||||
|  | ||||
| lscpu | ||||
|  | ||||
| # make sure the correct directories exists (suggested by @chrif): | ||||
| echo "Making directories..." | ||||
| mkdir -p $FIREFLY_PATH/storage/app/public | ||||
| mkdir -p $FIREFLY_PATH/storage/build | ||||
| mkdir -p $FIREFLY_PATH/storage/database | ||||
| mkdir -p $FIREFLY_PATH/storage/debugbar | ||||
| mkdir -p $FIREFLY_PATH/storage/export | ||||
| mkdir -p $FIREFLY_PATH/storage/framework/cache/data | ||||
| mkdir -p $FIREFLY_PATH/storage/framework/sessions | ||||
| mkdir -p $FIREFLY_PATH/storage/framework/testing | ||||
| mkdir -p $FIREFLY_PATH/storage/framework/views/v1 | ||||
| mkdir -p $FIREFLY_PATH/storage/framework/views/v2 | ||||
| mkdir -p $FIREFLY_PATH/storage/logs | ||||
| mkdir -p $FIREFLY_PATH/storage/upload | ||||
|  | ||||
|  | ||||
| echo "Touch DB file (if SQLlite)..." | ||||
| if [[ $DB_CONNECTION == "sqlite" ]] | ||||
| then | ||||
|     touch $FIREFLY_PATH/storage/database/database.sqlite | ||||
|     echo "Touched!" | ||||
| fi | ||||
|  | ||||
| if [[ $FF_DB_CONNECTION == "sqlite" ]] | ||||
| then | ||||
|     touch $FIREFLY_PATH/storage/database/database.sqlite | ||||
|     echo "Touched!" | ||||
| fi | ||||
|  | ||||
| # make sure we own the volumes: | ||||
| echo "Run chown on ${FIREFLY_PATH}/storage..." | ||||
| chown -R www-data:www-data -R $FIREFLY_PATH/storage | ||||
| echo "Run chmod on ${FIREFLY_PATH}/storage..." | ||||
| chmod -R 775 $FIREFLY_PATH/storage | ||||
|  | ||||
| # remove any lingering files that may break upgrades: | ||||
| echo "Remove log file..." | ||||
| rm -f $FIREFLY_PATH/storage/logs/laravel.log | ||||
|  | ||||
| echo "Map environment variables on .env file..." | ||||
| cat $FIREFLY_PATH/.deploy/docker/.env.docker | envsubst > $FIREFLY_PATH/.env | ||||
| echo "Dump auto load..." | ||||
| composer dump-autoload | ||||
| echo "Discover packages..." | ||||
| php artisan package:discover | ||||
|  | ||||
| echo "Run various artisan commands..." | ||||
| php artisan migrate --seed | ||||
| php artisan firefly:decrypt-all | ||||
| php artisan firefly:upgrade-database | ||||
| php artisan firefly:verify | ||||
| php artisan passport:install | ||||
| php artisan cache:clear | ||||
|  | ||||
| php artisan firefly:instructions install | ||||
|  | ||||
| echo "Go!" | ||||
| exec apache2-foreground | ||||
							
								
								
									
										35
									
								
								.deploy/docker/manifest.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										35
									
								
								.deploy/docker/manifest.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| if [ "$TRAVIS_BRANCH" == "develop" ]; then | ||||
|     TARGET=jc5x/firefly-iii:develop | ||||
|     ARM=jc5x/firefly-iii:develop-arm | ||||
|     AMD=jc5x/firefly-iii:develop-amd64 | ||||
|  | ||||
|     docker manifest create $TARGET $AMD $ARM | ||||
|     docker manifest annotate $TARGET $ARM --arch arm   --os linux | ||||
|     docker manifest annotate $TARGET $AMD --arch amd64 --os linux | ||||
|     docker manifest push $TARGET | ||||
| fi | ||||
|  | ||||
| echo "The version is $VERSION" | ||||
|  | ||||
| if [ "$TRAVIS_BRANCH" == "master" ]; then | ||||
|     TARGET=jc5x/firefly-iii:latest | ||||
|     ARM=jc5x/firefly-iii:latest-arm | ||||
|     AMD=jc5x/firefly-iii:latest-amd64 | ||||
|  | ||||
|     docker manifest create $TARGET $AMD $ARM | ||||
|     docker manifest annotate $TARGET $ARM --arch arm   --os linux | ||||
|     docker manifest annotate $TARGET $AMD --arch amd64 --os linux | ||||
|     docker manifest push $TARGET | ||||
|  | ||||
|     # and another one for version specific: | ||||
|     TARGET=jc5x/firefly-iii:release-$VERSION | ||||
|     ARM=jc5x/firefly-iii:release-$VERSION-arm | ||||
|     AMD=jc5x/firefly-iii:release-$VERSION-amd64 | ||||
|  | ||||
|     docker manifest create $TARGET $AMD $ARM | ||||
|     docker manifest annotate $TARGET $ARM --arch arm   --os linux | ||||
|     docker manifest annotate $TARGET $AMD --arch amd64 --os linux | ||||
|     docker manifest push $TARGET | ||||
| fi | ||||
							
								
								
									
										26
									
								
								.deploy/docker/vhost.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								.deploy/docker/vhost.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| server { | ||||
|     listen 80 default_server; | ||||
|  | ||||
|     server_name  _ *.vm docker; | ||||
|  | ||||
|     root "/app/public"; | ||||
|     index index.php; | ||||
|  | ||||
|     include /opt/docker/etc/nginx/vhost.common.d/*.conf; | ||||
| } | ||||
|  | ||||
| ############## | ||||
| # SSL | ||||
| ############## | ||||
|  | ||||
| server { | ||||
|     listen 443 default_server; | ||||
|  | ||||
|     server_name  _ *.vm docker; | ||||
|  | ||||
|     root "/app/public"; | ||||
|     index index.php; | ||||
|  | ||||
|     include /opt/docker/etc/nginx/vhost.common.d/*.conf; | ||||
|     include /opt/docker/etc/nginx/vhost.ssl.conf; | ||||
| } | ||||
							
								
								
									
										178
									
								
								.deploy/heroku/.env.heroku
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								.deploy/heroku/.env.heroku
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,178 @@ | ||||
| # You can leave this on "local". If you change it to production most console commands will ask for extra confirmation. | ||||
| # Never set it to "testing". | ||||
| APP_ENV=heroku | ||||
|  | ||||
| # Set to true if you want to see debug information in error screens. | ||||
| APP_DEBUG=false | ||||
|  | ||||
| # This should be your email address | ||||
| SITE_OWNER=heroku@example.com | ||||
|  | ||||
| # The encryption key for your database and sessions. Keep this very secure. | ||||
| # If you generate a new one all existing data must be considered LOST. | ||||
| # Change it to a string of exactly 32 chars or use command `php artisan key:generate` to generate it | ||||
| APP_KEY=7ahyYVPVsmxjdhsweWCauGeJfwc92NP2 | ||||
|  | ||||
| # Change this value to your preferred time zone. | ||||
| # Example: Europe/Amsterdam | ||||
| TZ=UTC | ||||
|  | ||||
| # This variable must match your installation's external address but keep in mind that | ||||
| # it's only used on the command line as a fallback value. | ||||
| APP_URL=http://localhost | ||||
|  | ||||
| # TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy. | ||||
| TRUSTED_PROXIES=** | ||||
|  | ||||
| # The log channel defines where your log entries go to. | ||||
| # 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/. | ||||
| # Several other options exist. You can use 'single' for one big fat error log (not recommended). | ||||
| # Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself. | ||||
| LOG_CHANNEL=stdout | ||||
|  | ||||
| # Log level. You can set this from least severe to most severe: | ||||
| # debug, info, notice, warning, error, critical, alert, emergency | ||||
| # If you set it to debug your logs will grow large, and fast. If you set it to emergency probably | ||||
| # nothing will get logged, ever. | ||||
| APP_LOG_LEVEL=debug | ||||
|  | ||||
| # Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III | ||||
| # If you use SQLite, set connection to `sqlite` and remove the database, username and password settings. | ||||
| DB_CONNECTION=pgsql | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| # If you're looking for performance improvements, you could install memcached. | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
|  | ||||
| # You can configure another file storage backend if you cannot use the local storage option. | ||||
| # To set this up, fill in the following variables. The upload path is used to store uploaded | ||||
| # files and the export path is to store exported data (before download). | ||||
| SFTP_HOST= | ||||
| SFTP_PORT= | ||||
| SFTP_UPLOAD_PATH= | ||||
| SFTP_EXPORT_PATH= | ||||
|  | ||||
| # SFTP uses either the username/password combination or the private key to authenticate. | ||||
| SFTP_USERNAME= | ||||
| SFTP_PASSWORD= | ||||
| SFTP_PRIV_KEY= | ||||
|  | ||||
| # Cookie settings. Should not be necessary to change these. | ||||
| COOKIE_PATH="/" | ||||
| COOKIE_DOMAIN= | ||||
| COOKIE_SECURE=false | ||||
|  | ||||
| # If you want Firefly III to mail you, update these settings | ||||
| # For instructions, see: https://firefly-iii.readthedocs.io/en/latest/installation/mail.html | ||||
| MAIL_DRIVER=log | ||||
| MAIL_HOST=smtp.mailtrap.io | ||||
| MAIL_PORT=2525 | ||||
| MAIL_FROM=changeme@example.com | ||||
| MAIL_USERNAME=null | ||||
| MAIL_PASSWORD=null | ||||
| MAIL_ENCRYPTION=null | ||||
|  | ||||
| # Other mail drivers: | ||||
| MAILGUN_DOMAIN= | ||||
| MAILGUN_SECRET= | ||||
| MANDRILL_SECRET= | ||||
| SPARKPOST_SECRET= | ||||
|  | ||||
| # Firefly III can send you the following messages | ||||
| SEND_REGISTRATION_MAIL=true | ||||
| SEND_ERROR_MESSAGE=true | ||||
|  | ||||
| # These messages contain (sensitive) transaction information: | ||||
| SEND_REPORT_JOURNALS=true | ||||
|  | ||||
| # Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places. | ||||
| MAPBOX_API_KEY= | ||||
|  | ||||
| # Firefly III currently supports two provider for live Currency Exchange Rates: | ||||
| # "fixer" is the default (for backward compatibility), and "ratesapi" is the new one. | ||||
| # RatesApi.IO (see https://ratesapi.io) is a FREE and OPEN SOURCE live currency exchange rates, | ||||
| # built compatible with Fixer.IO, based on data published by European Central Bank, and don't require API key. | ||||
| CER_PROVIDER=fixer | ||||
| # If you have select "fixer" as default currency exchange rates, | ||||
| # set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates. | ||||
| # Please note that this WILL ONLY WORK FOR PAID fixer.io accounts because they severely limited | ||||
| # the free API up to the point where you might as well offer nothing. | ||||
| FIXER_API_KEY= | ||||
|  | ||||
| # If you wish to track your own behavior over Firefly III, set a valid analytics tracker ID here. | ||||
| ANALYTICS_ID= | ||||
|  | ||||
| # Most parts of the database are encrypted by default, but you can turn this off if you want to. | ||||
| # This makes it easier to migrate your database. Not that some fields will never be decrypted. | ||||
| USE_ENCRYPTION=true | ||||
|  | ||||
| # Firefly III has two options for user authentication. "eloquent" is the default, | ||||
| # and "ldap" for LDAP servers. | ||||
| # For full instructions on these settings please visit: | ||||
| # https://firefly-iii.readthedocs.io/en/latest/installation/authentication.html | ||||
| LOGIN_PROVIDER=eloquent | ||||
|  | ||||
| # LDAP connection configuration | ||||
| # OpenLDAP, FreeIPA or ActiveDirectory | ||||
| ADLDAP_CONNECTION_SCHEME=OpenLDAP | ||||
| ADLDAP_AUTO_CONNECT=true | ||||
|  | ||||
| # LDAP connection settings | ||||
| ADLDAP_CONTROLLERS= | ||||
| ADLDAP_PORT=389 | ||||
| ADLDAP_TIMEOUT=5 | ||||
| ADLDAP_BASEDN="" | ||||
| ADLDAP_FOLLOW_REFFERALS=false | ||||
| ADLDAP_USE_SSL=false | ||||
| ADLDAP_USE_TLS=false | ||||
|  | ||||
| ADLDAP_ADMIN_USERNAME= | ||||
| ADLDAP_ADMIN_PASSWORD= | ||||
|  | ||||
| ADLDAP_ACCOUNT_PREFIX= | ||||
| ADLDAP_ACCOUNT_SUFFIX= | ||||
|  | ||||
| # LDAP authentication settings. | ||||
| ADLDAP_PASSWORD_SYNC=false | ||||
| ADLDAP_LOGIN_FALLBACK=false | ||||
|  | ||||
| ADLDAP_DISCOVER_FIELD=distinguishedname | ||||
| ADLDAP_AUTH_FIELD=distinguishedname | ||||
|  | ||||
| # Will allow SSO if your server provides an AUTH_USER field. | ||||
| WINDOWS_SSO_DISCOVER=samaccountname | ||||
| WINDOWS_SSO_KEY=AUTH_USER | ||||
|  | ||||
| # field to sync as local username. | ||||
| ADLDAP_SYNC_FIELD=userprincipalname | ||||
|  | ||||
| # You can disable the X-Frame-Options header if it interfears with tools like | ||||
| # Organizr. This is at your own risk. | ||||
| DISABLE_FRAME_HEADER=false | ||||
|  | ||||
| # Leave the following configuration vars as is. | ||||
| # Unless you like to tinker and know what you're doing. | ||||
| APP_NAME=FireflyIII | ||||
| ADLDAP_CONNECTION=default | ||||
| BROADCAST_DRIVER=log | ||||
| QUEUE_DRIVER=sync | ||||
| REDIS_HOST=127.0.0.1 | ||||
| REDIS_PASSWORD=null | ||||
| REDIS_PORT=6379 | ||||
| CACHE_PREFIX=firefly | ||||
| SEARCH_RESULT_LIMIT=50 | ||||
| PUSHER_KEY= | ||||
| PUSHER_SECRET= | ||||
| PUSHER_ID= | ||||
| DEMO_USERNAME= | ||||
| DEMO_PASSWORD= | ||||
| IS_DOCKER=false | ||||
| IS_SANDSTORM=false | ||||
| IS_HEROKU=true | ||||
| BUNQ_USE_SANDBOX=false | ||||
| FFIII_LAYOUT=v1 | ||||
							
								
								
									
										11
									
								
								.deploy/heroku/.locales
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								.deploy/heroku/.locales
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| en_US | ||||
| es_ES | ||||
| de_DE | ||||
| fr_FR | ||||
| it_IT | ||||
| nl_NL | ||||
| pl_PL | ||||
| pt_BR | ||||
| ru_RU | ||||
| zh_TW | ||||
| zh_CN | ||||
							
								
								
									
										82
									
								
								.deploy/kubernetes/firefly.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								.deploy/kubernetes/firefly.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | ||||
| apiVersion: v1 | ||||
| kind: PersistentVolumeClaim | ||||
| metadata: | ||||
|   name: mysql-pv-export-claim | ||||
|   labels: | ||||
|     app: firefly-local | ||||
| spec: | ||||
|   accessModes: | ||||
|     - ReadWriteOnce | ||||
|   resources: | ||||
|     requests: | ||||
|       storage: 20Gi | ||||
| --- | ||||
| apiVersion: v1 | ||||
| kind: PersistentVolumeClaim | ||||
| metadata: | ||||
|   name: mysql-pv-upload-claim | ||||
|   labels: | ||||
|     app: firefly-local | ||||
| spec: | ||||
|   accessModes: | ||||
|     - ReadWriteOnce | ||||
|   resources: | ||||
|     requests: | ||||
|       storage: 20Gi | ||||
| ---  | ||||
| apiVersion: apps/v1beta1 | ||||
| kind: Deployment | ||||
| metadata: | ||||
|   name: firefly-local | ||||
|   namespace: firefly | ||||
|   labels: | ||||
|     app: firefly-local | ||||
| spec: | ||||
|   selector: | ||||
|     matchLabels: | ||||
|       app: firefly-local | ||||
|   template: | ||||
|     metadata: | ||||
|       labels: | ||||
|         app: firefly-local | ||||
|     spec: | ||||
|       containers: | ||||
|       - image: firefly-local | ||||
|         name: firefly-local | ||||
|         env: | ||||
|         - name: FF_APP_ENV | ||||
|           value: "local" | ||||
|         - name: FF_APP_KEY | ||||
|           value: "S0m3R@nd0mString0f32Ch@rsEx@ct1y" | ||||
|         - name: FF_DB_HOST | ||||
|           value: "172.17.0.9"  | ||||
|         - name: FF_DB_NAME | ||||
|           value: "firefly_db" | ||||
|         - name: FF_DB_USER | ||||
|           value: "firefly_db" | ||||
|         - name: FF_DB_PASSWORD | ||||
|           value: "password"  | ||||
|         volumeMounts: | ||||
|         - mountPath: "/var/www/firefly-iii/storage/export" | ||||
|           name: mysql-persistent-export | ||||
|         - mountPath: "/var/www/firefly-iii/storage/upload" | ||||
|           name: mysql-persistent-upload  | ||||
|         imagePullPolicy: IfNotPresent | ||||
|       volumes: | ||||
|         - name: mysql-persistent-export | ||||
|           persistentVolumeClaim: | ||||
|             claimName: mysql-pv-export-claim | ||||
|         - name: mysql-persistent-upload | ||||
|           persistentVolumeClaim: | ||||
|             claimName: mysql-pv-upload-claim | ||||
| --- | ||||
| apiVersion: v1 | ||||
| kind: Service | ||||
| metadata: | ||||
|   name: firefly-local | ||||
| spec: | ||||
|   ports: | ||||
|     - port: 80 | ||||
|   type: NodePort | ||||
|   selector: | ||||
|     app: firefly-local | ||||
							
								
								
									
										49
									
								
								.deploy/kubernetes/sql.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								.deploy/kubernetes/sql.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| apiVersion: v1 | ||||
| kind: Secret | ||||
| metadata: | ||||
|   name: sql-pass | ||||
| type: Opaque | ||||
| data: | ||||
|   password: cGFzc3dvcmQ= | ||||
| --- | ||||
| apiVersion: apps/v1beta1 | ||||
| kind: Deployment | ||||
| metadata: | ||||
|   name: mysql | ||||
|   namespace: firefly | ||||
|   labels: | ||||
|     app: mysql | ||||
| spec: | ||||
|   selector: | ||||
|     matchLabels: | ||||
|       app: mysql | ||||
|   template: | ||||
|     metadata: | ||||
|       labels: | ||||
|         app: mysql | ||||
|     spec: | ||||
|       containers: | ||||
|       - image: mysql | ||||
|         imagePullPolicy: IfNotPresent | ||||
|         name: mysql | ||||
|         env: | ||||
|           - name: MYSQL_ROOT_PASSWORD | ||||
|             valueFrom: | ||||
|               secretKeyRef: | ||||
|                 name: sql-pass | ||||
|                 key: password | ||||
|         ports: | ||||
|         - containerPort: 3306 | ||||
|           name: mysql | ||||
| --- | ||||
| apiVersion: v1 | ||||
| kind: Service | ||||
| metadata: | ||||
|   name: mysql | ||||
| spec: | ||||
|   ports: | ||||
|     - port: 3306 | ||||
|   type: NodePort | ||||
|   selector: | ||||
|     app: mysql | ||||
|  | ||||
							
								
								
									
										178
									
								
								.deploy/sandstorm/.env.sandstorm
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										178
									
								
								.deploy/sandstorm/.env.sandstorm
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,178 @@ | ||||
| # You can leave this on "local". If you change it to production most console commands will ask for extra confirmation. | ||||
| # Never set it to "testing". | ||||
| APP_ENV=local | ||||
|  | ||||
| # Set to true if you want to see debug information in error screens. | ||||
| APP_DEBUG=true | ||||
|  | ||||
| # This should be your email address | ||||
| SITE_OWNER=sandstorm@example.com | ||||
|  | ||||
| # The encryption key for your database and sessions. Keep this very secure. | ||||
| # If you generate a new one all existing data must be considered LOST. | ||||
| # Change it to a string of exactly 32 chars or use command `php artisan key:generate` to generate it | ||||
| APP_KEY=SomeRandomStringOf32CharsExactly | ||||
|  | ||||
| # Change this value to your preferred time zone. | ||||
| # Example: Europe/Amsterdam | ||||
| TZ=UTC | ||||
|  | ||||
| # This variable must match your installation's external address but keep in mind that | ||||
| # it's only used on the command line as a fallback value. | ||||
| APP_URL=http://localhost | ||||
|  | ||||
| # TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy. | ||||
| TRUSTED_PROXIES= | ||||
|  | ||||
| # The log channel defines where your log entries go to. | ||||
| # 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/. | ||||
| # Several other options exist. You can use 'single' for one big fat error log (not recommended). | ||||
| # Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself. | ||||
| LOG_CHANNEL=stdout | ||||
|  | ||||
| # Log level. You can set this from least severe to most severe: | ||||
| # debug, info, notice, warning, error, critical, alert, emergency | ||||
| # If you set it to debug your logs will grow large, and fast. If you set it to emergency probably | ||||
| # nothing will get logged, ever. | ||||
| APP_LOG_LEVEL=debug | ||||
|  | ||||
| # Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III | ||||
| # If you use SQLite, set connection to `sqlite` and remove the database, username and password settings. | ||||
| DB_CONNECTION=mysql | ||||
| DB_HOST=127.0.0.1 | ||||
| DB_PORT=3306 | ||||
| DB_DATABASE=firefly | ||||
| DB_USERNAME=firefly | ||||
| DB_PASSWORD=firefly | ||||
|  | ||||
| # If you're looking for performance improvements, you could install memcached. | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
|  | ||||
| # You can configure another file storage backend if you cannot use the local storage option. | ||||
| # To set this up, fill in the following variables. The upload path is used to store uploaded | ||||
| # files and the export path is to store exported data (before download). | ||||
| SFTP_HOST= | ||||
| SFTP_PORT= | ||||
| SFTP_UPLOAD_PATH= | ||||
| SFTP_EXPORT_PATH= | ||||
|  | ||||
| # SFTP uses either the username/password combination or the private key to authenticate. | ||||
| SFTP_USERNAME= | ||||
| SFTP_PASSWORD= | ||||
| SFTP_PRIV_KEY= | ||||
|  | ||||
| # Cookie settings. Should not be necessary to change these. | ||||
| COOKIE_PATH="/" | ||||
| COOKIE_DOMAIN= | ||||
| COOKIE_SECURE=false | ||||
|  | ||||
| # If you want Firefly III to mail you, update these settings | ||||
| # For instructions, see: https://firefly-iii.readthedocs.io/en/latest/installation/mail.html | ||||
| MAIL_DRIVER=log | ||||
| MAIL_HOST=smtp.mailtrap.io | ||||
| MAIL_PORT=2525 | ||||
| MAIL_FROM=changeme@example.com | ||||
| MAIL_USERNAME=null | ||||
| MAIL_PASSWORD=null | ||||
| MAIL_ENCRYPTION=null | ||||
|  | ||||
| # Other mail drivers: | ||||
| MAILGUN_DOMAIN= | ||||
| MAILGUN_SECRET= | ||||
| MANDRILL_SECRET= | ||||
| SPARKPOST_SECRET= | ||||
|  | ||||
| # Firefly III can send you the following messages | ||||
| SEND_REGISTRATION_MAIL=true | ||||
| SEND_ERROR_MESSAGE=true | ||||
|  | ||||
| # These messages contain (sensitive) transaction information: | ||||
| SEND_REPORT_JOURNALS=true | ||||
|  | ||||
| # Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places. | ||||
| MAPBOX_API_KEY= | ||||
|  | ||||
| # Firefly III currently supports two provider for live Currency Exchange Rates: | ||||
| # "fixer" is the default (for backward compatibility), and "ratesapi" is the new one. | ||||
| # RatesApi.IO (see https://ratesapi.io) is a FREE and OPEN SOURCE live currency exchange rates, | ||||
| # built compatible with Fixer.IO, based on data published by European Central Bank, and don't require API key. | ||||
| CER_PROVIDER=fixer | ||||
| # If you have select "fixer" as default currency exchange rates, | ||||
| # set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates. | ||||
| # Please note that this WILL ONLY WORK FOR PAID fixer.io accounts because they severely limited | ||||
| # the free API up to the point where you might as well offer nothing. | ||||
| FIXER_API_KEY= | ||||
|  | ||||
| # If you wish to track your own behavior over Firefly III, set a valid analytics tracker ID here. | ||||
| ANALYTICS_ID= | ||||
|  | ||||
| # Most parts of the database are encrypted by default, but you can turn this off if you want to. | ||||
| # This makes it easier to migrate your database. Not that some fields will never be decrypted. | ||||
| USE_ENCRYPTION=true | ||||
|  | ||||
| # Firefly III has two options for user authentication. "eloquent" is the default, | ||||
| # and "ldap" for LDAP servers. | ||||
| # For full instructions on these settings please visit: | ||||
| # https://firefly-iii.readthedocs.io/en/latest/installation/authentication.html | ||||
| LOGIN_PROVIDER=eloquent | ||||
|  | ||||
| # LDAP connection configuration | ||||
|  # or FreeIPA or ActiveDirectory | ||||
| ADLDAP_CONNECTION_SCHEME=OpenLDAP | ||||
| ADLDAP_AUTO_CONNECT=true | ||||
|  | ||||
| # LDAP connection settings | ||||
| ADLDAP_CONTROLLERS= | ||||
| ADLDAP_PORT=389 | ||||
| ADLDAP_TIMEOUT=5 | ||||
| ADLDAP_BASEDN="" | ||||
| ADLDAP_FOLLOW_REFFERALS=false | ||||
| ADLDAP_USE_SSL=false | ||||
| ADLDAP_USE_TLS=false | ||||
|  | ||||
| ADLDAP_ADMIN_USERNAME= | ||||
| ADLDAP_ADMIN_PASSWORD= | ||||
|  | ||||
| ADLDAP_ACCOUNT_PREFIX= | ||||
| ADLDAP_ACCOUNT_SUFFIX= | ||||
|  | ||||
| # LDAP authentication settings. | ||||
| ADLDAP_PASSWORD_SYNC=false | ||||
| ADLDAP_LOGIN_FALLBACK=false | ||||
|  | ||||
| ADLDAP_DISCOVER_FIELD=distinguishedname | ||||
| ADLDAP_AUTH_FIELD=distinguishedname | ||||
|  | ||||
| # Will allow SSO if your server provides an AUTH_USER field. | ||||
| WINDOWS_SSO_DISCOVER=samaccountname | ||||
| WINDOWS_SSO_KEY=AUTH_USER | ||||
|  | ||||
| # field to sync as local username. | ||||
| ADLDAP_SYNC_FIELD=userprincipalname | ||||
|  | ||||
| # You can disable the X-Frame-Options header if it interfears with tools like | ||||
| # Organizr. This is at your own risk. | ||||
| DISABLE_FRAME_HEADER=true | ||||
|  | ||||
| # Leave the following configuration vars as is. | ||||
| # Unless you like to tinker and know what you're doing. | ||||
| APP_NAME=FireflyIII | ||||
| ADLDAP_CONNECTION=default | ||||
| BROADCAST_DRIVER=log | ||||
| QUEUE_DRIVER=sync | ||||
| REDIS_HOST=127.0.0.1 | ||||
| REDIS_PASSWORD=null | ||||
| REDIS_PORT=6379 | ||||
| CACHE_PREFIX=firefly | ||||
| SEARCH_RESULT_LIMIT=50 | ||||
| PUSHER_KEY= | ||||
| PUSHER_SECRET= | ||||
| PUSHER_ID= | ||||
| DEMO_USERNAME= | ||||
| DEMO_PASSWORD= | ||||
| IS_DOCKER=false | ||||
| IS_SANDSTORM=true | ||||
| IS_HEROKU=false | ||||
| BUNQ_USE_SANDBOX=false | ||||
| FFIII_LAYOUT=v1 | ||||
| @@ -1,4 +1,3 @@ | ||||
| # Ignore composer specific files and vendor folder | ||||
| composer.phar | ||||
| composer.lock | ||||
| vendor | ||||
|   | ||||
							
								
								
									
										60
									
								
								.env.docker
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								.env.docker
									
									
									
									
									
								
							| @@ -1,60 +0,0 @@ | ||||
| APP_ENV=${FF_APP_ENV} | ||||
| APP_DEBUG=false | ||||
| APP_NAME=FireflyIII | ||||
| APP_KEY=${FF_APP_KEY} | ||||
| APP_LOG=daily | ||||
| APP_LOG_LEVEL=warning | ||||
| APP_URL=http://localhost | ||||
| TRUSTED_PROXIES= | ||||
|  | ||||
| DB_CONNECTION=mysql | ||||
| DB_HOST=${FF_DB_HOST} | ||||
| DB_PORT=3306 | ||||
| DB_DATABASE=${FF_DB_NAME} | ||||
| DB_USERNAME=${FF_DB_USER} | ||||
| DB_PASSWORD=${FF_DB_PASSWORD} | ||||
|  | ||||
| BROADCAST_DRIVER=log | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
| QUEUE_DRIVER=sync | ||||
|  | ||||
| COOKIE_PATH="/" | ||||
| COOKIE_DOMAIN= | ||||
| COOKIE_SECURE=false | ||||
|  | ||||
| REDIS_HOST=127.0.0.1 | ||||
| REDIS_PASSWORD=null | ||||
| REDIS_PORT=6379 | ||||
|  | ||||
| MAIL_DRIVER=smtp | ||||
| MAIL_HOST=smtp.mailtrap.io | ||||
| MAIL_PORT=2525 | ||||
| MAIL_FROM=changeme@example.com | ||||
| MAIL_USERNAME=null | ||||
| MAIL_PASSWORD=null | ||||
| MAIL_ENCRYPTION=null | ||||
|  | ||||
| SEND_REGISTRATION_MAIL=true | ||||
| SEND_ERROR_MESSAGE=true | ||||
|  | ||||
| CACHE_PREFIX=firefly | ||||
|  | ||||
| SEARCH_RESULT_LIMIT=50 | ||||
| EXCHANGE_RATE_SERVICE=fixerio | ||||
|  | ||||
| MAPBOX_API_KEY= | ||||
| ANALYTICS_ID= | ||||
| SITE_OWNER=mail@example.com | ||||
| USE_ENCRYPTION=true | ||||
|  | ||||
| PUSHER_KEY= | ||||
| PUSHER_SECRET= | ||||
| PUSHER_ID= | ||||
|  | ||||
| DEMO_USERNAME= | ||||
| DEMO_PASSWORD= | ||||
|  | ||||
| IS_DOCKER=true | ||||
| IS_SANDSTORM=false | ||||
| IS_HEROKU=false | ||||
							
								
								
									
										152
									
								
								.env.example
									
									
									
									
									
								
							
							
						
						
									
										152
									
								
								.env.example
									
									
									
									
									
								
							| @@ -1,12 +1,43 @@ | ||||
| # You can leave this on "local". If you change it to production most console commands will ask for extra confirmation. | ||||
| # Never set it to "testing". | ||||
| APP_ENV=local | ||||
|  | ||||
| # Set to true if you want to see debug information in error screens. | ||||
| APP_DEBUG=false | ||||
| APP_NAME=FireflyIII | ||||
|  | ||||
| # This should be your email address | ||||
| SITE_OWNER=mail@example.com | ||||
|  | ||||
| # The encryption key for your database and sessions. Keep this very secure. | ||||
| # If you generate a new one all existing data must be considered LOST. | ||||
| # Change it to a string of exactly 32 chars or use command `php artisan key:generate` to generate it | ||||
| APP_KEY=SomeRandomStringOf32CharsExactly | ||||
| APP_LOG=daily | ||||
| APP_LOG_LEVEL=warning | ||||
|  | ||||
| # Change this value to your preferred time zone. | ||||
| # Example: Europe/Amsterdam | ||||
| TZ=Europe/Amsterdam | ||||
|  | ||||
| # This variable must match your installation's external address but keep in mind that | ||||
| # it's only used on the command line as a fallback value. | ||||
| APP_URL=http://localhost | ||||
|  | ||||
| # TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy. | ||||
| TRUSTED_PROXIES= | ||||
|  | ||||
| # The log channel defines where your log entries go to. | ||||
| # 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/. | ||||
| # Several other options exist. You can use 'single' for one big fat error log (not recommended). | ||||
| # Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself. | ||||
| LOG_CHANNEL=daily | ||||
|  | ||||
| # Log level. You can set this from least severe to most severe: | ||||
| # debug, info, notice, warning, error, critical, alert, emergency | ||||
| # If you set it to debug your logs will grow large, and fast. If you set it to emergency probably | ||||
| # nothing will get logged, ever. | ||||
| APP_LOG_LEVEL=notice | ||||
|  | ||||
| # Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III | ||||
| # For other database types, please see the FAQ: http://firefly-iii.readthedocs.io/en/latest/support/faq.html | ||||
| DB_CONNECTION=mysql | ||||
| DB_HOST=127.0.0.1 | ||||
| DB_PORT=3306 | ||||
| @@ -14,20 +45,31 @@ DB_DATABASE=homestead | ||||
| DB_USERNAME=homestead | ||||
| DB_PASSWORD=secret | ||||
|  | ||||
| BROADCAST_DRIVER=log | ||||
| # If you're looking for performance improvements, you could install memcached. | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
| QUEUE_DRIVER=sync | ||||
|  | ||||
| # You can configure another file storage backend if you cannot use the local storage option. | ||||
| # To set this up, fill in the following variables. The upload path is used to store uploaded | ||||
| # files and the export path is to store exported data (before download). | ||||
| SFTP_HOST= | ||||
| SFTP_PORT= | ||||
| SFTP_UPLOAD_PATH= | ||||
| SFTP_EXPORT_PATH= | ||||
|  | ||||
| # SFTP uses either the username/password combination or the private key to authenticate. | ||||
| SFTP_USERNAME= | ||||
| SFTP_PASSWORD= | ||||
| SFTP_PRIV_KEY= | ||||
|  | ||||
| # Cookie settings. Should not be necessary to change these. | ||||
| COOKIE_PATH="/" | ||||
| COOKIE_DOMAIN= | ||||
| COOKIE_SECURE=false | ||||
|  | ||||
| REDIS_HOST=127.0.0.1 | ||||
| REDIS_PASSWORD=null | ||||
| REDIS_PORT=6379 | ||||
|  | ||||
| MAIL_DRIVER=smtp | ||||
| # If you want Firefly III to mail you, update these settings | ||||
| # For instructions, see: https://firefly-iii.readthedocs.io/en/latest/installation/mail.html | ||||
| MAIL_DRIVER=log | ||||
| MAIL_HOST=smtp.mailtrap.io | ||||
| MAIL_PORT=2525 | ||||
| MAIL_FROM=changeme@example.com | ||||
| @@ -35,26 +77,102 @@ MAIL_USERNAME=null | ||||
| MAIL_PASSWORD=null | ||||
| MAIL_ENCRYPTION=null | ||||
|  | ||||
| # Other mail drivers: | ||||
| MAILGUN_DOMAIN= | ||||
| MAILGUN_SECRET= | ||||
| MANDRILL_SECRET= | ||||
| SPARKPOST_SECRET= | ||||
|  | ||||
| # Firefly III can send you the following messages | ||||
| SEND_REGISTRATION_MAIL=true | ||||
| SEND_ERROR_MESSAGE=true | ||||
|  | ||||
| CACHE_PREFIX=firefly | ||||
|  | ||||
| SEARCH_RESULT_LIMIT=50 | ||||
| EXCHANGE_RATE_SERVICE=fixerio | ||||
| # These messages contain (sensitive) transaction information: | ||||
| SEND_REPORT_JOURNALS=true | ||||
|  | ||||
| # Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places. | ||||
| MAPBOX_API_KEY= | ||||
|  | ||||
| # Firefly III currently supports two provider for live Currency Exchange Rates: | ||||
| # "fixer" is the default (for backward compatibility), and "ratesapi" is the new one. | ||||
| # RatesApi.IO (see https://ratesapi.io) is a FREE and OPEN SOURCE live currency exchange rates, | ||||
| # built compatible with Fixer.IO, based on data published by European Central Bank, and don't require API key. | ||||
| CER_PROVIDER=fixer | ||||
| # If you have select "fixer" as default currency exchange rates, | ||||
| # set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates. | ||||
| # Please note that this WILL ONLY WORK FOR PAID fixer.io accounts because they severely limited | ||||
| # the free API up to the point where you might as well offer nothing. | ||||
| FIXER_API_KEY= | ||||
|  | ||||
| # If you wish to track your own behavior over Firefly III, set a valid analytics tracker ID here. | ||||
| ANALYTICS_ID= | ||||
| SITE_OWNER=mail@example.com | ||||
|  | ||||
| # Most parts of the database are encrypted by default, but you can turn this off if you want to. | ||||
| # This makes it easier to migrate your database. Not that some fields will never be decrypted. | ||||
| USE_ENCRYPTION=true | ||||
|  | ||||
| # Firefly III has two options for user authentication. "eloquent" is the default, | ||||
| # and "ldap" for LDAP servers. | ||||
| # For full instructions on these settings please visit: | ||||
| # https://firefly-iii.readthedocs.io/en/latest/installation/authentication.html | ||||
| LOGIN_PROVIDER=eloquent | ||||
|  | ||||
| # LDAP connection configuration | ||||
| # OpenLDAP, FreeIPA or ActiveDirectory | ||||
| ADLDAP_CONNECTION_SCHEME=OpenLDAP | ||||
| ADLDAP_AUTO_CONNECT=true | ||||
|  | ||||
| # LDAP connection settings | ||||
| ADLDAP_CONTROLLERS= | ||||
| ADLDAP_PORT=389 | ||||
| ADLDAP_TIMEOUT=5 | ||||
| ADLDAP_BASEDN="" | ||||
| ADLDAP_FOLLOW_REFFERALS=false | ||||
| ADLDAP_USE_SSL=false | ||||
| ADLDAP_USE_TLS=false | ||||
|  | ||||
| ADLDAP_ADMIN_USERNAME= | ||||
| ADLDAP_ADMIN_PASSWORD= | ||||
|  | ||||
| ADLDAP_ACCOUNT_PREFIX= | ||||
| ADLDAP_ACCOUNT_SUFFIX= | ||||
|  | ||||
| # LDAP authentication settings. | ||||
| ADLDAP_PASSWORD_SYNC=false | ||||
| ADLDAP_LOGIN_FALLBACK=false | ||||
|  | ||||
| ADLDAP_DISCOVER_FIELD=distinguishedname | ||||
| ADLDAP_AUTH_FIELD=distinguishedname | ||||
|  | ||||
| # Will allow SSO if your server provides an AUTH_USER field. | ||||
| WINDOWS_SSO_DISCOVER=samaccountname | ||||
| WINDOWS_SSO_KEY=AUTH_USER | ||||
|  | ||||
| # field to sync as local username. | ||||
| ADLDAP_SYNC_FIELD=userprincipalname | ||||
|  | ||||
| # You can disable the X-Frame-Options header if it interfears with tools like | ||||
| # Organizr. This is at your own risk. | ||||
| DISABLE_FRAME_HEADER=false | ||||
|  | ||||
| # Leave the following configuration vars as is. | ||||
| # Unless you like to tinker and know what you're doing. | ||||
| APP_NAME=FireflyIII | ||||
| ADLDAP_CONNECTION=default | ||||
| BROADCAST_DRIVER=log | ||||
| QUEUE_DRIVER=sync | ||||
| REDIS_HOST=127.0.0.1 | ||||
| REDIS_PASSWORD=null | ||||
| REDIS_PORT=6379 | ||||
| CACHE_PREFIX=firefly | ||||
| SEARCH_RESULT_LIMIT=50 | ||||
| PUSHER_KEY= | ||||
| PUSHER_SECRET= | ||||
| PUSHER_ID= | ||||
|  | ||||
| DEMO_USERNAME= | ||||
| DEMO_PASSWORD= | ||||
|  | ||||
| IS_DOCKER=false | ||||
| IS_SANDSTORM=false | ||||
| IS_HEROKU=false | ||||
| BUNQ_USE_SANDBOX=false | ||||
| FFIII_LAYOUT=v1 | ||||
|   | ||||
							
								
								
									
										60
									
								
								.env.heroku
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								.env.heroku
									
									
									
									
									
								
							| @@ -1,60 +0,0 @@ | ||||
| APP_ENV=heroku | ||||
| APP_DEBUG=true | ||||
| APP_NAME=FireflyIII | ||||
| APP_KEY=7ahyYVPVsmxjdhsweWCauGeJfwc92NP2 | ||||
| APP_LOG=errorlog | ||||
| APP_LOG_LEVEL=debug | ||||
| APP_URL=http://localhost | ||||
| TRUSTED_PROXIES=* | ||||
|  | ||||
| DB_CONNECTION=pgsql | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| BROADCAST_DRIVER=log | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
| QUEUE_DRIVER=sync | ||||
|  | ||||
| COOKIE_PATH="/" | ||||
| COOKIE_DOMAIN= | ||||
| COOKIE_SECURE=false | ||||
|  | ||||
| REDIS_HOST=127.0.0.1 | ||||
| REDIS_PASSWORD=null | ||||
| REDIS_PORT=6379 | ||||
|  | ||||
| MAIL_DRIVER=smtp | ||||
| MAIL_HOST=smtp.mailtrap.io | ||||
| MAIL_PORT=2525 | ||||
| MAIL_FROM=changeme@example.com | ||||
| MAIL_USERNAME=null | ||||
| MAIL_PASSWORD=null | ||||
| MAIL_ENCRYPTION=null | ||||
|  | ||||
| SEND_REGISTRATION_MAIL=true | ||||
| SEND_ERROR_MESSAGE=true | ||||
|  | ||||
| CACHE_PREFIX=firefly | ||||
|  | ||||
| SEARCH_RESULT_LIMIT=50 | ||||
| EXCHANGE_RATE_SERVICE=fixerio | ||||
|  | ||||
| MAPBOX_API_KEY= | ||||
| ANALYTICS_ID= | ||||
| SITE_OWNER=heroku@example.com | ||||
| USE_ENCRYPTION=true | ||||
|  | ||||
| PUSHER_KEY= | ||||
| PUSHER_SECRET= | ||||
| PUSHER_ID= | ||||
|  | ||||
| DEMO_USERNAME= | ||||
| DEMO_PASSWORD= | ||||
|  | ||||
| IS_DOCKER=false | ||||
| IS_SANDSTORM=false | ||||
| IS_HEROKU=true | ||||
| @@ -1,60 +0,0 @@ | ||||
| APP_ENV=local | ||||
| APP_DEBUG=false | ||||
| APP_NAME=FireflyIII | ||||
| APP_KEY=SomeRandomStringOf32CharsExactly | ||||
| APP_LOG=syslog | ||||
| APP_LOG_LEVEL=info | ||||
| APP_URL=http://localhost | ||||
| TRUSTED_PROXIES= | ||||
|  | ||||
| DB_CONNECTION=mysql | ||||
| DB_HOST=127.0.0.1 | ||||
| DB_PORT=3306 | ||||
| DB_DATABASE=firefly | ||||
| DB_USERNAME=firefly | ||||
| DB_PASSWORD=firefly | ||||
|  | ||||
| BROADCAST_DRIVER=log | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
| QUEUE_DRIVER=sync | ||||
|  | ||||
| COOKIE_PATH="/" | ||||
| COOKIE_DOMAIN= | ||||
| COOKIE_SECURE=false | ||||
|  | ||||
| REDIS_HOST=127.0.0.1 | ||||
| REDIS_PASSWORD=null | ||||
| REDIS_PORT=6379 | ||||
|  | ||||
| MAIL_DRIVER=smtp | ||||
| MAIL_HOST=smtp.mailtrap.io | ||||
| MAIL_PORT=2525 | ||||
| MAIL_FROM=changeme@example.com | ||||
| MAIL_USERNAME=null | ||||
| MAIL_PASSWORD=null | ||||
| MAIL_ENCRYPTION=null | ||||
|  | ||||
| SEND_REGISTRATION_MAIL=true | ||||
| SEND_ERROR_MESSAGE=true | ||||
|  | ||||
| CACHE_PREFIX=firefly | ||||
|  | ||||
| SEARCH_RESULT_LIMIT=50 | ||||
| EXCHANGE_RATE_SERVICE=fixerio | ||||
|  | ||||
| MAPBOX_API_KEY= | ||||
| ANALYTICS_ID= | ||||
| SITE_OWNER=mail@example.com | ||||
| USE_ENCRYPTION=true | ||||
|  | ||||
| PUSHER_KEY= | ||||
| PUSHER_SECRET= | ||||
| PUSHER_ID= | ||||
|  | ||||
| DEMO_USERNAME= | ||||
| DEMO_PASSWORD= | ||||
|  | ||||
| IS_DOCKER=false | ||||
| IS_SANDSTORM=true | ||||
| IS_HEROKU=false | ||||
							
								
								
									
										60
									
								
								.env.testing
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								.env.testing
									
									
									
									
									
								
							| @@ -1,60 +0,0 @@ | ||||
| APP_ENV=testing | ||||
| APP_DEBUG=true | ||||
| APP_NAME=FireflyIII | ||||
| APP_KEY=TestTestTestTestTestTestTestTest | ||||
| APP_LOG=daily | ||||
| APP_LOG_LEVEL=debug | ||||
| APP_URL=http://localhost | ||||
| TRUSTED_PROXIES= | ||||
|  | ||||
| DB_CONNECTION=sqlite | ||||
| DB_HOST=127.0.0.1 | ||||
| DB_PORT=3306 | ||||
| #DB_DATABASE=firefly | ||||
| DB_USERNAME=homestead | ||||
| DB_PASSWORD= | ||||
|  | ||||
| BROADCAST_DRIVER=log | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
| QUEUE_DRIVER=sync | ||||
|  | ||||
| COOKIE_PATH="/" | ||||
| COOKIE_DOMAIN= | ||||
| COOKIE_SECURE=false | ||||
|  | ||||
| REDIS_HOST=127.0.0.1 | ||||
| REDIS_PASSWORD=null | ||||
| REDIS_PORT=6379 | ||||
|  | ||||
| MAIL_DRIVER=smtp | ||||
| MAIL_HOST=smtp.mailtrap.io | ||||
| MAIL_PORT=2525 | ||||
| MAIL_FROM=changeme@example.com | ||||
| MAIL_USERNAME=null | ||||
| MAIL_PASSWORD=null | ||||
| MAIL_ENCRYPTION=null | ||||
|  | ||||
| SEND_REGISTRATION_MAIL=true | ||||
| SEND_ERROR_MESSAGE=true | ||||
|  | ||||
| CACHE_PREFIX=firefly | ||||
|  | ||||
| SEARCH_RESULT_LIMIT=50 | ||||
| EXCHANGE_RATE_SERVICE=fixerio | ||||
|  | ||||
| MAPBOX_API_KEY= | ||||
| ANALYTICS_ID= | ||||
| SITE_OWNER=mail@example.com | ||||
| USE_ENCRYPTION=true | ||||
|  | ||||
| PUSHER_KEY= | ||||
| PUSHER_SECRET= | ||||
| PUSHER_ID= | ||||
|  | ||||
| DEMO_USERNAME= | ||||
| DEMO_PASSWORD= | ||||
|  | ||||
| IS_DOCKER=false | ||||
| IS_SANDSTORM=false | ||||
| IS_HEROKU=false | ||||
							
								
								
									
										11
									
								
								.github/ISSUE_TEMPLATE.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								.github/ISSUE_TEMPLATE.md
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +0,0 @@ | ||||
| I am running Firefly III version x.x.x  | ||||
|  | ||||
| #### Description of my issue: | ||||
|  | ||||
| #### Steps to reproduce  | ||||
|  | ||||
| (please include if this problem also exists on the demo site) | ||||
|  | ||||
| #### Other important details (log files, system info): | ||||
|  | ||||
| Please visit the /debug page to get extra debug information. | ||||
							
								
								
									
										27
									
								
								.github/ISSUE_TEMPLATE/Bug_report.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								.github/ISSUE_TEMPLATE/Bug_report.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| --- | ||||
| name: Bug report | ||||
| about: Create a report to help Firefly III improve | ||||
|  | ||||
| --- | ||||
|  | ||||
| **Bug description** | ||||
| I am running Firefly III version x.x.x, and my problem is: | ||||
|  | ||||
| <!-- Replace the version and describe your problem or your issue will be closed. --> | ||||
|  | ||||
| **Steps to reproduce** | ||||
| <!-- What do you need to do to trigger this bug? --> | ||||
|  | ||||
| **Expected behavior** | ||||
| <!-- What do you expect to see after those steps? --> | ||||
|  | ||||
| **Extra info** | ||||
| <!-- Please add extra info here, such as OS, browser, and the output from the /debug page of your Firefly III installation (click the version at the bottom). --> | ||||
|  | ||||
| **Bonus points** | ||||
| <!-- Earn bonus points by: | ||||
|  | ||||
| - Post a stacktrace from your log files | ||||
| - Add a screenshot | ||||
| - Remember the human | ||||
| --> | ||||
							
								
								
									
										25
									
								
								.github/ISSUE_TEMPLATE/Custom.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								.github/ISSUE_TEMPLATE/Custom.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| --- | ||||
| name: I have a question or a problem | ||||
| about: Ask away! | ||||
|  | ||||
| --- | ||||
|  | ||||
| I am running Firefly III version x.x.x | ||||
|  | ||||
| **Description** | ||||
| <!-- (if relevant of course) --> | ||||
|  | ||||
| **Extra info** | ||||
| <!-- Please add extra info here, such as OS, browser, and the output from the `/debug`-page of your Firefly III installation (click the version at the bottom). -->  | ||||
|  | ||||
|  | ||||
|  | ||||
| **Bonus points** | ||||
| <!-- Earn bonus points by: | ||||
|  | ||||
| - Add a screenshot | ||||
| - Make a drawing | ||||
| - Donate money (just kidding ;) | ||||
| - Replicate the problem on the demo site https://demo.firefly-iii.org/ | ||||
| - Remember the human | ||||
| --> | ||||
							
								
								
									
										32
									
								
								.github/ISSUE_TEMPLATE/Feature_request.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								.github/ISSUE_TEMPLATE/Feature_request.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| --- | ||||
| name: Feature request | ||||
| about: Suggest an idea or feature for Firefly III | ||||
|  | ||||
| --- | ||||
|  | ||||
| **Description** | ||||
| <!-- | ||||
| Please describe your feature request: | ||||
|  | ||||
| - I would like Firefly III to do ABC. | ||||
| - What if you would add feature XYZ? | ||||
| - Firefly III doesn't do DEF. | ||||
|  | ||||
| --> | ||||
|  | ||||
| **Solution** | ||||
| <!-- Describe what your feature would add to Firefly III. --> | ||||
|  | ||||
| **What are alternatives?** | ||||
| <!-- Please describe what alternatives currently exist. --> | ||||
|  | ||||
| **Additional context** | ||||
| <!-- Add any other context or screenshots about the feature request here. --> | ||||
|  | ||||
| **Bonus points** | ||||
| <!-- Earn bonus points by: | ||||
|  | ||||
| - Make a drawing | ||||
| - Donate money (just kidding ;) | ||||
| - Remember the human | ||||
| --> | ||||
							
								
								
									
										9
									
								
								.github/PULL_REQUEST_TEMPLATE.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.github/PULL_REQUEST_TEMPLATE.md
									
									
									
									
										vendored
									
									
								
							| @@ -1,9 +0,0 @@ | ||||
| Fixes # (if relevant) | ||||
|  | ||||
| Changes in this pull request: | ||||
|  | ||||
| -  | ||||
| -  | ||||
| -  | ||||
|  | ||||
| @JC5 | ||||
							
								
								
									
										11
									
								
								.github/SUPPORT.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								.github/SUPPORT.md
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +0,0 @@ | ||||
| # Welcome to Firefly III on Github! | ||||
|  | ||||
| :+1::tada: Thank you for taking the time to contribute something to Firefly III! | ||||
|  | ||||
| ## Bugs | ||||
|  | ||||
| First of all: thank you for reporting a bug instead of ditching the tool altogether. If you find a bug, please take the time and see if the [demo site](https://firefly-iii.nder.be/) is also suffering from this bug. Include as many log files and details as you think are necessary. Bugs have a lot of priority!  | ||||
|  | ||||
| ## Installation problems | ||||
|  | ||||
| Please take the time to read the [installation guide FAQ](https://firefly-iii.github.io/installation-guide-faq/) and make sure you search through closed issues for the problems other people have had. Your problem may be among them! If not, open an issue and I will help where I can. | ||||
| @@ -4,7 +4,7 @@ | ||||
| 
 | ||||
| ## Feature requests | ||||
| 
 | ||||
| I am always interested in expanding Firefly III's many features. If you are requesting a new feature, please check out the list of [often requested features](https://firefly-iii.github.io/requested-features/). | ||||
| I am always interested in expanding Firefly III's many features. Just open a ticket or [drop me a line](mailto:thegrumpydictator@gmail.com). | ||||
| 
 | ||||
| ## Pull requests | ||||
| 
 | ||||
							
								
								
									
										16
									
								
								.github/pull_request_template.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								.github/pull_request_template.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| <!-- | ||||
| Please read me: | ||||
|  | ||||
| 1) DO NOT create a pull request for the MASTER branch. | ||||
| 2) DO NOT create pull requests to add new CURRENCIES. | ||||
| --> | ||||
|  | ||||
| Fixes issue # (if relevant) | ||||
|  | ||||
| Changes in this pull request: | ||||
|  | ||||
| -  | ||||
| -  | ||||
| -  | ||||
|  | ||||
| @JC5 | ||||
							
								
								
									
										58
									
								
								.github/stale.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								.github/stale.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| # Configuration for probot-stale - https://github.com/probot/stale | ||||
|  | ||||
| # Number of days of inactivity before an Issue or Pull Request becomes stale | ||||
| daysUntilStale: 7 | ||||
|  | ||||
| # Number of days of inactivity before a stale Issue or Pull Request is closed. | ||||
| # Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. | ||||
| daysUntilClose: 7 | ||||
|  | ||||
| # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable | ||||
| # - "[Status] Maybe Later" | ||||
| exemptLabels: | ||||
|   - enhancement | ||||
|   - feature | ||||
|   - bug | ||||
|   - possible-bug | ||||
|   - announcement | ||||
|  | ||||
| # Set to true to ignore issues in a project (defaults to false) | ||||
| exemptProjects: false | ||||
|  | ||||
| # Set to true to ignore issues in a milestone (defaults to false) | ||||
| exemptMilestones: false | ||||
|  | ||||
| # Label to use when marking as stale | ||||
| staleLabel: stale | ||||
|  | ||||
| # Comment to post when marking as stale. Set to `false` to disable | ||||
| markComment: > | ||||
|   This issue has been automatically marked as stale because it has not had | ||||
|   recent activity. It will be closed if no further activity occurs. Thank you | ||||
|   for your contributions. | ||||
|  | ||||
| # Comment to post when removing the stale label. | ||||
| # unmarkComment: > | ||||
| #   Your comment here. | ||||
|  | ||||
| # Comment to post when closing a stale Issue or Pull Request. | ||||
| # closeComment: > | ||||
| #   Your comment here. | ||||
|  | ||||
| # Limit the number of actions per hour, from 1-30. Default is 30 | ||||
| limitPerRun: 30 | ||||
|  | ||||
| # Limit to only `issues` or `pulls` | ||||
| # only: issues | ||||
|  | ||||
| # Optionally, specify configuration settings that are specific to just 'issues' or 'pulls': | ||||
| # pulls: | ||||
| #   daysUntilStale: 30 | ||||
| #   markComment: > | ||||
| #     This pull request has been automatically marked as stale because it has not had | ||||
| #     recent activity. It will be closed if no further activity occurs. Thank you | ||||
| #     for your contributions. | ||||
|  | ||||
| # issues: | ||||
| #   exemptLabels: | ||||
| #     - confirmed | ||||
							
								
								
									
										11
									
								
								.github/support.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								.github/support.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| # Welcome to Firefly III on Github! | ||||
|  | ||||
| :+1::tada: Thank you for taking the time to contribute something to Firefly III! | ||||
|  | ||||
| ## Bugs | ||||
|  | ||||
| First of all: thank you for reporting a bug instead of ditching the tool altogether. If you find a bug, please take the time and see if the [demo site](https://demo.firefly-iii.org/) is also suffering from this bug. Include as many log files and details as you think are necessary. Bugs have a lot of priority!  | ||||
|  | ||||
| ## Installation problems | ||||
|  | ||||
| Please take the time to read the [installation guide FAQ](https://firefly-iii.org/installation-guide-faq/) and make sure you search through closed issues for the problems other people have had. Your problem may be among them! If not, open an issue and I will help where I can. | ||||
							
								
								
									
										14
									
								
								.htaccess
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								.htaccess
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| # Optional: force HTTPS: | ||||
| # <IfModule mod_rewrite.c> | ||||
| #	RewriteEngine On | ||||
| #	RewriteCond %{HTTPS} off | ||||
| #	RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L] | ||||
| # </IfModule> | ||||
|  | ||||
| # To hide directory listing | ||||
| Options All -Indexes | ||||
|  | ||||
| # To prevent access to .env and other files | ||||
| <Files .*> | ||||
|     Deny from all | ||||
| </Files> | ||||
							
								
								
									
										9
									
								
								.sandstorm/Vagrantfile
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.sandstorm/Vagrantfile
									
									
									
									
										vendored
									
									
								
							| @@ -9,9 +9,16 @@ VM_NAME = File.basename(File.dirname(File.dirname(__FILE__))) + "_sandstorm_#{Ti | ||||
| # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! | ||||
| VAGRANTFILE_API_VERSION = "2" | ||||
|  | ||||
| # ugly hack to prevent hashicorp's bitrot. See https://github.com/hashicorp/vagrant/issues/9442 | ||||
| # this setting is required for pre-2.0 vagrant, but causes an error as of 2.0.3, | ||||
| # remove entirely when confident nobody uses vagrant 1.x for anything. | ||||
| unless Vagrant::DEFAULT_SERVER_URL.frozen? | ||||
|   Vagrant::DEFAULT_SERVER_URL.replace('https://vagrantcloud.com') | ||||
| end | ||||
|  | ||||
| Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| | ||||
|   # Base on the Sandstorm snapshots of the official Debian 8 (jessie) box. | ||||
|   config.vm.box = "sandstorm/debian-jessie64" | ||||
|   config.vm.box = "debian/contrib-jessie64" | ||||
|  | ||||
|   if Vagrant.has_plugin?("vagrant-vbguest") then | ||||
|     # vagrant-vbguest is a Vagrant plugin that upgrades | ||||
|   | ||||
| @@ -3,11 +3,10 @@ | ||||
| # This script only runs once, when the app connects to sandstorm. | ||||
| set -euo pipefail | ||||
|  | ||||
|  | ||||
| echo "In build.sh" | ||||
|  | ||||
| cd /opt/app | ||||
|  | ||||
| cp .env.sandstorm .env | ||||
| cp .deploy/sandstorm/.env.sandstorm .env | ||||
|  | ||||
| if [ -f /opt/app/composer.json ] ; then | ||||
|     if [ ! -f composer.phar ] ; then | ||||
|   | ||||
| @@ -1,5 +1,485 @@ | ||||
| # 4.6.1.1 | ||||
| # 4.7.13 (API 0.9.2) | ||||
| - 4.7.13 was released to fix an issue that affected the Softaculous build. | ||||
| - A routine has been added that warns about transactions with a 0.00 amount. | ||||
| - PHP maximum execution time is now 600 seconds in the Docker image. | ||||
| - Moved several files outside of the root of Firefly III | ||||
| - Fix issue where missing preference breaks the database upgrade. | ||||
| - [Issue 2100](https://github.com/firefly-iii/firefly-iii/issues/2100) Mass edit transactions results in a reset of the date. | ||||
|  | ||||
| # 4.7.12 | ||||
| - 4.7.12 was released to fix several shortcomings in v4.7.11's Docker image. Those in turn were caused by me. My apologies. | ||||
| - [Issue 2085](https://github.com/firefly-iii/firefly-iii/issues/2085) Upgraded the LDAP code. To keep using LDAP, set the `LOGIN_PROVIDER` to `ldap`. | ||||
| - [Issue 2061](https://github.com/firefly-iii/firefly-iii/issues/2061) Some users reported empty update popups.  | ||||
| - [Issue 2070](https://github.com/firefly-iii/firefly-iii/issues/2070) A cache issue prevented rules from being applied correctly. | ||||
| - [Issue 2071](https://github.com/firefly-iii/firefly-iii/issues/2071) Several issues with Postgres and date values with time zone information in them. | ||||
| - [Issue 2081](https://github.com/firefly-iii/firefly-iii/issues/2081) Rules were not being applied when importing using FinTS. | ||||
| - [Issue 2082](https://github.com/firefly-iii/firefly-iii/issues/2082) The mass-editor changed all dates to today. | ||||
|  | ||||
| # 4.7.11 | ||||
| - Experimental audit logging channel to track important events (separate from debug logging). | ||||
| - [Issue 2003](https://github.com/firefly-iii/firefly-iii/issues/2003), [issue 2006](https://github.com/firefly-iii/firefly-iii/issues/2006) Transactions can be stored with a timestamp. The user-interface does not support this yet. But the API does. | ||||
| - Docker image tags a new manifest for arm and amd64. | ||||
| - [skuzzle](https://github.com/skuzzle) removed an annoying console.log statement. | ||||
| - [Issue 2048](https://github.com/firefly-iii/firefly-iii/issues/2048) Fix "Are you sure?" popup, thanks to @nescafe2002! | ||||
| - [Issue 2049](https://github.com/firefly-iii/firefly-iii/issues/2049) Empty preferences would crash Firefly III. | ||||
| - [Issue 2052](https://github.com/firefly-iii/firefly-iii/issues/2052) Rules could not auto-covert to liabilities. | ||||
| - Webbased upgrade routine will also decrypt the database. | ||||
| - Last use date for categories was off. | ||||
| - The `date`-field in any transaction object now returns a ISO 8601 timestamp instead of a date. | ||||
|  | ||||
| # 4.7.10 | ||||
| - [Issue 2037](https://github.com/firefly-iii/firefly-iii/issues/2037) Added some new magic keywords to reports. | ||||
| - Added a new currency exchange rate service, [ratesapi.io](https://ratesapi.io/), that does not require expensive API keys. Built by [@BoGnY](https://github.com/BoGnY). | ||||
| - Added Chinese Traditional translations. Thanks! | ||||
| - [Issue 1977](https://github.com/firefly-iii/firefly-iii/issues/1977) Docker image now includes memcached support | ||||
| - [Issue 2031](https://github.com/firefly-iii/firefly-iii/issues/2031) A new generic debit/credit indicator for imports. | ||||
| - The new Docker image no longer has the capability to run cron jobs, and will no longer generate your recurring transactions for you. This has been done to simplify the build and make sure your Docker container runs one service, as it should. To set up a cron job for your new Docker container, [check out the documentation](https://docs.firefly-iii.org/en/latest/installation/cronjob.html). | ||||
| - Due to a change in the database structure, this upgrade will reset your preferences. Sorry about that. | ||||
| - I will no longer accept PR's that introduce new currencies. | ||||
| - Firefly III no longer encrypts the database and will [decrypt the database]() on its first run. | ||||
| - [Issue 1923](https://github.com/firefly-iii/firefly-iii/issues/1923) Broken window position for date picker. | ||||
| - [Issue 1967](https://github.com/firefly-iii/firefly-iii/issues/1967) Attachments were hidden in bill view. | ||||
| - [Issue 1927](https://github.com/firefly-iii/firefly-iii/issues/1927) It was impossible to make recurring transactions skip. | ||||
| - [Issue 1929](https://github.com/firefly-iii/firefly-iii/issues/1929) Fix the recurring transactions calendar overview. | ||||
| - [Issue 1933](https://github.com/firefly-iii/firefly-iii/issues/1933) Fixed a bug that made it impossible to authenticate to FreeIPA servers. | ||||
| - [Issue 1938](https://github.com/firefly-iii/firefly-iii/issues/1938) The importer can now handle the insane way Postbank (DE) formats its numbers. | ||||
| - [Issue 1942](https://github.com/firefly-iii/firefly-iii/issues/1942) Favicons are relative so Scriptaculous installations work better. | ||||
| - [Issue 1944](https://github.com/firefly-iii/firefly-iii/issues/1944) Make sure that the search allows you to mass-select transactions. | ||||
| - [Issue 1945](https://github.com/firefly-iii/firefly-iii/issues/1945) Slight UI change so the drop-down menu renders better. | ||||
| - [Issue 1955](https://github.com/firefly-iii/firefly-iii/issues/1955) Fixed a bug in the category report. | ||||
| - [Issue 1968](https://github.com/firefly-iii/firefly-iii/issues/1968) The yearly range would jump to 1-Jan / 1-Jan instead of 1-Jan / 31-Dec | ||||
| - [Issue 1975](https://github.com/firefly-iii/firefly-iii/issues/1975) Fixed explanation for missing credit card liabilities. | ||||
| - [Issue 1979](https://github.com/firefly-iii/firefly-iii/issues/1979) Make sure tags are trimmed. | ||||
| - [Issue 1983](https://github.com/firefly-iii/firefly-iii/issues/1983) Could not use your favorite decimal separator. | ||||
| - [Issue 1989](https://github.com/firefly-iii/firefly-iii/issues/1989) Bug in YNAB importer forced you to select all accounts. | ||||
| - [Issue 1990](https://github.com/firefly-iii/firefly-iii/issues/1990) Rule description was invisible in edit screen. | ||||
| - [Issue 1996](https://github.com/firefly-iii/firefly-iii/issues/1996) Deleted budget would inadvertently also hide transactions. | ||||
| - [Issue 2001](https://github.com/firefly-iii/firefly-iii/issues/2001) Various issues with tag chart view. | ||||
| - [Issue 2009](https://github.com/firefly-iii/firefly-iii/issues/2009) Could not change recurrence back to "forever". | ||||
| - [Issue 2033](https://github.com/firefly-iii/firefly-iii/issues/2033) Longitude can go from -180 to 180. | ||||
| - [Issue 2034](https://github.com/firefly-iii/firefly-iii/issues/2034) Rules were not being triggered in mass-edit. | ||||
| - #2043 In rare instances the repetition of a recurring transaction was displayed incorrectly. | ||||
| - Fixed broken translations in the recurring transactions overview. | ||||
| - When you create a recurring transfer you make make it fill (or empty) a piggy bank. This was not working, despite a fix in 4.7.8. | ||||
| - Fixed a bug where the importer would not be capable of creating new currencies. | ||||
| - Rule trigger tester would skip the amount. | ||||
| - OAuth2 form can now submit back to original requester. | ||||
| - Submitting transactions with a disabled currency will auto-enable the currency. | ||||
| - The documentation now states that "Deposit" is a possible return when you get a transaction. | ||||
| - "savingAsset" was incorrectly documented as "savingsAsset". | ||||
| - Account endpoint can now return type "reconciliation" and "initial-balance" correctly. | ||||
| - New API endpoint under `/summary/basic` that gives you a basic overview of the user's finances. | ||||
| - New API endpoints under `/chart/*` to allow you to render charts. | ||||
| - `/accounts/x/transactions` now supports the limit query parameter. | ||||
| - `/budgets/x/transactions` now supports the limit query parameter. | ||||
| - `/available_budgets` now supports custom start and end date parameters. | ||||
| - New endpoint `/preferences/prefName` to retrieve a single preference. | ||||
| - Added field `account_name` to all piggy banks. | ||||
| - New tag cloud in API. | ||||
|  | ||||
| # 4.7.9 | ||||
| - [Issue 1622](https://github.com/firefly-iii/firefly-iii/issues/1622) Can now unlink a transaction from a bill. | ||||
| - [Issue 1848](https://github.com/firefly-iii/firefly-iii/issues/1848) Added support for the Swiss Franc. | ||||
| - [Issue 1828](https://github.com/firefly-iii/firefly-iii/issues/1828) Focus on fields for easy access. | ||||
| - [Issue 1859](https://github.com/firefly-iii/firefly-iii/issues/1859) Warning when seeding database. | ||||
| - Completely rewritten API. Check out the documentation [here](https://api-docs.firefly-iii.org/). | ||||
| - Currencies can now be enabled and disabled, making for cleaner views. | ||||
| - You can disable the `X-Frame-Options` header if this is necessary. | ||||
| - New fancy favicons. | ||||
| - Updated and improved docker build. | ||||
| - Docker build no longer builds its own cURL. | ||||
| - [Issue 1607](https://github.com/firefly-iii/firefly-iii/issues/1607) [issue 1857](https://github.com/firefly-iii/firefly-iii/issues/1857) [issue 1895](https://github.com/firefly-iii/firefly-iii/issues/1895) Improved bunq import and added support for auto-savings. | ||||
| - [Issue 1766](https://github.com/firefly-iii/firefly-iii/issues/1766) Extra commands so cache dir is owned by www user. | ||||
| - [Issue 1811](https://github.com/firefly-iii/firefly-iii/issues/1811) 404 when generating report without options. | ||||
| - [Issue 1835](https://github.com/firefly-iii/firefly-iii/issues/1835) Strange debug popup removed. | ||||
| - [Issue 1840](https://github.com/firefly-iii/firefly-iii/issues/1840) Error when exporting data. | ||||
| - [Issue 1857](https://github.com/firefly-iii/firefly-iii/issues/1857) Bunq import words again (see above). | ||||
| - [Issue 1858](https://github.com/firefly-iii/firefly-iii/issues/1858) SQL errors when importing CSV. | ||||
| - [Issue 1861](https://github.com/firefly-iii/firefly-iii/issues/1861) Period navigator was broken. | ||||
| - [Issue 1864](https://github.com/firefly-iii/firefly-iii/issues/1864) First description was empty on split transactions. | ||||
| - [Issue 1865](https://github.com/firefly-iii/firefly-iii/issues/1865) Bad math when showing categories. | ||||
| - [Issue 1868](https://github.com/firefly-iii/firefly-iii/issues/1868) Fixes to FinTS import. | ||||
| - [Issue 1872](https://github.com/firefly-iii/firefly-iii/issues/1872) Some images had 404's. | ||||
| - [Issue 1877](https://github.com/firefly-iii/firefly-iii/issues/1877) Several encryption / decryption issues. | ||||
| - [Issue 1878](https://github.com/firefly-iii/firefly-iii/issues/1878) Wrong nav links | ||||
| - [Issue 1884](https://github.com/firefly-iii/firefly-iii/issues/1884) Budget API improvements (see above) | ||||
| - [Issue 1888](https://github.com/firefly-iii/firefly-iii/issues/1888) Transaction API improvements (see above) | ||||
| - [Issue 1890](https://github.com/firefly-iii/firefly-iii/issues/1890) Fixes in Bills API | ||||
| - [Issue 1891](https://github.com/firefly-iii/firefly-iii/issues/1891) Typo fixed. | ||||
| - [Issue 1893](https://github.com/firefly-iii/firefly-iii/issues/1893) Update piggies from recurring transactions. | ||||
| - [Issue 1898](https://github.com/firefly-iii/firefly-iii/issues/1898) Bug in tag report. | ||||
| - [Issue 1901](https://github.com/firefly-iii/firefly-iii/issues/1901) Redirect when cloning transactions. | ||||
| - [Issue 1909](https://github.com/firefly-iii/firefly-iii/issues/1909) Date range fixes. | ||||
| - [Issue 1916](https://github.com/firefly-iii/firefly-iii/issues/1916) Date range fixes. | ||||
|  | ||||
| # 4.7.8 | ||||
|  | ||||
| - [Issue 1005](https://github.com/firefly-iii/firefly-iii/issues/1005) You can now configure Firefly III to use LDAP.  | ||||
| - [Issue 1071](https://github.com/firefly-iii/firefly-iii/issues/1071) You can execute transaction rules using the command line (so you can cronjob it) | ||||
| - [Issue 1108](https://github.com/firefly-iii/firefly-iii/issues/1108) You can now reorder budgets. | ||||
| - [Issue 1159](https://github.com/firefly-iii/firefly-iii/issues/1159) The ability to import transactions from FinTS-enabled banks. | ||||
| - [Issue 1727](https://github.com/firefly-iii/firefly-iii/issues/1727) You can now use SFTP as storage for uploads and exports. | ||||
| - [Issue 1733](https://github.com/firefly-iii/firefly-iii/issues/1733) You can configure Firefly III not to send emails with transaction information in them. | ||||
| - [Issue 1040](https://github.com/firefly-iii/firefly-iii/issues/1040) Fixed various things that would not scale properly in the past. | ||||
| - [Issue 1771](https://github.com/firefly-iii/firefly-iii/issues/1771) A link to the transaction that fits the bill. | ||||
| - [Issue 1800](https://github.com/firefly-iii/firefly-iii/issues/1800) Icon updated to match others. | ||||
| - MySQL database connection now forces the InnoDB to be used. | ||||
| - [Issue 1583](https://github.com/firefly-iii/firefly-iii/issues/1583) Some times recurring transactions would not fire. | ||||
| - [Issue 1607](https://github.com/firefly-iii/firefly-iii/issues/1607) Problems with the bunq API, finally solved?! (I feel like a clickbait YouTube video now) | ||||
| - [Issue 1698](https://github.com/firefly-iii/firefly-iii/issues/1698) Certificate problems in the Docker container | ||||
| - [Issue 1751](https://github.com/firefly-iii/firefly-iii/issues/1751) Bug in autocomplete | ||||
| - [Issue 1760](https://github.com/firefly-iii/firefly-iii/issues/1760) Tag report bad math | ||||
| - [Issue 1765](https://github.com/firefly-iii/firefly-iii/issues/1765) API inconsistencies for piggy banks. | ||||
| - [Issue 1774](https://github.com/firefly-iii/firefly-iii/issues/1774) Integer exception in SQLite databases | ||||
| - [Issue 1775](https://github.com/firefly-iii/firefly-iii/issues/1775) Heroku now supports all locales | ||||
| - [Issue 1778](https://github.com/firefly-iii/firefly-iii/issues/1778) More autocomplete problems fixed | ||||
| - [Issue 1747](https://github.com/firefly-iii/firefly-iii/issues/1747) Rules now stop at the right moment. | ||||
| - [Issue 1781](https://github.com/firefly-iii/firefly-iii/issues/1781) Problems when creating new rules. | ||||
| - [Issue 1784](https://github.com/firefly-iii/firefly-iii/issues/1784) Can now create a liability with an empty balance. | ||||
| - [Issue 1785](https://github.com/firefly-iii/firefly-iii/issues/1785) Redirect error | ||||
| - [Issue 1790](https://github.com/firefly-iii/firefly-iii/issues/1790) Show attachments for bills. | ||||
| - [Issue 1792](https://github.com/firefly-iii/firefly-iii/issues/1792) Mention excluded accounts. | ||||
| - [Issue 1798](https://github.com/firefly-iii/firefly-iii/issues/1798) Could not recreate deleted piggy banks | ||||
| - [Issue 1805](https://github.com/firefly-iii/firefly-iii/issues/1805) Fixes when handling foreign currencies | ||||
| - [Issue 1807](https://github.com/firefly-iii/firefly-iii/issues/1807) Also decrypt deleted records. | ||||
| - [Issue 1812](https://github.com/firefly-iii/firefly-iii/issues/1812) Fix in transactions API | ||||
| - [Issue 1815](https://github.com/firefly-iii/firefly-iii/issues/1815) Opening balance account name can now be translated. | ||||
| - [Issue 1830](https://github.com/firefly-iii/firefly-iii/issues/1830) Multi-user in a single browser could leak autocomplete data. | ||||
|  | ||||
| # 4.7.7 | ||||
| - [Issue 954](https://github.com/firefly-iii/firefly-iii/issues/954) Some additional view chart ranges | ||||
| - [Issue 1710](https://github.com/firefly-iii/firefly-iii/issues/1710) Added a new currency ([hamuz](https://github.com/hamuz))  | ||||
| - Transactions will now store (in the database) how they were created. | ||||
| - [Issue 907](https://github.com/firefly-iii/firefly-iii/issues/907) Better and more options on the transaction list. | ||||
| - [Issue 1450](https://github.com/firefly-iii/firefly-iii/issues/1450) Add a rule to change the type of a transaction automagically | ||||
| - [Issue 1701](https://github.com/firefly-iii/firefly-iii/issues/1701) Fix reference to PHP executable ([hertzg](https://github.com/hertzg)) | ||||
| - Budget limits have currency information, for future expansion. | ||||
| - Some charts and pages can handle multiple currencies better. | ||||
| - New GA code for those who use it. | ||||
| - The credit card liability type has been removed. | ||||
| - [Issue 896](https://github.com/firefly-iii/firefly-iii/issues/896) Better redirection when coming from deleted objects. | ||||
| - [Issue 1519](https://github.com/firefly-iii/firefly-iii/issues/1519) Fix autocomplete tags | ||||
| - [Issue 1607](https://github.com/firefly-iii/firefly-iii/issues/1607) Some fixes for the bunq api calls | ||||
| - [Issue 1650](https://github.com/firefly-iii/firefly-iii/issues/1650) Add a negated amount column for CSV imports ([hamuz](https://github.com/hamuz)) | ||||
| - [Issue 1658](https://github.com/firefly-iii/firefly-iii/issues/1658) Make font heavy again. | ||||
| - [Issue 1660](https://github.com/firefly-iii/firefly-iii/issues/1660) Add a negated amount column for CSV imports ([hamuz](https://github.com/hamuz)) | ||||
| - [Issue 1667](https://github.com/firefly-iii/firefly-iii/issues/1667) Fix pie charts | ||||
| - [Issue 1668](https://github.com/firefly-iii/firefly-iii/issues/1668) YNAB iso_code fix | ||||
| - [Issue 1670](https://github.com/firefly-iii/firefly-iii/issues/1670) Fix piggy bank API error | ||||
| - [Issue 1671](https://github.com/firefly-iii/firefly-iii/issues/1671) More options for liability accounts. | ||||
| - [Issue 1673](https://github.com/firefly-iii/firefly-iii/issues/1673) Fix reconciliation issues. | ||||
| - [Issue 1675](https://github.com/firefly-iii/firefly-iii/issues/1675) Wrong sum in tag report. | ||||
| - [Issue 1679](https://github.com/firefly-iii/firefly-iii/issues/1679) Change type of a transaction wouldn't trigger rules. | ||||
| - [Issue 1682](https://github.com/firefly-iii/firefly-iii/issues/1682) Add liability accounts to transaction conversion | ||||
| - [Issue 1683](https://github.com/firefly-iii/firefly-iii/issues/1683) See matching transaction showed transfers twice. | ||||
| - [Issue 1685](https://github.com/firefly-iii/firefly-iii/issues/1685) fix autocomplete for rules | ||||
| - [Issue 1690](https://github.com/firefly-iii/firefly-iii/issues/1690) Missing highlighted button in intro popup | ||||
| - [Issue 1691](https://github.com/firefly-iii/firefly-iii/issues/1691) No mention of liabilities in demo text | ||||
| - [Issue 1695](https://github.com/firefly-iii/firefly-iii/issues/1695) Small fixes in bills pages. | ||||
| - [Issue 1708](https://github.com/firefly-iii/firefly-iii/issues/1708) Fix by [mathieupost](https://github.com/mathieupost) for bunq | ||||
| - [Issue 1709](https://github.com/firefly-iii/firefly-iii/issues/1709) Fix oauth buttons  | ||||
| - [Issue 1712](https://github.com/firefly-iii/firefly-iii/issues/1712) Double slash fix by [hamuz](https://github.com/hamuz) | ||||
| - [Issue 1719](https://github.com/firefly-iii/firefly-iii/issues/1719) Add missing accounts to API | ||||
| - [Issue 1720](https://github.com/firefly-iii/firefly-iii/issues/1720) Fix validation for transaction type. | ||||
| - [Issue 1723](https://github.com/firefly-iii/firefly-iii/issues/1723) API broken for currency exchange rates. | ||||
| - [Issue 1728](https://github.com/firefly-iii/firefly-iii/issues/1728) Fix problem with transaction factory. | ||||
| - [Issue 1729](https://github.com/firefly-iii/firefly-iii/issues/1729) Fix bulk transaction editor | ||||
| - [Issue 1731](https://github.com/firefly-iii/firefly-iii/issues/1731) API failure for budget limits. | ||||
| - Secure headers now allow Mapbox and the 2FA QR code. | ||||
|  | ||||
| # 4.7.6.2 | ||||
| - Docker file builds again. | ||||
| - Fix CSS of OAuth2 authorization view. | ||||
|  | ||||
| # 4.7.6.1 | ||||
| - An issue where I switched variables from the Docker `.env` file to the normal `.env` file and vice versa -- breaking both. | ||||
| - [Issue 1649](https://github.com/firefly-iii/firefly-iii/issues/1649) 2FA QR code would not show up due to very strict security policy headers | ||||
| - Docker build gave a cURL error whenever it runs PHP commands. | ||||
|  | ||||
| # 4.7.6 | ||||
| - [Issue 145](https://github.com/firefly-iii/firefly-iii/issues/145) You can now download transactions from YNAB. | ||||
| - [Issue 306](https://github.com/firefly-iii/firefly-iii/issues/306) You can now add liabilities to Firefly III. | ||||
| - [Issue 740](https://github.com/firefly-iii/firefly-iii/issues/740) Various charts are now currency aware. | ||||
| - [Issue 833](https://github.com/firefly-iii/firefly-iii/issues/833) Bills can use non-default currencies. | ||||
| - [Issue 1578](https://github.com/firefly-iii/firefly-iii/issues/1578) Firefly III will notify you if the cron job hasn't fired. | ||||
| - [Issue 1623](https://github.com/firefly-iii/firefly-iii/issues/1623) New transactions will link back from the success message. | ||||
| - [Issue 1624](https://github.com/firefly-iii/firefly-iii/issues/1624) transactions will link to the object. | ||||
| - You can call the cron job over the web now (see docs). | ||||
| - You don't need to call the cron job every minute any more. | ||||
| - Various charts are now red/green to signify income and expenses. | ||||
| - Option to add or remove accounts from the net worth calculations. | ||||
| - This will be the last release on PHP 7.1. Future versions will require PHP 7.2. | ||||
| - [Issue 1460](https://github.com/firefly-iii/firefly-iii/issues/1460) Downloading transactions from bunq should go more smoothly. | ||||
| - [Issue 1464](https://github.com/firefly-iii/firefly-iii/issues/1464) Fixed the docker file to work on Raspberry Pi's. | ||||
| - [Issue 1540](https://github.com/firefly-iii/firefly-iii/issues/1540) The Docker file now has a working cron job for recurring transactions. | ||||
| - [Issue 1564](https://github.com/firefly-iii/firefly-iii/issues/1564) Fix double transfers when importing from bunq. | ||||
| - [Issue 1575](https://github.com/firefly-iii/firefly-iii/issues/1575) Some views would give a XSRF token warning | ||||
| - [Issue 1576](https://github.com/firefly-iii/firefly-iii/issues/1576) Fix assigning budgets | ||||
| - [Issue 1580](https://github.com/firefly-iii/firefly-iii/issues/1580) Missing string for translation | ||||
| - [Issue 1581](https://github.com/firefly-iii/firefly-iii/issues/1581) Expand help text | ||||
| - [Issue 1584](https://github.com/firefly-iii/firefly-iii/issues/1584) Link to administration is back. | ||||
| - [Issue 1586](https://github.com/firefly-iii/firefly-iii/issues/1586) Date fields in import were mislabeled. | ||||
| - [Issue 1593](https://github.com/firefly-iii/firefly-iii/issues/1593) Link types are translatable. | ||||
| - [Issue 1594](https://github.com/firefly-iii/firefly-iii/issues/1594) Very long breadcrumbs are weird. | ||||
| - [Issue 1598](https://github.com/firefly-iii/firefly-iii/issues/1598) Fix budget calculations. | ||||
| - [Issue 1597](https://github.com/firefly-iii/firefly-iii/issues/1597) Piggy banks are always inactive. | ||||
| - [Issue 1605](https://github.com/firefly-iii/firefly-iii/issues/1605) System will ignore foreign currency setting if user doesn't indicate the amount. | ||||
| - [Issue 1608](https://github.com/firefly-iii/firefly-iii/issues/1608) Spelling error in command line import. | ||||
| - [Issue 1609](https://github.com/firefly-iii/firefly-iii/issues/1609) Link to budgets page was absolute. | ||||
| - [Issue 1615](https://github.com/firefly-iii/firefly-iii/issues/1615) Fix currency bug in transactions. | ||||
| - [Issue 1616](https://github.com/firefly-iii/firefly-iii/issues/1616) Fix null pointer exception in pie charts. | ||||
| - [Issue 1617](https://github.com/firefly-iii/firefly-iii/issues/1617) Fix for complex tag names in URL's. | ||||
| - [Issue 1620](https://github.com/firefly-iii/firefly-iii/issues/1620) Fixed index reference in API. | ||||
| - [Issue 1639](https://github.com/firefly-iii/firefly-iii/issues/1639) Firefly III trusts the Heroku load balancer, fixing deployment on Heroku. | ||||
| - [Issue 1642](https://github.com/firefly-iii/firefly-iii/issues/1642) Fix issue with split journals. | ||||
| - [Issue 1643](https://github.com/firefly-iii/firefly-iii/issues/1643) Fix reconciliation issue. | ||||
| - Users can no longer give income a budget. | ||||
| - Fix bug in Spectre import. | ||||
| - Heroku would not make you owner. | ||||
| - Add `.htaccess` files to all public directories. | ||||
| - New secure headers will make Firefly III slightly more secure. | ||||
| - The rule "tester" will now also take the "strict"-checkbox into account. | ||||
|  | ||||
| # 4.7.5.3 | ||||
| - [Issue 1527](https://github.com/firefly-iii/firefly-iii/issues/1527), fixed views for transactions without a budget. | ||||
| - [Issue 1553](https://github.com/firefly-iii/firefly-iii/issues/1553), report could not handle transactions before the first one in the system. | ||||
| - [Issue 1549](https://github.com/firefly-iii/firefly-iii/issues/1549) update a budget will also update any rules that refer to that budget. | ||||
| - [Issue 1530](https://github.com/firefly-iii/firefly-iii/issues/1530), fix issue with bill chart. | ||||
| - [Issue 1563](https://github.com/firefly-iii/firefly-iii/issues/1563), fix piggy bank suggested amount | ||||
| - [Issue 1571](https://github.com/firefly-iii/firefly-iii/issues/1571), fix OAuth in Sandstorm | ||||
| - [Issue 1568](https://github.com/firefly-iii/firefly-iii/issues/1568), bug in Sandstorm user code. | ||||
| - [Issue 1569](https://github.com/firefly-iii/firefly-iii/issues/1569), optimized Sandstorm build by [ocdtrekkie](https://github.com/ocdtrekkie) | ||||
| - Fixed a bug where transfers would be stored inversely when using the CSV import. | ||||
| - Retired the "Rabobank description"-fix, because it is no longer necessary. | ||||
| - Fixed a bug where users could not delete budget limits in the API. | ||||
| - Piggy bank notes are visible again. | ||||
|  | ||||
| # 4.7.5.1 | ||||
| - [Issue 1531](https://github.com/firefly-iii/firefly-iii/issues/1531), the database routine incorrectly reports empty categories. | ||||
| - [Issue 1532](https://github.com/firefly-iii/firefly-iii/issues/1532), broken dropdown for autosuggest things. | ||||
| - [Issue 1533](https://github.com/firefly-iii/firefly-iii/issues/1533), fix where the import could not import category names. | ||||
| - [Issue 1538](https://github.com/firefly-iii/firefly-iii/issues/1538), fix a bug where Spectre would not work when ignoring rules. | ||||
| - [Issue 1542](https://github.com/firefly-iii/firefly-iii/issues/1542), fix a bug where the importer was incapable of generating new currencies. | ||||
| - [Issue 1541](https://github.com/firefly-iii/firefly-iii/issues/1541), no longer ignore composer.lock in Docker ignore. | ||||
| - Bills are stored inactive. | ||||
|  | ||||
| # 4.7.5 | ||||
| - A new feature called "recurring transactions" that will make Firefly III automatically create transactions for you. | ||||
| - New API end points for attachments, available budgets, budgets, budget limits, categories, configuration, currency exchange rates, journal links, link types, piggy banks, preferences, recurring transactions, rules, rule groups and tags. | ||||
| - Added support for YunoHost. | ||||
| - The 2FA secret is visible so you can type it into 2FA apps. | ||||
| - Bunq and Spectre imports will now ask to apply rules. | ||||
| - Sandstorm users can now make API keys. | ||||
| - Various typo's in the English translations. [issue 1493](https://github.com/firefly-iii/firefly-iii/issues/1493) | ||||
| - Bug where Spectre was never called [issue 1492](https://github.com/firefly-iii/firefly-iii/issues/1492) | ||||
| - Clear cache after journal is created through API [issue 1483](https://github.com/firefly-iii/firefly-iii/issues/1483) | ||||
| - Make sure docker directories exist [issue 1500](https://github.com/firefly-iii/firefly-iii/issues/1500) | ||||
| - Broken link to bill edit [issue 1505](https://github.com/firefly-iii/firefly-iii/issues/1505) | ||||
| - Several bugs in the editing of split transactions [issue 1509](https://github.com/firefly-iii/firefly-iii/issues/1509) | ||||
| - Import routine ignored formatting of several date fields [issue 1510](https://github.com/firefly-iii/firefly-iii/issues/1510) | ||||
| - Piggy bank events now show the correct currency [issue 1446](https://github.com/firefly-iii/firefly-iii/issues/1446) | ||||
| - Inactive accounts are no longer suggested [issue 1463](https://github.com/firefly-iii/firefly-iii/issues/1463) | ||||
| - Some income / expense charts are less confusing [issue 1518](https://github.com/firefly-iii/firefly-iii/issues/1518) | ||||
| - Validation bug in multi-currency create view [issue 1521](https://github.com/firefly-iii/firefly-iii/issues/1521) | ||||
|  | ||||
| # 4.7.4 | ||||
| - [Issue 1409](https://github.com/firefly-iii/firefly-iii/issues/1409), add Indian Rupee and explain that users can do this themselves [issue 1413](https://github.com/firefly-iii/firefly-iii/issues/1413) | ||||
| - [Issue 1445](https://github.com/firefly-iii/firefly-iii/issues/1445), upgrade Curl in Docker image. | ||||
| - [Issue 1386](https://github.com/firefly-iii/firefly-iii/issues/1386), quick links to often used pages. | ||||
| - [Issue 1405](https://github.com/firefly-iii/firefly-iii/issues/1405), show proposed amount to piggy banks. | ||||
| - [Issue 1416](https://github.com/firefly-iii/firefly-iii/issues/1416), ability to delete lost attachments. | ||||
| - A completely rewritten import routine that can handle bunq (thanks everybody for testing!), CSV files and Spectre. Please make sure you read about this at http://bit.ly/FF3-new-import | ||||
| - [Issue 1392](https://github.com/firefly-iii/firefly-iii/issues/1392), explicitly mention rules are inactive (when they are). | ||||
| - [Issue 1406](https://github.com/firefly-iii/firefly-iii/issues/1406), bill conversion to rules will be smarter about the rules they create. | ||||
| - [Issue 1369](https://github.com/firefly-iii/firefly-iii/issues/1369), you can now properly order piggy banks again. | ||||
| - [Issue 1389](https://github.com/firefly-iii/firefly-iii/issues/1389), null-pointer in the import routine. | ||||
| - [Issue 1400](https://github.com/firefly-iii/firefly-iii/issues/1400), missing translation. | ||||
| - [Issue 1403](https://github.com/firefly-iii/firefly-iii/issues/1403), bill would always be marked as inactive in edit screen. | ||||
| - [Issue 1418](https://github.com/firefly-iii/firefly-iii/issues/1418), missing note text on bill page. | ||||
| - Export routine would break when encountering un-decryptable files. | ||||
| - [Issue 1425](https://github.com/firefly-iii/firefly-iii/issues/1425), empty fields when edit multiple transactions at once. | ||||
| - [Issue 1449](https://github.com/firefly-iii/firefly-iii/issues/1449), bad calculations in "budget left to spend" view. | ||||
| - [Issue 1451](https://github.com/firefly-iii/firefly-iii/issues/1451), same but in another view. | ||||
| - [Issue 1453](https://github.com/firefly-iii/firefly-iii/issues/1453), same as [issue 1403](https://github.com/firefly-iii/firefly-iii/issues/1403). | ||||
| - [Issue 1455](https://github.com/firefly-iii/firefly-iii/issues/1455), could add income to a budget. | ||||
| - [Issue 1442](https://github.com/firefly-iii/firefly-iii/issues/1442), issues with editing a split deposit. | ||||
| - [Issue 1452](https://github.com/firefly-iii/firefly-iii/issues/1452), date range problems with tags. | ||||
| - [Issue 1458](https://github.com/firefly-iii/firefly-iii/issues/1458), same for transactions. | ||||
| - [Issue 1415](https://github.com/firefly-iii/firefly-iii/issues/1415), will email you when OAuth2 keys are generated. | ||||
|  | ||||
| # 4.7.3.2 | ||||
| - Forgot to increase the version number :(. | ||||
|  | ||||
| # 4.7.3.1 | ||||
| - Fixed a critical bug where the rules-engine would fire inadvertently. | ||||
|  | ||||
| # 4.7.3 | ||||
| - Currency added to API | ||||
| - Firfely III will also generate a cash wallet for new users. | ||||
| - Can now reset Spectre and bunq settings | ||||
| - Docker file has a time zone | ||||
| - Allow database connection to be configured in Docker file | ||||
| - Can now view and edit attachments in edit-screen | ||||
| - User can visit hidden `/attachments` page | ||||
| - [Issue 1356](https://github.com/firefly-iii/firefly-iii/issues/1356): Budgets will show the remaining amount per day | ||||
| - [Issue 1367](https://github.com/firefly-iii/firefly-iii/issues/1367): Rules now come in strict and non-strict mode. | ||||
| - Added a security.txt | ||||
| - More support for trusted proxies | ||||
| - Improved edit routine for split transactions. | ||||
| - Upgrade routine can handle `proc_close` being disabled. | ||||
| - Bills now use rules to match transactions, making it more flexible. | ||||
| - [Issue 1328](https://github.com/firefly-iii/firefly-iii/issues/1328): piggy banks no have a more useful chart. | ||||
| - Spectre API upgraded to v4 | ||||
| - Move to MariaDB ([issue 1366](https://github.com/firefly-iii/firefly-iii/issues/1366)) | ||||
| - Piggy banks take currency from parent account ([issue 1334](https://github.com/firefly-iii/firefly-iii/issues/1334)) | ||||
| - [Issue 1341](https://github.com/firefly-iii/firefly-iii/issues/1341): Removed depricated command from dockerfile | ||||
| - Several issues with docker image ([issue 1320](https://github.com/firefly-iii/firefly-iii/issues/1320), [issue 1382](https://github.com/firefly-iii/firefly-iii/issues/1382)). | ||||
| - Fix giant tags and division by zero ([issue 1325](https://github.com/firefly-iii/firefly-iii/issues/1325) and others) | ||||
| - Several issues with bunq import ([issue 1352](https://github.com/firefly-iii/firefly-iii/issues/1352), [issue 1330](https://github.com/firefly-iii/firefly-iii/issues/1330), [issue 1378](https://github.com/firefly-iii/firefly-iii/issues/1378), [issue 1380](https://github.com/firefly-iii/firefly-iii/issues/1380)) | ||||
| - [Issue 1246](https://github.com/firefly-iii/firefly-iii/issues/1246): date picker is internationalised | ||||
| - [Issue 1327](https://github.com/firefly-iii/firefly-iii/issues/1327): fix formattting issues in piggy banks | ||||
| - [Issue 1348](https://github.com/firefly-iii/firefly-iii/issues/1348): 500 error in API | ||||
| - [Issue 1349](https://github.com/firefly-iii/firefly-iii/issues/1349): Errors in import routine | ||||
| - Several fixes for (multi-currency) reconciliation ([issue 1336](https://github.com/firefly-iii/firefly-iii/issues/1336), [issue 1363](https://github.com/firefly-iii/firefly-iii/issues/1363)) | ||||
| - [Issue 1353](https://github.com/firefly-iii/firefly-iii/issues/1353): return NULL values in range-indicator | ||||
| - Bug in split transaction edit routine | ||||
| - Piggy bank percentage was very specific. | ||||
| - Logging in Slack is easier to config. | ||||
| - [Issue 1312](https://github.com/firefly-iii/firefly-iii/issues/1312) Import broken for ING accounts | ||||
| - [Issue 1313](https://github.com/firefly-iii/firefly-iii/issues/1313) Error when creating new asset account | ||||
| - [Issue 1317](https://github.com/firefly-iii/firefly-iii/issues/1317) Forgot an include :( | ||||
| - Null pointer exception in transaction overview. | ||||
| - Installations running in subdirs were incapable of creating OAuth tokens. | ||||
| - OAuth keys were not created in all cases. | ||||
|  | ||||
| # 4.7.2 | ||||
| - [Issue 1123](https://github.com/firefly-iii/firefly-iii/issues/1123) First browser based update routine. | ||||
| - Add support for Italian. | ||||
| - [Issue 1232](https://github.com/firefly-iii/firefly-iii/issues/1232) Allow user to specify Docker database port. | ||||
| - [Issue 1197](https://github.com/firefly-iii/firefly-iii/issues/1197) Beter account list overview  | ||||
| - [Issue 1202](https://github.com/firefly-iii/firefly-iii/issues/1202) Some budgetary warnings  | ||||
| - [Issue 1284](https://github.com/firefly-iii/firefly-iii/issues/1284) Experimental support for bunq import | ||||
| - [Issue 1248](https://github.com/firefly-iii/firefly-iii/issues/1248) Ability to import BIC, ability to import SEPA fields.  | ||||
| - [Issue 1102](https://github.com/firefly-iii/firefly-iii/issues/1102) Summary line for bills  | ||||
| - More info to debug page. | ||||
| - [Issue 1186](https://github.com/firefly-iii/firefly-iii/issues/1186) You can see the latest account balance in CRUD forms  | ||||
| - Add Kubernetes YAML files, kindly created by a FF3 user. | ||||
| - [Issue 1244](https://github.com/firefly-iii/firefly-iii/issues/1244) Better line for "today" marker and add it to other chart as well ([issue 1214](https://github.com/firefly-iii/firefly-iii/issues/1214)) | ||||
| - [Issue 1219](https://github.com/firefly-iii/firefly-iii/issues/1219) Languages in dropdown  | ||||
| - [Issue 1189](https://github.com/firefly-iii/firefly-iii/issues/1189) Inactive accounts get removed from net worth  | ||||
| - [Issue 1220](https://github.com/firefly-iii/firefly-iii/issues/1220) Attachment description and notes migrated to just "notes".  | ||||
| - [Issue 1236](https://github.com/firefly-iii/firefly-iii/issues/1236) Multi currency balance box  | ||||
| - [Issue 1240](https://github.com/firefly-iii/firefly-iii/issues/1240) Better overview for accounts.  | ||||
| - [Issue 1292](https://github.com/firefly-iii/firefly-iii/issues/1292) Removed some charts from the "all"-overview of budgets and categories  | ||||
| - [Issue 1245](https://github.com/firefly-iii/firefly-iii/issues/1245) Improved recognition of IBANs  | ||||
| - Improved import routine. | ||||
| - Update notifier will wait three days before notifying users. | ||||
| - [Issue 1300](https://github.com/firefly-iii/firefly-iii/issues/1300) Virtual balance of credit cards does not count for net worth  | ||||
| - [Issue 1247](https://github.com/firefly-iii/firefly-iii/issues/1247) Can now see overspent amount  | ||||
| - [Issue 1221](https://github.com/firefly-iii/firefly-iii/issues/1221) Upgrade to Laravel 5.6  | ||||
| - [Issue 1187](https://github.com/firefly-iii/firefly-iii/issues/1187) Updated the password verifier to use Troy Hunt's new API  | ||||
| - Revenue chart is now on frontpage permanently | ||||
| - [Issue 1153](https://github.com/firefly-iii/firefly-iii/issues/1153) 2FA settings are in your profile now  | ||||
| - [Issue 1227](https://github.com/firefly-iii/firefly-iii/issues/1227) Can set the timezone in config or in Docker  | ||||
| - [Issue 1294](https://github.com/firefly-iii/firefly-iii/issues/1294) Ability to link a transaction to itself  | ||||
| - Correct reference to journal description in split form. | ||||
| - [Issue 1234](https://github.com/firefly-iii/firefly-iii/issues/1234) Fix budget page issues in SQLite  | ||||
| - [Issue 1262](https://github.com/firefly-iii/firefly-iii/issues/1262) Can now use double and epty headers in CSV files  | ||||
| - [Issue 1258](https://github.com/firefly-iii/firefly-iii/issues/1258) Fixed a possible date mismatch in piggy banks | ||||
| - [Issue 1283](https://github.com/firefly-iii/firefly-iii/issues/1283) Bulk delete was broken  | ||||
| - [Issue 1293](https://github.com/firefly-iii/firefly-iii/issues/1293) Layout problem with notes  | ||||
| - [Issue 1257](https://github.com/firefly-iii/firefly-iii/issues/1257) Improve transaction lists query count  | ||||
| - [Issue 1291](https://github.com/firefly-iii/firefly-iii/issues/1291) Fixer IO problems  | ||||
| - [Issue 1239](https://github.com/firefly-iii/firefly-iii/issues/1239) Could not edit expense or revenue accounts ([issue 1298](https://github.com/firefly-iii/firefly-iii/issues/1298))  | ||||
| - [Issue 1297](https://github.com/firefly-iii/firefly-iii/issues/1297) Could not convert to withdrawal  | ||||
| - [Issue 1226](https://github.com/firefly-iii/firefly-iii/issues/1226) Category overview in default report shows no income.  | ||||
| - Various other bugs and problems ([issue 1198](https://github.com/firefly-iii/firefly-iii/issues/1198), [issue 1213](https://github.com/firefly-iii/firefly-iii/issues/1213), [issue 1237](https://github.com/firefly-iii/firefly-iii/issues/1237), [issue 1238](https://github.com/firefly-iii/firefly-iii/issues/1238), [issue 1199](https://github.com/firefly-iii/firefly-iii/issues/1199), [issue 1200](https://github.com/firefly-iii/firefly-iii/issues/1200)) | ||||
| - Fixed an issue with token validation on the command line. | ||||
|  | ||||
| # 4.7.1 | ||||
| - A brand new API. Read about it in the [documentation](http://firefly-iii.readthedocs.io/en/latest/). | ||||
| - Add support for Spanish. [issue 1194](https://github.com/firefly-iii/firefly-iii/issues/1194) | ||||
| - Some custom preferences are selected by default for a better user experience. | ||||
| - Some new currencies [issue 1211](https://github.com/firefly-iii/firefly-iii/issues/1211) | ||||
| - Fixed [issue 1155](https://github.com/firefly-iii/firefly-iii/issues/1155) (reported by [ndandanov](https://github.com/ndandanov)) | ||||
| - [Issue 1156](https://github.com/firefly-iii/firefly-iii/issues/1156) [issue 1182](https://github.com/firefly-iii/firefly-iii/issues/1182) and other issues related to SQLite databases. | ||||
| - Multi-page budget overview was broken (reported by [jinformatique](https://github.com/jinformatique)) | ||||
| - Importing CSV files with semi-colons in them did not work [issue 1172](https://github.com/firefly-iii/firefly-iii/issues/1172) [issue 1183](https://github.com/firefly-iii/firefly-iii/issues/1183) [issue 1210](https://github.com/firefly-iii/firefly-iii/issues/1210) | ||||
| - Could not use account number that was in use by a deleted account [issue 1174](https://github.com/firefly-iii/firefly-iii/issues/1174)  | ||||
| - Fixed spelling error that lead to 404's [issue 1175](https://github.com/firefly-iii/firefly-iii/issues/1175) [issue 1190](https://github.com/firefly-iii/firefly-iii/issues/1190) | ||||
| - Fixed tag autocomplete [issue 1178](https://github.com/firefly-iii/firefly-iii/issues/1178) | ||||
| - Better links for "new transaction" buttons [issue 1185](https://github.com/firefly-iii/firefly-iii/issues/1185) | ||||
| - Cache errors in budget charts [issue 1192](https://github.com/firefly-iii/firefly-iii/issues/1192) | ||||
| - Deleting transactions that are linked to other other transactions would lead to errors [issue 1209](https://github.com/firefly-iii/firefly-iii/issues/1209) | ||||
|  | ||||
| # 4.7.0 | ||||
| - Support for Russian and Portuguese (Brazil) | ||||
| - Support for the Spectre API (Salt Edge) | ||||
| - Many strings now translatable thanks to [Nik-vr](https://github.com/Nik-vr) ([issue 1118](https://github.com/firefly-iii/firefly-iii/issues/1118), [issue 1116](https://github.com/firefly-iii/firefly-iii/issues/1116), [issue 1109](https://github.com/firefly-iii/firefly-iii/issues/1109), ) | ||||
| - Many buttons to quickly create stuff | ||||
| - Sum of tables in reports, requested by [MacPaille](https://github.com/MacPaille) ([issue 1106](https://github.com/firefly-iii/firefly-iii/issues/1106)) | ||||
| - Future versions of Firefly III will notify you there is a new version, as suggested by [8bitgentleman](https://github.com/8bitgentleman) in [issue 1050](https://github.com/firefly-iii/firefly-iii/issues/1050) | ||||
| - Improved net worth box [issue 1101](https://github.com/firefly-iii/firefly-iii/issues/1101) ([Nik-vr](https://github.com/Nik-vr)) | ||||
| - Nice dropdown in transaction list [issue 1082](https://github.com/firefly-iii/firefly-iii/issues/1082) | ||||
| - Better support for local fonts thanks to [devlearner](https://github.com/devlearner) ([issue 1145](https://github.com/firefly-iii/firefly-iii/issues/1145)) | ||||
| - Improve attachment support and view capabilities (suggested by [trinhit](https://github.com/trinhit) in [issue 1146](https://github.com/firefly-iii/firefly-iii/issues/1146)) | ||||
| - Whole new [read me file](https://github.com/firefly-iii/firefly-iii/blob/master/readme.md), [new end user documentation](https://firefly-iii.readthedocs.io/en/latest/) and an [updated website](https://www.firefly-iii.org/)! | ||||
| - Many charts and info-blocks now scale property ([issue 989](https://github.com/firefly-iii/firefly-iii/issues/989) and [issue 1040](https://github.com/firefly-iii/firefly-iii/issues/1040)) | ||||
| - Charts work in IE thanks to [devlearner](https://github.com/devlearner) ([issue 1107](https://github.com/firefly-iii/firefly-iii/issues/1107)) | ||||
| - Various fixes in import routine | ||||
| - Bug that left charts empty ([issue 1088](https://github.com/firefly-iii/firefly-iii/issues/1088)), reported by various users amongst which [jinformatique](https://github.com/jinformatique) | ||||
| - [Issue 1124](https://github.com/firefly-iii/firefly-iii/issues/1124), as reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 1125](https://github.com/firefly-iii/firefly-iii/issues/1125), as reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 1126](https://github.com/firefly-iii/firefly-iii/issues/1126), as reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 1131](https://github.com/firefly-iii/firefly-iii/issues/1131), as reported by [dp87](https://github.com/dp87) | ||||
| - [Issue 1129](https://github.com/firefly-iii/firefly-iii/issues/1129), as reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 1132](https://github.com/firefly-iii/firefly-iii/issues/1132), as reported by [gavu](https://github.com/gavu) | ||||
| - Issue with cache in Sandstorm ([issue 1130](https://github.com/firefly-iii/firefly-iii/issues/1130)) | ||||
| - [Issue 1134](https://github.com/firefly-iii/firefly-iii/issues/1134) | ||||
| - [Issue 1140](https://github.com/firefly-iii/firefly-iii/issues/1140) | ||||
| - [Issue 1141](https://github.com/firefly-iii/firefly-iii/issues/1141), reported by [ErikFontanel](https://github.com/ErikFontanel) | ||||
| - [Issue 1142](https://github.com/firefly-iii/firefly-iii/issues/1142) | ||||
| - Removed many access rights from the demo user | ||||
|  | ||||
| # 4.6.13 | ||||
| - [Issue 1074](https://github.com/firefly-iii/firefly-iii/issues/1074), suggested by [MacPaille](https://github.com/MacPaille) | ||||
| - [Issue 1077](https://github.com/firefly-iii/firefly-iii/issues/1077), suggested by [wtercato](https://github.com/wtercato) | ||||
| - Bulk edit of transactions thanks to [vicmosin](https://github.com/vicmosin) ([issue 1078](https://github.com/firefly-iii/firefly-iii/issues/1078)) | ||||
| - Support for Turkish. | ||||
| - [Issue 1090](https://github.com/firefly-iii/firefly-iii/issues/1090), suggested by [Findus23](https://github.com/Findus23) | ||||
| - [Issue 1097](https://github.com/firefly-iii/firefly-iii/issues/1097), suggested by [kelvinhammond](https://github.com/kelvinhammond) | ||||
| - [Issue 1093](https://github.com/firefly-iii/firefly-iii/issues/1093), suggested by [jinformatique](https://github.com/jinformatique) | ||||
| - [Issue 1098](https://github.com/firefly-iii/firefly-iii/issues/1098), suggested by [Nik-vr](https://github.com/Nik-vr) | ||||
| - [Issue 972](https://github.com/firefly-iii/firefly-iii/issues/972), reported by [pjotrvdh](https://github.com/pjotrvdh) | ||||
| - [Issue 1079](https://github.com/firefly-iii/firefly-iii/issues/1079), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 1080](https://github.com/firefly-iii/firefly-iii/issues/1080), reported by [zjean](https://github.com/zjean) | ||||
| - [Issue 1083](https://github.com/firefly-iii/firefly-iii/issues/1083), reported by [skuzzle](https://github.com/skuzzle) | ||||
| - [Issue 1085](https://github.com/firefly-iii/firefly-iii/issues/1085), reported by [nicoschreiner](https://github.com/nicoschreiner) | ||||
| - [Issue 1087](https://github.com/firefly-iii/firefly-iii/issues/1087), reported by [4oo4](https://github.com/4oo4) | ||||
| - [Issue 1089](https://github.com/firefly-iii/firefly-iii/issues/1089), reported by [robin5210](https://github.com/robin5210) | ||||
| - [Issue 1092](https://github.com/firefly-iii/firefly-iii/issues/1092), reported by [kelvinhammond](https://github.com/kelvinhammond) | ||||
| - [Issue 1096](https://github.com/firefly-iii/firefly-iii/issues/1096), reported by [wtercato](https://github.com/wtercato) | ||||
|  | ||||
| # 4.6.12 | ||||
| - Support for Indonesian. | ||||
| - New report, see [issue 384](https://github.com/firefly-iii/firefly-iii/issues/384) | ||||
| - [Issue 964](https://github.com/firefly-iii/firefly-iii/issues/964) as suggested by [gavu](https://github.com/gavu) | ||||
| - Greatly improved Docker support and documentation. | ||||
| - [Issue 1046](https://github.com/firefly-iii/firefly-iii/issues/1046), as reported by [pkoziol](https://github.com/pkoziol) | ||||
| - [Issue 1047](https://github.com/firefly-iii/firefly-iii/issues/1047), as reported by [pkoziol](https://github.com/pkoziol) | ||||
| - [Issue 1048](https://github.com/firefly-iii/firefly-iii/issues/1048), as reported by [webence](https://github.com/webence) | ||||
| - [Issue 1049](https://github.com/firefly-iii/firefly-iii/issues/1049), as reported by [nicoschreiner](https://github.com/nicoschreiner)  | ||||
| - [Issue 1015](https://github.com/firefly-iii/firefly-iii/issues/1015), as reporterd by a user on Tweakers.net | ||||
| - [Issue 1056](https://github.com/firefly-iii/firefly-iii/issues/1056), as reported by [repercussion](https://github.com/repercussion)  | ||||
| - [Issue 1061](https://github.com/firefly-iii/firefly-iii/issues/1061), as reported by [Meizikyn](https://github.com/Meizikyn) | ||||
| - [Issue 1045](https://github.com/firefly-iii/firefly-iii/issues/1045), as reported by [gavu](https://github.com/gavu) | ||||
| - First code for [issue 1040](https://github.com/firefly-iii/firefly-iii/issues/1040) ([simonsmiley](https://github.com/simonsmiley)) | ||||
| - [Issue 1059](https://github.com/firefly-iii/firefly-iii/issues/1059), as reported by [4oo4](https://github.com/4oo4) | ||||
| - [Issue 1063](https://github.com/firefly-iii/firefly-iii/issues/1063), as reported by [pkoziol](https://github.com/pkoziol) | ||||
| - [Issue 1064](https://github.com/firefly-iii/firefly-iii/issues/1064), as reported by [pkoziol](https://github.com/pkoziol) | ||||
| - [Issue 1066](https://github.com/firefly-iii/firefly-iii/issues/1066), reported by [wtercato](https://github.com/wtercato) | ||||
|  | ||||
| # 4.6.1.1 | ||||
| - Import routine can scan for matching bills, [issue 956](https://github.com/firefly-iii/firefly-iii/issues/956) | ||||
| - Import will no longer scan for rules, this has become optional. Originally suggested in [issue 956](https://github.com/firefly-iii/firefly-iii/issues/956) by [gavu](https://github.com/gavu)  | ||||
| - [Issue 1033](https://github.com/firefly-iii/firefly-iii/issues/1033), as reported by [Jumanjii](https://github.com/Jumanjii) | ||||
|   | ||||
| @@ -9,6 +9,10 @@ CURL_OPTS="--silent --show-error" | ||||
| echo localhost > /etc/hostname | ||||
| hostname localhost | ||||
|  | ||||
| # Install curl that is needed below. | ||||
| apt-get update | ||||
| apt-get install -y curl | ||||
|  | ||||
| # The following line copies stderr through stderr to cat without accidentally leaving it in the | ||||
| # output file. Be careful when changing. See: https://github.com/sandstorm-io/vagrant-spk/pull/159 | ||||
| curl $CURL_OPTS https://install.sandstorm.io/ 2>&1 > /host-dot-sandstorm/caches/install.sh | cat | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| # Runs every time we create a new grain! | ||||
| echo "Now in launcher.sh" | ||||
|  | ||||
| # Create a bunch of folders under the clean /var that php, nginx, and mysql expect to exist | ||||
| mkdir -p /var/lib/mysql | ||||
| @@ -24,28 +25,27 @@ mkdir -p /var/storage/build | ||||
| mkdir -p /var/storage/database | ||||
| mkdir -p /var/storage/debugbar | ||||
| mkdir -p /var/storage/export | ||||
| mkdir -p /var/storage/framework/cache | ||||
| mkdir -p /var/storage/framework/cache/v1 | ||||
| mkdir -p /var/storage/framework/sessions | ||||
| mkdir -p /var/storage/framework/views | ||||
| mkdir -p /var/storage/framework/views/v1 | ||||
| mkdir -p /var/storage/logs | ||||
| mkdir -p /var/storage/upload | ||||
|  | ||||
|  | ||||
| # Ensure mysql tables created | ||||
| HOME=/etc/mysql /usr/bin/mysql_install_db --force | ||||
|  | ||||
| # Spawn mysqld, php | ||||
| HOME=/etc/mysql /usr/sbin/mysqld & | ||||
|  | ||||
| /usr/sbin/php-fpm7.1 --nodaemonize --fpm-config /etc/php/7.1/fpm/php-fpm.conf & | ||||
| /usr/sbin/php-fpm7.2 --nodaemonize --fpm-config /etc/php/7.2/fpm/php-fpm.conf & | ||||
|  | ||||
| # Wait until mysql and php have bound their sockets, indicating readiness | ||||
| while [ ! -e /var/run/mysqld/mysqld.sock ] ; do | ||||
|     echo "waiting for mysql to be available at /var/run/mysqld/mysqld.sock" | ||||
|     sleep .5 | ||||
| done | ||||
| while [ ! -e /var/run/php7.1-fpm.sock ] ; do | ||||
|     echo "waiting for php7.1-fpm to be available at /var/run/php7.1-fpm.sock" | ||||
| while [ ! -e /var/run/php7.2-fpm.sock ] ; do | ||||
|     echo "waiting for php7.2-fpm to be available at /var/run/php7.2-fpm.sock" | ||||
|     sleep .5 | ||||
| done | ||||
|  | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -15,8 +15,8 @@ const pkgdef :Spk.PackageDefinition = ( | ||||
|  | ||||
|   manifest = ( | ||||
|     appTitle = (defaultText = "Firefly III"), | ||||
|     appVersion = 5, | ||||
|     appMarketingVersion = (defaultText = "4.6.11.1"), | ||||
|     appVersion = 23, | ||||
|     appMarketingVersion = (defaultText = "4.7.13"), | ||||
|  | ||||
|     actions = [ | ||||
|       # Define your "new document" handlers here. | ||||
| @@ -41,7 +41,7 @@ const pkgdef :Spk.PackageDefinition = ( | ||||
|         market = (png = (dpi1x = embed "app-graphics/firefly-iii-150.png")) | ||||
|       ), | ||||
|  | ||||
|       website = "https://firefly-iii.github.io/", | ||||
|       website = "https://firefly-iii.org/", | ||||
|       codeUrl = "https://github.com/firefly-iii/firefly-iii", | ||||
|       license = (openSource = gpl3), | ||||
|       # The license this package is distributed under.  See | ||||
| @@ -65,9 +65,9 @@ const pkgdef :Spk.PackageDefinition = ( | ||||
|         # Sizes are given in device-independent pixels, so if you took these | ||||
|         # screenshots on a Retina-style high DPI screen, divide each dimension by two. | ||||
|  | ||||
|         (width = 1291, height = 800, png = embed "screenshots/screenshot-1.png"), | ||||
|         (width = 1291, height = 800, png = embed "screenshots/screenshot-2.png"), | ||||
|         (width = 1291, height = 800, png = embed "screenshots/screenshot-3.png"), | ||||
|         (width = 1290, height = 800, png = embed "screenshots/screenshot-1.png"), | ||||
|         (width = 1290, height = 800, png = embed "screenshots/screenshot-2.png"), | ||||
|         (width = 1290, height = 800, png = embed "screenshots/screenshot-3.png"), | ||||
|  | ||||
|       ], | ||||
|       changeLog = (defaultText = embed "changelog.md"), | ||||
| @@ -103,7 +103,7 @@ const pkgdef :Spk.PackageDefinition = ( | ||||
|   # not have been detected as a dependency during `spk dev`. If you list | ||||
|   # a directory here, its entire contents will be included recursively. | ||||
|  | ||||
|   #bridgeConfig = ( | ||||
|   bridgeConfig = ( | ||||
|   #  # Used for integrating permissions and roles into the Sandstorm shell | ||||
|   #  # and for sandstorm-http-bridge to pass to your app. | ||||
|   #  # Uncomment this block and adjust the permissions and roles to make | ||||
| @@ -165,12 +165,12 @@ const pkgdef :Spk.PackageDefinition = ( | ||||
|   #      ), | ||||
|   #    ], | ||||
|   #  ), | ||||
|   #  #apiPath = "/api", | ||||
|   apiPath = "/api/v1/", | ||||
|   #  # Apps can export an API to the world.  The API is to be used primarily by Javascript | ||||
|   #  # code and native apps, so it can't serve out regular HTML to browsers.  If a request | ||||
|   #  # comes in to your app's API, sandstorm-http-bridge will prefix the request's path with | ||||
|   #  # this string, if specified. | ||||
|   #), | ||||
|   ), | ||||
| ); | ||||
|  | ||||
| const myCommand :Spk.Manifest.Command = ( | ||||
|   | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 173 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 171 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 163 KiB | 
| @@ -53,10 +53,11 @@ http { | ||||
| 		} | ||||
| 		location ~ \.php$ { | ||||
| 			try_files $uri =404; | ||||
|             fastcgi_pass unix:/var/run/php7.1-fpm.sock; | ||||
|             fastcgi_pass unix:/var/run/php7.2-fpm.sock; | ||||
|             fastcgi_index index.php; | ||||
|             fastcgi_split_path_info ^(.+\.php)(/.+)$; | ||||
| 			fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name; | ||||
| 			fastcgi_read_timeout 900; | ||||
|  | ||||
|  | ||||
| 			fastcgi_param  QUERY_STRING       $query_string; | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
|  | ||||
| # When you change this file, you must take manual action. Read this doc: | ||||
| # - https://docs.sandstorm.io/en/latest/vagrant-spk/customizing/#setupsh | ||||
| echo "Now in setup.sh" | ||||
|  | ||||
| set -euo pipefail | ||||
|  | ||||
| @@ -12,10 +13,18 @@ apt-get update | ||||
| apt-get install -y python-software-properties software-properties-common | ||||
|  | ||||
| # install all languages | ||||
| #en_US | ||||
| sed -i 's/# es_ES.UTF-8 UTF-8/es_ES.UTF-8 UTF-8/g' /etc/locale.gen | ||||
| sed -i 's/# de_DE.UTF-8 UTF-8/de_DE.UTF-8 UTF-8/g' /etc/locale.gen | ||||
| sed -i 's/# fr_FR.UTF-8 UTF-8/fr_FR.UTF-8 UTF-8/g' /etc/locale.gen | ||||
| sed -i 's/# it_IT.UTF-8 UTF-8/it_IT.UTF-8 UTF-8/g' /etc/locale.gen | ||||
| sed -i 's/# nl_NL.UTF-8 UTF-8/nl_NL.UTF-8 UTF-8/g' /etc/locale.gen | ||||
| sed -i 's/# pl_PL.UTF-8 UTF-8/pl_PL.UTF-8 UTF-8/g' /etc/locale.gen | ||||
| sed -i 's/# pt_BR.UTF-8 UTF-8/pt_BR.UTF-8 UTF-8/g' /etc/locale.gen | ||||
| sed -i 's/# ru_RU.UTF-8 UTF-8/ru_RU.UTF-8 UTF-8/g' /etc/locale.gen | ||||
| sed -i 's/# zh_TW.UTF-8 UTF-8/zh_TW.UTF-8 UTF-8/g' /etc/locale.gen | ||||
| sed -i 's/# zh_CN.UTF-8 UTF-8/zh_CN.UTF-8 UTF-8/g' /etc/locale.gen | ||||
|  | ||||
| dpkg-reconfigure --frontend=noninteractive locales | ||||
|  | ||||
|  | ||||
| @@ -26,43 +35,43 @@ apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E9C74FEEA2098A6E | ||||
| add-apt-repository "deb http://packages.dotdeb.org jessie all" | ||||
|  | ||||
| # add another repos | ||||
| apt-get install apt-transport-https lsb-release ca-certificates | ||||
| apt-get install -y apt-transport-https lsb-release ca-certificates | ||||
| wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg | ||||
| echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list | ||||
|  | ||||
| # install packages. | ||||
| apt-get update | ||||
| apt-get install -y nginx php7.1-fpm php7.1-mysql php7.1-gd php7.1-cli php7.1-curl git php7.1-dev php7.1-zip php7.1-intl php7.1-dom php7.1-mbstring php7.1-bcmath mysql-server | ||||
| apt-get install -y nginx php7.2-fpm php7.2-mysql php7.2-gd php7.2-cli php7.2-curl php7.2-ldap git php7.2-dev php7.2-zip php7.2-intl php7.2-dom php7.2-mbstring php7.2-bcmath mysql-server | ||||
| service nginx stop | ||||
| service php7.1-fpm stop | ||||
| service php7.2-fpm stop | ||||
| service mysql stop | ||||
| systemctl disable nginx | ||||
| systemctl disable php7.1-fpm | ||||
| systemctl disable php7.2-fpm | ||||
| systemctl disable mysql | ||||
|  | ||||
| # make php.ini display errors: | ||||
| sed -i 's/display_errors = Off/display_errors = On/g' /etc/php/7.1/fpm/php.ini | ||||
| sed -i 's/display_errors = Off/display_errors = On/g' /etc/php/7.2/fpm/php.ini | ||||
|  | ||||
| # patch /etc/php/7.1/fpm/pool.d/www.conf to not change uid/gid to www-data | ||||
| # patch /etc/php/7.2/fpm/pool.d/www.conf to not change uid/gid to www-data | ||||
| sed --in-place='' \ | ||||
|        --expression='s/^listen.owner = www-data/;listen.owner = www-data/' \ | ||||
|        --expression='s/^listen.group = www-data/;listen.group = www-data/' \ | ||||
|        /etc/php/7.1/fpm/pool.d/www.conf | ||||
| # patch /etc/php/7.1/fpm/php-fpm.conf to not have a pidfile | ||||
|        /etc/php/7.2/fpm/pool.d/www.conf | ||||
| # patch /etc/php/7.2/fpm/php-fpm.conf to not have a pidfile | ||||
| sed --in-place='' \ | ||||
|        --expression='s/^pid =/;pid =/' \ | ||||
|        /etc/php/7.1/fpm/php-fpm.conf | ||||
|        /etc/php/7.2/fpm/php-fpm.conf | ||||
|  | ||||
| # move sock file to better dir: | ||||
| sed --in-place='' \ | ||||
|        --expression='s/^listen = \/run\/php\/php7.1-fpm.sock/listen = \/var\/run\/php7.1-fpm.sock/' \ | ||||
|        /etc/php/7.1/fpm/pool.d/www.conf | ||||
|        --expression='s/^listen = \/run\/php\/php7.2-fpm.sock/listen = \/var\/run\/php7.2-fpm.sock/' \ | ||||
|        /etc/php/7.2/fpm/pool.d/www.conf | ||||
|  | ||||
| # patch /etc/php/7.1/fpm/pool.d/www.conf to no clear environment variables | ||||
| # patch /etc/php/7.2/fpm/pool.d/www.conf to no clear environment variables | ||||
| # so we can pass in SANDSTORM=1 to apps | ||||
| sed --in-place='' \ | ||||
|        --expression='s/^;clear_env = no/clear_env=no/' \ | ||||
|        /etc/php/7.1/fpm/pool.d/www.conf | ||||
|        /etc/php/7.2/fpm/pool.d/www.conf | ||||
| # patch mysql conf to not change uid, and to use /var/tmp over /tmp | ||||
| # for secure-file-priv see https://github.com/sandstorm-io/vagrant-spk/issues/195 | ||||
| sed --in-place='' \ | ||||
|   | ||||
							
								
								
									
										105
									
								
								.scrutinizer.yml
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								.scrutinizer.yml
									
									
									
									
									
								
							| @@ -1,51 +1,58 @@ | ||||
| # .scrutinizer.yml | ||||
| tools: | ||||
|   external_code_coverage: false | ||||
| filter: | ||||
|   paths: | ||||
| ---  | ||||
| build:  | ||||
|   nodes:  | ||||
|     analysis:  | ||||
|       project_setup:  | ||||
|         override: true | ||||
|       tests:  | ||||
|         override:  | ||||
|           - php-scrutinizer-run | ||||
| checks:  | ||||
|   javascript: true | ||||
|   php:  | ||||
|     align_assignments: true | ||||
|     avoid_fixme_comments: true | ||||
|     avoid_multiple_statements_on_same_line: true | ||||
|     avoid_perl_style_comments: true | ||||
|     avoid_todo_comments: true | ||||
|     duplication: false | ||||
|     encourage_single_quotes: true | ||||
|     newline_at_end_of_file: true | ||||
|     no_goto: true | ||||
|     no_long_variable_names:  | ||||
|       maximum: "20" | ||||
|     no_short_method_names:  | ||||
|       minimum: "3" | ||||
|     no_short_variable_names:  | ||||
|       minimum: "3" | ||||
|     optional_parameters_at_the_end: true | ||||
|     parameter_doc_comments: true | ||||
|     remove_extra_empty_lines: true | ||||
|     return_doc_comment_if_not_inferrable: true | ||||
|     return_doc_comments: true | ||||
|     uppercase_constants: true | ||||
|     use_self_instead_of_fqcn: true | ||||
| coding_style:  | ||||
|   php:  | ||||
|     spaces:  | ||||
|       around_operators:  | ||||
|         concatenation: true | ||||
|       other:  | ||||
|         after_type_cast: false | ||||
| filter:  | ||||
|   excluded_paths:  | ||||
|     - database/migrations/* | ||||
|     - bootstrap/* | ||||
|     - config/* | ||||
|     - docker/* | ||||
|     - public/js/lib/* | ||||
|     - public/lib/adminlte/js/* | ||||
|     - public/lib/bootstrap/js/* | ||||
|     - resources/* | ||||
|     - routes/* | ||||
|     - storage/* | ||||
|   paths:  | ||||
|     - app/* | ||||
|     - public/js/ff/* | ||||
|   excluded_paths: | ||||
|     - "database/migrations/*" | ||||
|     - "bootstrap/*" | ||||
|     - "config/*" | ||||
|     - "docker/*" | ||||
|     - "public/js/lib/*" | ||||
|     - "public/lib/adminlte/js/*" | ||||
|     - "public/lib/bootstrap/js/*" | ||||
|     - "resources/*" | ||||
|     - "routes/*" | ||||
|     - "storage/*" | ||||
| checks: | ||||
|     php: | ||||
|         use_self_instead_of_fqcn: true | ||||
|         uppercase_constants: true | ||||
|         return_doc_comments: true | ||||
|         return_doc_comment_if_not_inferrable: true | ||||
|         remove_extra_empty_lines: true | ||||
|         parameter_doc_comments: true | ||||
|         optional_parameters_at_the_end: true | ||||
|         no_short_variable_names: | ||||
|             minimum: '3' | ||||
|         no_short_method_names: | ||||
|             minimum: '3' | ||||
|         no_long_variable_names: | ||||
|             maximum: '20' | ||||
|         no_goto: true | ||||
|         newline_at_end_of_file: true | ||||
|         encourage_single_quotes: true | ||||
|         avoid_todo_comments: true | ||||
|         avoid_perl_style_comments: true | ||||
|         avoid_fixme_comments: true | ||||
|         avoid_multiple_statements_on_same_line: true | ||||
|         align_assignments: true | ||||
|         duplication: false | ||||
|     javascript: true | ||||
|  | ||||
| coding_style: | ||||
|     php: | ||||
|         spaces: | ||||
|             around_operators: | ||||
|                 concatenation: true | ||||
|             other: | ||||
|                 after_type_cast: false | ||||
| tools:  | ||||
|   external_code_coverage: false | ||||
|   | ||||
							
								
								
									
										48
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								.travis.yml
									
									
									
									
									
								
							| @@ -1,31 +1,29 @@ | ||||
| language: php | ||||
| php: | ||||
|   - 7.1 | ||||
| sudo: required | ||||
| language: bash | ||||
| env: | ||||
|   - VERSION=4.7.13 | ||||
|  | ||||
| cache: | ||||
|     directories: | ||||
|         - vendor | ||||
|         - $HOME/.composer/cache | ||||
|  | ||||
| install: | ||||
|   - rm composer.lock | ||||
|   - composer update --no-scripts | ||||
|   - cp .env.testing .env | ||||
|   - php artisan clear-compiled | ||||
|   - php artisan optimize | ||||
|   - php artisan env | ||||
|   - cp .env.testing .env | ||||
|   - wget -q https://github.com/firefly-iii/test-data/raw/master/storage/database.sqlite -O storage/database/database.sqlite | ||||
|   - mkdir -p build/logs | ||||
|  | ||||
| script: | ||||
|   - phpunit -c phpunit.coverage.xml | ||||
|  | ||||
| after_success: | ||||
|   - travis_retry php vendor/bin/coveralls -x storage/build/clover-all.xml | ||||
| dist: xenial | ||||
|  | ||||
| # safelist | ||||
| branches: | ||||
|   only: | ||||
|   - develop | ||||
|   - master | ||||
|   - master | ||||
|  | ||||
| services: | ||||
|   - docker | ||||
|  | ||||
| script: | ||||
|   # enable experimental features. | ||||
|   - echo '{"experimental":true}' | sudo tee /etc/docker/daemon.json | ||||
|   - mkdir $HOME/.docker | ||||
|   - touch $HOME/.docker/config.json | ||||
|   - echo '{"experimental":"enabled"}' | sudo tee $HOME/.docker/config.json | ||||
|   - sudo service docker restart | ||||
|   - docker version -f '{{.Server.Experimental}}' | ||||
|   - docker version | ||||
|   # build everything | ||||
|   - .deploy/docker/build-amd64.sh | ||||
|   - .deploy/docker/build-arm.sh | ||||
|   - .deploy/docker/manifest.sh | ||||
							
								
								
									
										897
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										897
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -1,897 +0,0 @@ | ||||
| # Change Log | ||||
| All notable changes to this project will be documented in this file. | ||||
| This project adheres to [Semantic Versioning](http://semver.org/). | ||||
|  | ||||
| ## [4.6.11.1] - 2017-12-08 | ||||
| ### Added | ||||
| - Import routine can scan for matching bills, [issue 956](https://github.com/firefly-iii/firefly-iii/issues/956) | ||||
|  | ||||
| ### Changed | ||||
| - Import will no longer scan for rules, this has become optional. Originally suggested in [issue 956](https://github.com/firefly-iii/firefly-iii/issues/956) by [gavu](https://github.com/gavu)  | ||||
| - [Issue 1033](https://github.com/firefly-iii/firefly-iii/issues/1033), as reported by [Jumanjii](https://github.com/Jumanjii) | ||||
| - [Issue 1033](https://github.com/firefly-iii/firefly-iii/issues/1034), as reported by [Aquariu](https://github.com/Aquariu) | ||||
| - Extra admin check for [issue 1039](https://github.com/firefly-iii/firefly-iii/issues/1039), as reported by [ocdtrekkie](https://github.com/ocdtrekkie) | ||||
|  | ||||
| ### Fixed | ||||
| - Missing translations ([issue 1026](https://github.com/firefly-iii/firefly-iii/issues/1026)), as reported by [gavu](https://github.com/gavu) and [zjean](https://github.com/zjean) | ||||
| - [Issue 1028](https://github.com/firefly-iii/firefly-iii/issues/1028), reported by [zjean](https://github.com/zjean) | ||||
| - [Issue 1029](https://github.com/firefly-iii/firefly-iii/issues/1029), reported by [zjean](https://github.com/zjean) | ||||
| - [Issue 1030](https://github.com/firefly-iii/firefly-iii/issues/1030), as reported by [Traxxi](https://github.com/Traxxi) | ||||
| - [Issue 1036](https://github.com/firefly-iii/firefly-iii/issues/1036), as reported by [webence](https://github.com/webence) | ||||
| - [Issue 1038](https://github.com/firefly-iii/firefly-iii/issues/1038), as reported by [gavu](https://github.com/gavu) | ||||
|  | ||||
| ## [4.6.11] - 2017-11-30 | ||||
| ### Added | ||||
| - A debug page at `/debug` for easier debug. | ||||
| - Strings translatable (see [issue 976](https://github.com/firefly-iii/firefly-iii/issues/976)), thanks to [Findus23](https://github.com/Findus23) | ||||
| - Even more strings are translatable (and translated), thanks to [pkoziol](https://github.com/pkoziol) (see [issue 979](https://github.com/firefly-iii/firefly-iii/issues/979)) | ||||
| - Reconciliation of accounts ([issue 736](https://github.com/firefly-iii/firefly-iii/issues/736)), as requested by [kristophr](https://github.com/kristophr) and several others | ||||
|  | ||||
| ### Changed | ||||
| - Extended currency list, as suggested by @emuhendis in [issue 994](https://github.com/firefly-iii/firefly-iii/issues/994) | ||||
| - [Issue 996](https://github.com/firefly-iii/firefly-iii/issues/996) as suggested by [dp87](https://github.com/dp87) | ||||
|  | ||||
| ### Removed | ||||
| - Disabled Heroku support until I get it working again. | ||||
|  | ||||
| ### Fixed | ||||
| - [Issue 980](https://github.com/firefly-iii/firefly-iii/issues/980), reported by [Tim-Frensch](https://github.com/Tim-Frensch) | ||||
| - [Issue 987](https://github.com/firefly-iii/firefly-iii/issues/987), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 988](https://github.com/firefly-iii/firefly-iii/issues/988), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 992](https://github.com/firefly-iii/firefly-iii/issues/992), reported by [ncicovic](https://github.com/ncicovic) | ||||
| - [Issue 993](https://github.com/firefly-iii/firefly-iii/issues/993), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 997](https://github.com/firefly-iii/firefly-iii/issues/997), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 1000](https://github.com/firefly-iii/firefly-iii/issues/1000), reported by [xpfgsyb](https://github.com/xpfgsyb) | ||||
| - [Issue 1001](https://github.com/firefly-iii/firefly-iii/issues/1001), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 1002](https://github.com/firefly-iii/firefly-iii/issues/1002), reported by [ursweiss](https://github.com/ursweiss) | ||||
| - [Issue 1003](https://github.com/firefly-iii/firefly-iii/issues/1003), reported by [ursweiss](https://github.com/ursweiss) | ||||
| - [Issue 1004](https://github.com/firefly-iii/firefly-iii/issues/1004), reported by [Aquariu](https://github.com/Aquariu) | ||||
| - [Issue 1010](https://github.com/firefly-iii/firefly-iii/issues/1010) | ||||
| - [Issue 1014](https://github.com/firefly-iii/firefly-iii/issues/1014), reported by [ursweiss](https://github.com/ursweiss) | ||||
| - [Issue 1016](https://github.com/firefly-iii/firefly-iii/issues/1016) | ||||
| - [Issue 1024](https://github.com/firefly-iii/firefly-iii/issues/1024), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 1025](https://github.com/firefly-iii/firefly-iii/issues/1025), reported by [gavu](https://github.com/gavu) | ||||
|  | ||||
|  | ||||
| ## [4.6.10] - 2017-11-xx | ||||
| ### Added | ||||
| - Greatly expanded Docker support thanks to [alazare619](https://github.com/alazare619) | ||||
| - [Issue 967](https://github.com/firefly-iii/firefly-iii/issues/967), thanks to [Aquariu](https://github.com/Aquariu) | ||||
|  | ||||
| ### Changed | ||||
| - Improved Sandstorm support. | ||||
|  | ||||
| ### Fixed | ||||
| - [Issue 963](https://github.com/firefly-iii/firefly-iii/issues/963), as reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 970](https://github.com/firefly-iii/firefly-iii/issues/970), as reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 971](https://github.com/firefly-iii/firefly-iii/issues/971), as reported by [gavu](https://github.com/gavu) | ||||
| - Various Sandstorm.io related issues. | ||||
|  | ||||
| ## [4.6.9] - 2017-10-22 | ||||
| ### Added | ||||
| - Firefly III is now available on the [Sandstorm.io](https://apps.sandstorm.io/app/uws252ya9mep4t77tevn85333xzsgrpgth8q4y1rhknn1hammw70) market. | ||||
| - Issue template | ||||
| - Pull request template | ||||
| - Clean up routine to remove double budget limits (see [issue 932](https://github.com/firefly-iii/firefly-iii/issues/932)) | ||||
|  | ||||
| ### Changed | ||||
| - Changed license to GPLv3. | ||||
|  | ||||
| ### Fixed | ||||
| - [Issue 895](https://github.com/firefly-iii/firefly-iii/issues/895), as reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 902](https://github.com/firefly-iii/firefly-iii/issues/902), as reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 916](https://github.com/firefly-iii/firefly-iii/issues/916), as reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 942](https://github.com/firefly-iii/firefly-iii/issues/942), as reported by [pkoziol](https://github.com/pkoziol) | ||||
| - [Issue 943](https://github.com/firefly-iii/firefly-iii/issues/943), as reported by [aclex](https://github.com/aclex) | ||||
| - [Issue 944](https://github.com/firefly-iii/firefly-iii/issues/944), as reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 932](https://github.com/firefly-iii/firefly-iii/issues/932), as reported by [nicoschreiner](https://github.com/nicoschreiner) | ||||
| - [Issue 933](https://github.com/firefly-iii/firefly-iii/issues/933), as reported by [nicoschreiner](https://github.com/nicoschreiner) | ||||
|  | ||||
| ## [4.6.8] - 2017-10-15 | ||||
| ### Added | ||||
| - Verify routine will check if deposits have a budget (they shouldn't). | ||||
| - New translations! | ||||
|  | ||||
| ### Changed | ||||
| - Changed docker files for [issue 919](https://github.com/firefly-iii/firefly-iii/issues/919) and [issue 915](https://github.com/firefly-iii/firefly-iii/issues/915) | ||||
|  | ||||
| ### Fixed | ||||
| - [Issue 917](https://github.com/firefly-iii/firefly-iii/issues/917), as reported by [Wr0ngName](https://github.com/Wr0ngName) | ||||
| - Rules can no longer set a budget for a transfer or a deposit ([issue 916](https://github.com/firefly-iii/firefly-iii/issues/916)) | ||||
| - Fixed [issue 925](https://github.com/firefly-iii/firefly-iii/issues/925), [issue 928](https://github.com/firefly-iii/firefly-iii/issues/928) as reported by [dzaikos](https://github.com/dzaikos) and [DeltaKiloz](https://github.com/DeltaKiloz) | ||||
| - A fix for [issue 926](https://github.com/firefly-iii/firefly-iii/issues/926), as reported by [Aquariu](https://github.com/Aquariu) | ||||
|  | ||||
| ## [4.6.7] - 2017-10-09 | ||||
| ### Added | ||||
| - [Issue 872](https://github.com/firefly-iii/firefly-iii/issues/872), reported [gavu](https://github.com/gavu) | ||||
|  | ||||
| ### Fixed | ||||
| - [Issue 878](https://github.com/firefly-iii/firefly-iii/issues/878), fixed by [Findus23](https://github.com/Findus23) | ||||
| - [Issue 881](https://github.com/firefly-iii/firefly-iii/issues/881), reported by [nicoschreiner](https://github.com/nicoschreiner) | ||||
| - [Issue 884](https://github.com/firefly-iii/firefly-iii/issues/884), by [gavu](https://github.com/gavu) | ||||
| - [Issue 840](https://github.com/firefly-iii/firefly-iii/issues/840), reported by [MacPaille](https://github.com/MacPaille) | ||||
| - [Issue 882](https://github.com/firefly-iii/firefly-iii/issues/882), reported by [nicoschreiner](https://github.com/nicoschreiner) | ||||
| - [Issue 891](https://github.com/firefly-iii/firefly-iii/issues/891), [issue 892](https://github.com/firefly-iii/firefly-iii/issues/892), reported by [nicoschreiner](https://github.com/nicoschreiner) | ||||
| - [Issue 891](https://github.com/firefly-iii/firefly-iii/issues/891), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 827](https://github.com/firefly-iii/firefly-iii/issues/827), fixed by [pkoziol](https://github.com/pkoziol) | ||||
| - [Issue 903](https://github.com/firefly-iii/firefly-iii/issues/903), fixed by [hduijn](https://github.com/hduijn) | ||||
| - [Issue 904](https://github.com/firefly-iii/firefly-iii/issues/904), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 910](https://github.com/firefly-iii/firefly-iii/issues/910), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 911](https://github.com/firefly-iii/firefly-iii/issues/911), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 915](https://github.com/firefly-iii/firefly-iii/issues/915), reported by [TomWis97](https://github.com/TomWis97) | ||||
| - [Issue 917](https://github.com/firefly-iii/firefly-iii/issues/917), reported by [Wr0ngName](https://github.com/Wr0ngName) | ||||
|  | ||||
| ## [4.6.6] - 2017-09-30 | ||||
| ### Added | ||||
| - [Issue 826](https://github.com/firefly-iii/firefly-iii/issues/826), reported by [pkoziol](https://github.com/pkoziol). | ||||
| - [Issue 855](https://github.com/firefly-iii/firefly-iii/issues/855), by [ms32035](https://github.com/ms32035) | ||||
| - [Issue 786](https://github.com/firefly-iii/firefly-iii/issues/786), by [SmilingWorlock](https://github.com/SmilingWorlock) | ||||
| - [Issue 875](https://github.com/firefly-iii/firefly-iii/issues/875), by [gavu](https://github.com/gavu) | ||||
| - [Issue 834](https://github.com/firefly-iii/firefly-iii/issues/834), by [gavu](https://github.com/gavu) (and others) | ||||
|  | ||||
|  | ||||
| ### Changed | ||||
| - Upgraded to Laravel 5.5 | ||||
| - Add version parameter to CSS and JS files | ||||
| - [Issue 823](https://github.com/firefly-iii/firefly-iii/issues/823), [issue 824](https://github.com/firefly-iii/firefly-iii/issues/824) fixed Docker config by [DieBauer](https://github.com/DieBauer) | ||||
|  | ||||
| ### Fixed | ||||
| - [Issue 830](https://github.com/firefly-iii/firefly-iii/issues/830) | ||||
| - [Issue 822](https://github.com/firefly-iii/firefly-iii/issues/822), reported by [gazben](https://github.com/gazben) | ||||
| - [Issue 827](https://github.com/firefly-iii/firefly-iii/issues/827), reported by [pkoziol](https://github.com/pkoziol) | ||||
| - [Issue 835](https://github.com/firefly-iii/firefly-iii/issues/835), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 836](https://github.com/firefly-iii/firefly-iii/issues/836), reported by [pkoziol](https://github.com/pkoziol) | ||||
| - [Issue 838](https://github.com/firefly-iii/firefly-iii/issues/838), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 839](https://github.com/firefly-iii/firefly-iii/issues/839), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 843](https://github.com/firefly-iii/firefly-iii/issues/843), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 837](https://github.com/firefly-iii/firefly-iii/issues/837), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 845](https://github.com/firefly-iii/firefly-iii/issues/845), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 846](https://github.com/firefly-iii/firefly-iii/issues/846), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 848](https://github.com/firefly-iii/firefly-iii/issues/848), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 854](https://github.com/firefly-iii/firefly-iii/issues/854), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 866](https://github.com/firefly-iii/firefly-iii/issues/866), reported by [pkoziol](https://github.com/pkoziol) | ||||
| - [Issue 847](https://github.com/firefly-iii/firefly-iii/issues/847), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 853](https://github.com/firefly-iii/firefly-iii/issues/853), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 857](https://github.com/firefly-iii/firefly-iii/issues/857), reported by [pkoziol](https://github.com/pkoziol) | ||||
| - [Issue 865](https://github.com/firefly-iii/firefly-iii/issues/865), reported by [simonsmiley](https://github.com/simonsmiley) | ||||
| - [Issue 826](https://github.com/firefly-iii/firefly-iii/issues/826), reported by [pkoziol](https://github.com/pkoziol) | ||||
| - [Issue 856](https://github.com/firefly-iii/firefly-iii/issues/856), reported by [ms32035](https://github.com/ms32035) | ||||
| - [Issue 860](https://github.com/firefly-iii/firefly-iii/issues/860), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 861](https://github.com/firefly-iii/firefly-iii/issues/861), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 870](https://github.com/firefly-iii/firefly-iii/issues/870), reported by [gavu](https://github.com/gavu) | ||||
|  | ||||
| ## [4.6.5] - 2017-09-09 | ||||
|  | ||||
| ### Added | ||||
| - [Issue 616](https://github.com/firefly-iii/firefly-iii/issues/616), The ability to link transactions | ||||
| - [Issue 763](https://github.com/firefly-iii/firefly-iii/issues/763), as suggested by [tannie](https://github.com/tannie) | ||||
| - [Issue 770](https://github.com/firefly-iii/firefly-iii/issues/770), as suggested by [skibbipl](https://github.com/skibbipl) | ||||
| - [Issue 780](https://github.com/firefly-iii/firefly-iii/issues/780), as suggested by [skibbipl](https://github.com/skibbipl) | ||||
| - [Issue 784](https://github.com/firefly-iii/firefly-iii/issues/784), as suggested by [SmilingWorlock](https://github.com/SmilingWorlock) | ||||
| - Lots of code for future support of automated Bunq imports | ||||
|  | ||||
| ### Changed | ||||
| - Rewrote the export routine | ||||
| - [Issue 782](https://github.com/firefly-iii/firefly-iii/issues/782), as suggested by [NiceGuyIT](https://github.com/NiceGuyIT) | ||||
| - [Issue 800](https://github.com/firefly-iii/firefly-iii/issues/800), as suggested by [jleeong](https://github.com/jleeong) | ||||
|  | ||||
| ### Fixed | ||||
| - [Issue 724](https://github.com/firefly-iii/firefly-iii/issues/724), reported by [skibbipl](https://github.com/skibbipl) | ||||
| - [Issue 738](https://github.com/firefly-iii/firefly-iii/issues/738), reported by [skibbipl](https://github.com/skibbipl) | ||||
| - [Issue 760](https://github.com/firefly-iii/firefly-iii/issues/760), reported by [leander091](https://github.com/leander091) | ||||
| - [Issue 764](https://github.com/firefly-iii/firefly-iii/issues/764), reported by [tannie](https://github.com/tannie) | ||||
| - [Issue 792](https://github.com/firefly-iii/firefly-iii/issues/792), reported by [jleeong](https://github.com/jleeong) | ||||
| - [Issue 793](https://github.com/firefly-iii/firefly-iii/issues/793), reported by [nicoschreiner](https://github.com/nicoschreiner) | ||||
| - [Issue 797](https://github.com/firefly-iii/firefly-iii/issues/797), reported by [leander091](https://github.com/leander091) | ||||
| - [Issue 801](https://github.com/firefly-iii/firefly-iii/issues/801), reported by [pkoziol](https://github.com/pkoziol) | ||||
| - [Issue 803](https://github.com/firefly-iii/firefly-iii/issues/803), reported by [pkoziol](https://github.com/pkoziol) | ||||
| - [Issue 805](https://github.com/firefly-iii/firefly-iii/issues/805), reported by [pkoziol](https://github.com/pkoziol) | ||||
| - [Issue 806](https://github.com/firefly-iii/firefly-iii/issues/806), reported by [pkoziol](https://github.com/pkoziol) | ||||
| - [Issue 807](https://github.com/firefly-iii/firefly-iii/issues/807), reported by [pkoziol](https://github.com/pkoziol) | ||||
| - [Issue 808](https://github.com/firefly-iii/firefly-iii/issues/808), reported by [pkoziol](https://github.com/pkoziol) | ||||
| - [Issue 809](https://github.com/firefly-iii/firefly-iii/issues/809), reported by [pkoziol](https://github.com/pkoziol) | ||||
| - [Issue 814](https://github.com/firefly-iii/firefly-iii/issues/814), reported by [nicoschreiner](https://github.com/nicoschreiner) | ||||
| - [Issue 818](https://github.com/firefly-iii/firefly-iii/issues/818), reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 819](https://github.com/firefly-iii/firefly-iii/issues/819), reported by [DieBauer](https://github.com/DieBauer) | ||||
| - [Issue 820](https://github.com/firefly-iii/firefly-iii/issues/820), reported by [simonsmiley](https://github.com/simonsmiley)  | ||||
| - Various other fixes | ||||
|  | ||||
|  | ||||
| ## [4.6.4] - 2017-08-13 | ||||
| ### Added | ||||
| - PHP7.1 support | ||||
| - Routine to decrypt attachments from the command line, for [issue 671](https://github.com/firefly-iii/firefly-iii/issues/671) | ||||
| - A routine that can check if your password has been stolen in the past. | ||||
| - Split transaction shows amount left to be split | ||||
|  | ||||
|  | ||||
| ### Changed | ||||
| - Importer can (potentially) handle new import routines such as banks. | ||||
| - Importer can fall back from JSON errors  | ||||
|  | ||||
| ### Removed | ||||
| - PHP7.0 support | ||||
| - Support for extended tag modes | ||||
| - Remove "time jumps" to non-empty periods | ||||
|  | ||||
|  | ||||
| ### Fixed | ||||
| - [Issue 717](https://github.com/firefly-iii/firefly-iii/issues/717), reported by [NiceGuyIT](https://github.com/NiceGuyIT) | ||||
| - [Issue 718](https://github.com/firefly-iii/firefly-iii/issues/718), reported by [wtercato](https://github.com/wtercato) | ||||
| - [Issue 722](https://github.com/firefly-iii/firefly-iii/issues/722), reported by [simonsmiley](https://github.com/simonsmiley) | ||||
| - [Issue 648](https://github.com/firefly-iii/firefly-iii/issues/648), reported by [skibbipl](https://github.com/skibbipl) | ||||
| - [Issue 730](https://github.com/firefly-iii/firefly-iii/issues/730), reported by [ragnarkarlsson](https://github.com/ragnarkarlsson) | ||||
| - [Issue 733](https://github.com/firefly-iii/firefly-iii/issues/733), reported by [xpfgsyb](https://github.com/xpfgsyb) | ||||
| - [Issue 735](https://github.com/firefly-iii/firefly-iii/issues/735), reported by [kristophr](https://github.com/kristophr) | ||||
| - [Issue 739](https://github.com/firefly-iii/firefly-iii/issues/739), reported by [skibbipl](https://github.com/skibbipl) | ||||
| - [Issue 515](https://github.com/firefly-iii/firefly-iii/issues/515), reported by [schwalberich](https://github.com/schwalberich) | ||||
| - [Issue 743](https://github.com/firefly-iii/firefly-iii/issues/743), reported by [simonsmiley](https://github.com/simonsmiley) | ||||
| - [Issue 746](https://github.com/firefly-iii/firefly-iii/issues/746), reported by [tannie](https://github.com/tannie) | ||||
| - [Issue 747](https://github.com/firefly-iii/firefly-iii/issues/747), reported by [tannie](https://github.com/tannie) | ||||
|  | ||||
|  | ||||
| ## [4.6.3.1] - 2017-07-23 | ||||
| ### Fixed | ||||
| - Hotfix to close [issue 715](https://github.com/firefly-iii/firefly-iii/issues/715) | ||||
|  | ||||
| ## [4.6.3] - 2017-07-23 | ||||
|  | ||||
| This will be the last release to support PHP 7.0. | ||||
|  | ||||
| ### Added | ||||
| - New guidelines and new introduction tour to aid new users. | ||||
| - Rules can now be applied at will to transactions, not just rule groups. | ||||
|  | ||||
| ### Changed | ||||
| - Improved category overview. | ||||
| - Improved budget overview. | ||||
| - Improved budget report. | ||||
| - Improved command line import responsiveness and speed. | ||||
| - All code comparisons are now strict. | ||||
| - Improve search page. | ||||
| - Charts are easier to read thanks to [simonsmiley](https://github.com/simonsmiley) | ||||
| - Fixed [issue 708](https://github.com/firefly-iii/firefly-iii/issues/708). | ||||
|  | ||||
| ### Fixed | ||||
| - Fixed bug where import would not respect default account. [issue 694](https://github.com/firefly-iii/firefly-iii/issues/694) | ||||
| - Fixed various broken paths | ||||
| - Fixed several import inconsistencies. | ||||
| - Various bug fixes. | ||||
|  | ||||
| ## [4.6.2] - 2017-07-08 | ||||
| ### Added | ||||
| - Links added to boxes, idea by [simonsmiley](https://github.com/simonsmiley) | ||||
|  | ||||
| ### Fixed | ||||
| - Various bugs in import routine | ||||
|  | ||||
| ## [4.6.1] - 2017-07-02 | ||||
| ### Fixed | ||||
| - Fixed several small issues all around. | ||||
|  | ||||
| ## [4.6.0] - 2017-06-28 | ||||
|  | ||||
| ### Changed | ||||
| - Revamped import routine. Will be buggy. | ||||
|  | ||||
| ### Fixed | ||||
| - [Issue 667](https://github.com/firefly-iii/firefly-iii/issues/667), postgresql reported by [skibbipl](https://github.com/skibbipl). | ||||
| - [Issue 680](https://github.com/firefly-iii/firefly-iii/issues/680), fixed by [Xeli](https://github.com/Xeli) | ||||
| - Fixed [issue 660](https://github.com/firefly-iii/firefly-iii/issues/660) | ||||
| - Fixes [issue 672](https://github.com/firefly-iii/firefly-iii/issues/672), reported by [dzaikos](https://github.com/dzaikos) | ||||
| - Fix a bug where the balance routine forgot to account for accounts without a currency preference. | ||||
| - Various other bugfixes. | ||||
|  | ||||
| ## [4.5.0] - 2017-06-07 | ||||
|  | ||||
| ### Added | ||||
| - Better support for multi-currency transactions and display of transactions, accounts and everything. This requires a database overhaul (moving the currency information to specific transactions) so be careful when upgrading. | ||||
| - Translations for Spanish and Slovenian. | ||||
| - New interface for budget page, ~~stolen from~~ inspired by YNAB. | ||||
| - Expanded Docker to work with postgresql as well, thanks to [kressh](https://github.com/kressh) | ||||
|  | ||||
| ### Fixed | ||||
| - PostgreSQL support in database upgrade routine ([issue 644](https://github.com/firefly-iii/firefly-iii/issues/644), reported by [skibbipl](https://github.com/skibbipl)) | ||||
| - Frontpage budget chart was off, fix by [nhaarman](https://github.com/nhaarman) | ||||
| - Was not possible to remove opening balance. | ||||
|  | ||||
| ## [4.4.3] - 2017-05-03 | ||||
| ### Added | ||||
| - Added support for Slovenian | ||||
| - Removed support for Spanish. No translations whatsoever by the guy who requested it. | ||||
| - Removed support for Russian. Same thing. | ||||
| - Removed support for Croatian. Same thing. | ||||
| - Removed support for Chinese Traditional, Hong Kong. Same thing. | ||||
|  | ||||
| ### Changed | ||||
| - The journal collector, an internal piece of code to collect transactions, now uses a slightly different method of collecting journals. This may cause problems. | ||||
|  | ||||
| ### Fixed | ||||
| - [Issue 638](https://github.com/firefly-iii/firefly-iii/issues/638) as reported by [worldworm](https://github.com/worldworm). | ||||
| - Possible fix for [issue 624](https://github.com/firefly-iii/firefly-iii/issues/624) | ||||
|  | ||||
| ## [4.4.2] - 2017-04-27 | ||||
| ### Fixed | ||||
| - Fixed a bug where the opening balance could not be stored. | ||||
|  | ||||
| ## [4.4.1] - 2017-04-27 | ||||
|  | ||||
| ### Added | ||||
| - Support for deployment on Heroku | ||||
|  | ||||
| ### Fixed | ||||
| - Bug in new-user routine. | ||||
|  | ||||
| ## [4.4.0] - 2017-04-23 | ||||
| ### Added | ||||
| - Firefly III can now handle foreign currencies better, including some code to get the exchange rate live from the web. | ||||
| - Can now make rules for attachments, see [issue 608](https://github.com/firefly-iii/firefly-iii/issues/608), as suggested by [dzaikos](https://github.com/dzaikos). | ||||
|  | ||||
| ### Fixed | ||||
| - Fixed [issue 629](https://github.com/firefly-iii/firefly-iii/issues/629), reported by @forcaeluz | ||||
| - Fixed [issue 630](https://github.com/firefly-iii/firefly-iii/issues/630), reported by @welbert | ||||
| - And more various bug fixes. | ||||
|  | ||||
| ## [4.3.8] - 2017-04-08 | ||||
|  | ||||
| ### Added | ||||
| - Better overview / show pages. | ||||
| - [Issue 628](https://github.com/firefly-iii/firefly-iii/issues/628), as reported by [xzaz](https://github.com/xzaz). | ||||
| - Greatly expanded test coverage | ||||
|  | ||||
| ### Fixed | ||||
| - [Issue 619](https://github.com/firefly-iii/firefly-iii/issues/619), as reported by [dfiel](https://github.com/dfiel). | ||||
| - [Issue 620](https://github.com/firefly-iii/firefly-iii/issues/620), as reported by [forcaeluz](https://github.com/forcaeluz). | ||||
| - Attempt to fix [issue 624](https://github.com/firefly-iii/firefly-iii/issues/624), as reported by [TheSerenin](https://github.com/TheSerenin). | ||||
| - Favicon link is relative now, fixed by [welbert](https://github.com/welbert). | ||||
| - Some search bugs | ||||
|  | ||||
| ## [4.3.7] - 2017-03-06 | ||||
| ### Added | ||||
| - Nice user friendly views for empty lists. | ||||
| - Extended contribution guidelines. | ||||
| - First version of financial report filtered on tags. | ||||
| - Suggested monthly savings for piggy banks, by [Zsub](https://github.com/Zsub) | ||||
| - Better test coverage. | ||||
|  | ||||
| ### Changed | ||||
| - Slightly changed tag overview. | ||||
| - Consistent icon for bill in list. | ||||
| - Slightly changed account overview. | ||||
|  | ||||
| ### Removed | ||||
| - Removed IDE specific views from .gitignore, [issue 598](https://github.com/firefly-iii/firefly-iii/issues/598) | ||||
|  | ||||
| ### Fixed | ||||
| - Force key generation during installation. | ||||
| - The `date` function takes the fieldname where a date is stored, not the literal date by [Zsub](https://github.com/Zsub) | ||||
| - Improved budget frontpage chart, as suggested by [skibbipl](https://github.com/skibbipl) | ||||
| - [Issue 602](https://github.com/firefly-iii/firefly-iii/issues/602) and [issue 607](https://github.com/firefly-iii/firefly-iii/issues/607), as reported by [skibbipl](https://github.com/skibbipl) and [dzaikos](https://github.com/dzaikos). | ||||
| - [Issue 605](https://github.com/firefly-iii/firefly-iii/issues/605), as reported by [Zsub](https://github.com/Zsub). | ||||
| - [Issue 599](https://github.com/firefly-iii/firefly-iii/issues/599), as reported by [leander091](https://github.com/leander091). | ||||
| - [Issue 610](https://github.com/firefly-iii/firefly-iii/issues/610), as reported by [skibbipl](https://github.com/skibbipl). | ||||
| - [Issue 611](https://github.com/firefly-iii/firefly-iii/issues/611), as reported by [ragnarkarlsson](https://github.com/ragnarkarlsson). | ||||
| - [Issue 612](https://github.com/firefly-iii/firefly-iii/issues/612), as reported by [ragnarkarlsson](https://github.com/ragnarkarlsson). | ||||
| - [Issue 614](https://github.com/firefly-iii/firefly-iii/issues/614), as reported by [worldworm](https://github.com/worldworm). | ||||
| - Various other bug fixes. | ||||
|  | ||||
| ## [4.3.6] - 2017-02-20 | ||||
| ### Fixed | ||||
| - [Issue 578](https://github.com/firefly-iii/firefly-iii/issues/578), reported by [xpfgsyb](https://github.com/xpfgsyb). | ||||
|  | ||||
| ## [4.3.5] - 2017-02-19 | ||||
| ### Added | ||||
| - Beta support for Sandstorm.IO | ||||
| - Docker support by [schoentoon](https://github.com/schoentoon), [elohmeier](https://github.com/elohmeier), [patrickkostjens](https://github.com/patrickkostjens) and [crash7](https://github.com/crash7)! | ||||
| - Can now use special keywords in the search to search for specic dates, categories, etc. | ||||
|  | ||||
| ### Changed | ||||
| - Updated to laravel 5.4! | ||||
| - User friendly error message | ||||
| - Updated locales to support more operating systems, first reported in [issue 536](https://github.com/firefly-iii/firefly-iii/issues/536) by [dabenzel](https://github.com/dabenzel) | ||||
| - Updated budget report | ||||
| - Improved 404 page | ||||
| - Smooth curves, improved by [elamperti](https://github.com/elamperti). | ||||
|  | ||||
| ### Fixed | ||||
| - [Issue 549](https://github.com/firefly-iii/firefly-iii/issues/549) | ||||
| - [Issue 553](https://github.com/firefly-iii/firefly-iii/issues/553) | ||||
| - Fixed [issue 559](https://github.com/firefly-iii/firefly-iii/issues/559) reported by [elamperti](https://github.com/elamperti). | ||||
| - [Issue 565](https://github.com/firefly-iii/firefly-iii/issues/565), as reported by a user over the mail | ||||
| - [Issue 566](https://github.com/firefly-iii/firefly-iii/issues/566), as reported by [dspeckmann](https://github.com/dspeckmann) | ||||
| - [Issue 567](https://github.com/firefly-iii/firefly-iii/issues/567), as reported by [winsomniak](https://github.com/winsomniak) | ||||
| - [Issue 569](https://github.com/firefly-iii/firefly-iii/issues/569), as reported by [winsomniak](https://github.com/winsomniak) | ||||
| - [Issue 572](https://github.com/firefly-iii/firefly-iii/issues/572), as reported by [zjean](https://github.com/zjean) | ||||
| - Many issues with the transaction filters which will fix reports (they tended to display the wrong amount). | ||||
|  | ||||
| ## [4.3.4] - 2017-02-02 | ||||
| ### Fixed | ||||
| - Fixed bug [issue 550](https://github.com/firefly-iii/firefly-iii/issues/550), reported by [worldworm](https://github.com/worldworm)! | ||||
| - Fixed bug [issue 551](https://github.com/firefly-iii/firefly-iii/issues/551), reported by [t-me](https://github.com/t-me)! | ||||
|  | ||||
| ## [4.3.3] - 2017-01-30 | ||||
|  | ||||
| _The 100th release of Firefly!_ | ||||
|  | ||||
| ### Added | ||||
| - Add locales to Docker ([issue 534](https://github.com/firefly-iii/firefly-iii/issues/534)) by [elohmeier](https://github.com/elohmeier). | ||||
| - Optional database encryption. On by default. | ||||
| - Datepicker for Firefox and other browsers. | ||||
| - New instruction block for updating and installing. | ||||
| - Ability to clone transactions. | ||||
| - Use multi-select Bootstrap thing instead of massive lists of checkboxes. | ||||
|  | ||||
| ### Removed | ||||
| - Lots of old Javascript | ||||
|  | ||||
| ### Fixed | ||||
| - Missing sort broke various charts | ||||
| - Bug in reports that made amounts behave weird | ||||
| - Various bug fixes | ||||
|  | ||||
| ### Security | ||||
| - Tested FF against the naughty string list. | ||||
|  | ||||
| ## [4.3.2] - 2017-01-09 | ||||
|  | ||||
| An intermediate release because something in the Twig and Twigbridge libraries is broken and I have to make sure it doesn't affect you guys. But some cool features were on their way so there's that oo. | ||||
|  | ||||
| ### Added | ||||
| - Some code for [issue 475](https://github.com/firefly-iii/firefly-iii/issues/475), consistent overviews. | ||||
| - Better currency display. Make sure you have locale packages installed. | ||||
|  | ||||
| ### Changed | ||||
| - Uses a new version of Laravel. | ||||
|  | ||||
| ### Fixed | ||||
| - The password reset routine was broken. | ||||
| - [Issue 522](https://github.com/firefly-iii/firefly-iii/issues/522), thanks to [xpfgsyb](https://github.com/xpfgsyb) | ||||
| - [Issue 524](https://github.com/firefly-iii/firefly-iii/issues/524), thanks to [worldworm](https://github.com/worldworm) | ||||
| - [Issue 526](https://github.com/firefly-iii/firefly-iii/issues/526), thanks to [worldworm](https://github.com/worldworm) | ||||
| - [Issue 528](https://github.com/firefly-iii/firefly-iii/issues/528), thanks to [skibbipl](https://github.com/skibbipl) | ||||
| - Various other fixes. | ||||
|  | ||||
| ## [4.3.1] - 2017-01-04 | ||||
| ### Added | ||||
| - Support for Russian and Polish.  | ||||
| - Support for a proper demo website. | ||||
| - Support for custom decimal places in currencies ([issue 506](https://github.com/firefly-iii/firefly-iii/issues/506), suggested by [xpfgsyb](https://github.com/xpfgsyb)). | ||||
| - Most amounts are now right-aligned ([issue 511](https://github.com/firefly-iii/firefly-iii/issues/511), suggested by [xpfgsyb](https://github.com/xpfgsyb)). | ||||
| - German is now a "complete" language, more than 75% translated! | ||||
|  | ||||
| ### Changed | ||||
| - **[New Github repository!](github.com/firefly-iii/firefly-iii)** | ||||
| - Better category overview. | ||||
| - [Issue 502](https://github.com/firefly-iii/firefly-iii/issues/502), thanks to [zjean](https://github.com/zjean) | ||||
|  | ||||
| ### Removed | ||||
| - Removed a lot of administration functions. | ||||
| - Removed ability to activate users. | ||||
|  | ||||
| ### Fixed | ||||
| - [Issue 501](https://github.com/firefly-iii/firefly-iii/issues/501), thanks to [zjean](https://github.com/zjean) | ||||
| - [Issue 513](https://github.com/firefly-iii/firefly-iii/issues/513), thanks to [skibbipl](https://github.com/skibbipl)  | ||||
|  | ||||
| ### Security | ||||
| - [Issue 519](https://github.com/firefly-iii/firefly-iii/issues/519), thanks to [xpfgsyb](https://github.com/xpfgsyb) | ||||
|  | ||||
| ## [4.3.0] - 2016-12-26 | ||||
| ### Added | ||||
| - New method of keeping track of available budget, see [issue 489](https://github.com/firefly-iii/firefly-iii/issues/489) | ||||
| - Support for Spanish | ||||
| - Firefly III now has an extended demo mode. Will expand further in the future. | ||||
|   | ||||
|  | ||||
| ### Changed | ||||
| - New favicon | ||||
| - Import routine no longer gives transactions a description [issue 483](https://github.com/firefly-iii/firefly-iii/issues/483) | ||||
|  | ||||
|  | ||||
| ### Removed | ||||
| - All test data generation code. | ||||
|  | ||||
| ### Fixed | ||||
| - Removed import accounts from search results [issue 478](https://github.com/firefly-iii/firefly-iii/issues/478) | ||||
| - Redirect after delete will no longer go back to deleted item [issue 477](https://github.com/firefly-iii/firefly-iii/issues/477) | ||||
| - Cannot math [issue 482](https://github.com/firefly-iii/firefly-iii/issues/482) | ||||
| - Fixed bug in virtual balance field [issue 479](https://github.com/firefly-iii/firefly-iii/issues/479) | ||||
|  | ||||
| ## [4.2.2] - 2016-12-18 | ||||
| ### Added | ||||
| - New budget report (still a bit of a beta) | ||||
| - Can now edit user | ||||
|  | ||||
| ### Changed | ||||
| - New config for specific events. Still need to build Notifications. | ||||
|  | ||||
| ### Fixed | ||||
| - Various bugs | ||||
| - [Issue 472](https://github.com/firefly-iii/firefly-iii/issues/472) thanks to [zjean](https://github.com/zjean) | ||||
|  | ||||
| ## [4.2.1] - 2016-12-09 | ||||
| ### Added | ||||
| - BIC support (see [issue 430](https://github.com/firefly-iii/firefly-iii/issues/430)) | ||||
| - New category report section and chart (see the general financial report) | ||||
|  | ||||
|  | ||||
| ### Changed | ||||
| - Date range picker now also available on mobile devices (see [issue 435](https://github.com/firefly-iii/firefly-iii/issues/435)) | ||||
| - Extended range of amounts for [issue 439](https://github.com/firefly-iii/firefly-iii/issues/439) | ||||
| - Rewrote all routes. Old bookmarks may break. | ||||
|  | ||||
| ## [4.2.0] - 2016-11-27 | ||||
| ### Added | ||||
| - Lots of (empty) tests | ||||
| - Expanded transaction lists ([issue 377](https://github.com/firefly-iii/firefly-iii/issues/377)) | ||||
| - New charts at account view | ||||
| - First code for [issue 305](https://github.com/firefly-iii/firefly-iii/issues/305) | ||||
|  | ||||
|  | ||||
| ### Changed | ||||
| - Updated all email messages. | ||||
| - Made some fonts local | ||||
|  | ||||
| ### Fixed | ||||
| - [Issue 408](https://github.com/firefly-iii/firefly-iii/issues/408) | ||||
| - Various issues with split journals | ||||
| - [Issue 414](https://github.com/firefly-iii/firefly-iii/issues/414), thx [zjean](https://github.com/zjean) | ||||
| - [Issue 419](https://github.com/firefly-iii/firefly-iii/issues/419), thx [schwalberich](https://github.com/schwalberich)  | ||||
| - [Issue 422](https://github.com/firefly-iii/firefly-iii/issues/422), thx [xzaz](https://github.com/xzaz) | ||||
| - Various import bugs, such as [issue 416](https://github.com/firefly-iii/firefly-iii/issues/416) ([zjean](https://github.com/zjean)) | ||||
|  | ||||
| ## [4.1.7] - 2016-11-19 | ||||
| ### Added | ||||
| - Check for database table presence in console commands. | ||||
| - Category report | ||||
| - Reinstated old test routines. | ||||
|  | ||||
|  | ||||
| ### Changed | ||||
| - Confirm account setting is no longer in `.env` file. | ||||
| - Titles are now in reverse (current page > parent > firefly iii) | ||||
| - Easier update of language files thanks to Github implementation. | ||||
| - Uniform colours for charts. | ||||
|  | ||||
| ### Fixed | ||||
| - Made all pages more mobile friendly. | ||||
| - Fixed [issue 395](https://github.com/firefly-iii/firefly-iii/issues/395) found by [marcoveeneman](https://github.com/marcoveeneman). | ||||
| - Fixed [issue 398](https://github.com/firefly-iii/firefly-iii/issues/398) found by [marcoveeneman](https://github.com/marcoveeneman). | ||||
| - Fixed [issue 401](https://github.com/firefly-iii/firefly-iii/issues/401) found by [marcoveeneman](https://github.com/marcoveeneman). | ||||
| - Many optimizations. | ||||
| - Updated many libraries. | ||||
| - Various bugs found by myself. | ||||
|  | ||||
|  | ||||
| ## [4.1.6] - 2016-11-06 | ||||
| ### Added | ||||
| - New budget table for multi year report. | ||||
|  | ||||
| ### Changed | ||||
| - Greatly expanded help pages and their function. | ||||
| - Built a new transaction collector, which I think was the idea of [roberthorlings](https://github.com/roberthorlings) originally. | ||||
| - Rebuilt seach engine. | ||||
|  | ||||
| ### Fixed | ||||
| - [Issue 375](https://github.com/firefly-iii/firefly-iii/issues/375), thanks to [schoentoon](https://github.com/schoentoon) which made it impossible to resurrect currencies. | ||||
| - [Issue 370](https://github.com/firefly-iii/firefly-iii/issues/370) thanks to [ksmolder](https://github.com/ksmolder) | ||||
| - [Issue 378](https://github.com/firefly-iii/firefly-iii/issues/378), thanks to [HomelessAvatar](https://github.com/HomelessAvatar) | ||||
|  | ||||
| ## [4.1.5] - 2016-11-01 | ||||
| ### Changed | ||||
| - Report parts are loaded using AJAX, making a lot of code more simple. | ||||
| - Help content will fall back to English. | ||||
| - Help content is translated through Crowdin. | ||||
|  | ||||
| ### Fixed | ||||
| - [Issue 370](https://github.com/firefly-iii/firefly-iii/issues/370) | ||||
|  | ||||
| ## [4.1.4] - 2016-10-30 | ||||
| ### Added | ||||
| - New Dockerfile thanks to [schoentoon](https://github.com/schoentoon) | ||||
| - Added changing the destination account as rule action. | ||||
| - Added changing the source account as rule action. | ||||
| - Can convert transactions into different types. | ||||
|  | ||||
| ### Changed | ||||
| - Changed the export routine to be more future-proof. | ||||
| - Improved help routine. | ||||
| - Integrated CrowdIn translations. | ||||
| - Simplified reports | ||||
| - Change error message to refer to solution. | ||||
|  | ||||
| ### Fixed | ||||
| - [Issue 367](https://github.com/firefly-iii/firefly-iii/issues/367) thanks to [HungryFeline](https://github.com/HungryFeline) | ||||
| - [Issue 366](https://github.com/firefly-iii/firefly-iii/issues/366) thanks to [3mz3t](https://github.com/3mz3t) | ||||
| - [Issue 362](https://github.com/firefly-iii/firefly-iii/issues/362) and [issue 341](https://github.com/firefly-iii/firefly-iii/issues/341) thanks to [bnw](https://github.com/bnw) | ||||
| - [Issue 355](https://github.com/firefly-iii/firefly-iii/issues/355) thanks to [roberthorlings](https://github.com/roberthorlings) | ||||
|  | ||||
| ## [4.1.3] - 2016-10-22 | ||||
| ### Fixed | ||||
| - Some event handlers called the wrong method. | ||||
|  | ||||
| ## [4.1.2] - 2016-10-22 | ||||
|  | ||||
| ### Fixed | ||||
| - A bug is fixed in the journal event handler that prevented Firefly III from actually storing journals. | ||||
|  | ||||
| ## [4.1.1] - 2016-10-22 | ||||
|  | ||||
| ### Added | ||||
| - Option to show deposit accounts on the front page. | ||||
| - Script to upgrade split transactions | ||||
| - Can now save notes on piggy banks. | ||||
| - Extend user admin options. | ||||
| - Run import jobs from the command line | ||||
|  | ||||
|  | ||||
| ### Changed | ||||
| - New preferences screen layout. | ||||
|  | ||||
| ### Deprecated | ||||
| - ``firefly:import`` is now ``firefly:start-import`` | ||||
|  | ||||
| ### Removed | ||||
| - Lots of old code | ||||
|  | ||||
| ### Fixed | ||||
| - [Issue 357](https://github.com/firefly-iii/firefly-iii/issues/357), where non utf-8 files would break Firefly. | ||||
| - Tab delimiter is not properly loaded from import configuration ([roberthorlings](https://github.com/roberthorlings)) | ||||
| - System response to yearly bills | ||||
|  | ||||
| ## [4.0.2] - 2016-10-14 | ||||
| ### Added | ||||
| - Added ``intl`` dependency to composer file to ease installation (thanks [telyn](https://github.com/telyn)) | ||||
| - Added support for Croatian. | ||||
|  | ||||
| ### Changed | ||||
| - Updated all copyright notices to refer to the [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/) | ||||
| - Fixed [issue 344](https://github.com/firefly-iii/firefly-iii/issues/344) | ||||
| - Fixed [issue 346](https://github.com/firefly-iii/firefly-iii/issues/346), thanks to [SanderKleykens](https://github.com/SanderKleykens) | ||||
| - [Issue 351](https://github.com/firefly-iii/firefly-iii/issues/351) | ||||
| - Did some internal remodelling. | ||||
|  | ||||
| ### Fixed | ||||
| - PostgreSQL compatibility thanks to [SanderKleykens](https://github.com/SanderKleykens) | ||||
| - [roberthorlings](https://github.com/roberthorlings) fixed a bug in the ABN Amro import specific. | ||||
|  | ||||
|  | ||||
| ## [4.0.1] - 2016-10-04 | ||||
| ### Added | ||||
| - New ING import specific by [tomwerf](https://github.com/tomwerf) | ||||
| - New Presidents Choice specific to fix [issue 307](https://github.com/firefly-iii/firefly-iii/issues/307) | ||||
| - Added some trimming ([issue 335](https://github.com/firefly-iii/firefly-iii/issues/335)) | ||||
|  | ||||
| ### Fixed | ||||
| - Fixed a bug where incoming transactions would not be properly filtered in several reports. | ||||
| - [Issue 334](https://github.com/firefly-iii/firefly-iii/issues/334) by [cyberkov](https://github.com/cyberkov) | ||||
| - [Issue 337](https://github.com/firefly-iii/firefly-iii/issues/337) | ||||
| - [Issue 336](https://github.com/firefly-iii/firefly-iii/issues/336) | ||||
| - [Issue 338](https://github.com/firefly-iii/firefly-iii/issues/338) found by [roberthorlings](https://github.com/roberthorlings) | ||||
|  | ||||
| ## [4.0.0] - 2016-09-26 | ||||
| ### Added | ||||
| - Upgraded to Laravel 5.3, most other libraries upgraded as well. | ||||
| - Added GBP as currency, thanks to [Mortalife](https://github.com/Mortalife) | ||||
|  | ||||
| ### Changed | ||||
| - Jump to version 4.0.0. | ||||
| - Firefly III is now subject to a [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/) license. Previous versions of this software are still MIT licensed. | ||||
|  | ||||
| ### Fixed | ||||
| - Support for specific decimal places, thanks to [Mortalife](https://github.com/Mortalife) | ||||
| - Various CSS fixes | ||||
| - Various bugs, thanks to [fuf](https://github.com/fuf), [sandermulders](https://github.com/sandermulders) and [vissert](https://github.com/vissert) | ||||
| - Various queries optimized for MySQL 5.7 | ||||
|  | ||||
| ## [3.10.4] - 2016-09-14 | ||||
| ### Fixed | ||||
| - Migration fix by [sandermulders](https://github.com/sandermulders) | ||||
| - Tricky import bug fix thanks to [vissert](https://github.com/vissert) | ||||
| - Currency preference will be correctly pulled from user settings, thanks to [fuf](https://github.com/fuf) | ||||
| - Simplified code for upgrade instructions. | ||||
|  | ||||
|  | ||||
| ## [3.10.3] - 2016-08-29 | ||||
| ### Added | ||||
| - More fields for mass-edit, thanks to [vissert](https://github.com/vissert) ([issue 282](https://github.com/firefly-iii/firefly-iii/issues/282)) | ||||
| - First start of German translation | ||||
|  | ||||
| ### Changed | ||||
| - More optional fields for transactions and the ability to filter them. | ||||
|  | ||||
| ### Removed | ||||
| - Preference for budget maximum. | ||||
|  | ||||
| ### Fixed | ||||
| - A bug in the translation routine broke the import. | ||||
| - It was possible to destroy your Firefly installation by removing all currencies. Thanks [mondjef](https://github.com/mondjef) | ||||
| - Translation bugs. | ||||
| - Import bug. | ||||
|  | ||||
| ### Security | ||||
| - Firefly will not accept registrations beyond the first one, by default. | ||||
|  | ||||
|  | ||||
| ## [3.10.2] - 2016-08-29 | ||||
| ### Added | ||||
| - New Chinese translations. Set Firefly III to show incomplete translations to follow the progress. Want to translate Firefly III in Chinese, or in any other language? Then check out [the Crowdin project](https://crowdin.com/project/firefly-iii). | ||||
| - Added more admin pages. They do nothing yet. | ||||
|  | ||||
| ### Changed | ||||
| - Import routine will now also apply user rules. | ||||
| - Various code cleanup. | ||||
| - Some small HTML changes. | ||||
|  | ||||
| ### Fixed | ||||
| - Bug in the mass edit routines. | ||||
| - Firefly III over a proxy will now work (see [issue 290](https://github.com/firefly-iii/firefly-iii/issues/290), thanks [dfiel](https://github.com/dfiel) for reporting. | ||||
| - Sneaky bug in the import routine, fixed by [Bonno](https://github.com/Bonno)  | ||||
|  | ||||
| ## [3.10.1] - 2016-08-25 | ||||
| ### Added | ||||
| - More feedback in the import procedure. | ||||
| - Extended model for import job. | ||||
| - Web bases import procedure. | ||||
|  | ||||
|  | ||||
| ### Changed | ||||
| - Scrutinizer configuration | ||||
| - Various code clean up. | ||||
|  | ||||
| ### Removed | ||||
| - Code climate YAML file. | ||||
|  | ||||
| ### Fixed | ||||
| - Fixed a bug where a migration would check an empty table name. | ||||
| - Fixed various bugs in the import routine. | ||||
| - Fixed various bugs in the piggy banks pages. | ||||
| - Fixed a bug in the `firefly:verify` routine | ||||
|  | ||||
| ## [3.10] - 2016-08-12 | ||||
| ### Added | ||||
| - New charts in year report | ||||
| - Can add / remove money from piggy bank on mobile device. | ||||
| - Bill overview shows some useful things. | ||||
| - Firefly will track registration / activation IP addresses. | ||||
|  | ||||
|  | ||||
| ### Changed | ||||
| - Rewrote the import routine. | ||||
| - The date picker now supports more ranges and periods. | ||||
| - Rewrote all migrations. [issue 272](https://github.com/firefly-iii/firefly-iii/issues/272) | ||||
|  | ||||
| ### Fixed | ||||
| - [Issue 264](https://github.com/firefly-iii/firefly-iii/issues/264) | ||||
| - [Issue 265](https://github.com/firefly-iii/firefly-iii/issues/265) | ||||
| - Fixed amount calculation problems, [issue 266](https://github.com/firefly-iii/firefly-iii/issues/266), thanks [xzaz](https://github.com/xzaz) | ||||
| - [Issue 271](https://github.com/firefly-iii/firefly-iii/issues/271) | ||||
| - [Issue 278](https://github.com/firefly-iii/firefly-iii/issues/278), [issue 273](https://github.com/firefly-iii/firefly-iii/issues/273), thanks [StevenReitsma](https://github.com/StevenReitsma) and [rubella](https://github.com/rubella) | ||||
| - Bug in attachment download routine would report the wrong size to the user's browser. | ||||
| - Various NULL errors fixed. | ||||
| - Various strict typing errors fixed. | ||||
| - Fixed pagination problems, [issue 276](https://github.com/firefly-iii/firefly-iii/issues/276), thanks [xzaz](https://github.com/xzaz) | ||||
| - Fixed a bug where an expense would be assigned to a piggy bank if you created a transfer first. | ||||
| - Bulk update problems, [issue 280](https://github.com/firefly-iii/firefly-iii/issues/280), thanks [stickgrinder](https://github.com/stickgrinder) | ||||
| - Fixed various problems with amount reporting of split transactions. | ||||
|  | ||||
| ## [3.9.1] - 2016-06-06 | ||||
| ### Fixed | ||||
| - Fixed a bug where removing money from a piggy bank would not work. See [issue 265](https://github.com/firefly-iii/firefly-iii/issues/265) and [issue 269](https://github.com/firefly-iii/firefly-iii/issues/269) | ||||
|  | ||||
| ## [3.9.0] - 2016-05-22 | ||||
| ### Added | ||||
| - [zjean](https://github.com/zjean) has added code that allows you to force "https://"-URL's. | ||||
| - [tonicospinelli](https://github.com/tonicospinelli) has added Portuguese (Brazil) translations. | ||||
| - Firefly III supports the *splitting* of transactions: | ||||
|   - A withdrawal (expense) can be split into multiple sub-transactions (with multiple destinations) | ||||
|   - Likewise for deposits (incomes). You can set multiple sources. | ||||
|   - Likewise for transfers. | ||||
|  | ||||
| ### Changed | ||||
| - Update a lot of libraries. | ||||
| - Big improvement to test data generation. | ||||
| - Cleaned up many repositories. | ||||
|  | ||||
| ### Removed | ||||
| - Front page boxes will no longer respond to credit card bills. | ||||
|  | ||||
| ### Fixed | ||||
| - Many bugs | ||||
|  | ||||
| ## [3.8.4] - 2016-04-24 | ||||
| ### Added | ||||
| - Lots of new translations. | ||||
| - Can now set page size. | ||||
| - Can now mass edit transactions. | ||||
| - Can now mass delete transactions. | ||||
| - Firefly will now attempt to verify the integrity of your database when updating. | ||||
|  | ||||
| ### Changed | ||||
| - New version of Charts library. | ||||
|  | ||||
| ### Fixed | ||||
| - Several CSV related bugs. | ||||
| - Several other bugs. | ||||
| - Bugs fixed by [Bonno](https://github.com/Bonno). | ||||
|  | ||||
| ## [3.8.3] - 2016-04-17 | ||||
| ### Added | ||||
| - New audit report to see what happened. | ||||
|  | ||||
| ### Changed | ||||
| - New Chart JS release used. | ||||
| - Help function is more reliable. | ||||
|  | ||||
| ### Fixed | ||||
| - Expected bill amount is now correct. | ||||
| - Upgrade will now invalidate cache. | ||||
| - Search was broken. | ||||
| - Queries run better | ||||
|  | ||||
| ## [3.8.2] - 2016-04-03 | ||||
| ### Added | ||||
| - Small user administration at /admin. | ||||
| - Informational popups are working in reports. | ||||
|  | ||||
| ### Changed | ||||
| - User activation emails are better | ||||
|  | ||||
| ### Fixed | ||||
| - Some bugs related to accounts and rules. | ||||
|  | ||||
|  | ||||
| ## [3.8.1] - 2016-03-29 | ||||
| ### Added | ||||
| - More translations | ||||
| - Extended cookie control. | ||||
| - User accounts can now be activated (disabled by default). | ||||
| - Bills can now take the source and destination account name into account. | ||||
|  | ||||
| ### Changed | ||||
| - The pages related to rules have new URL's. | ||||
|  | ||||
| ### Fixed | ||||
| - Spelling errors. | ||||
| - Problems related to the "account repository". | ||||
| - Some views showed empty (0.0) amounts. | ||||
|  | ||||
| ## [3.8.0] - 2016-03-20 | ||||
| ### Added | ||||
| - Two factor authentication, thanks to the excellent work of [zjean](https://github.com/zjean). | ||||
| - A new chart showing your net worth in year and multi-year reports. | ||||
| - You can now see if your current or future rules actually match any transactions, thanks to the excellent work of [roberthorlings](https://github.com/roberthorlings). | ||||
| - New date fields for transactions. They are not used yet in reports or anything, but they can be filled in. | ||||
| - New routine to export your data. | ||||
| - Firefly III will mail the site owner when blocked users try to login, or when blocked domains are used in registrations. | ||||
|  | ||||
|  | ||||
| ### Changed | ||||
| - Firefly III now requires PHP 7.0 minimum. | ||||
|  | ||||
|  | ||||
| ### Fixed | ||||
| - HTML fixes, thanks to [roberthorlings](https://github.com/roberthorlings) and [zjean](https://github.com/zjean).. | ||||
| - A bug fix in the ABN Amro importer, thanks to [roberthorlings](https://github.com/roberthorlings) | ||||
| - It was not possible to change the opening balance, once it had been set. Thanks to [xnyhps](https://github.com/xnyhps) and [marcoveeneman](https://github.com/marcoveeneman) for spotting this. | ||||
| - Various other bug fixes. | ||||
|  | ||||
|  | ||||
|  | ||||
| ## [3.4.2] - 2015-05-25 | ||||
| ### Added | ||||
| - Initial release. | ||||
|  | ||||
| ### Changed | ||||
| - Initial release. | ||||
|  | ||||
| ### Deprecated | ||||
| - Initial release. | ||||
|  | ||||
| ### Removed | ||||
| - Initial release. | ||||
|  | ||||
| ### Fixed | ||||
| - Initial release. | ||||
|  | ||||
| ### Security | ||||
| - Initial release. | ||||
							
								
								
									
										86
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										86
									
								
								Dockerfile
									
									
									
									
									
								
							| @@ -1,52 +1,56 @@ | ||||
| FROM php:7.1-apache | ||||
| FROM php:7.2-apache | ||||
|  | ||||
| RUN apt-get update -y && \ | ||||
|     apt-get install -y --no-install-recommends libcurl4-openssl-dev \ | ||||
|                                                zlib1g-dev \ | ||||
|                                                libjpeg62-turbo-dev \ | ||||
|                                                libpng12-dev \ | ||||
|                                                libicu-dev \ | ||||
|                                                libedit-dev \ | ||||
|                                                libtidy-dev \ | ||||
|                                                libxml2-dev \ | ||||
|                                                libsqlite3-dev \ | ||||
|                                                libpq-dev \ | ||||
|                                                libbz2-dev \ | ||||
|                                                gettext-base \ | ||||
|                                                locales && \ | ||||
|     apt-get clean && \ | ||||
|     rm -rf /var/lib/apt/lists/* | ||||
| ENV FIREFLY_PATH=/var/www/firefly-iii COMPOSER_ALLOW_SUPERUSER=1 | ||||
| LABEL version="1.4" maintainer="thegrumpydictator@gmail.com" | ||||
|  | ||||
| RUN docker-php-ext-install -j$(nproc) curl gd intl json readline tidy zip bcmath xml mbstring pdo_sqlite pdo_mysql bz2 pdo_pgsql | ||||
| # Create volumes | ||||
| VOLUME $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload | ||||
|  | ||||
| # Generate locales supported by firefly | ||||
| RUN echo "en_US.UTF-8 UTF-8\nde_DE.UTF-8 UTF-8\nnl_NL.UTF-8 UTF-8\npt_BR.UTF-8 UTF-8" > /etc/locale.gen && locale-gen | ||||
|  | ||||
| COPY ./docker/apache2.conf /etc/apache2/apache2.conf | ||||
|  | ||||
| # Enable apache mod rewrite.. | ||||
| RUN a2enmod rewrite | ||||
|  | ||||
| # Enable apache mod ssl.. | ||||
| RUN a2enmod ssl | ||||
|  | ||||
| # Setup the Composer installer | ||||
| RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer | ||||
|  | ||||
| # Copy Apache Configs | ||||
| COPY ./docker/apache-firefly.conf /etc/apache2/sites-available/000-default.conf | ||||
|  | ||||
| ENV FIREFLY_PATH /var/www/firefly-iii | ||||
| # Install some stuff | ||||
| RUN apt-get update && apt-get install -y libpng-dev \ | ||||
|                                             libicu-dev \ | ||||
|                                             unzip \ | ||||
|                                             gettext-base \ | ||||
|                                             libldap2-dev \ | ||||
|                                             libpq-dev \ | ||||
|                                             locales \ | ||||
|                                             libmemcached-dev && \ | ||||
|                                             apt-get clean && \ | ||||
|                                             rm -rf /var/lib/apt/lists/* | ||||
|  | ||||
| # Copy in Firefly III source | ||||
| WORKDIR $FIREFLY_PATH | ||||
| ADD . $FIREFLY_PATH | ||||
|  | ||||
| # The working directory | ||||
| COPY . $FIREFLY_PATH | ||||
| # copy ca certs to correct location | ||||
| COPY ./.deploy/docker/cacert.pem /usr/local/ssl/cert.pem | ||||
|  | ||||
| RUN chown -R www-data:www-data /var/www && chmod -R 775 $FIREFLY_PATH/storage | ||||
| # copy Apache config to correct spot. | ||||
| COPY ./.deploy/docker/apache2.conf /etc/apache2/apache2.conf | ||||
|  | ||||
| RUN composer install --prefer-dist --no-dev --no-scripts | ||||
| # Enable default site (Firefly III) | ||||
| COPY ./.deploy/docker/apache-firefly.conf /etc/apache2/sites-available/000-default.conf | ||||
|  | ||||
| # Run a lot of installation commands: | ||||
| RUN chown -R www-data:www-data /var/www && \ | ||||
|     chmod -R 775 $FIREFLY_PATH/storage && \ | ||||
|     a2enmod rewrite && a2enmod ssl && \ | ||||
|     docker-php-ext-configure ldap --with-libdir=lib/$(gcc -dumpmachine)/ && \ | ||||
|     docker-php-ext-install -j$(nproc) zip bcmath ldap gd pdo_pgsql pdo_mysql intl opcache && \ | ||||
|     pecl install memcached-3.1.3 && \ | ||||
|     docker-php-ext-enable memcached && \ | ||||
|     curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer && \ | ||||
|     echo "de_DE.UTF-8 UTF-8\nen_US.UTF-8 UTF-8\nes_ES.UTF-8 UTF-8\nfr_FR.UTF-8 UTF-8\nid_ID.UTF-8 UTF-8\nit_IT.UTF-8 UTF-8\nnl_NL.UTF-8 UTF-8\npl_PL.UTF-8 UTF-8\npt_BR.UTF-8 UTF-8\nru_RU.UTF-8 UTF-8\ntr_TR.UTF-8 UTF-8\nzh_TW.UTF-8 UTF-8\nzh_CN.UTF-8 UTF-8\n\n" > /etc/locale.gen && \ | ||||
|     locale-gen && \ | ||||
|     composer install --prefer-dist --no-dev --no-scripts --no-suggest | ||||
|  | ||||
| # configure PHP | ||||
| RUN cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini && \ | ||||
|     sed -i 's/max_execution_time = 30/max_execution_time = 600/' /usr/local/etc/php/php.ini && \ | ||||
|     sed -i 's/memory_limit = 128M/memory_limit = 512M/' /usr/local/etc/php/php.ini | ||||
|  | ||||
| # Expose port 80 | ||||
| EXPOSE 80 | ||||
|  | ||||
| ENTRYPOINT ["docker/entrypoint.sh"] | ||||
| # Run entrypoint thing | ||||
| ENTRYPOINT [".deploy/docker/entrypoint.sh"] | ||||
|   | ||||
							
								
								
									
										57
									
								
								Dockerfile.amd64
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								Dockerfile.amd64
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| FROM php:7.2-apache | ||||
| ARG ARCH | ||||
| ENV FIREFLY_PATH=/var/www/firefly-iii COMPOSER_ALLOW_SUPERUSER=1 | ||||
| LABEL version="1.4" maintainer="thegrumpydictator@gmail.com" | ||||
|  | ||||
| # Create volumes | ||||
| VOLUME $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload | ||||
|  | ||||
| # Install some stuff | ||||
| RUN apt-get update && apt-get install -y libpng-dev \ | ||||
|                                             libicu-dev \ | ||||
|                                             unzip \ | ||||
|                                             gettext-base \ | ||||
|                                             libldap2-dev \ | ||||
|                                             libpq-dev \ | ||||
|                                             locales \ | ||||
|                                             libmemcached-dev && \ | ||||
|                                             apt-get clean && \ | ||||
|                                             rm -rf /var/lib/apt/lists/* | ||||
|  | ||||
| # Copy in Firefly III source | ||||
| WORKDIR $FIREFLY_PATH | ||||
| ADD . $FIREFLY_PATH | ||||
|  | ||||
| # copy ca certs to correct location | ||||
| COPY ./.deploy/docker/cacert.pem /usr/local/ssl/cert.pem | ||||
|  | ||||
| # copy Apache config to correct spot. | ||||
| COPY ./.deploy/docker/apache2.conf /etc/apache2/apache2.conf | ||||
|  | ||||
| # Enable default site (Firefly III) | ||||
| COPY ./.deploy/docker/apache-firefly.conf /etc/apache2/sites-available/000-default.conf | ||||
|  | ||||
| # Run a lot of installation commands: | ||||
| RUN chown -R www-data:www-data /var/www && \ | ||||
|     chmod -R 775 $FIREFLY_PATH/storage && \ | ||||
|     a2enmod rewrite && a2enmod ssl && \ | ||||
|     docker-php-ext-configure ldap --with-libdir=lib/$(gcc -dumpmachine)/ && \ | ||||
|     docker-php-ext-install -j$(nproc) zip bcmath ldap gd pdo_pgsql pdo_mysql intl opcache && \ | ||||
|     pecl install memcached-3.1.3 && \ | ||||
|     docker-php-ext-enable memcached && \ | ||||
|     curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer && \ | ||||
|     echo "de_DE.UTF-8 UTF-8\nen_US.UTF-8 UTF-8\nes_ES.UTF-8 UTF-8\nfr_FR.UTF-8 UTF-8\nid_ID.UTF-8 UTF-8\nit_IT.UTF-8 UTF-8\nnl_NL.UTF-8 UTF-8\npl_PL.UTF-8 UTF-8\npt_BR.UTF-8 UTF-8\nru_RU.UTF-8 UTF-8\ntr_TR.UTF-8 UTF-8\nzh_TW.UTF-8 UTF-8\nzh_CN.UTF-8 UTF-8\n\n" > /etc/locale.gen && \ | ||||
|     locale-gen && \ | ||||
|     composer install --prefer-dist --no-dev --no-scripts --no-suggest | ||||
|  | ||||
| # configure PHP | ||||
| RUN cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini && \ | ||||
|     sed -i 's/max_execution_time = 30/max_execution_time = 600/' /usr/local/etc/php/php.ini && \ | ||||
|     sed -i 's/memory_limit = 128M/memory_limit = 512M/' /usr/local/etc/php/php.ini | ||||
|  | ||||
|  | ||||
| # Expose port 80 | ||||
| EXPOSE 80 | ||||
|  | ||||
| # Run entrypoint thing | ||||
| ENTRYPOINT [".deploy/docker/entrypoint.sh"] | ||||
							
								
								
									
										56
									
								
								Dockerfile.arm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								Dockerfile.arm
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| FROM arm32v7/php:7.2.8-apache-stretch | ||||
| ARG ARCH | ||||
| COPY tmp/qemu-arm-static /usr/bin/qemu-arm-static | ||||
| ENV FIREFLY_PATH=/var/www/firefly-iii COMPOSER_ALLOW_SUPERUSER=1 | ||||
| LABEL version="1.4" maintainer="thegrumpydictator@gmail.com" | ||||
|  | ||||
| # Create volumes | ||||
| VOLUME $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload | ||||
|  | ||||
| # Install some stuff | ||||
| RUN apt-get update && apt-get install -y libpng-dev \ | ||||
|                                             libicu-dev \ | ||||
|                                             unzip \ | ||||
|                                             gettext-base \ | ||||
|                                             libldap2-dev \ | ||||
|                                             libpq-dev \ | ||||
|                                             locales \ | ||||
|                                             libmemcached-dev | ||||
|  | ||||
| # Copy in Firefly III source | ||||
| WORKDIR $FIREFLY_PATH | ||||
| ADD . $FIREFLY_PATH | ||||
|  | ||||
| # copy ca certs to correct location | ||||
| COPY ./.deploy/docker/cacert.pem /usr/local/ssl/cert.pem | ||||
|  | ||||
| # copy Apache config to correct spot. | ||||
| COPY ./.deploy/docker/apache2.conf /etc/apache2/apache2.conf | ||||
|  | ||||
| # Enable default site (Firefly III) | ||||
| COPY ./.deploy/docker/apache-firefly.conf /etc/apache2/sites-available/000-default.conf | ||||
|  | ||||
| # Run a lot of installation commands: | ||||
| RUN chown -R www-data:www-data /var/www && \ | ||||
|     chmod -R 775 $FIREFLY_PATH/storage && \ | ||||
|     a2enmod rewrite && a2enmod ssl && \ | ||||
|     docker-php-ext-configure ldap --with-libdir=lib/$(gcc -dumpmachine)/ && \ | ||||
|     docker-php-ext-install -j$(nproc) zip bcmath ldap gd pdo_pgsql pdo_mysql intl opcache && \ | ||||
|     pecl install memcached-3.1.3 && \ | ||||
|     docker-php-ext-enable memcached && \ | ||||
|     curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer && \ | ||||
|     echo "de_DE.UTF-8 UTF-8\nen_US.UTF-8 UTF-8\nes_ES.UTF-8 UTF-8\nfr_FR.UTF-8 UTF-8\nid_ID.UTF-8 UTF-8\nit_IT.UTF-8 UTF-8\nnl_NL.UTF-8 UTF-8\npl_PL.UTF-8 UTF-8\npt_BR.UTF-8 UTF-8\nru_RU.UTF-8 UTF-8\ntr_TR.UTF-8 UTF-8\nzh_TW.UTF-8 UTF-8\nzh_CN.UTF-8 UTF-8\n\n" > /etc/locale.gen && \ | ||||
|     locale-gen && \ | ||||
|     composer install --prefer-dist --no-dev --no-scripts --no-suggest | ||||
|  | ||||
| # configure PHP | ||||
| RUN cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini && \ | ||||
|     sed -i 's/max_execution_time = 30/max_execution_time = 600/' /usr/local/etc/php/php.ini && \ | ||||
|     sed -i 's/memory_limit = 128M/memory_limit = 512M/' /usr/local/etc/php/php.ini | ||||
|  | ||||
|  | ||||
| # Expose port 80 | ||||
| EXPOSE 80 | ||||
|  | ||||
| # Run entrypoint thing | ||||
| ENTRYPOINT [".deploy/docker/entrypoint.sh"] | ||||
							
								
								
									
										56
									
								
								Dockerfile.arm64
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								Dockerfile.arm64
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| FROM arm32v7/php:7.2.8-apache-stretch | ||||
| ARG ARCH | ||||
| COPY tmp/qemu-arm-static /usr/bin/qemu-arm-static | ||||
| ENV FIREFLY_PATH=/var/www/firefly-iii COMPOSER_ALLOW_SUPERUSER=1 | ||||
| LABEL version="1.4" maintainer="thegrumpydictator@gmail.com" | ||||
|  | ||||
| # Create volumes | ||||
| VOLUME $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload | ||||
|  | ||||
| # Install some stuff | ||||
| RUN apt-get update && apt-get install -y libpng-dev \ | ||||
|                                             libicu-dev \ | ||||
|                                             unzip \ | ||||
|                                             gettext-base \ | ||||
|                                             libldap2-dev \ | ||||
|                                             libpq-dev \ | ||||
|                                             locales \ | ||||
|                                             libmemcached-dev | ||||
|  | ||||
| # Copy in Firefly III source | ||||
| WORKDIR $FIREFLY_PATH | ||||
| ADD . $FIREFLY_PATH | ||||
|  | ||||
| # copy ca certs to correct location | ||||
| COPY ./.deploy/docker/cacert.pem /usr/local/ssl/cert.pem | ||||
|  | ||||
| # copy Apache config to correct spot. | ||||
| COPY ./.deploy/docker/apache2.conf /etc/apache2/apache2.conf | ||||
|  | ||||
| # Enable default site (Firefly III) | ||||
| COPY ./.deploy/docker/apache-firefly.conf /etc/apache2/sites-available/000-default.conf | ||||
|  | ||||
| # Run a lot of installation commands: | ||||
| RUN chown -R www-data:www-data /var/www && \ | ||||
|     chmod -R 775 $FIREFLY_PATH/storage && \ | ||||
|     a2enmod rewrite && a2enmod ssl && \ | ||||
|     docker-php-ext-configure ldap --with-libdir=lib/$(gcc -dumpmachine)/ && \ | ||||
|     docker-php-ext-install -j$(nproc) zip bcmath ldap gd pdo_pgsql pdo_mysql intl opcache && \ | ||||
|     pecl install memcached-3.1.3 && \ | ||||
|     docker-php-ext-enable memcached && \ | ||||
|     curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer && \ | ||||
|     echo "de_DE.UTF-8 UTF-8\nen_US.UTF-8 UTF-8\nes_ES.UTF-8 UTF-8\nfr_FR.UTF-8 UTF-8\nid_ID.UTF-8 UTF-8\nit_IT.UTF-8 UTF-8\nnl_NL.UTF-8 UTF-8\npl_PL.UTF-8 UTF-8\npt_BR.UTF-8 UTF-8\nru_RU.UTF-8 UTF-8\ntr_TR.UTF-8 UTF-8\nzh_TW.UTF-8 UTF-8\nzh_CN.UTF-8 UTF-8\n\n" > /etc/locale.gen && \ | ||||
|     locale-gen && \ | ||||
|     composer install --prefer-dist --no-dev --no-scripts --no-suggest | ||||
|  | ||||
| # configure PHP | ||||
| RUN cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini && \ | ||||
|     sed -i 's/max_execution_time = 30/max_execution_time = 600/' /usr/local/etc/php/php.ini && \ | ||||
|     sed -i 's/memory_limit = 128M/memory_limit = 512M/' /usr/local/etc/php/php.ini | ||||
|  | ||||
|  | ||||
| # Expose port 80 | ||||
| EXPOSE 80 | ||||
|  | ||||
| # Run entrypoint thing | ||||
| ENTRYPOINT [".deploy/docker/entrypoint.sh"] | ||||
							
								
								
									
										81
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										81
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,81 +0,0 @@ | ||||
| # Firefly III: A personal finances manager  | ||||
|  | ||||
| [](https://secure.php.net/downloads.php) [](https://packagist.org/packages/grumpydictator/firefly-iii) [](https://www.gnu.org/licenses/gpl.html) [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=44UKUT455HUFA)  | ||||
|  | ||||
| [](https://i.nder.be/h327vx3y) [](https://i.nder.be/hkpynqr9) | ||||
|  | ||||
| [](https://i.nder.be/cwznmryd) [](https://i.nder.be/gum2qf8z) | ||||
|  | ||||
| "Firefly III" is a financial manager for your personal finances. It can help you keep track of your expenses and income. | ||||
| Firefly III supports the use of budgets. You can categorize and tag your transactions. | ||||
| It also supports credit cards, shared  household accounts and savings accounts. | ||||
| There are many financial reports available. | ||||
|  | ||||
| ## Want to try Firefly III? | ||||
|  | ||||
| There is a **[demo site](https://firefly-iii.nder.be)** with an example financial administration already present. You can use Docker, Heroku or Sandstorm.io (see below) to quickly setup your own instance. | ||||
|  | ||||
| ## Install Firefly III | ||||
|  | ||||
| ### Using docker | ||||
|  | ||||
| You can use docker-compose to [set up your personal secure](https://firefly-iii.github.io/using-docker.html) Firefly III environment. Advanced users can use the Dockerfile directly.  | ||||
|  | ||||
| ### Using vagrant (or other VMs) | ||||
|  | ||||
| You can install Firefly III on any Linux or Windows machine. You'll need a web server (preferrably on Linux) and access to the command line. Please read the [installation guide](https://firefly-iii.github.io/using-installing.html). | ||||
|  | ||||
| ### Using Heroku | ||||
|  | ||||
| [](https://heroku.com/deploy?template=https://github.com/firefly-iii/firefly-iii/tree/master) | ||||
|  | ||||
| Register for a free Heroku account and instantly run Firefly III on your very own cloud instance. | ||||
|  | ||||
| _My Heroku configuration is currently broken, but I'm trying to fix it._ | ||||
|  | ||||
| ### Using Sandstorm.io | ||||
|  | ||||
| You can find Firefly III in [the Sandstorm.io marketplace](https://apps.sandstorm.io/app/uws252ya9mep4t77tevn85333xzsgrpgth8q4y1rhknn1hammw70). You can run it on your own installation or on Oasis. | ||||
|  | ||||
| ## More about Firefly III | ||||
|  | ||||
| Personal financial management is pretty difficult, and everybody has their own approach to it. | ||||
| Some people make budgets, other people limit their cashflow by throwing away their credit cards,  | ||||
| others try to increase their current cashflow. There are tons of ways to save and earn money. | ||||
|  | ||||
| Firefly works on the principle that if you know where you're money is going, you can stop it from going there. | ||||
|  | ||||
| ### Some advantages of using Firefly | ||||
|  | ||||
| - Firefly can import any CSV file, so migrating from other systems is easy. | ||||
| - Firefly runs on your own server, so you are fully in control of your data. Remember, there is no such thing as "the cloud", it’s just somebody else’s computer! | ||||
| - Firefly has lots of features without being fancy or bloated. | ||||
| - If you feel you're missing something you can just ask me and I'll add it! | ||||
|  | ||||
| Firefly III has become pretty awesome over the years! (but please excuse me for bragging, it's just that I'm proud of it). | ||||
| [You can read more about Firefly III, and its features, on the Github Pages](https://firefly-iii.github.io/). | ||||
|  | ||||
| ### Contributing | ||||
|  | ||||
| Please read [CONTRIBUTING.md](https://github.com/firefly-iii/firefly-iii/blob/master/.github/CONTRIBUTING.md) for details on contributing, and the process for submitting pull requests. Please check out the [code of conduct](https://github.com/firefly-iii/firefly-iii/blob/master/CODE_OF_CONDUCT.md) as well. | ||||
|  | ||||
| ### Versioning | ||||
|  | ||||
| We use [SemVer](http://semver.org/) for versioning. For the versions available, see [the tags](https://github.com/firefly-iii/firefly-iii/tags) on this repository. | ||||
|  | ||||
| ### Authors | ||||
|  | ||||
| * James Cole | ||||
| * Over time, [many people have contributed to Firefly III](https://github.com/firefly-iii/firefly-iii/graphs/contributors). | ||||
|  | ||||
| ### License | ||||
|  | ||||
| This work [is licensed](https://github.com/firefly-iii/firefly-iii/blob/master/LICENSE) under the [GPL v3](https://www.gnu.org/licenses/gpl.html). | ||||
|  | ||||
| ### Other stuff | ||||
|  | ||||
| If you like Firefly and if it helps you save lots of money, why not send me [a dime for every dollar saved](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=44UKUT455HUFA) (this is a joke, although the Paypal form works just fine, try it!) | ||||
|  | ||||
| If you want to contact me, please open an issue or [email me](mailto:thegrumpydictator@gmail.com). | ||||
|  | ||||
| [](https://travis-ci.org/firefly-iii/firefly-iii) [](https://scrutinizer-ci.com/g/firefly-iii/firefly-iii/?branch=master) [](https://coveralls.io/github/firefly-iii/firefly-iii?branch=master) | ||||
							
								
								
									
										5
									
								
								app.json
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								app.json
									
									
									
									
									
								
							| @@ -2,7 +2,7 @@ | ||||
|   "name": "Firefly III", | ||||
|   "description": "A free and open source personal finances manager", | ||||
|   "repository": "https://github.com/firefly-iii/firefly-iii", | ||||
|   "website": "https://firefly-iii.github.io/", | ||||
|   "website": "https://firefly-iii.org/", | ||||
|   "logo": "https://raw.githubusercontent.com/firefly-iii/firefly-iii/master/public/mstile-150x150.png", | ||||
|   "keywords": [ | ||||
|     "finance", | ||||
| @@ -51,6 +51,9 @@ | ||||
|   "buildpacks": [ | ||||
|     { | ||||
|       "url": "heroku/php" | ||||
|     }, | ||||
|     { | ||||
|       "url": "https://github.com/heroku/heroku-buildpack-locale" | ||||
|     } | ||||
|   ], | ||||
|   "env": { | ||||
|   | ||||
							
								
								
									
										87
									
								
								app/Api/V1/Controllers/AboutController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								app/Api/V1/Controllers/AboutController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * AboutController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use DB; | ||||
| use FireflyIII\Transformers\UserTransformer; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Returns basic information about this installation. | ||||
|  * | ||||
|  * Class AboutController. | ||||
|  */ | ||||
| class AboutController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Returns system information. | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function about(): JsonResponse | ||||
|     { | ||||
|         $search        = ['~', '#']; | ||||
|         $replace       = ['\~', '# ']; | ||||
|         $phpVersion    = str_replace($search, $replace, PHP_VERSION); | ||||
|         $phpOs         = str_replace($search, $replace, PHP_OS); | ||||
|         $currentDriver = DB::getDriverName(); | ||||
|         $data | ||||
|                        = [ | ||||
|             'version'     => config('firefly.version'), | ||||
|             'api_version' => config('firefly.api_version'), | ||||
|             'php_version' => $phpVersion, | ||||
|             'os'          => $phpOs, | ||||
|             'driver'      => $currentDriver, | ||||
|         ]; | ||||
|  | ||||
|         return response()->json(['data' => $data])->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns information about the user. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function user(Request $request): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var UserTransformer $transformer */ | ||||
|         $transformer = app(UserTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item(auth()->user(), $transformer, 'users'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										309
									
								
								app/Api/V1/Controllers/AccountController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										309
									
								
								app/Api/V1/Controllers/AccountController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,309 @@ | ||||
| <?php | ||||
| /** | ||||
|  * AccountController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\AccountRequest; | ||||
| use FireflyIII\Helpers\Collector\TransactionCollectorInterface; | ||||
| use FireflyIII\Helpers\Filter\InternalTransferFilter; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\AccountFilter; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Transformers\AccountTransformer; | ||||
| use FireflyIII\Transformers\PiggyBankTransformer; | ||||
| use FireflyIII\Transformers\TransactionTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use Illuminate\Support\Collection; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class AccountController. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class AccountController extends Controller | ||||
| { | ||||
|     use AccountFilter, TransactionFilter; | ||||
|     /** @var AccountRepositoryInterface The account repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * AccountController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user = auth()->user(); | ||||
|                 // @var AccountRepositoryInterface repository | ||||
|                 $this->repository = app(AccountRepositoryInterface::class); | ||||
|                 $this->repository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param \FireflyIII\Models\Account $account | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(Account $account): JsonResponse | ||||
|     { | ||||
|         $this->repository->destroy($account, null); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // read type from URI | ||||
|         $type = $request->get('type') ?? 'all'; | ||||
|         $this->parameters->set('type', $type); | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $types    = $this->mapAccountTypes($this->parameters->get('type')); | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of accounts. Count it and split it. | ||||
|         $collection = $this->repository->getAccountsByType($types); | ||||
|         $count      = $collection->count(); | ||||
|         $accounts   = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.accounts.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var AccountTransformer $transformer */ | ||||
|         $transformer = app(AccountTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($accounts, $transformer, 'accounts'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * List all of them. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return JsonResponse] | ||||
|      */ | ||||
|     public function piggyBanks(Request $request, Account $account): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of budgets. Count it and split it. | ||||
|         $collection = $this->repository->getPiggyBanks($account); | ||||
|         $count      = $collection->count(); | ||||
|         $piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.accounts.piggy_banks', [$account->id]) . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var PiggyBankTransformer $transformer */ | ||||
|         $transformer = app(PiggyBankTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($piggyBanks, $transformer, 'piggy_banks'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show single instance. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, Account $account): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var AccountTransformer $transformer */ | ||||
|         $transformer = app(AccountTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|         $resource = new Item($account, $transformer, 'accounts'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a new instance. | ||||
|      * | ||||
|      * @param AccountRequest $request | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function store(AccountRequest $request): JsonResponse | ||||
|     { | ||||
|         $data    = $request->getAll(); | ||||
|         $account = $this->repository->store($data); | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var AccountTransformer $transformer */ | ||||
|         $transformer = app(AccountTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($account, $transformer, 'accounts'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show all transactions. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function transactions(Request $request, Account $account): JsonResponse | ||||
|     { | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $type     = $request->get('type') ?? 'default'; | ||||
|         $this->parameters->set('type', $type); | ||||
|  | ||||
|         // user can overrule page size with limit parameter. | ||||
|         $limit = $this->parameters->get('limit'); | ||||
|         if (null !== $limit && $limit > 0) { | ||||
|             $pageSize = $limit; | ||||
|         } | ||||
|  | ||||
|         $types   = $this->mapTransactionTypes($this->parameters->get('type')); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|  | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var User $admin */ | ||||
|         $admin = auth()->user(); | ||||
|         /** @var TransactionCollectorInterface $collector */ | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setUser($admin); | ||||
|         $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); | ||||
|         if ($this->repository->isAsset($account)) { | ||||
|             $collector->setAccounts(new Collection([$account])); | ||||
|         } | ||||
|         if (!$this->repository->isAsset($account)) { | ||||
|             $collector->setOpposingAccounts(new Collection([$account])); | ||||
|         } | ||||
|  | ||||
|         if (\in_array(TransactionType::TRANSFER, $types, true)) { | ||||
|             $collector->removeFilter(InternalTransferFilter::class); | ||||
|         } | ||||
|  | ||||
|         if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) { | ||||
|             $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); | ||||
|         } | ||||
|         $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); | ||||
|         $collector->setTypes($types); | ||||
|         $paginator = $collector->getPaginatedTransactions(); | ||||
|         $paginator->setPath(route('api.v1.accounts.transactions', [$account->id]) . $this->buildParams()); | ||||
|         $transactions = $paginator->getCollection(); | ||||
|  | ||||
|         /** @var TransactionTransformer $transformer */ | ||||
|         $transformer = app(TransactionTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($transactions, $transformer, 'transactions'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update account. | ||||
|      * | ||||
|      * @param AccountRequest $request | ||||
|      * @param Account        $account | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function update(AccountRequest $request, Account $account): JsonResponse | ||||
|     { | ||||
|         $data         = $request->getAll(); | ||||
|         $data['type'] = config('firefly.shortNamesByFullName.' . $account->accountType->type); | ||||
|         $this->repository->update($account, $data); | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var AccountTransformer $transformer */ | ||||
|         $transformer = app(AccountTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|         $resource = new Item($account, $transformer, 'accounts'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										249
									
								
								app/Api/V1/Controllers/AttachmentController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								app/Api/V1/Controllers/AttachmentController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,249 @@ | ||||
| <?php | ||||
| /** | ||||
|  * AttachmentController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\AttachmentRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Attachments\AttachmentHelperInterface; | ||||
| use FireflyIII\Models\Attachment; | ||||
| use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface; | ||||
| use FireflyIII\Transformers\AttachmentTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Http\Response as LaravelResponse; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class AttachmentController. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class AttachmentController extends Controller | ||||
| { | ||||
|     /** @var AttachmentRepositoryInterface The attachment repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * AccountController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user             = auth()->user(); | ||||
|                 $this->repository = app(AttachmentRepositoryInterface::class); | ||||
|                 $this->repository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param Attachment $attachment | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(Attachment $attachment): JsonResponse | ||||
|     { | ||||
|         $this->repository->destroy($attachment); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Download an attachment. | ||||
|      * | ||||
|      * @param Attachment $attachment | ||||
|      * | ||||
|      * @return LaravelResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function download(Attachment $attachment): LaravelResponse | ||||
|     { | ||||
|         if (false === $attachment->uploaded) { | ||||
|             throw new FireflyException('No file has been uploaded for this attachment (yet).'); | ||||
|         } | ||||
|         if ($this->repository->exists($attachment)) { | ||||
|             $content = $this->repository->getContent($attachment); | ||||
|             $quoted  = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\')); | ||||
|  | ||||
|             /** @var LaravelResponse $response */ | ||||
|             $response = response($content); | ||||
|             $response | ||||
|                 ->header('Content-Description', 'File Transfer') | ||||
|                 ->header('Content-Type', 'application/octet-stream') | ||||
|                 ->header('Content-Disposition', 'attachment; filename=' . $quoted) | ||||
|                 ->header('Content-Transfer-Encoding', 'binary') | ||||
|                 ->header('Connection', 'Keep-Alive') | ||||
|                 ->header('Expires', '0') | ||||
|                 ->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0') | ||||
|                 ->header('Pragma', 'public') | ||||
|                 ->header('Content-Length', \strlen($content)); | ||||
|  | ||||
|             return $response; | ||||
|         } | ||||
|         throw new FireflyException('Could not find the indicated attachment. The file is no longer there.'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of accounts. Count it and split it. | ||||
|         $collection  = $this->repository->get(); | ||||
|         $count       = $collection->count(); | ||||
|         $attachments = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.attachments.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var AttachmentTransformer $transformer */ | ||||
|         $transformer = app(AttachmentTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($attachments, $transformer, 'attachments'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param Request    $request | ||||
|      * @param Attachment $attachment | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, Attachment $attachment): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var AttachmentTransformer $transformer */ | ||||
|         $transformer = app(AttachmentTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($attachment, $transformer, 'attachments'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param AttachmentRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(AttachmentRequest $request): JsonResponse | ||||
|     { | ||||
|         $data       = $request->getAll(); | ||||
|         $attachment = $this->repository->store($data); | ||||
|         $manager    = new Manager; | ||||
|         $baseUrl    = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var AttachmentTransformer $transformer */ | ||||
|         $transformer = app(AttachmentTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($attachment, $transformer, 'attachments'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param AttachmentRequest $request | ||||
|      * @param Attachment        $attachment | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(AttachmentRequest $request, Attachment $attachment): JsonResponse | ||||
|     { | ||||
|         $data = $request->getAll(); | ||||
|         $this->repository->update($attachment, $data); | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var AttachmentTransformer $transformer */ | ||||
|         $transformer = app(AttachmentTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($attachment, $transformer, 'attachments'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Upload an attachment. | ||||
|      * | ||||
|      * @param Request    $request | ||||
|      * @param Attachment $attachment | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function upload(Request $request, Attachment $attachment): JsonResponse | ||||
|     { | ||||
|         /** @var AttachmentHelperInterface $helper */ | ||||
|         $helper = app(AttachmentHelperInterface::class); | ||||
|         $body   = $request->getContent(); | ||||
|         $helper->saveAttachmentFromApi($attachment, $body); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										231
									
								
								app/Api/V1/Controllers/AvailableBudgetController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								app/Api/V1/Controllers/AvailableBudgetController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,231 @@ | ||||
| <?php | ||||
| /** | ||||
|  * AvailableBudgetController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\AvailableBudgetRequest; | ||||
| use FireflyIII\Factory\TransactionCurrencyFactory; | ||||
| use FireflyIII\Models\AvailableBudget; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| use FireflyIII\Transformers\AvailableBudgetTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class AvailableBudgetController. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class AvailableBudgetController extends Controller | ||||
| { | ||||
|     /** @var BudgetRepositoryInterface The budget repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * AccountController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user             = auth()->user(); | ||||
|                 $this->repository = app(BudgetRepositoryInterface::class); | ||||
|                 $this->repository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param AvailableBudget $availableBudget | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(AvailableBudget $availableBudget): JsonResponse | ||||
|     { | ||||
|         $this->repository->destroyAvailableBudget($availableBudget); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of available budgets. Count it and split it. | ||||
|         $collection = $this->repository->getAvailableBudgets(); | ||||
|  | ||||
|         // filter list on start and end date, if present. | ||||
|         // TODO: put this in the query. | ||||
|         $start = $this->parameters->get('start'); | ||||
|         $end   = $this->parameters->get('end'); | ||||
|         if (null !== $start && null !== $end) { | ||||
|             $collection = $collection->filter( | ||||
|                 function (AvailableBudget $availableBudget) use ($start, $end) { | ||||
|                     return $availableBudget->start_date->gte($start) && $availableBudget->end_date->lte($end); | ||||
|                 } | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         $count            = $collection->count(); | ||||
|         $availableBudgets = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($availableBudgets, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.available_budgets.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var AvailableBudgetTransformer $transformer */ | ||||
|         $transformer = app(AvailableBudgetTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($availableBudgets, $transformer, 'available_budgets'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param Request          $request | ||||
|      * @param  AvailableBudget $availableBudget | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, AvailableBudget $availableBudget): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var AvailableBudgetTransformer $transformer */ | ||||
|         $transformer = app(AvailableBudgetTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($availableBudget, $transformer, 'available_budgets'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param AvailableBudgetRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function store(AvailableBudgetRequest $request): JsonResponse | ||||
|     { | ||||
|         $data = $request->getAll(); | ||||
|         /** @var TransactionCurrencyFactory $factory */ | ||||
|         $factory  = app(TransactionCurrencyFactory::class); | ||||
|         $currency = $factory->find($data['currency_id'], $data['currency_code']); | ||||
|  | ||||
|         if (null === $currency) { | ||||
|             $currency = app('amount')->getDefaultCurrency(); | ||||
|         } | ||||
|         $availableBudget = $this->repository->setAvailableBudget($currency, $data['start'], $data['end'], $data['amount']); | ||||
|         $manager         = new Manager; | ||||
|         $baseUrl         = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var AvailableBudgetTransformer $transformer */ | ||||
|         $transformer = app(AvailableBudgetTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($availableBudget, $transformer, 'available_budgets'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param AvailableBudgetRequest $request | ||||
|      * @param AvailableBudget        $availableBudget | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(AvailableBudgetRequest $request, AvailableBudget $availableBudget): JsonResponse | ||||
|     { | ||||
|         $data = $request->getAll(); | ||||
|  | ||||
|         /** @var TransactionCurrencyFactory $factory */ | ||||
|         $factory = app(TransactionCurrencyFactory::class); | ||||
|         /** @var TransactionCurrency $currency */ | ||||
|         $currency = $factory->find($data['currency_id'] ?? null, $data['currency_code'] ?? null); | ||||
|  | ||||
|         if (null === $currency) { | ||||
|             // use default currency: | ||||
|             $currency = app('amount')->getDefaultCurrency(); | ||||
|         } | ||||
|         $currency->enabled = true; | ||||
|         $currency->save(); | ||||
|         unset($data['currency_code']); | ||||
|         $data['currency_id'] = $currency->id; | ||||
|  | ||||
|  | ||||
|         $this->repository->updateAvailableBudget($availableBudget, $data); | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var AvailableBudgetTransformer $transformer */ | ||||
|         $transformer = app(AvailableBudgetTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($availableBudget, $transformer, 'available_budgets'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										321
									
								
								app/Api/V1/Controllers/BillController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										321
									
								
								app/Api/V1/Controllers/BillController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,321 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * BillController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\BillRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Collector\TransactionCollectorInterface; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Repositories\Bill\BillRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Transformers\AttachmentTransformer; | ||||
| use FireflyIII\Transformers\BillTransformer; | ||||
| use FireflyIII\Transformers\RuleTransformer; | ||||
| use FireflyIII\Transformers\TransactionTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use Illuminate\Support\Collection; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class BillController. | ||||
|  */ | ||||
| class BillController extends Controller | ||||
| { | ||||
|     use TransactionFilter; | ||||
|     /** @var BillRepositoryInterface The bill repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * BillController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $admin */ | ||||
|                 $admin = auth()->user(); | ||||
|  | ||||
|                 /** @var BillRepositoryInterface repository */ | ||||
|                 $this->repository = app(BillRepositoryInterface::class); | ||||
|                 $this->repository->setUser($admin); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * @param Bill    $bill | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function attachments(Request $request, Bill $bill): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $pageSize   = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $collection = $this->repository->getAttachments($bill); | ||||
|  | ||||
|         $count       = $collection->count(); | ||||
|         $attachments = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.bills.attachments', [$bill->id]) . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var AttachmentTransformer $transformer */ | ||||
|         $transformer = app(AttachmentTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($attachments, $transformer, 'attachments'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  Bill $bill | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(Bill $bill): JsonResponse | ||||
|     { | ||||
|         $this->repository->destroy($bill); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         $pageSize  = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $paginator = $this->repository->getPaginator($pageSize); | ||||
|         /** @var Collection $bills */ | ||||
|         $bills = $paginator->getCollection(); | ||||
|  | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var BillTransformer $transformer */ | ||||
|         $transformer = app(BillTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($bills, $transformer, 'bills'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List all of them. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * @param Bill    $bill | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function rules(Request $request, Bill $bill): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of budgets. Count it and split it. | ||||
|         $collection = $this->repository->getRulesForBill($bill); | ||||
|         $count      = $collection->count(); | ||||
|         $rules      = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.bills.rules', [$bill->id]) . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var RuleTransformer $transformer */ | ||||
|         $transformer = app(RuleTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|  | ||||
|         $resource = new FractalCollection($rules, $transformer, 'rules'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show the specified bill. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * @param Bill    $bill | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, Bill $bill): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var BillTransformer $transformer */ | ||||
|         $transformer = app(BillTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($bill, $transformer, 'bills'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a bill. | ||||
|      * | ||||
|      * @param BillRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(BillRequest $request): JsonResponse | ||||
|     { | ||||
|         $bill = $this->repository->store($request->getAll()); | ||||
|         if (null !== $bill) { | ||||
|             $manager = new Manager(); | ||||
|             $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|             $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|             /** @var BillTransformer $transformer */ | ||||
|             $transformer = app(BillTransformer::class); | ||||
|             $transformer->setParameters($this->parameters); | ||||
|  | ||||
|             $resource = new Item($bill, $transformer, 'bills'); | ||||
|  | ||||
|             return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         } | ||||
|         throw new FireflyException('Could not store new bill.'); // @codeCoverageIgnore | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show all transactions. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @param Bill    $bill | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function transactions(Request $request, Bill $bill): JsonResponse | ||||
|     { | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $type     = $request->get('type') ?? 'default'; | ||||
|         $this->parameters->set('type', $type); | ||||
|  | ||||
|         $types   = $this->mapTransactionTypes($this->parameters->get('type')); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var User $admin */ | ||||
|         $admin = auth()->user(); | ||||
|         /** @var TransactionCollectorInterface $collector */ | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setUser($admin); | ||||
|         $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); | ||||
|         $collector->setAllAssetAccounts(); | ||||
|         $collector->setBills(new Collection([$bill])); | ||||
|  | ||||
|         if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) { | ||||
|             $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); | ||||
|         } | ||||
|         $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); | ||||
|         $collector->setTypes($types); | ||||
|         $paginator = $collector->getPaginatedTransactions(); | ||||
|         $paginator->setPath(route('api.v1.bills.transactions', [$bill->id]) . $this->buildParams()); | ||||
|         $transactions = $paginator->getCollection(); | ||||
|  | ||||
|         /** @var TransactionTransformer $transformer */ | ||||
|         $transformer = app(TransactionTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($transactions, $transformer, 'transactions'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update a bill. | ||||
|      * | ||||
|      * @param BillRequest $request | ||||
|      * @param Bill        $bill | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(BillRequest $request, Bill $bill): JsonResponse | ||||
|     { | ||||
|         $data    = $request->getAll(); | ||||
|         $bill    = $this->repository->update($bill, $data); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var BillTransformer $transformer */ | ||||
|         $transformer = app(BillTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($bill, $transformer, 'bills'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										321
									
								
								app/Api/V1/Controllers/BudgetController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										321
									
								
								app/Api/V1/Controllers/BudgetController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,321 @@ | ||||
| <?php | ||||
| /** | ||||
|  * BudgetController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\BudgetLimitRequest; | ||||
| use FireflyIII\Api\V1\Requests\BudgetRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Collector\TransactionCollectorInterface; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Transformers\BudgetLimitTransformer; | ||||
| use FireflyIII\Transformers\BudgetTransformer; | ||||
| use FireflyIII\Transformers\TransactionTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class BudgetController. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class BudgetController extends Controller | ||||
| { | ||||
|     use TransactionFilter; | ||||
|     /** @var BudgetRepositoryInterface The budget repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * BudgetController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $admin */ | ||||
|                 $admin = auth()->user(); | ||||
|  | ||||
|                 /** @var BudgetRepositoryInterface repository */ | ||||
|                 $this->repository = app(BudgetRepositoryInterface::class); | ||||
|                 $this->repository->setUser($admin); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * @param Budget  $budget | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function budgetLimits(Request $request, Budget $budget): JsonResponse | ||||
|     { | ||||
|         $manager  = new Manager; | ||||
|         $baseUrl  = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $this->parameters->set('budget_id', $budget->id); | ||||
|         $collection   = $this->repository->getBudgetLimits($budget, $this->parameters->get('start'), $this->parameters->get('end')); | ||||
|         $count        = $collection->count(); | ||||
|         $budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|         $paginator    = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.budgets.budget_limits', [$budget->id]) . $this->buildParams()); | ||||
|  | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var BudgetLimitTransformer $transformer */ | ||||
|         $transformer = app(BudgetLimitTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|  | ||||
|         $resource = new FractalCollection($budgetLimits, $transformer, 'budget_limits'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(Budget $budget): JsonResponse | ||||
|     { | ||||
|         $this->repository->destroy($budget); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of budgets. Count it and split it. | ||||
|         $collection = $this->repository->getBudgets(); | ||||
|         $count      = $collection->count(); | ||||
|         $budgets    = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($budgets, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.budgets.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var BudgetTransformer $transformer */ | ||||
|         $transformer = app(BudgetTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($budgets, $transformer, 'budgets'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show a budget. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * @param Budget  $budget | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, Budget $budget): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var BudgetTransformer $transformer */ | ||||
|         $transformer = app(BudgetTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($budget, $transformer, 'budgets'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a budget. | ||||
|      * | ||||
|      * @param BudgetRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(BudgetRequest $request): JsonResponse | ||||
|     { | ||||
|         $budget = $this->repository->store($request->getAll()); | ||||
|         if (null !== $budget) { | ||||
|             $manager = new Manager(); | ||||
|             $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|             $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|             /** @var BudgetTransformer $transformer */ | ||||
|             $transformer = app(BudgetTransformer::class); | ||||
|             $transformer->setParameters($this->parameters); | ||||
|  | ||||
|             $resource = new Item($budget, $transformer, 'budgets'); | ||||
|  | ||||
|             return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         } | ||||
|         throw new FireflyException('Could not store new budget.'); // @codeCoverageIgnore | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param BudgetLimitRequest $request | ||||
|      * @param Budget             $budget | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function storeBudgetLimit(BudgetLimitRequest $request, Budget $budget): JsonResponse | ||||
|     { | ||||
|         $data           = $request->getAll(); | ||||
|         $data['budget'] = $budget; | ||||
|         $budgetLimit    = $this->repository->storeBudgetLimit($data); | ||||
|         $manager        = new Manager; | ||||
|         $baseUrl        = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var BudgetLimitTransformer $transformer */ | ||||
|         $transformer = app(BudgetLimitTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($budgetLimit, $transformer, 'budget_limits'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show all transactions. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @param Budget  $budget | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function transactions(Request $request, Budget $budget): JsonResponse | ||||
|     { | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // user can overrule page size with limit parameter. | ||||
|         $limit = $this->parameters->get('limit'); | ||||
|         if (null !== $limit && $limit > 0) { | ||||
|             $pageSize = $limit; | ||||
|         } | ||||
|  | ||||
|         $type = $request->get('type') ?? 'default'; | ||||
|         $this->parameters->set('type', $type); | ||||
|  | ||||
|         $types   = $this->mapTransactionTypes($this->parameters->get('type')); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var User $admin */ | ||||
|         $admin = auth()->user(); | ||||
|         /** @var TransactionCollectorInterface $collector */ | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setUser($admin); | ||||
|         $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); | ||||
|         $collector->setAllAssetAccounts(); | ||||
|         $collector->setBudget($budget); | ||||
|  | ||||
|         if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) { | ||||
|             $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); | ||||
|         } | ||||
|  | ||||
|         $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); | ||||
|         $collector->setTypes($types); | ||||
|         $paginator = $collector->getPaginatedTransactions(); | ||||
|         $paginator->setPath(route('api.v1.budgets.transactions', [$budget->id]) . $this->buildParams()); | ||||
|         $transactions = $paginator->getCollection(); | ||||
|  | ||||
|         /** @var TransactionTransformer $transformer */ | ||||
|         $transformer = app(TransactionTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|  | ||||
|         $resource = new FractalCollection($transactions, $transformer, 'transactions'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update a budget. | ||||
|      * | ||||
|      * @param BudgetRequest $request | ||||
|      * @param Budget        $budget | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(BudgetRequest $request, Budget $budget): JsonResponse | ||||
|     { | ||||
|         $data    = $request->getAll(); | ||||
|         $budget  = $this->repository->update($budget, $data); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var BudgetTransformer $transformer */ | ||||
|         $transformer = app(BudgetTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($budget, $transformer, 'budgets'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										254
									
								
								app/Api/V1/Controllers/BudgetLimitController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								app/Api/V1/Controllers/BudgetLimitController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,254 @@ | ||||
| <?php | ||||
| /** | ||||
|  * BudgetLimitController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\BudgetLimitRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Collector\TransactionCollectorInterface; | ||||
| use FireflyIII\Models\BudgetLimit; | ||||
| use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Transformers\BudgetLimitTransformer; | ||||
| use FireflyIII\Transformers\TransactionTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use Illuminate\Support\Collection; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class BudgetLimitController. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class BudgetLimitController extends Controller | ||||
| { | ||||
|     use TransactionFilter; | ||||
|     /** @var BudgetRepositoryInterface The budget repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * AccountController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user             = auth()->user(); | ||||
|                 $this->repository = app(BudgetRepositoryInterface::class); | ||||
|                 $this->repository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param BudgetLimit $budgetLimit | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(BudgetLimit $budgetLimit): JsonResponse | ||||
|     { | ||||
|         $this->repository->destroyBudgetLimit($budgetLimit); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         $manager  = new Manager; | ||||
|         $baseUrl  = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $budgetId = (int)($request->get('budget_id') ?? 0); | ||||
|         $budget   = $this->repository->findNull($budgetId); | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $this->parameters->set('budget_id', $budgetId); | ||||
|  | ||||
|         $collection = new Collection; | ||||
|         if (null === $budget) { | ||||
|             $collection = $this->repository->getAllBudgetLimits($this->parameters->get('start'), $this->parameters->get('end')); | ||||
|         } | ||||
|         if (null !== $budget) { | ||||
|             $collection = $this->repository->getBudgetLimits($budget, $this->parameters->get('start'), $this->parameters->get('end')); | ||||
|         } | ||||
|  | ||||
|         $count        = $collection->count(); | ||||
|         $budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|         $paginator    = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.budget_limits.index') . $this->buildParams()); | ||||
|  | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var BudgetLimitTransformer $transformer */ | ||||
|         $transformer = app(BudgetLimitTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($budgetLimits, $transformer, 'budget_limits'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param Request     $request | ||||
|      * @param BudgetLimit $budgetLimit | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, BudgetLimit $budgetLimit): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var BudgetLimitTransformer $transformer */ | ||||
|         $transformer = app(BudgetLimitTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($budgetLimit, $transformer, 'budget_limits'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param BudgetLimitRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(BudgetLimitRequest $request): JsonResponse | ||||
|     { | ||||
|         $data   = $request->getAll(); | ||||
|         $budget = $this->repository->findNull($data['budget_id']); | ||||
|         if (null === $budget) { | ||||
|             throw new FireflyException('Unknown budget.'); | ||||
|         } | ||||
|         $data['budget'] = $budget; | ||||
|         $budgetLimit    = $this->repository->storeBudgetLimit($data); | ||||
|         $manager        = new Manager; | ||||
|         $baseUrl        = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var BudgetLimitTransformer $transformer */ | ||||
|         $transformer = app(BudgetLimitTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($budgetLimit, $transformer, 'budget_limits'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show all transactions. | ||||
|      * | ||||
|      * @param Request     $request | ||||
|      * @param BudgetLimit $budgetLimit | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function transactions(Request $request, BudgetLimit $budgetLimit): JsonResponse | ||||
|     { | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $type     = $request->get('type') ?? 'default'; | ||||
|         $this->parameters->set('type', $type); | ||||
|  | ||||
|         $types   = $this->mapTransactionTypes($this->parameters->get('type')); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var User $admin */ | ||||
|         $admin = auth()->user(); | ||||
|         /** @var TransactionCollectorInterface $collector */ | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setUser($admin); | ||||
|         $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); | ||||
|         $collector->setAllAssetAccounts(); | ||||
|         $collector->setBudget($budgetLimit->budget); | ||||
|         $collector->setRange($budgetLimit->start_date, $budgetLimit->end_date); | ||||
|         $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); | ||||
|         $collector->setTypes($types); | ||||
|         $paginator = $collector->getPaginatedTransactions(); | ||||
|         $paginator->setPath(route('api.v1.budget_limits.transactions', [$budgetLimit->id]) . $this->buildParams()); | ||||
|         $transactions = $paginator->getCollection(); | ||||
|  | ||||
|         /** @var TransactionTransformer $transformer */ | ||||
|         $transformer = app(TransactionTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($transactions, $transformer, 'transactions'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param BudgetLimitRequest $request | ||||
|      * @param BudgetLimit        $budgetLimit | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(BudgetLimitRequest $request, BudgetLimit $budgetLimit): JsonResponse | ||||
|     { | ||||
|         $data           = $request->getAll(); | ||||
|         $data['budget'] = $budgetLimit->budget; | ||||
|         $budgetLimit    = $this->repository->updateBudgetLimit($budgetLimit, $data); | ||||
|         $manager        = new Manager; | ||||
|         $baseUrl        = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var BudgetLimitTransformer $transformer */ | ||||
|         $transformer = app(BudgetLimitTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($budgetLimit, $transformer, 'budget_limits'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										259
									
								
								app/Api/V1/Controllers/CategoryController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										259
									
								
								app/Api/V1/Controllers/CategoryController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,259 @@ | ||||
| <?php | ||||
| /** | ||||
|  * CategoryController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\CategoryRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Collector\TransactionCollectorInterface; | ||||
| use FireflyIII\Helpers\Filter\InternalTransferFilter; | ||||
| use FireflyIII\Models\Category; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Repositories\Category\CategoryRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Transformers\CategoryTransformer; | ||||
| use FireflyIII\Transformers\TransactionTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class CategoryController. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class CategoryController extends Controller | ||||
| { | ||||
|     use TransactionFilter; | ||||
|     /** @var CategoryRepositoryInterface The category repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * CategoryController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $admin */ | ||||
|                 $admin = auth()->user(); | ||||
|  | ||||
|                 /** @var CategoryRepositoryInterface repository */ | ||||
|                 $this->repository = app(CategoryRepositoryInterface::class); | ||||
|                 $this->repository->setUser($admin); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(Category $category): JsonResponse | ||||
|     { | ||||
|         $this->repository->destroy($category); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of budgets. Count it and split it. | ||||
|         $collection = $this->repository->getCategories(); | ||||
|         $count      = $collection->count(); | ||||
|         $categories = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($categories, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.categories.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var CategoryTransformer $transformer */ | ||||
|         $transformer = app(CategoryTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|  | ||||
|         $resource = new FractalCollection($categories, $transformer, 'categories'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Show the category. | ||||
|      * | ||||
|      * @param Request  $request | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, Category $category): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var CategoryTransformer $transformer */ | ||||
|         $transformer = app(CategoryTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($category, $transformer, 'categories'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store new category. | ||||
|      * | ||||
|      * @param CategoryRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(CategoryRequest $request): JsonResponse | ||||
|     { | ||||
|         $category = $this->repository->store($request->getAll()); | ||||
|         if (null !== $category) { | ||||
|             $manager = new Manager(); | ||||
|             $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|             $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|             /** @var CategoryTransformer $transformer */ | ||||
|             $transformer = app(CategoryTransformer::class); | ||||
|             $transformer->setParameters($this->parameters); | ||||
|  | ||||
|             $resource = new Item($category, $transformer, 'categories'); | ||||
|  | ||||
|             return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         } | ||||
|         throw new FireflyException('Could not store new category.'); // @codeCoverageIgnore | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show all transactions. | ||||
|      * | ||||
|      * @param Request  $request | ||||
|      * | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function transactions(Request $request, Category $category): JsonResponse | ||||
|     { | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $type     = $request->get('type') ?? 'default'; | ||||
|         $this->parameters->set('type', $type); | ||||
|  | ||||
|         $types   = $this->mapTransactionTypes($this->parameters->get('type')); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var User $admin */ | ||||
|         $admin = auth()->user(); | ||||
|         /** @var TransactionCollectorInterface $collector */ | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setUser($admin); | ||||
|         $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); | ||||
|         $collector->setAllAssetAccounts(); | ||||
|         $collector->setCategory($category); | ||||
|  | ||||
|         if (\in_array(TransactionType::TRANSFER, $types, true)) { | ||||
|             $collector->removeFilter(InternalTransferFilter::class); | ||||
|         } | ||||
|  | ||||
|         if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) { | ||||
|             $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); | ||||
|         } | ||||
|         $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); | ||||
|         $collector->setTypes($types); | ||||
|         $paginator = $collector->getPaginatedTransactions(); | ||||
|         $paginator->setPath(route('api.v1.categories.transactions', [$category->id]) . $this->buildParams()); | ||||
|         $transactions = $paginator->getCollection(); | ||||
|  | ||||
|         /** @var TransactionTransformer $transformer */ | ||||
|         $transformer = app(TransactionTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($transactions, $transformer, 'transactions'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the category. | ||||
|      * | ||||
|      * @param CategoryRequest $request | ||||
|      * @param Category        $category | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(CategoryRequest $request, Category $category): JsonResponse | ||||
|     { | ||||
|         $data     = $request->getAll(); | ||||
|         $category = $this->repository->update($category, $data); | ||||
|         $manager  = new Manager(); | ||||
|         $baseUrl  = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var CategoryTransformer $transformer */ | ||||
|         $transformer = app(CategoryTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($category, $transformer, 'categories'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										348
									
								
								app/Api/V1/Controllers/Chart/AccountController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										348
									
								
								app/Api/V1/Controllers/Chart/AccountController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,348 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * AccountController.php | ||||
|  * Copyright (c) 2019 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers\Chart; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class AccountController | ||||
|  */ | ||||
| class AccountController extends Controller | ||||
| { | ||||
|     /** @var CurrencyRepositoryInterface */ | ||||
|     private $currencyRepository; | ||||
|     /** @var AccountRepositoryInterface */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * AccountController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user             = auth()->user(); | ||||
|                 $this->repository = app(AccountRepositoryInterface::class); | ||||
|                 $this->repository->setUser($user); | ||||
|  | ||||
|                 $this->currencyRepository = app(CurrencyRepositoryInterface::class); | ||||
|                 $this->currencyRepository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function expenseOverview(Request $request): JsonResponse | ||||
|     { | ||||
|         // parameters for chart: | ||||
|         $start = (string)$request->get('start'); | ||||
|         $end   = (string)$request->get('end'); | ||||
|         if ('' === $start || '' === $end) { | ||||
|             throw new FireflyException('Start and end are mandatory parameters.'); | ||||
|         } | ||||
|  | ||||
|         $start = Carbon::createFromFormat('Y-m-d', $start); | ||||
|         $end   = Carbon::createFromFormat('Y-m-d', $end); | ||||
|         $start->subDay(); | ||||
|  | ||||
|         // prep some vars: | ||||
|         $currencies = []; | ||||
|         $chartData  = []; | ||||
|         $tempData   = []; | ||||
|  | ||||
|         // grab all accounts and names | ||||
|         $accounts      = $this->repository->getAccountsByType([AccountType::EXPENSE]); | ||||
|         $accountNames  = $this->extractNames($accounts); | ||||
|         $startBalances = app('steam')->balancesPerCurrencyByAccounts($accounts, $start); | ||||
|         $endBalances   = app('steam')->balancesPerCurrencyByAccounts($accounts, $end); | ||||
|  | ||||
|         // loop the end balances. This is an array for each account ($expenses) | ||||
|         foreach ($endBalances as $accountId => $expenses) { | ||||
|             $accountId = (int)$accountId; | ||||
|             // loop each expense entry (each entry can be a different currency). | ||||
|             foreach ($expenses as $currencyId => $endAmount) { | ||||
|                 $currencyId = (int)$currencyId; | ||||
|  | ||||
|                 // see if there is an accompanying start amount. | ||||
|                 // grab the difference and find the currency. | ||||
|                 $startAmount             = $startBalances[$accountId][$currencyId] ?? '0'; | ||||
|                 $diff                    = bcsub($endAmount, $startAmount); | ||||
|                 $currencies[$currencyId] = $currencies[$currencyId] ?? $this->currencyRepository->findNull($currencyId); | ||||
|                 if (0 !== bccomp($diff, '0')) { | ||||
|                     // store the values in a temporary array. | ||||
|                     $tempData[] = [ | ||||
|                         'name'        => $accountNames[$accountId], | ||||
|                         'difference'  => $diff, | ||||
|                         'diff_float'  => (float)$diff, | ||||
|                         'currency_id' => $currencyId, | ||||
|                     ]; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // sort temp array by amount. | ||||
|         $amounts = array_column($tempData, 'diff_float'); | ||||
|         array_multisort($amounts, SORT_DESC, $tempData); | ||||
|  | ||||
|         // loop all found currencies and build the data array for the chart. | ||||
|         /** | ||||
|          * @var int                 $currencyId | ||||
|          * @var TransactionCurrency $currency | ||||
|          */ | ||||
|         foreach ($currencies as $currencyId => $currency) { | ||||
|             $currentSet             = [ | ||||
|                 'label'                   => trans('firefly.box_spent_in_currency', ['currency' => $currency->symbol]), | ||||
|                 'currency_id'             => $currency->id, | ||||
|                 'currency_code'           => $currency->code, | ||||
|                 'currency_symbol'         => $currency->symbol, | ||||
|                 'currency_decimal_places' => $currency->decimal_places, | ||||
|                 'type'                    => 'bar', // line, area or bar | ||||
|                 'yAxisID'                 => 0, // 0, 1, 2 | ||||
|                 'entries'                 => $this->expandNames($tempData), | ||||
|             ]; | ||||
|             $chartData[$currencyId] = $currentSet; | ||||
|         } | ||||
|  | ||||
|         // loop temp data and place data in correct array: | ||||
|         foreach ($tempData as $entry) { | ||||
|             $currencyId                               = $entry['currency_id']; | ||||
|             $name                                     = $entry['name']; | ||||
|             $chartData[$currencyId]['entries'][$name] = round($entry['difference'], $chartData[$currencyId]['currency_decimal_places']); | ||||
|         } | ||||
|         $chartData = array_values($chartData); | ||||
|  | ||||
|         return response()->json($chartData); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function overview(Request $request): JsonResponse | ||||
|     { | ||||
|         // parameters for chart: | ||||
|         $start = (string)$request->get('start'); | ||||
|         $end   = (string)$request->get('end'); | ||||
|         if ('' === $start || '' === $end) { | ||||
|             throw new FireflyException('Start and end are mandatory parameters.'); | ||||
|         } | ||||
|  | ||||
|         $start = Carbon::createFromFormat('Y-m-d', $start); | ||||
|         $end   = Carbon::createFromFormat('Y-m-d', $end); | ||||
|  | ||||
|         // user's preferences | ||||
|         $defaultSet = $this->repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET])->pluck('id')->toArray(); | ||||
|         $frontPage  = app('preferences')->get('frontPageAccounts', $defaultSet); | ||||
|         $default    = app('amount')->getDefaultCurrency(); | ||||
|         if (0 === \count($frontPage->data)) { | ||||
|             $frontPage->data = $defaultSet; | ||||
|             $frontPage->save(); | ||||
|         } | ||||
|  | ||||
|         // get accounts: | ||||
|         $accounts  = $this->repository->getAccountsById($frontPage->data); | ||||
|         $chartData = []; | ||||
|         /** @var Account $account */ | ||||
|         foreach ($accounts as $account) { | ||||
|             $currency = $this->repository->getAccountCurrency($account); | ||||
|             if (null === $currency) { | ||||
|                 $currency = $default; | ||||
|             } | ||||
|             $currentSet = [ | ||||
|                 'label'                   => $account->name, | ||||
|                 'currency_id'             => $currency->id, | ||||
|                 'currency_code'           => $currency->code, | ||||
|                 'currency_symbol'         => $currency->symbol, | ||||
|                 'currency_decimal_places' => $currency->decimal_places, | ||||
|                 'type'                    => 'line', // line, area or bar | ||||
|                 'yAxisID'                 => 0, // 0, 1, 2 | ||||
|                 'entries'                 => [], | ||||
|             ]; | ||||
|  | ||||
|             $currentStart = clone $start; | ||||
|             $range        = app('steam')->balanceInRange($account, $start, clone $end); | ||||
|             $previous     = round(array_values($range)[0], 12); | ||||
|             while ($currentStart <= $end) { | ||||
|                 $format   = $currentStart->format('Y-m-d'); | ||||
|                 $label    = $currentStart->format('Y-m-d'); | ||||
|                 $balance  = isset($range[$format]) ? round($range[$format], 12) : $previous; | ||||
|                 $previous = $balance; | ||||
|                 $currentStart->addDay(); | ||||
|                 $currentSet['entries'][$label] = $balance; | ||||
|             } | ||||
|             $chartData[] = $currentSet; | ||||
|         } | ||||
|  | ||||
|         return response()->json($chartData); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function revenueOverview(Request $request): JsonResponse | ||||
|     { | ||||
|         // parameters for chart: | ||||
|         $start = (string)$request->get('start'); | ||||
|         $end   = (string)$request->get('end'); | ||||
|         if ('' === $start || '' === $end) { | ||||
|             throw new FireflyException('Start and end are mandatory parameters.'); | ||||
|         } | ||||
|  | ||||
|         $start = Carbon::createFromFormat('Y-m-d', $start); | ||||
|         $end   = Carbon::createFromFormat('Y-m-d', $end); | ||||
|         $start->subDay(); | ||||
|  | ||||
|         // prep some vars: | ||||
|         $currencies = []; | ||||
|         $chartData  = []; | ||||
|         $tempData   = []; | ||||
|  | ||||
|         // grab all accounts and names | ||||
|         $accounts      = $this->repository->getAccountsByType([AccountType::REVENUE]); | ||||
|         $accountNames  = $this->extractNames($accounts); | ||||
|         $startBalances = app('steam')->balancesPerCurrencyByAccounts($accounts, $start); | ||||
|         $endBalances   = app('steam')->balancesPerCurrencyByAccounts($accounts, $end); | ||||
|  | ||||
|         // loop the end balances. This is an array for each account ($expenses) | ||||
|         foreach ($endBalances as $accountId => $expenses) { | ||||
|             $accountId = (int)$accountId; | ||||
|             // loop each expense entry (each entry can be a different currency). | ||||
|             foreach ($expenses as $currencyId => $endAmount) { | ||||
|                 $currencyId = (int)$currencyId; | ||||
|  | ||||
|                 // see if there is an accompanying start amount. | ||||
|                 // grab the difference and find the currency. | ||||
|                 $startAmount             = $startBalances[$accountId][$currencyId] ?? '0'; | ||||
|                 $diff                    = bcsub($endAmount, $startAmount); | ||||
|                 $currencies[$currencyId] = $currencies[$currencyId] ?? $this->currencyRepository->findNull($currencyId); | ||||
|                 if (0 !== bccomp($diff, '0')) { | ||||
|                     // store the values in a temporary array. | ||||
|                     $tempData[] = [ | ||||
|                         'name'        => $accountNames[$accountId], | ||||
|                         'difference'  => bcmul($diff, '-1'), | ||||
|                         'diff_float'  => (float)$diff * -1, | ||||
|                         'currency_id' => $currencyId, | ||||
|                     ]; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // sort temp array by amount. | ||||
|         $amounts = array_column($tempData, 'diff_float'); | ||||
|         array_multisort($amounts, SORT_DESC, $tempData); | ||||
|  | ||||
|         // loop all found currencies and build the data array for the chart. | ||||
|         /** | ||||
|          * @var int                 $currencyId | ||||
|          * @var TransactionCurrency $currency | ||||
|          */ | ||||
|         foreach ($currencies as $currencyId => $currency) { | ||||
|             $currentSet             = [ | ||||
|                 'label'                   => trans('firefly.box_earned_in_currency', ['currency' => $currency->symbol]), | ||||
|                 'currency_id'             => $currency->id, | ||||
|                 'currency_code'           => $currency->code, | ||||
|                 'currency_symbol'         => $currency->symbol, | ||||
|                 'currency_decimal_places' => $currency->decimal_places, | ||||
|                 'type'                    => 'bar', // line, area or bar | ||||
|                 'yAxisID'                 => 0, // 0, 1, 2 | ||||
|                 'entries'                 => $this->expandNames($tempData), | ||||
|             ]; | ||||
|             $chartData[$currencyId] = $currentSet; | ||||
|         } | ||||
|  | ||||
|         // loop temp data and place data in correct array: | ||||
|         foreach ($tempData as $entry) { | ||||
|             $currencyId                               = $entry['currency_id']; | ||||
|             $name                                     = $entry['name']; | ||||
|             $chartData[$currencyId]['entries'][$name] = round($entry['difference'], $chartData[$currencyId]['currency_decimal_places']); | ||||
|         } | ||||
|         $chartData = array_values($chartData); | ||||
|  | ||||
|         return response()->json($chartData); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Small helper function for the revenue and expense account charts. | ||||
|      * TODO should include Trait instead of doing this. | ||||
|      * | ||||
|      * @param array $names | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function expandNames(array $names): array | ||||
|     { | ||||
|         $result = []; | ||||
|         foreach ($names as $entry) { | ||||
|             $result[$entry['name']] = 0; | ||||
|         } | ||||
|  | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Small helper function for the revenue and expense account charts. | ||||
|      * TODO should include Trait instead of doing this. | ||||
|      * | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function extractNames(Collection $accounts): array | ||||
|     { | ||||
|         $return = []; | ||||
|         /** @var Account $account */ | ||||
|         foreach ($accounts as $account) { | ||||
|             $return[$account->id] = $account->name; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										111
									
								
								app/Api/V1/Controllers/Chart/AvailableBudgetController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								app/Api/V1/Controllers/Chart/AvailableBudgetController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * AvailableBudgetController.php | ||||
|  * Copyright (c) 2019 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers\Chart; | ||||
|  | ||||
|  | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Models\AvailableBudget; | ||||
| use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class AvailableBudgetController | ||||
|  */ | ||||
| class AvailableBudgetController extends Controller | ||||
| { | ||||
|     /** @var BudgetRepositoryInterface */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * AvailableBudgetController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user             = auth()->user(); | ||||
|                 $this->repository = app(BudgetRepositoryInterface::class); | ||||
|                 $this->repository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AvailableBudget $availableBudget | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function overview(AvailableBudget $availableBudget): JsonResponse | ||||
|     { | ||||
|         $currency          = $availableBudget->transactionCurrency; | ||||
|         $budgets           = $this->repository->getActiveBudgets(); | ||||
|         $budgetInformation = $this->repository->spentInPeriodMc($budgets, new Collection, $availableBudget->start_date, $availableBudget->end_date); | ||||
|         $spent             = 0.0; | ||||
|  | ||||
|         // get for current currency | ||||
|         foreach ($budgetInformation as $spentInfo) { | ||||
|             if ($spentInfo['currency_id'] === $availableBudget->transaction_currency_id) { | ||||
|                 $spent = $spentInfo['amount']; | ||||
|             } | ||||
|         } | ||||
|         $left = bcadd($availableBudget->amount, (string)$spent); | ||||
|         // left less than zero? Set to zero. | ||||
|         if (bccomp($left, '0') === -1) { | ||||
|             $left = '0'; | ||||
|         } | ||||
|  | ||||
|         $chartData = [ | ||||
|             [ | ||||
|                 'label'                   => trans('firefly.spent'), | ||||
|                 'currency_id'             => $currency->id, | ||||
|                 'currency_code'           => $currency->code, | ||||
|                 'currency_symbol'         => $currency->symbol, | ||||
|                 'currency_decimal_places' => $currency->decimal_places, | ||||
|                 'type'                    => 'pie', | ||||
|                 'yAxisID'                 => 0, // 0, 1, 2 | ||||
|                 'entries'                 => [$spent * -1], | ||||
|             ], | ||||
|             [ | ||||
|                 'label'                   => trans('firefly.left'), | ||||
|                 'currency_id'             => $currency->id, | ||||
|                 'currency_code'           => $currency->code, | ||||
|                 'currency_symbol'         => $currency->symbol, | ||||
|                 'currency_decimal_places' => $currency->decimal_places, | ||||
|                 'type'                    => 'line', // line, area or bar | ||||
|                 'yAxisID'                 => 0, // 0, 1, 2 | ||||
|                 'entries'                 => [round($left, $currency->decimal_places)], | ||||
|             ], | ||||
|         ]; | ||||
|  | ||||
|         return response()->json($chartData); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										209
									
								
								app/Api/V1/Controllers/Chart/CategoryController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								app/Api/V1/Controllers/Chart/CategoryController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,209 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * CategoryController.php | ||||
|  * Copyright (c) 2019 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers\Chart; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Repositories\Category\CategoryRepositoryInterface; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class CategoryController | ||||
|  */ | ||||
| class CategoryController extends Controller | ||||
| { | ||||
|     /** @var CategoryRepositoryInterface */ | ||||
|     private $categoryRepository; | ||||
|  | ||||
|     /** | ||||
|      * AccountController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user                     = auth()->user(); | ||||
|                 $this->categoryRepository = app(CategoryRepositoryInterface::class); | ||||
|                 $this->categoryRepository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function overview(Request $request): JsonResponse | ||||
|     { | ||||
|         // parameters for chart: | ||||
|         $start = (string)$request->get('start'); | ||||
|         $end   = (string)$request->get('end'); | ||||
|         if ('' === $start || '' === $end) { | ||||
|             throw new FireflyException('Start and end are mandatory parameters.'); | ||||
|         } | ||||
|         $start      = Carbon::createFromFormat('Y-m-d', $start); | ||||
|         $end        = Carbon::createFromFormat('Y-m-d', $end); | ||||
|         $tempData   = []; | ||||
|         $spent      = $this->categoryRepository->spentInPeriodPerCurrency(new Collection, new Collection, $start, $end); | ||||
|         $earned     = $this->categoryRepository->earnedInPeriodPerCurrency(new Collection, new Collection, $start, $end); | ||||
|         $categories = []; | ||||
|  | ||||
|         // earned: | ||||
|         foreach ($earned as $categoryId => $row) { | ||||
|             $categoryName = $row['name']; | ||||
|             foreach ($row['earned'] as $currencyId => $income) { | ||||
|                 // find or make set for currency: | ||||
|                 $key           = sprintf('%s-e', $currencyId); | ||||
|                 $decimalPlaces = $income['currency_decimal_places']; | ||||
|                 if (!isset($tempData[$key])) { | ||||
|                     $tempData[$key] = [ | ||||
|                         'label'                   => (string)trans('firefly.box_earned_in_currency', ['currency' => $income['currency_symbol']]), | ||||
|                         'currency_id'             => $income['currency_id'], | ||||
|                         'currency_code'           => $income['currency_code'], | ||||
|                         'currency_symbol'         => $income['currency_symbol'], | ||||
|                         'currency_decimal_places' => $decimalPlaces, | ||||
|                         'type'                    => 'bar', // line, area or bar | ||||
|                         'yAxisID'                 => 0, // 0, 1, 2 | ||||
|                         'entries'                 => [], | ||||
|                     ]; | ||||
|                 } | ||||
|                 $amount                    = round($income['earned'], $decimalPlaces); | ||||
|                 $categories[$categoryName] = isset($categories[$categoryName]) ? $categories[$categoryName] + $amount : $amount; | ||||
|                 $tempData[$key]['entries'][$categoryName] | ||||
|                                            = $amount; | ||||
|  | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // earned with no category: | ||||
|         $noCategory = $this->categoryRepository->earnedInPeriodPcWoCategory(new Collection, $start, $end); | ||||
|         foreach ($noCategory as $currencyId => $income) { | ||||
|             $categoryName = (string)trans('firefly.no_category'); | ||||
|             // find or make set for currency: | ||||
|             $key           = sprintf('%s-e', $currencyId); | ||||
|             $decimalPlaces = $income['currency_decimal_places']; | ||||
|             if (!isset($tempData[$key])) { | ||||
|                 $tempData[$key] = [ | ||||
|                     'label'                   => (string)trans('firefly.box_earned_in_currency', ['currency' => $income['currency_symbol']]), | ||||
|                     'currency_id'             => $income['currency_id'], | ||||
|                     'currency_code'           => $income['currency_code'], | ||||
|                     'currency_symbol'         => $income['currency_symbol'], | ||||
|                     'currency_decimal_places' => $decimalPlaces, | ||||
|                     'type'                    => 'bar', // line, area or bar | ||||
|                     'yAxisID'                 => 0, // 0, 1, 2 | ||||
|                     'entries'                 => [], | ||||
|                 ]; | ||||
|             } | ||||
|             $amount                    = round($income['spent'], $decimalPlaces); | ||||
|             $categories[$categoryName] = isset($categories[$categoryName]) ? $categories[$categoryName] + $amount : $amount; | ||||
|             $tempData[$key]['entries'][$categoryName] | ||||
|                                        = $amount; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         // spent | ||||
|         foreach ($spent as $categoryId => $row) { | ||||
|             $categoryName = $row['name']; | ||||
|             // create a new set if necessary, "spent (EUR)": | ||||
|             foreach ($row['spent'] as $currencyId => $expense) { | ||||
|                 // find or make set for currency: | ||||
|                 $key           = sprintf('%s-s', $currencyId); | ||||
|                 $decimalPlaces = $expense['currency_decimal_places']; | ||||
|                 if (!isset($tempData[$key])) { | ||||
|                     $tempData[$key] = [ | ||||
|                         'label'                   => (string)trans('firefly.box_spent_in_currency', ['currency' => $expense['currency_symbol']]), | ||||
|                         'currency_id'             => $expense['currency_id'], | ||||
|                         'currency_code'           => $expense['currency_code'], | ||||
|                         'currency_symbol'         => $expense['currency_symbol'], | ||||
|                         'currency_decimal_places' => $decimalPlaces, | ||||
|                         'type'                    => 'bar', // line, area or bar | ||||
|                         'yAxisID'                 => 0, // 0, 1, 2 | ||||
|                         'entries'                 => [], | ||||
|                     ]; | ||||
|                 } | ||||
|                 $amount                    = round($expense['spent'], $decimalPlaces); | ||||
|                 $categories[$categoryName] = isset($categories[$categoryName]) ? $categories[$categoryName] + $amount : $amount; | ||||
|                 $tempData[$key]['entries'][$categoryName] | ||||
|                                            = $amount; | ||||
|  | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // spent with no category | ||||
|         $noCategory = $this->categoryRepository->spentInPeriodPcWoCategory(new Collection, $start, $end); | ||||
|         foreach ($noCategory as $currencyId => $expense) { | ||||
|             $categoryName = (string)trans('firefly.no_category'); | ||||
|             // find or make set for currency: | ||||
|             $key           = sprintf('%s-s', $currencyId); | ||||
|             $decimalPlaces = $expense['currency_decimal_places']; | ||||
|             if (!isset($tempData[$key])) { | ||||
|                 $tempData[$key] = [ | ||||
|                     'label'                   => (string)trans('firefly.box_spent_in_currency', ['currency' => $expense['currency_symbol']]), | ||||
|                     'currency_id'             => $expense['currency_id'], | ||||
|                     'currency_code'           => $expense['currency_code'], | ||||
|                     'currency_symbol'         => $expense['currency_symbol'], | ||||
|                     'currency_decimal_places' => $decimalPlaces, | ||||
|                     'type'                    => 'bar', // line, area or bar | ||||
|                     'yAxisID'                 => 0, // 0, 1, 2 | ||||
|                     'entries'                 => [], | ||||
|                 ]; | ||||
|             } | ||||
|             $amount                    = round($expense['spent'], $decimalPlaces); | ||||
|             $categories[$categoryName] = isset($categories[$categoryName]) ? $categories[$categoryName] + $amount : $amount; | ||||
|             $tempData[$key]['entries'][$categoryName] | ||||
|                                        = $amount; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         asort($categories); | ||||
|         $keys = array_keys($categories); | ||||
|  | ||||
|         // re-sort every spent array and add 0 for missing entries. | ||||
|         foreach ($tempData as $index => $set) { | ||||
|             $oldSet = $set['entries']; | ||||
|             $newSet = []; | ||||
|             foreach ($keys as $key) { | ||||
|                 $value        = $oldSet[$key] ?? 0; | ||||
|                 $value        = $value < 0 ? $value * -1 : $value; | ||||
|                 $newSet[$key] = $value; | ||||
|             } | ||||
|             $tempData[$index]['entries'] = $newSet; | ||||
|         } | ||||
|         $chartData = array_values($tempData); | ||||
|  | ||||
|         return response()->json($chartData); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										120
									
								
								app/Api/V1/Controllers/ConfigurationController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								app/Api/V1/Controllers/ConfigurationController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,120 @@ | ||||
| <?php | ||||
| /** | ||||
|  * ConfigurationController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\ConfigurationRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\Configuration; | ||||
| use FireflyIII\Repositories\User\UserRepositoryInterface; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
|  | ||||
| /** | ||||
|  * Class ConfigurationController. | ||||
|  */ | ||||
| class ConfigurationController extends Controller | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** @var UserRepositoryInterface The user repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * BudgetController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @noinspection UnusedConstructorDependenciesInspection */ | ||||
|                 $this->repository = app(UserRepositoryInterface::class); | ||||
|                 /** @var User $admin */ | ||||
|                 $admin = auth()->user(); | ||||
|  | ||||
|                 if (!$this->repository->hasRole($admin, 'owner')) { | ||||
|                     throw new FireflyException('No access to method.'); // @codeCoverageIgnore | ||||
|                 } | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show all configuration. | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(): JsonResponse | ||||
|     { | ||||
|         $configData = $this->getConfigData(); | ||||
|  | ||||
|         return response()->json(['data' => $configData])->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the configuration. | ||||
|      * | ||||
|      * @param ConfigurationRequest $request | ||||
|      * @param string               $name | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      */ | ||||
|     public function update(ConfigurationRequest $request, string $name): JsonResponse | ||||
|     { | ||||
|         $data = $request->getAll(); | ||||
|         app('fireflyconfig')->set($name, $data['value']); | ||||
|         $configData = $this->getConfigData(); | ||||
|  | ||||
|         return response()->json(['data' => $configData])->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all config values. | ||||
|      * | ||||
|      * @return array | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      */ | ||||
|     private function getConfigData(): array | ||||
|     { | ||||
|         /** @var Configuration $isDemoSite */ | ||||
|         $isDemoSite = app('fireflyconfig')->get('is_demo_site'); | ||||
|         /** @var Configuration $updateCheck */ | ||||
|         $updateCheck = app('fireflyconfig')->get('permission_update_check'); | ||||
|         /** @var Configuration $lastCheck */ | ||||
|         $lastCheck = app('fireflyconfig')->get('last_update_check'); | ||||
|         /** @var Configuration $singleUser */ | ||||
|         $singleUser = app('fireflyconfig')->get('single_user_mode'); | ||||
|         $data       = [ | ||||
|             'is_demo_site'            => null === $isDemoSite ? null : $isDemoSite->data, | ||||
|             'permission_update_check' => null === $updateCheck ? null : (int)$updateCheck->data, | ||||
|             'last_update_check'       => null === $lastCheck ? null : (int)$lastCheck->data, | ||||
|             'single_user_mode'        => null === $singleUser ? null : $singleUser->data, | ||||
|         ]; | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										128
									
								
								app/Api/V1/Controllers/Controller.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								app/Api/V1/Controllers/Controller.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,128 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * Controller.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Carbon\Exceptions\InvalidDateException; | ||||
| use Illuminate\Foundation\Auth\Access\AuthorizesRequests; | ||||
| use Illuminate\Foundation\Bus\DispatchesJobs; | ||||
| use Illuminate\Foundation\Validation\ValidatesRequests; | ||||
| use Illuminate\Routing\Controller as BaseController; | ||||
| use Log; | ||||
| use Symfony\Component\HttpFoundation\ParameterBag; | ||||
|  | ||||
| /** | ||||
|  * Class Controller. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @SuppressWarnings(PHPMD.NumberOfChildren) | ||||
|  */ | ||||
| class Controller extends BaseController | ||||
| { | ||||
|     use AuthorizesRequests, DispatchesJobs, ValidatesRequests; | ||||
|  | ||||
|     /** @var ParameterBag Parameters from the URI are stored here. */ | ||||
|     protected $parameters; | ||||
|  | ||||
|     /** | ||||
|      * Controller constructor. | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         // get global parameters | ||||
|         $this->parameters = $this->getParameters(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Method to help build URI's. | ||||
|      * | ||||
|      * @return string | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      */ | ||||
|     protected function buildParams(): string | ||||
|     { | ||||
|         $return = '?'; | ||||
|         $params = []; | ||||
|         foreach ($this->parameters as $key => $value) { | ||||
|             if ('page' === $key) { | ||||
|                 continue; | ||||
|             } | ||||
|             if ($value instanceof Carbon) { | ||||
|                 $params[$key] = $value->format('Y-m-d'); | ||||
|                 continue; | ||||
|             } | ||||
|             $params[$key] = $value; | ||||
|         } | ||||
|         $return .= http_build_query($params); | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Method to grab all parameters from the URI. | ||||
|      * | ||||
|      * @return ParameterBag | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      */ | ||||
|     private function getParameters(): ParameterBag | ||||
|     { | ||||
|         $bag  = new ParameterBag; | ||||
|         $page = (int)request()->get('page'); | ||||
|         if (0 === $page) { | ||||
|             $page = 1; | ||||
|         } | ||||
|         $bag->set('page', $page); | ||||
|  | ||||
|         // some date fields: | ||||
|         $dates = ['start', 'end', 'date']; | ||||
|         foreach ($dates as $field) { | ||||
|             $date = request()->query->get($field); | ||||
|             $obj  = null; | ||||
|             if (null !== $date) { | ||||
|                 try { | ||||
|                     $obj = Carbon::parse($date); | ||||
|                 } catch (InvalidDateException $e) { | ||||
|                     // don't care | ||||
|                     Log::error(sprintf('Invalid date exception in API controller: %s', $e->getMessage())); | ||||
|                 } | ||||
|             } | ||||
|             $bag->set($field, $obj); | ||||
|         } | ||||
|  | ||||
|         // integer fields: | ||||
|         $integers = ['limit']; | ||||
|         foreach ($integers as $integer) { | ||||
|             $value = request()->query->get($integer); | ||||
|             if (null !== $value) { | ||||
|                 $bag->set($integer, (int)$value); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $bag; | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										749
									
								
								app/Api/V1/Controllers/CurrencyController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										749
									
								
								app/Api/V1/Controllers/CurrencyController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,749 @@ | ||||
| <?php | ||||
| /** | ||||
|  * CurrencyController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\CurrencyRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Collector\TransactionCollectorInterface; | ||||
| use FireflyIII\Helpers\Filter\InternalTransferFilter; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AvailableBudget; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\BudgetLimit; | ||||
| use FireflyIII\Models\Recurrence; | ||||
| use FireflyIII\Models\RecurrenceTransaction; | ||||
| use FireflyIII\Models\Rule; | ||||
| use FireflyIII\Models\RuleTrigger; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Bill\BillRepositoryInterface; | ||||
| use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; | ||||
| use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; | ||||
| use FireflyIII\Repositories\Rule\RuleRepositoryInterface; | ||||
| use FireflyIII\Repositories\User\UserRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\AccountFilter; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Transformers\AccountTransformer; | ||||
| use FireflyIII\Transformers\AvailableBudgetTransformer; | ||||
| use FireflyIII\Transformers\BillTransformer; | ||||
| use FireflyIII\Transformers\BudgetLimitTransformer; | ||||
| use FireflyIII\Transformers\CurrencyExchangeRateTransformer; | ||||
| use FireflyIII\Transformers\CurrencyTransformer; | ||||
| use FireflyIII\Transformers\RecurrenceTransformer; | ||||
| use FireflyIII\Transformers\RuleTransformer; | ||||
| use FireflyIII\Transformers\TransactionTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use Illuminate\Support\Collection; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class CurrencyController. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class CurrencyController extends Controller | ||||
| { | ||||
|     use AccountFilter, TransactionFilter; | ||||
|     /** @var CurrencyRepositoryInterface The currency repository */ | ||||
|     private $repository; | ||||
|     /** @var UserRepositoryInterface The user repository */ | ||||
|     private $userRepository; | ||||
|  | ||||
|     /** | ||||
|      * CurrencyRepository constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $admin */ | ||||
|                 $admin = auth()->user(); | ||||
|  | ||||
|                 /** @var CurrencyRepositoryInterface repository */ | ||||
|                 $this->repository     = app(CurrencyRepositoryInterface::class); | ||||
|                 $this->userRepository = app(UserRepositoryInterface::class); | ||||
|                 $this->repository->setUser($admin); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display a list of accounts. | ||||
|      * | ||||
|      * @param Request             $request | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function accounts(Request $request, TransactionCurrency $currency): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // read type from URI | ||||
|         $type = $request->get('type') ?? 'all'; | ||||
|         $this->parameters->set('type', $type); | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $types    = $this->mapAccountTypes($this->parameters->get('type')); | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of accounts. Count it and split it. | ||||
|         /** @var AccountRepositoryInterface $accountRepository */ | ||||
|         $accountRepository = app(AccountRepositoryInterface::class); | ||||
|         $unfiltered        = $accountRepository->getAccountsByType($types); | ||||
|  | ||||
|         // filter list on currency preference: | ||||
|         $collection = $unfiltered->filter( | ||||
|             function (Account $account) use ($currency, $accountRepository) { | ||||
|                 $currencyId = (int)$accountRepository->getMetaValue($account, 'currency_id'); | ||||
|  | ||||
|                 return $currencyId === $currency->id; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         $count    = $collection->count(); | ||||
|         $accounts = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.currencies.accounts', [$currency->code]) . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var AccountTransformer $transformer */ | ||||
|         $transformer = app(AccountTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|  | ||||
|         $resource = new FractalCollection($accounts, $transformer, 'accounts'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @param Request             $request | ||||
|      * | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function availableBudgets(Request $request, TransactionCurrency $currency): JsonResponse | ||||
|     { | ||||
|         /** @var User $admin */ | ||||
|         $admin = auth()->user(); | ||||
|  | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of available budgets. Count it and split it. | ||||
|         /** @var BudgetRepositoryInterface $repository */ | ||||
|         $repository = app(BudgetRepositoryInterface::class); | ||||
|         $repository->setUser($admin); | ||||
|         $unfiltered = $repository->getAvailableBudgets(); | ||||
|  | ||||
|         // filter list. | ||||
|         $collection = $unfiltered->filter( | ||||
|             function (AvailableBudget $availableBudget) use ($currency) { | ||||
|                 return $availableBudget->transaction_currency_id === $currency->id; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         $count            = $collection->count(); | ||||
|         $availableBudgets = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($availableBudgets, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.currencies.available_budgets', [$currency->code]) . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var AvailableBudgetTransformer $transformer */ | ||||
|         $transformer = app(AvailableBudgetTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($availableBudgets, $transformer, 'available_budgets'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List all bills | ||||
|      * | ||||
|      * @param Request             $request | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function bills(Request $request, TransactionCurrency $currency): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         /** @var BillRepositoryInterface $repository */ | ||||
|         $repository = app(BillRepositoryInterface::class); | ||||
|         $pageSize   = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $paginator  = $repository->getPaginator($pageSize); | ||||
|         /** @var Collection $bills */ | ||||
|         $unfiltered = $paginator->getCollection(); | ||||
|  | ||||
|         // filter and paginate list: | ||||
|         $collection = $unfiltered->filter( | ||||
|             function (Bill $bill) use ($currency) { | ||||
|                 return $bill->transaction_currency_id === $currency->id; | ||||
|             } | ||||
|         ); | ||||
|         $count      = $collection->count(); | ||||
|         $bills      = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.currencies.bills', [$currency->code]) . $this->buildParams()); | ||||
|  | ||||
|  | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var BillTransformer $transformer */ | ||||
|         $transformer = app(BillTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($bills, $transformer, 'bills'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List all budget limits | ||||
|      * | ||||
|      * @param Request             $request | ||||
|      * | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function budgetLimits(Request $request, TransactionCurrency $currency): JsonResponse | ||||
|     { | ||||
|         /** @var BudgetRepositoryInterface $repository */ | ||||
|         $repository = app(BudgetRepositoryInterface::class); | ||||
|         $manager    = new Manager; | ||||
|         $baseUrl    = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $pageSize   = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $unfiltered = $repository->getAllBudgetLimits($this->parameters->get('start'), $this->parameters->get('end')); | ||||
|  | ||||
|         // TODO replace this | ||||
|         // filter budget limits on currency ID | ||||
|         $collection = $unfiltered->filter( | ||||
|             function (BudgetLimit $budgetLimit) use ($currency) { | ||||
|                 return $budgetLimit->transaction_currency_id === $currency->id; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         $count        = $collection->count(); | ||||
|         $budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|         $paginator    = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.currencies.budget_limits', [$currency->code]) . $this->buildParams()); | ||||
|  | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var BudgetLimitTransformer $transformer */ | ||||
|         $transformer = app(BudgetLimitTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($budgetLimits, $transformer, 'budget_limits'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show a list of known exchange rates | ||||
|      * | ||||
|      * @param Request             $request | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function cer(Request $request, TransactionCurrency $currency): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager    = new Manager; | ||||
|         $baseUrl    = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $pageSize   = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $collection = $this->repository->getExchangeRates($currency); | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|  | ||||
|         $count         = $collection->count(); | ||||
|         $exchangeRates = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|         $paginator     = new LengthAwarePaginator($exchangeRates, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.currencies.cer', [$currency->code]) . $this->buildParams()); | ||||
|  | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var CurrencyExchangeRateTransformer $transformer */ | ||||
|         $transformer = app(CurrencyExchangeRateTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($exchangeRates, $transformer, 'currency_exchange_rates'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  TransactionCurrency $currency | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function delete(TransactionCurrency $currency): JsonResponse | ||||
|     { | ||||
|         /** @var User $admin */ | ||||
|         $admin = auth()->user(); | ||||
|  | ||||
|         if (!$this->userRepository->hasRole($admin, 'owner')) { | ||||
|             // access denied: | ||||
|             throw new FireflyException('No access to method, user is not owner.'); // @codeCoverageIgnore | ||||
|         } | ||||
|         if ($this->repository->currencyInUse($currency)) { | ||||
|             throw new FireflyException('No access to method, currency is in use.'); // @codeCoverageIgnore | ||||
|         } | ||||
|         $this->repository->destroy($currency); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Disable a currency. | ||||
|      * | ||||
|      * @param Request             $request | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function disable(Request $request, TransactionCurrency $currency): JsonResponse | ||||
|     { | ||||
|         // must be unused. | ||||
|         if ($this->repository->currencyInUse($currency)) { | ||||
|             return response()->json([], 409); | ||||
|         } | ||||
|         $this->repository->disable($currency); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user()); | ||||
|         $this->parameters->set('defaultCurrency', $defaultCurrency); | ||||
|  | ||||
|         /** @var CurrencyTransformer $transformer */ | ||||
|         $transformer = app(CurrencyTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($currency, $transformer, 'currencies'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Enable a currency. | ||||
|      * | ||||
|      * @param Request             $request | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function enable(Request $request, TransactionCurrency $currency): JsonResponse | ||||
|     { | ||||
|         $this->repository->enable($currency); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user()); | ||||
|         $this->parameters->set('defaultCurrency', $defaultCurrency); | ||||
|  | ||||
|         /** @var CurrencyTransformer $transformer */ | ||||
|         $transformer = app(CurrencyTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($currency, $transformer, 'currencies'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         $pageSize   = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $collection = $this->repository->getAll(); | ||||
|         $count      = $collection->count(); | ||||
|         // slice them: | ||||
|         $currencies = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|         $paginator  = new LengthAwarePaginator($currencies, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.currencies.index') . $this->buildParams()); | ||||
|  | ||||
|  | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user()); | ||||
|         $this->parameters->set('defaultCurrency', $defaultCurrency); | ||||
|  | ||||
|         /** @var CurrencyTransformer $transformer */ | ||||
|         $transformer = app(CurrencyTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($currencies, $transformer, 'currencies'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Make the currency a default currency. | ||||
|      * | ||||
|      * @param Request             $request | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function makeDefault(Request $request, TransactionCurrency $currency): JsonResponse | ||||
|     { | ||||
|         $this->repository->enable($currency); | ||||
|  | ||||
|         app('preferences')->set('currencyPreference', $currency->code); | ||||
|         app('preferences')->mark(); | ||||
|  | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $this->parameters->set('defaultCurrency', $currency); | ||||
|  | ||||
|         /** @var CurrencyTransformer $transformer */ | ||||
|         $transformer = app(CurrencyTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($currency, $transformer, 'currencies'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List all recurring transactions. | ||||
|      * | ||||
|      * @param Request             $request | ||||
|      * | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return JsonResponse] | ||||
|      */ | ||||
|     public function recurrences(Request $request, TransactionCurrency $currency): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of budgets. Count it and split it. | ||||
|         /** @var RecurringRepositoryInterface $repository */ | ||||
|         $repository = app(RecurringRepositoryInterface::class); | ||||
|         $unfiltered = $repository->getAll(); | ||||
|  | ||||
|         // filter selection | ||||
|         $collection = $unfiltered->filter( | ||||
|             function (Recurrence $recurrence) use ($currency) { | ||||
|                 /** @var RecurrenceTransaction $transaction */ | ||||
|                 foreach ($recurrence->recurrenceTransactions as $transaction) { | ||||
|                     if ($transaction->transaction_currency_id === $currency->id || $transaction->foreign_currency_id === $currency->id) { | ||||
|                         return $recurrence; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 return null; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|  | ||||
|         $count      = $collection->count(); | ||||
|         $piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.currencies.recurrences', [$currency->code]) . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var RecurrenceTransformer $transformer */ | ||||
|         $transformer = app(RecurrenceTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($piggyBanks, $transformer, 'recurrences'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List all of them. | ||||
|      * | ||||
|      * @param Request             $request | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return JsonResponse] | ||||
|      */ | ||||
|     public function rules(Request $request, TransactionCurrency $currency): JsonResponse | ||||
|     { | ||||
|         $manager  = new Manager; | ||||
|         $baseUrl  = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of budgets. Count it and split it. | ||||
|         /** @var RuleRepositoryInterface $repository */ | ||||
|         $repository = app(RuleRepositoryInterface::class); | ||||
|         $unfiltered = $repository->getAll(); | ||||
|  | ||||
|         $collection = $unfiltered->filter( | ||||
|             function (Rule $rule) use ($currency) { | ||||
|                 /** @var RuleTrigger $trigger */ | ||||
|                 foreach ($rule->ruleTriggers as $trigger) { | ||||
|                     if ('currency_is' === $trigger->trigger_type && $currency->name === $trigger->trigger_value) { | ||||
|                         return $rule; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 return null; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         $count = $collection->count(); | ||||
|         $rules = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.rules.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var RuleTransformer $transformer */ | ||||
|         $transformer = app(RuleTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($rules, $transformer, 'rules'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show a currency. | ||||
|      * | ||||
|      * @param Request             $request | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, TransactionCurrency $currency): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user()); | ||||
|         $this->parameters->set('defaultCurrency', $defaultCurrency); | ||||
|  | ||||
|         /** @var CurrencyTransformer $transformer */ | ||||
|         $transformer = app(CurrencyTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($currency, $transformer, 'currencies'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store new currency. | ||||
|      * | ||||
|      * @param CurrencyRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(CurrencyRequest $request): JsonResponse | ||||
|     { | ||||
|         $currency = $this->repository->store($request->getAll()); | ||||
|  | ||||
|         if (null !== $currency) { | ||||
|             if (true === $request->boolean('default')) { | ||||
|                 app('preferences')->set('currencyPreference', $currency->code); | ||||
|                 app('preferences')->mark(); | ||||
|             } | ||||
|             $manager = new Manager(); | ||||
|             $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|             $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|             $defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user()); | ||||
|             $this->parameters->set('defaultCurrency', $defaultCurrency); | ||||
|  | ||||
|             /** @var CurrencyTransformer $transformer */ | ||||
|             $transformer = app(CurrencyTransformer::class); | ||||
|             $transformer->setParameters($this->parameters); | ||||
|  | ||||
|             $resource = new Item($currency, $transformer, 'currencies'); | ||||
|  | ||||
|             return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         } | ||||
|         throw new FireflyException('Could not store new currency.'); // @codeCoverageIgnore | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show all transactions. | ||||
|      * | ||||
|      * @param Request             $request | ||||
|      * | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function transactions(Request $request, TransactionCurrency $currency): JsonResponse | ||||
|     { | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $type     = $request->get('type') ?? 'default'; | ||||
|         $this->parameters->set('type', $type); | ||||
|  | ||||
|         $types   = $this->mapTransactionTypes($this->parameters->get('type')); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var User $admin */ | ||||
|         $admin = auth()->user(); | ||||
|         /** @var TransactionCollectorInterface $collector */ | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setUser($admin); | ||||
|         $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); | ||||
|         $collector->setAllAssetAccounts(); | ||||
|         $collector->setCurrency($currency); | ||||
|  | ||||
|         if (\in_array(TransactionType::TRANSFER, $types, true)) { | ||||
|             $collector->removeFilter(InternalTransferFilter::class); | ||||
|         } | ||||
|  | ||||
|         if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) { | ||||
|             $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); | ||||
|         } | ||||
|         $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); | ||||
|         $collector->setTypes($types); | ||||
|         $paginator = $collector->getPaginatedTransactions(); | ||||
|         $paginator->setPath(route('api.v1.currencies.transactions', [$currency->code]) . $this->buildParams()); | ||||
|         $transactions = $paginator->getCollection(); | ||||
|  | ||||
|         /** @var TransactionTransformer $transformer */ | ||||
|         $transformer = app(TransactionTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($transactions, $transformer, 'transactions'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update a currency. | ||||
|      * | ||||
|      * @param CurrencyRequest     $request | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(CurrencyRequest $request, TransactionCurrency $currency): JsonResponse | ||||
|     { | ||||
|         $data     = $request->getAll(); | ||||
|         $currency = $this->repository->update($currency, $data); | ||||
|  | ||||
|         if (true === $request->boolean('default')) { | ||||
|             app('preferences')->set('currencyPreference', $currency->code); | ||||
|             app('preferences')->mark(); | ||||
|         } | ||||
|  | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user()); | ||||
|         $this->parameters->set('defaultCurrency', $defaultCurrency); | ||||
|  | ||||
|         /** @var CurrencyTransformer $transformer */ | ||||
|         $transformer = app(CurrencyTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($currency, $transformer, 'currencies'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										114
									
								
								app/Api/V1/Controllers/CurrencyExchangeRateController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								app/Api/V1/Controllers/CurrencyExchangeRateController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,114 @@ | ||||
| <?php | ||||
| /** | ||||
|  * CurrencyExchangeRateController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; | ||||
| use FireflyIII\Services\Currency\ExchangeRateInterface; | ||||
| use FireflyIII\Transformers\CurrencyExchangeRateTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class CurrencyExchangeRateController | ||||
|  */ | ||||
| class CurrencyExchangeRateController extends Controller | ||||
| { | ||||
|     /** @var CurrencyRepositoryInterface The currency repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * CurrencyExchangeRateController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $admin */ | ||||
|                 $admin = auth()->user(); | ||||
|  | ||||
|                 $this->repository = app(CurrencyRepositoryInterface::class); | ||||
|                 $this->repository->setUser($admin); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show an exchange rate. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $fromCurrency = $this->repository->findByCodeNull($request->get('from') ?? 'EUR'); | ||||
|         $toCurrency   = $this->repository->findByCodeNull($request->get('to') ?? 'USD'); | ||||
|  | ||||
|         if (null === $fromCurrency) { | ||||
|             throw new FireflyException('Unknown source currency.'); | ||||
|         } | ||||
|         if (null === $toCurrency) { | ||||
|             throw new FireflyException('Unknown destination currency.'); | ||||
|         } | ||||
|  | ||||
|         $dateObj = Carbon::createFromFormat('Y-m-d', $request->get('date') ?? date('Y-m-d')); | ||||
|         $this->parameters->set('from', $fromCurrency->code); | ||||
|         $this->parameters->set('to', $toCurrency->code); | ||||
|         $this->parameters->set('date', $dateObj->format('Y-m-d')); | ||||
|         $this->parameters->set('amount', $request->get('amount')); | ||||
|  | ||||
|         $rate = $this->repository->getExchangeRate($fromCurrency, $toCurrency, $dateObj); | ||||
|         if (null === $rate) { | ||||
|             /** @var User $admin */ | ||||
|             $admin = auth()->user(); | ||||
|             // create service: | ||||
|             /** @var ExchangeRateInterface $service */ | ||||
|             $service = app(ExchangeRateInterface::class); | ||||
|             $service->setUser($admin); | ||||
|             $rate = $service->getRate($fromCurrency, $toCurrency, $dateObj); | ||||
|         } | ||||
|         /** @var CurrencyExchangeRateTransformer $transformer */ | ||||
|         $transformer = app(CurrencyExchangeRateTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|         $resource = new Item($rate, $transformer, 'currency_exchange_rates'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										185
									
								
								app/Api/V1/Controllers/ImportController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								app/Api/V1/Controllers/ImportController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,185 @@ | ||||
| <?php | ||||
| /** | ||||
|  * ImportController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Helpers\Collector\TransactionCollectorInterface; | ||||
| use FireflyIII\Helpers\Filter\InternalTransferFilter; | ||||
| use FireflyIII\Models\ImportJob; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Transformers\ImportJobTransformer; | ||||
| use FireflyIII\Transformers\TransactionTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use Illuminate\Support\Collection; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class ImportController | ||||
|  */ | ||||
| class ImportController extends Controller | ||||
| { | ||||
|     use TransactionFilter; | ||||
|     /** @var ImportJobRepositoryInterface Import job repository. */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * LinkTypeController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user             = auth()->user(); | ||||
|                 $this->repository = app(ImportJobRepositoryInterface::class); | ||||
|                 $this->repository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function listAll(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager  = new Manager; | ||||
|         $baseUrl  = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of accounts. Count it and split it. | ||||
|         $collection = $this->repository->get(); | ||||
|         $count      = $collection->count(); | ||||
|         $importJobs = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($importJobs, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.import.list') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var ImportJobTransformer $transformer */ | ||||
|         $transformer = app(ImportJobTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($importJobs, $transformer, 'import_jobs'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Request   $request | ||||
|      * @param ImportJob $importJob | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, ImportJob $importJob): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var ImportJobTransformer $transformer */ | ||||
|         $transformer = app(ImportJobTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($importJob, $transformer, 'import_jobs'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show all transactions | ||||
|      * | ||||
|      * @param Request   $request | ||||
|      * @param ImportJob $importJob | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function transactions(Request $request, ImportJob $importJob): JsonResponse | ||||
|     { | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $type     = $request->get('type') ?? 'default'; | ||||
|         $this->parameters->set('type', $type); | ||||
|  | ||||
|         $types   = $this->mapTransactionTypes($this->parameters->get('type')); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $tag          = $importJob->tag; | ||||
|         $transactions = new Collection(); | ||||
|         $paginator    = new LengthAwarePaginator($transactions, 0, $pageSize); | ||||
|         $paginator->setPath(route('api.v1.import.transactions', [$importJob->key]) . $this->buildParams()); | ||||
|  | ||||
|         if (null !== $tag) { | ||||
|             /** @var User $admin */ | ||||
|             $admin = auth()->user(); | ||||
|             /** @var TransactionCollectorInterface $collector */ | ||||
|             $collector = app(TransactionCollectorInterface::class); | ||||
|             $collector->setUser($admin); | ||||
|             $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); | ||||
|             $collector->setAllAssetAccounts(); | ||||
|             $collector->setTag($tag); | ||||
|  | ||||
|             if (\in_array(TransactionType::TRANSFER, $types, true)) { | ||||
|                 $collector->removeFilter(InternalTransferFilter::class); | ||||
|             } | ||||
|  | ||||
|             if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) { | ||||
|                 $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); | ||||
|             } | ||||
|             $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); | ||||
|             $collector->setTypes($types); | ||||
|             $paginator = $collector->getPaginatedTransactions(); | ||||
|             $paginator->setPath(route('api.v1.transactions.index') . $this->buildParams()); | ||||
|             $transactions = $paginator->getCollection(); | ||||
|         } | ||||
|  | ||||
|         /** @var TransactionTransformer $transformer */ | ||||
|         $transformer = app(TransactionTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($transactions, $transformer, 'transactions'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										282
									
								
								app/Api/V1/Controllers/LinkTypeController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										282
									
								
								app/Api/V1/Controllers/LinkTypeController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,282 @@ | ||||
| <?php | ||||
| /** | ||||
|  * LinkTypeController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\LinkTypeRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Collector\TransactionCollectorInterface; | ||||
| use FireflyIII\Helpers\Filter\InternalTransferFilter; | ||||
| use FireflyIII\Models\LinkType; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface; | ||||
| use FireflyIII\Repositories\User\UserRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Transformers\LinkTypeTransformer; | ||||
| use FireflyIII\Transformers\TransactionTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class LinkTypeController. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class LinkTypeController extends Controller | ||||
| { | ||||
|     use TransactionFilter; | ||||
|     /** @var LinkTypeRepositoryInterface The link type repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** @var UserRepositoryInterface The user repository */ | ||||
|     private $userRepository; | ||||
|  | ||||
|     /** | ||||
|      * LinkTypeController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user                 = auth()->user(); | ||||
|                 $this->repository     = app(LinkTypeRepositoryInterface::class); | ||||
|                 $this->userRepository = app(UserRepositoryInterface::class); | ||||
|                 $this->repository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Delete the resource. | ||||
|      * | ||||
|      * @param LinkType $linkType | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function delete(LinkType $linkType): JsonResponse | ||||
|     { | ||||
|         if (false === $linkType->editable) { | ||||
|             throw new FireflyException(sprintf('You cannot delete this link type (#%d, "%s")', $linkType->id, $linkType->name)); | ||||
|         } | ||||
|         $this->repository->destroy($linkType); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List all of them. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse] | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager  = new Manager; | ||||
|         $baseUrl  = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of accounts. Count it and split it. | ||||
|         $collection = $this->repository->get(); | ||||
|         $count      = $collection->count(); | ||||
|         $linkTypes  = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($linkTypes, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.link_types.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var LinkTypeTransformer $transformer */ | ||||
|         $transformer = app(LinkTypeTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($linkTypes, $transformer, 'link_types'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List single resource. | ||||
|      * | ||||
|      * @param Request  $request | ||||
|      * @param LinkType $linkType | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, LinkType $linkType): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         /** @var LinkTypeTransformer $transformer */ | ||||
|         $transformer = app(LinkTypeTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($linkType, $transformer, 'link_types'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store new object. | ||||
|      * | ||||
|      * @param LinkTypeRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(LinkTypeRequest $request): JsonResponse | ||||
|     { | ||||
|         /** @var User $admin */ | ||||
|         $admin = auth()->user(); | ||||
|  | ||||
|         if (!$this->userRepository->hasRole($admin, 'owner')) { | ||||
|             throw new FireflyException('You need the "owner"-role to do this.'); | ||||
|         } | ||||
|         $data = $request->getAll(); | ||||
|         // if currency ID is 0, find the currency by the code: | ||||
|         $linkType = $this->repository->store($data); | ||||
|         $manager  = new Manager; | ||||
|         $baseUrl  = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var LinkTypeTransformer $transformer */ | ||||
|         $transformer = app(LinkTypeTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|         $resource = new Item($linkType, $transformer, 'link_types'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Delete the resource. | ||||
|      * | ||||
|      * @param Request  $request | ||||
|      * @param LinkType $linkType | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function transactions(Request $request, LinkType $linkType): JsonResponse | ||||
|     { | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $type     = $request->get('type') ?? 'default'; | ||||
|         $this->parameters->set('type', $type); | ||||
|  | ||||
|         $types   = $this->mapTransactionTypes($this->parameters->get('type')); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         // whatever is returned by the query, it must be part of these journals: | ||||
|         $journalIds = $this->repository->getJournalIds($linkType); | ||||
|  | ||||
|         /** @var User $admin */ | ||||
|         $admin = auth()->user(); | ||||
|         /** @var TransactionCollectorInterface $collector */ | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setUser($admin); | ||||
|         $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); | ||||
|         $collector->setAllAssetAccounts(); | ||||
|         $collector->setJournalIds($journalIds); | ||||
|  | ||||
|         if (\in_array(TransactionType::TRANSFER, $types, true)) { | ||||
|             $collector->removeFilter(InternalTransferFilter::class); | ||||
|         } | ||||
|  | ||||
|         if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) { | ||||
|             $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); | ||||
|         } | ||||
|         $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); | ||||
|         $collector->setTypes($types); | ||||
|         $paginator = $collector->getPaginatedTransactions(); | ||||
|         $paginator->setPath(route('api.v1.transactions.index') . $this->buildParams()); | ||||
|         $transactions = $paginator->getCollection(); | ||||
|  | ||||
|         /** @var TransactionTransformer $transformer */ | ||||
|         $transformer = app(TransactionTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($transactions, $transformer, 'transactions'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Update object. | ||||
|      * | ||||
|      * @param LinkTypeRequest $request | ||||
|      * @param LinkType        $linkType | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function update(LinkTypeRequest $request, LinkType $linkType): JsonResponse | ||||
|     { | ||||
|         if (false === $linkType->editable) { | ||||
|             throw new FireflyException(sprintf('You cannot edit this link type (#%d, "%s")', $linkType->id, $linkType->name)); | ||||
|         } | ||||
|  | ||||
|         /** @var User $admin */ | ||||
|         $admin = auth()->user(); | ||||
|  | ||||
|         if (!$this->userRepository->hasRole($admin, 'owner')) { | ||||
|             throw new FireflyException('You need the "owner"-role to do this.'); | ||||
|         } | ||||
|  | ||||
|         $data = $request->getAll(); | ||||
|         $this->repository->update($linkType, $data); | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var LinkTypeTransformer $transformer */ | ||||
|         $transformer = app(LinkTypeTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($linkType, $transformer, 'link_types'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										237
									
								
								app/Api/V1/Controllers/PiggyBankController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										237
									
								
								app/Api/V1/Controllers/PiggyBankController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,237 @@ | ||||
| <?php | ||||
| /** | ||||
|  * PiggyBankController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\PiggyBankRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; | ||||
| use FireflyIII\Transformers\PiggyBankEventTransformer; | ||||
| use FireflyIII\Transformers\PiggyBankTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class PiggyBankController. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class PiggyBankController extends Controller | ||||
| { | ||||
|  | ||||
|     /** @var PiggyBankRepositoryInterface The piggy bank repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * PiggyBankController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $admin */ | ||||
|                 $admin = auth()->user(); | ||||
|  | ||||
|                 $this->repository = app(PiggyBankRepositoryInterface::class); | ||||
|                 $this->repository->setUser($admin); | ||||
|  | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Delete the resource. | ||||
|      * | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(PiggyBank $piggyBank): JsonResponse | ||||
|     { | ||||
|         $this->repository->destroy($piggyBank); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List all of them. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse] | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of budgets. Count it and split it. | ||||
|         $collection = $this->repository->getPiggyBanks(); | ||||
|         $count      = $collection->count(); | ||||
|         $piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.piggy_banks.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var PiggyBankTransformer $transformer */ | ||||
|         $transformer = app(PiggyBankTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($piggyBanks, $transformer, 'piggy_banks'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List single resource. | ||||
|      * | ||||
|      * @param Request   $request | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function piggyBankEvents(Request $request, PiggyBank $piggyBank): JsonResponse | ||||
|     { | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $manager  = new Manager(); | ||||
|         $baseUrl  = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $collection = $this->repository->getEvents($piggyBank); | ||||
|         $count      = $collection->count(); | ||||
|         $events     = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.piggy_banks.events', [$piggyBank->id]) . $this->buildParams()); | ||||
|  | ||||
|         /** @var PiggyBankEventTransformer $transformer */ | ||||
|         $transformer = app(PiggyBankEventTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($events, $transformer, 'piggy_bank_events'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List single resource. | ||||
|      * | ||||
|      * @param Request   $request | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, PiggyBank $piggyBank): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var PiggyBankTransformer $transformer */ | ||||
|         $transformer = app(PiggyBankTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($piggyBank, $transformer, 'piggy_banks'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store new object. | ||||
|      * | ||||
|      * @param PiggyBankRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(PiggyBankRequest $request): JsonResponse | ||||
|     { | ||||
|         $piggyBank = $this->repository->store($request->getAll()); | ||||
|         if (null !== $piggyBank) { | ||||
|             $manager = new Manager(); | ||||
|             $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|             $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|             /** @var PiggyBankTransformer $transformer */ | ||||
|             $transformer = app(PiggyBankTransformer::class); | ||||
|             $transformer->setParameters($this->parameters); | ||||
|  | ||||
|             $resource = new Item($piggyBank, $transformer, 'piggy_banks'); | ||||
|  | ||||
|             return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         } | ||||
|         throw new FireflyException('Could not store new piggy bank.'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update piggy bank. | ||||
|      * | ||||
|      * @param PiggyBankRequest $request | ||||
|      * @param PiggyBank        $piggyBank | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(PiggyBankRequest $request, PiggyBank $piggyBank): JsonResponse | ||||
|     { | ||||
|         $piggyBank = $this->repository->update($piggyBank, $request->getAll()); | ||||
|         $manager   = new Manager(); | ||||
|         $baseUrl   = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var PiggyBankTransformer $transformer */ | ||||
|         $transformer = app(PiggyBankTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($piggyBank, $transformer, 'piggy_banks'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										189
									
								
								app/Api/V1/Controllers/PreferenceController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										189
									
								
								app/Api/V1/Controllers/PreferenceController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,189 @@ | ||||
| <?php | ||||
| /** | ||||
|  * PreferencesController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\PreferenceRequest; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Models\Preference; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Transformers\PreferenceTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Collection; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * Class PreferenceController | ||||
|  */ | ||||
| class PreferenceController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * LinkTypeController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user       = auth()->user(); | ||||
|                 $repository = app(AccountRepositoryInterface::class); | ||||
|                 $repository->setUser($user); | ||||
|  | ||||
|                 // an important fallback is that the frontPageAccount array gets refilled automatically | ||||
|                 // when it turns up empty. | ||||
|                 $frontPageAccounts = app('preferences')->getForUser($user, 'frontPageAccounts', [])->data; | ||||
|                 if (0 === \count($frontPageAccounts)) { | ||||
|                     /** @var Collection $accounts */ | ||||
|                     $accounts   = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]); | ||||
|                     $accountIds = $accounts->pluck('id')->toArray(); | ||||
|                     app('preferences')->setForUser($user, 'frontPageAccounts', $accountIds); | ||||
|                 } | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List all of them. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse] | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         /** @var User $user */ | ||||
|         $user      = auth()->user(); | ||||
|         $available = [ | ||||
|             'language', 'customFiscalYear', 'fiscalYearStart', 'currencyPreference', | ||||
|             'transaction_journal_optional_fields', 'frontPageAccounts', 'viewRange', | ||||
|             'listPageSize, twoFactorAuthEnabled', | ||||
|         ]; | ||||
|  | ||||
|         $preferences = new Collection; | ||||
|         foreach ($available as $name) { | ||||
|             $pref = app('preferences')->getForUser($user, $name); | ||||
|             if (null !== $pref) { | ||||
|                 $preferences->push($pref); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var PreferenceTransformer $transformer */ | ||||
|         $transformer = app(PreferenceTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($preferences, $transformer, 'preferences'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Return a single preference by name. | ||||
|      * | ||||
|      * @param Request    $request | ||||
|      * @param Preference $preference | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      */ | ||||
|     public function show(Request $request, Preference $preference): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         /** @var PreferenceTransformer $transformer */ | ||||
|         $transformer = app(PreferenceTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($preference, $transformer, 'preferences'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update a preference. | ||||
|      * | ||||
|      * @param PreferenceRequest $request | ||||
|      * @param Preference        $preference | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      */ | ||||
|     public function update(PreferenceRequest $request, Preference $preference): JsonResponse | ||||
|     { | ||||
|  | ||||
|         $data     = $request->getAll(); | ||||
|         $newValue = $data['data']; | ||||
|         switch ($preference->name) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'transaction_journal_optional_fields': | ||||
|             case 'frontPageAccounts': | ||||
|                 $newValue = explode(',', $data['data']); | ||||
|                 break; | ||||
|             case 'listPageSize': | ||||
|                 $newValue = (int)$data['data']; | ||||
|                 break; | ||||
|             case 'customFiscalYear': | ||||
|             case 'twoFactorAuthEnabled': | ||||
|                 $newValue = 1 === (int)$data['data']; | ||||
|                 break; | ||||
|         } | ||||
|         $result = app('preferences')->set($preference->name, $newValue); | ||||
|  | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         /** @var PreferenceTransformer $transformer */ | ||||
|         $transformer = app(PreferenceTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($result, $transformer, 'preferences'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										280
									
								
								app/Api/V1/Controllers/RecurrenceController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										280
									
								
								app/Api/V1/Controllers/RecurrenceController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,280 @@ | ||||
| <?php | ||||
| /** | ||||
|  * RecurrenceController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\RecurrenceRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Collector\TransactionCollectorInterface; | ||||
| use FireflyIII\Helpers\Filter\InternalTransferFilter; | ||||
| use FireflyIII\Models\Recurrence; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; | ||||
| use FireflyIII\Support\Cronjobs\RecurringCronjob; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Transformers\RecurrenceTransformer; | ||||
| use FireflyIII\Transformers\TransactionTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class RecurrenceController | ||||
|  */ | ||||
| class RecurrenceController extends Controller | ||||
| { | ||||
|     use TransactionFilter; | ||||
|     /** @var RecurringRepositoryInterface The recurring transaction repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * RecurrenceController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user = auth()->user(); | ||||
|  | ||||
|                 /** @var RecurringRepositoryInterface repository */ | ||||
|                 $this->repository = app(RecurringRepositoryInterface::class); | ||||
|                 $this->repository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Delete the resource. | ||||
|      * | ||||
|      * @param Recurrence $recurrence | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(Recurrence $recurrence): JsonResponse | ||||
|     { | ||||
|         $this->repository->destroy($recurrence); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List all of them. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse] | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of budgets. Count it and split it. | ||||
|         $collection = $this->repository->getAll(); | ||||
|         $count      = $collection->count(); | ||||
|         $piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.recurrences.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var RecurrenceTransformer $transformer */ | ||||
|         $transformer = app(RecurrenceTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($piggyBanks, $transformer, 'recurrences'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List single resource. | ||||
|      * | ||||
|      * @param Request    $request | ||||
|      * @param Recurrence $recurrence | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, Recurrence $recurrence): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var RecurrenceTransformer $transformer */ | ||||
|         $transformer = app(RecurrenceTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($recurrence, $transformer, 'recurrences'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store new object. | ||||
|      * | ||||
|      * @param RecurrenceRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function store(RecurrenceRequest $request): JsonResponse | ||||
|     { | ||||
|         $recurrence = $this->repository->store($request->getAll()); | ||||
|         $manager    = new Manager(); | ||||
|         $baseUrl    = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var RecurrenceTransformer $transformer */ | ||||
|         $transformer = app(RecurrenceTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($recurrence, $transformer, 'recurrences'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show transactions for this recurrence. | ||||
|      * | ||||
|      * @param Request    $request | ||||
|      * @param Recurrence $recurrence | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function transactions(Request $request, Recurrence $recurrence): JsonResponse | ||||
|     { | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $type     = $request->get('type') ?? 'default'; | ||||
|         $this->parameters->set('type', $type); | ||||
|  | ||||
|         $types   = $this->mapTransactionTypes($this->parameters->get('type')); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         // whatever is returned by the query, it must be part of these journals: | ||||
|         $journalIds = $this->repository->getJournalIds($recurrence); | ||||
|  | ||||
|         /** @var User $admin */ | ||||
|         $admin = auth()->user(); | ||||
|         /** @var TransactionCollectorInterface $collector */ | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setUser($admin); | ||||
|         $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); | ||||
|         $collector->setAllAssetAccounts(); | ||||
|         $collector->setJournalIds($journalIds); | ||||
|  | ||||
|         if (\in_array(TransactionType::TRANSFER, $types, true)) { | ||||
|             $collector->removeFilter(InternalTransferFilter::class); | ||||
|         } | ||||
|  | ||||
|         if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) { | ||||
|             $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); | ||||
|         } | ||||
|         $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); | ||||
|         $collector->setTypes($types); | ||||
|         $paginator = $collector->getPaginatedTransactions(); | ||||
|         $paginator->setPath(route('api.v1.transactions.index') . $this->buildParams()); | ||||
|         $transactions = $paginator->getCollection(); | ||||
|  | ||||
|         /** @var TransactionTransformer $transformer */ | ||||
|         $transformer = app(TransactionTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($transactions, $transformer, 'transactions'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function trigger(): JsonResponse | ||||
|     { | ||||
|         /** @var RecurringCronjob $recurring */ | ||||
|         $recurring = app(RecurringCronjob::class); | ||||
|         try { | ||||
|             $result = $recurring->fire(); | ||||
|         } catch (FireflyException $e) { | ||||
|             Log::error($e->getMessage()); | ||||
|             throw new FireflyException('Could not fire recurring cron job.'); | ||||
|         } | ||||
|         if (false === $result) { | ||||
|             return response()->json([], 204); | ||||
|         } | ||||
|         if (true === $result) { | ||||
|             return response()->json(); | ||||
|         } | ||||
|  | ||||
|         return response()->json([], 418); // @codeCoverageIgnore | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update single recurrence. | ||||
|      * | ||||
|      * @param RecurrenceRequest $request | ||||
|      * @param Recurrence        $recurrence | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(RecurrenceRequest $request, Recurrence $recurrence): JsonResponse | ||||
|     { | ||||
|         $data     = $request->getAll(); | ||||
|         $category = $this->repository->update($recurrence, $data); | ||||
|         $manager  = new Manager(); | ||||
|         $baseUrl  = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         /** @var RecurrenceTransformer $transformer */ | ||||
|         $transformer = app(RecurrenceTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($category, $transformer, 'recurrences'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										317
									
								
								app/Api/V1/Controllers/RuleController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										317
									
								
								app/Api/V1/Controllers/RuleController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,317 @@ | ||||
| <?php | ||||
| /** | ||||
|  * RuleController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Api\V1\Requests\RuleRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Jobs\ExecuteRuleOnExistingTransactions; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Models\Rule; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Rule\RuleRepositoryInterface; | ||||
| use FireflyIII\TransactionRules\TransactionMatcher; | ||||
| use FireflyIII\Transformers\RuleTransformer; | ||||
| use FireflyIII\Transformers\TransactionTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use Illuminate\Support\Collection; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class RuleController | ||||
|  */ | ||||
| class RuleController extends Controller | ||||
| { | ||||
|     /** @var AccountRepositoryInterface Account repository */ | ||||
|     private $accountRepository; | ||||
|     /** @var RuleRepositoryInterface The rule repository */ | ||||
|     private $ruleRepository; | ||||
|  | ||||
|     /** | ||||
|      * RuleController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user = auth()->user(); | ||||
|  | ||||
|                 $this->ruleRepository = app(RuleRepositoryInterface::class); | ||||
|                 $this->ruleRepository->setUser($user); | ||||
|  | ||||
|                 $this->accountRepository = app(AccountRepositoryInterface::class); | ||||
|                 $this->accountRepository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Delete the resource. | ||||
|      * | ||||
|      * @param Rule $rule | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(Rule $rule): JsonResponse | ||||
|     { | ||||
|         $this->ruleRepository->destroy($rule); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List all of them. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse] | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of budgets. Count it and split it. | ||||
|         $collection = $this->ruleRepository->getAll(); | ||||
|         $count      = $collection->count(); | ||||
|         $rules      = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.rules.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var RuleTransformer $transformer */ | ||||
|         $transformer = app(RuleTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($rules, $transformer, 'rules'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List single resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * @param Rule    $rule | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, Rule $rule): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var RuleTransformer $transformer */ | ||||
|         $transformer = app(RuleTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($rule, $transformer, 'rules'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store new object. | ||||
|      * | ||||
|      * @param RuleRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function store(RuleRequest $request): JsonResponse | ||||
|     { | ||||
|         $rule    = $this->ruleRepository->store($request->getAll()); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var RuleTransformer $transformer */ | ||||
|         $transformer = app(RuleTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($rule, $transformer, 'rules'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Request $request | ||||
|      * @param Rule    $rule | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function testRule(Request $request, Rule $rule): JsonResponse | ||||
|     { | ||||
|         $pageSize     = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $page         = 0 === (int)$request->query('page') ? 1 : (int)$request->query('page'); | ||||
|         $startDate    = null === $request->query('start_date') ? null : Carbon::createFromFormat('Y-m-d', $request->query('start_date')); | ||||
|         $endDate      = null === $request->query('end_date') ? null : Carbon::createFromFormat('Y-m-d', $request->query('end_date')); | ||||
|         $searchLimit  = 0 === (int)$request->query('search_limit') ? (int)config('firefly.test-triggers.limit') : (int)$request->query('search_limit'); | ||||
|         $triggerLimit = 0 === (int)$request->query('triggered_limit') ? (int)config('firefly.test-triggers.range') : (int)$request->query('triggered_limit'); | ||||
|         $accountList  = '' === (string)$request->query('accounts') ? [] : explode(',', $request->query('accounts')); | ||||
|         $accounts     = new Collection; | ||||
|  | ||||
|         foreach ($accountList as $accountId) { | ||||
|             Log::debug(sprintf('Searching for asset account with id "%s"', $accountId)); | ||||
|             $account = $this->accountRepository->findNull((int)$accountId); | ||||
|             if (null !== $account && AccountType::ASSET === $account->accountType->type) { | ||||
|                 Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name)); | ||||
|                 $accounts->push($account); | ||||
|             } | ||||
|             if (null === $account) { | ||||
|                 Log::debug(sprintf('No asset account with id "%s"', $accountId)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** @var Rule $rule */ | ||||
|         Log::debug(sprintf('Now testing rule #%d, "%s"', $rule->id, $rule->title)); | ||||
|         /** @var TransactionMatcher $matcher */ | ||||
|         $matcher = app(TransactionMatcher::class); | ||||
|         // set all parameters: | ||||
|         $matcher->setRule($rule); | ||||
|         $matcher->setStartDate($startDate); | ||||
|         $matcher->setEndDate($endDate); | ||||
|         $matcher->setSearchLimit($searchLimit); | ||||
|         $matcher->setTriggeredLimit($triggerLimit); | ||||
|         $matcher->setAccounts($accounts); | ||||
|  | ||||
|         $matchingTransactions = $matcher->findTransactionsByRule(); | ||||
|         $matchingTransactions = $matchingTransactions->unique('id'); | ||||
|  | ||||
|         // make paginator out of results. | ||||
|         $count        = $matchingTransactions->count(); | ||||
|         $transactions = $matchingTransactions->slice(($page - 1) * $pageSize, $pageSize); | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($transactions, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.rules.test', [$rule->id]) . $this->buildParams()); | ||||
|  | ||||
|         // resulting list is presented as JSON thing. | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var TransactionTransformer $transformer */ | ||||
|         $transformer = app(TransactionTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($matchingTransactions, $transformer, 'transactions'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Execute the given rule group on a set of existing transactions. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * @param Rule    $rule | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function triggerRule(Request $request, Rule $rule): JsonResponse | ||||
|     { | ||||
|         // Get parameters specified by the user | ||||
|         /** @var User $user */ | ||||
|         $user        = auth()->user(); | ||||
|         $startDate   = new Carbon($request->get('start_date')); | ||||
|         $endDate     = new Carbon($request->get('end_date')); | ||||
|         $accountList = '' === (string)$request->query('accounts') ? [] : explode(',', $request->query('accounts')); | ||||
|         $accounts    = new Collection; | ||||
|  | ||||
|         foreach ($accountList as $accountId) { | ||||
|             Log::debug(sprintf('Searching for asset account with id "%s"', $accountId)); | ||||
|             $account = $this->accountRepository->findNull((int)$accountId); | ||||
|             if (null !== $account && $this->accountRepository->isAsset($account)) { | ||||
|                 Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name)); | ||||
|                 $accounts->push($account); | ||||
|             } | ||||
|             if (null === $account) { | ||||
|                 Log::debug(sprintf('No asset account with id "%s"', $accountId)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Create a job to do the work asynchronously | ||||
|         $job = new ExecuteRuleOnExistingTransactions($rule); | ||||
|  | ||||
|         // Apply parameters to the job | ||||
|         $job->setUser($user); | ||||
|         $job->setAccounts($accounts); | ||||
|         $job->setStartDate($startDate); | ||||
|         $job->setEndDate($endDate); | ||||
|  | ||||
|         // Dispatch a new job to execute it in a queue | ||||
|         $this->dispatch($job); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update a rule. | ||||
|      * | ||||
|      * @param RuleRequest $request | ||||
|      * @param Rule        $rule | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(RuleRequest $request, Rule $rule): JsonResponse | ||||
|     { | ||||
|         $rule    = $this->ruleRepository->update($rule, $request->getAll()); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var RuleTransformer $transformer */ | ||||
|         $transformer = app(RuleTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($rule, $transformer, 'rules'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										401
									
								
								app/Api/V1/Controllers/RuleGroupController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										401
									
								
								app/Api/V1/Controllers/RuleGroupController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,401 @@ | ||||
| <?php | ||||
| /** | ||||
|  * RuleGroupController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Api\V1\Requests\RuleGroupRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Jobs\ExecuteRuleOnExistingTransactions; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Models\Rule; | ||||
| use FireflyIII\Models\RuleGroup; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface; | ||||
| use FireflyIII\TransactionRules\TransactionMatcher; | ||||
| use FireflyIII\Transformers\RuleGroupTransformer; | ||||
| use FireflyIII\Transformers\RuleTransformer; | ||||
| use FireflyIII\Transformers\TransactionTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use Illuminate\Support\Collection; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
| use Log; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class RuleGroupController | ||||
|  */ | ||||
| class RuleGroupController extends Controller | ||||
| { | ||||
|     /** @var AccountRepositoryInterface Account repository */ | ||||
|     private $accountRepository; | ||||
|     /** @var RuleGroupRepositoryInterface The rule group repository */ | ||||
|     private $ruleGroupRepository; | ||||
|  | ||||
|     /** | ||||
|      * RuleGroupController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user = auth()->user(); | ||||
|  | ||||
|                 $this->ruleGroupRepository = app(RuleGroupRepositoryInterface::class); | ||||
|                 $this->ruleGroupRepository->setUser($user); | ||||
|  | ||||
|                 $this->accountRepository = app(AccountRepositoryInterface::class); | ||||
|                 $this->accountRepository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Delete the resource. | ||||
|      * | ||||
|      * @param RuleGroup $ruleGroup | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(RuleGroup $ruleGroup): JsonResponse | ||||
|     { | ||||
|         $this->ruleGroupRepository->destroy($ruleGroup, null); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List all of them. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse] | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of rule groups. Count it and split it. | ||||
|         $collection = $this->ruleGroupRepository->get(); | ||||
|         $count      = $collection->count(); | ||||
|         $ruleGroups = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($ruleGroups, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.rule_groups.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var RuleGroupTransformer $transformer */ | ||||
|         $transformer = app(RuleGroupTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($ruleGroups, $transformer, 'rule_groups'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Request   $request | ||||
|      * @param RuleGroup $group | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function rules(Request $request, RuleGroup $group): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of budgets. Count it and split it. | ||||
|         $collection = $this->ruleGroupRepository->getRules($group); | ||||
|         $count      = $collection->count(); | ||||
|         $rules      = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.rule_groups.rules', [$group->id]) . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var RuleTransformer $transformer */ | ||||
|         $transformer = app(RuleTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($rules, $transformer, 'rules'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List single resource. | ||||
|      * | ||||
|      * @param Request   $request | ||||
|      * @param RuleGroup $ruleGroup | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, RuleGroup $ruleGroup): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var RuleGroupTransformer $transformer */ | ||||
|         $transformer = app(RuleGroupTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($ruleGroup, $transformer, 'rule_groups'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store new object. | ||||
|      * | ||||
|      * @param RuleGroupRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function store(RuleGroupRequest $request): JsonResponse | ||||
|     { | ||||
|         $ruleGroup = $this->ruleGroupRepository->store($request->getAll()); | ||||
|         $manager   = new Manager(); | ||||
|         $baseUrl   = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var RuleGroupTransformer $transformer */ | ||||
|         $transformer = app(RuleGroupTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($ruleGroup, $transformer, 'rule_groups'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Request   $request | ||||
|      * @param RuleGroup $group | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function testGroup(Request $request, RuleGroup $group): JsonResponse | ||||
|     { | ||||
|         Log::debug('Now in testGroup()'); | ||||
|         /** @var Collection $rules */ | ||||
|         $rules = $this->ruleGroupRepository->getActiveRules($group); | ||||
|         if (0 === $rules->count()) { | ||||
|             throw new FireflyException('No rules in this rule group.'); | ||||
|         } | ||||
|         $parameters           = $this->getTestParameters($request); | ||||
|         $accounts             = $this->getAccountParameter($parameters['account_list']); | ||||
|         $matchingTransactions = new Collection; | ||||
|  | ||||
|         Log::debug(sprintf('Going to test %d rules', $rules->count())); | ||||
|         /** @var Rule $rule */ | ||||
|         foreach ($rules as $rule) { | ||||
|             Log::debug(sprintf('Now testing rule #%d, "%s"', $rule->id, $rule->title)); | ||||
|             /** @var TransactionMatcher $matcher */ | ||||
|             $matcher = app(TransactionMatcher::class); | ||||
|             // set all parameters: | ||||
|             $matcher->setRule($rule); | ||||
|             $matcher->setStartDate($parameters['start_date']); | ||||
|             $matcher->setEndDate($parameters['end_date']); | ||||
|             $matcher->setSearchLimit($parameters['search_limit']); | ||||
|             $matcher->setTriggeredLimit($parameters['trigger_limit']); | ||||
|             $matcher->setAccounts($accounts); | ||||
|  | ||||
|             $result               = $matcher->findTransactionsByRule(); | ||||
|             $matchingTransactions = $result->merge($matchingTransactions); | ||||
|         } | ||||
|         $matchingTransactions = $matchingTransactions->unique('id'); | ||||
|  | ||||
|         // make paginator out of results. | ||||
|         $count        = $matchingTransactions->count(); | ||||
|         $transactions = $matchingTransactions->slice(($parameters['page'] - 1) * $parameters['page_size'], $parameters['page_size']); | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($transactions, $count, $parameters['page_size'], $parameters['page']); | ||||
|         $paginator->setPath(route('api.v1.rule_groups.test', [$group->id]) . $this->buildParams()); | ||||
|  | ||||
|         // resulting list is presented as JSON thing. | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var TransactionTransformer $transformer */ | ||||
|         $transformer = app(TransactionTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($matchingTransactions, $transformer, 'transactions'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Execute the given rule group on a set of existing transactions. | ||||
|      * | ||||
|      * @param Request   $request | ||||
|      * @param RuleGroup $group | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function triggerGroup(Request $request, RuleGroup $group): JsonResponse | ||||
|     { | ||||
|         // Get parameters specified by the user | ||||
|         /** @var User $user */ | ||||
|         $user        = auth()->user(); | ||||
|         $startDate   = new Carbon($request->get('start_date')); | ||||
|         $endDate     = new Carbon($request->get('end_date')); | ||||
|         $accountList = '' === (string)$request->query('accounts') ? [] : explode(',', $request->query('accounts')); | ||||
|         $accounts    = new Collection; | ||||
|  | ||||
|         foreach ($accountList as $accountId) { | ||||
|             Log::debug(sprintf('Searching for asset account with id "%s"', $accountId)); | ||||
|             $account = $this->accountRepository->findNull((int)$accountId); | ||||
|             if (null !== $account && AccountType::ASSET === $account->accountType->type) { | ||||
|                 Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name)); | ||||
|                 $accounts->push($account); | ||||
|             } | ||||
|             if (null === $account) { | ||||
|                 Log::debug(sprintf('No asset account with id "%s"', $accountId)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** @var Collection $rules */ | ||||
|         $rules = $this->ruleGroupRepository->getActiveRules($group); | ||||
|         foreach ($rules as $rule) { | ||||
|             // Create a job to do the work asynchronously | ||||
|             $job = new ExecuteRuleOnExistingTransactions($rule); | ||||
|  | ||||
|             // Apply parameters to the job | ||||
|             $job->setUser($user); | ||||
|             $job->setAccounts($accounts); | ||||
|             $job->setStartDate($startDate); | ||||
|             $job->setEndDate($endDate); | ||||
|  | ||||
|             // Dispatch a new job to execute it in a queue | ||||
|             $this->dispatch($job); | ||||
|         } | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update a rule group. | ||||
|      * TODO update order of rule group | ||||
|      * | ||||
|      * @param RuleGroupRequest $request | ||||
|      * @param RuleGroup        $ruleGroup | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(RuleGroupRequest $request, RuleGroup $ruleGroup): JsonResponse | ||||
|     { | ||||
|         $ruleGroup = $this->ruleGroupRepository->update($ruleGroup, $request->getAll()); | ||||
|         $manager   = new Manager(); | ||||
|         $baseUrl   = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var RuleGroupTransformer $transformer */ | ||||
|         $transformer = app(RuleGroupTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($ruleGroup, $transformer, 'rule_groups'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $accounts | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     private function getAccountParameter(array $accounts): Collection | ||||
|     { | ||||
|         $return = new Collection; | ||||
|         foreach ($accounts as $accountId) { | ||||
|             Log::debug(sprintf('Searching for asset account with id "%s"', $accountId)); | ||||
|             $account = $this->accountRepository->findNull((int)$accountId); | ||||
|             if (null !== $account && AccountType::ASSET === $account->accountType->type) { | ||||
|                 Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name)); | ||||
|                 $return->push($account); | ||||
|             } | ||||
|             if (null === $account) { | ||||
|                 Log::debug(sprintf('No asset account with id "%s"', $accountId)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getTestParameters(Request $request): array | ||||
|     { | ||||
|         return [ | ||||
|             'page_size'     => (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data, | ||||
|             'page'          => 0 === (int)$request->query('page') ? 1 : (int)$request->query('page'), | ||||
|             'start_date'    => null === $request->query('start_date') ? null : Carbon::createFromFormat('Y-m-d', $request->query('start_date')), | ||||
|             'end_date'      => null === $request->query('end_date') ? null : Carbon::createFromFormat('Y-m-d', $request->query('end_date')), | ||||
|             'search_limit'  => 0 === (int)$request->query('search_limit') ? (int)config('firefly.test-triggers.limit') : (int)$request->query('search_limit'), | ||||
|             'trigger_limit' => 0 === (int)$request->query('triggered_limit') | ||||
|                 ? (int)config('firefly.test-triggers.range') | ||||
|                 : (int)$request->query( | ||||
|                     'triggered_limit' | ||||
|                 ), | ||||
|             'account_list'  => '' === (string)$request->query('accounts') ? [] : explode(',', $request->query('accounts')), | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										417
									
								
								app/Api/V1/Controllers/SummaryController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										417
									
								
								app/Api/V1/Controllers/SummaryController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,417 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * SummaryController.php | ||||
|  * Copyright (c) 2019 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Collector\TransactionCollectorInterface; | ||||
| use FireflyIII\Helpers\Report\NetWorthInterface; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Bill\BillRepositoryInterface; | ||||
| use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class SummaryController | ||||
|  */ | ||||
| class SummaryController extends Controller | ||||
| { | ||||
|     /** @var AccountRepositoryInterface */ | ||||
|     private $accountRepository; | ||||
|     /** @var BillRepositoryInterface */ | ||||
|     private $billRepository; | ||||
|     /** @var BudgetRepositoryInterface */ | ||||
|     private $budgetRepository; | ||||
|     /** @var CurrencyRepositoryInterface */ | ||||
|     private $currencyRepos; | ||||
|  | ||||
|     /** | ||||
|      * AccountController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user                    = auth()->user(); | ||||
|                 $this->currencyRepos     = app(CurrencyRepositoryInterface::class); | ||||
|                 $this->billRepository    = app(BillRepositoryInterface::class); | ||||
|                 $this->budgetRepository  = app(BudgetRepositoryInterface::class); | ||||
|                 $this->accountRepository = app(AccountRepositoryInterface::class); | ||||
|  | ||||
|                 $this->billRepository->setUser($user); | ||||
|                 $this->currencyRepos->setUser($user); | ||||
|                 $this->budgetRepository->setUser($user); | ||||
|                 $this->accountRepository->setUser($user); | ||||
|  | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function basic(Request $request): JsonResponse | ||||
|     { | ||||
|         // parameters for boxes: | ||||
|         $start = (string)$request->get('start'); | ||||
|         $end   = (string)$request->get('end'); | ||||
|         if ('' === $start || '' === $end) { | ||||
|             throw new FireflyException('Start and end are mandatory parameters.'); | ||||
|         } | ||||
|         $start = Carbon::createFromFormat('Y-m-d', $start); | ||||
|         $end   = Carbon::createFromFormat('Y-m-d', $end); | ||||
|         // balance information: | ||||
|         $balanceData  = $this->getBalanceInformation($start, $end); | ||||
|         $billData     = $this->getBillInformation($start, $end); | ||||
|         $spentData    = $this->getLeftToSpendInfo($start, $end); | ||||
|         $networthData = $this->getNetWorthInfo($start, $end); | ||||
|         $total        = array_merge($balanceData, $billData, $spentData, $networthData); | ||||
|  | ||||
|         // TODO: liabilities with icon line-chart | ||||
|  | ||||
|         return response()->json($total); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Check if date is outside session range. | ||||
|      * | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return bool | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      */ | ||||
|     protected function notInDateRange(Carbon $date, Carbon $start, Carbon $end): bool // Validate a preference | ||||
|     { | ||||
|         $result = false; | ||||
|         if ($start->greaterThanOrEqualTo($date) && $end->greaterThanOrEqualTo($date)) { | ||||
|             $result = true; | ||||
|         } | ||||
|         // start and end in the past? use $end | ||||
|         if ($start->lessThanOrEqualTo($date) && $end->lessThanOrEqualTo($date)) { | ||||
|             $result = true; | ||||
|         } | ||||
|  | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method will scroll through the results of the spentInPeriodMc() array and return the correct info. | ||||
|      * | ||||
|      * @param array               $spentInfo | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     private function findInSpentArray(array $spentInfo, TransactionCurrency $currency): float | ||||
|     { | ||||
|         foreach ($spentInfo as $array) { | ||||
|             if ($array['currency_id'] === $currency->id) { | ||||
|                 return $array['amount']; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return 0.0; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getBalanceInformation(Carbon $start, Carbon $end): array | ||||
|     { | ||||
|         // prep some arrays: | ||||
|         $incomes  = []; | ||||
|         $expenses = []; | ||||
|         $sums     = []; | ||||
|         $return   = []; | ||||
|  | ||||
|         // collect income of user: | ||||
|         /** @var TransactionCollectorInterface $collector */ | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setAllAssetAccounts()->setRange($start, $end) | ||||
|                   ->setTypes([TransactionType::DEPOSIT]) | ||||
|                   ->withOpposingAccount(); | ||||
|         $set = $collector->getTransactions(); | ||||
|         /** @var Transaction $transaction */ | ||||
|         foreach ($set as $transaction) { | ||||
|             $currencyId           = (int)$transaction->transaction_currency_id; | ||||
|             $incomes[$currencyId] = $incomes[$currencyId] ?? '0'; | ||||
|             $incomes[$currencyId] = bcadd($incomes[$currencyId], $transaction->transaction_amount); | ||||
|             $sums[$currencyId]    = $sums[$currencyId] ?? '0'; | ||||
|             $sums[$currencyId]    = bcadd($sums[$currencyId], $transaction->transaction_amount); | ||||
|         } | ||||
|  | ||||
|         // collect expenses: | ||||
|         /** @var TransactionCollectorInterface $collector */ | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setAllAssetAccounts()->setRange($start, $end) | ||||
|                   ->setTypes([TransactionType::WITHDRAWAL]) | ||||
|                   ->withOpposingAccount(); | ||||
|         $set = $collector->getTransactions(); | ||||
|         /** @var Transaction $transaction */ | ||||
|         foreach ($set as $transaction) { | ||||
|             $currencyId            = (int)$transaction->transaction_currency_id; | ||||
|             $expenses[$currencyId] = $expenses[$currencyId] ?? '0'; | ||||
|             $expenses[$currencyId] = bcadd($expenses[$currencyId], $transaction->transaction_amount); | ||||
|             $sums[$currencyId]     = $sums[$currencyId] ?? '0'; | ||||
|             $sums[$currencyId]     = bcadd($sums[$currencyId], $transaction->transaction_amount); | ||||
|         } | ||||
|  | ||||
|         // format amounts: | ||||
|         $keys = array_keys($sums); | ||||
|         foreach ($keys as $currencyId) { | ||||
|             $currency = $this->currencyRepos->findNull($currencyId); | ||||
|             if (null === $currency) { | ||||
|                 continue; | ||||
|             } | ||||
|             // create objects for big array. | ||||
|             $return[] = [ | ||||
|                 'key'                     => sprintf('balance-in-%s', $currency->code), | ||||
|                 'title'                   => trans('firefly.box_balance_in_currency', ['currency' => $currency->symbol]), | ||||
|                 'monetary_value'          => round($sums[$currencyId] ?? 0, $currency->decimal_places), | ||||
|                 'currency_id'             => $currency->id, | ||||
|                 'currency_code'           => $currency->code, | ||||
|                 'currency_symbol'         => $currency->symbol, | ||||
|                 'currency_decimal_places' => $currency->decimal_places, | ||||
|                 'value_parsed'            => app('amount')->formatAnything($currency, $sums[$currencyId] ?? '0', false), | ||||
|                 'local_icon'              => 'balance-scale', | ||||
|                 'sub_title'               => app('amount')->formatAnything($currency, $expenses[$currencyId] ?? '0', false) . | ||||
|                                              ' + ' . app('amount')->formatAnything($currency, $incomes[$currencyId] ?? '0', false), | ||||
|             ]; | ||||
|             $return[] = [ | ||||
|                 'key'                     => sprintf('spent-in-%s', $currency->code), | ||||
|                 'title'                   => trans('firefly.box_spent_in_currency', ['currency' => $currency->symbol]), | ||||
|                 'monetary_value'          => round($expenses[$currencyId] ?? 0, $currency->decimal_places), | ||||
|                 'currency_id'             => $currency->id, | ||||
|                 'currency_code'           => $currency->code, | ||||
|                 'currency_symbol'         => $currency->symbol, | ||||
|                 'currency_decimal_places' => $currency->decimal_places, | ||||
|                 'value_parsed'            => app('amount')->formatAnything($currency, $expenses[$currencyId] ?? '0', false), | ||||
|                 'local_icon'              => 'balance-scale', | ||||
|                 'sub_title'               => '', | ||||
|             ]; | ||||
|             $return[] = [ | ||||
|                 'key'                     => sprintf('earned-in-%s', $currency->code), | ||||
|                 'title'                   => trans('firefly.box_earned_in_currency', ['currency' => $currency->symbol]), | ||||
|                 'monetary_value'          => round($incomes[$currencyId] ?? 0, $currency->decimal_places), | ||||
|                 'currency_id'             => $currency->id, | ||||
|                 'currency_code'           => $currency->code, | ||||
|                 'currency_symbol'         => $currency->symbol, | ||||
|                 'currency_decimal_places' => $currency->decimal_places, | ||||
|                 'value_parsed'            => app('amount')->formatAnything($currency, $incomes[$currencyId] ?? '0', false), | ||||
|                 'local_icon'              => 'balance-scale', | ||||
|                 'sub_title'               => '', | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getBillInformation(Carbon $start, Carbon $end): array | ||||
|     { | ||||
|         /* | ||||
|          * Since both this method and the chart use the exact same data, we can suffice | ||||
|          * with calling the one method in the bill repository that will get this amount. | ||||
|          */ | ||||
|         $paidAmount   = $this->billRepository->getBillsPaidInRangePerCurrency($start, $end); | ||||
|         $unpaidAmount = $this->billRepository->getBillsUnpaidInRangePerCurrency($start, $end); | ||||
|         $return       = []; | ||||
|         foreach ($paidAmount as $currencyId => $amount) { | ||||
|             $amount   = bcmul($amount, '-1'); | ||||
|             $currency = $this->currencyRepos->findNull((int)$currencyId); | ||||
|             if (null === $currency) { | ||||
|                 continue; | ||||
|             } | ||||
|             $return[] = [ | ||||
|                 'key'                     => sprintf('bills-paid-in-%s', $currency->code), | ||||
|                 'title'                   => trans('firefly.box_bill_paid_in_currency', ['currency' => $currency->symbol]), | ||||
|                 'monetary_value'          => round($amount, $currency->decimal_places), | ||||
|                 'currency_id'             => $currency->id, | ||||
|                 'currency_code'           => $currency->code, | ||||
|                 'currency_symbol'         => $currency->symbol, | ||||
|                 'currency_decimal_places' => $currency->decimal_places, | ||||
|                 'value_parsed'            => app('amount')->formatAnything($currency, $amount, false), | ||||
|                 'local_icon'              => 'check', | ||||
|                 'sub_title'               => '', | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         foreach ($unpaidAmount as $currencyId => $amount) { | ||||
|             $amount   = bcmul($amount, '-1'); | ||||
|             $currency = $this->currencyRepos->findNull((int)$currencyId); | ||||
|             if (null === $currency) { | ||||
|                 continue; | ||||
|             } | ||||
|             $return[] = [ | ||||
|                 'key'                     => sprintf('bills-unpaid-in-%s', $currency->code), | ||||
|                 'title'                   => trans('firefly.box_bill_unpaid_in_currency', ['currency' => $currency->symbol]), | ||||
|                 'monetary_value'          => round($amount, $currency->decimal_places), | ||||
|                 'currency_id'             => $currency->id, | ||||
|                 'currency_code'           => $currency->code, | ||||
|                 'currency_symbol'         => $currency->symbol, | ||||
|                 'currency_decimal_places' => $currency->decimal_places, | ||||
|                 'value_parsed'            => app('amount')->formatAnything($currency, $amount, false), | ||||
|                 'local_icon'              => 'calendar-o', | ||||
|                 'sub_title'               => '', | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getLeftToSpendInfo(Carbon $start, Carbon $end): array | ||||
|     { | ||||
|         $return    = []; | ||||
|         $today     = new Carbon; | ||||
|         $available = $this->budgetRepository->getAvailableBudgetWithCurrency($start, $end); | ||||
|         $budgets   = $this->budgetRepository->getActiveBudgets(); | ||||
|         $spentInfo = $this->budgetRepository->spentInPeriodMc($budgets, new Collection, $start, $end); | ||||
|         foreach ($available as $currencyId => $amount) { | ||||
|             $currency = $this->currencyRepos->findNull($currencyId); | ||||
|             if (null === $currency) { | ||||
|                 continue; | ||||
|             } | ||||
|             $spentInCurrency = (string)$this->findInSpentArray($spentInfo, $currency); | ||||
|             $leftToSpend     = bcadd($amount, $spentInCurrency); | ||||
|  | ||||
|             $days   = $today->diffInDays($end) + 1; | ||||
|             $perDay = '0'; | ||||
|             if (0 !== $days && bccomp($leftToSpend, '0') > -1) { | ||||
|                 $perDay = bcdiv($leftToSpend, (string)$days); | ||||
|             } | ||||
|  | ||||
|             $return[] = [ | ||||
|                 'key'                     => sprintf('left-to-spend-in-%s', $currency->code), | ||||
|                 'title'                   => trans('firefly.box_left_to_spend_in_currency', ['currency' => $currency->symbol]), | ||||
|                 'monetary_value'          => round($leftToSpend, $currency->decimal_places), | ||||
|                 'currency_id'             => $currency->id, | ||||
|                 'currency_code'           => $currency->code, | ||||
|                 'currency_symbol'         => $currency->symbol, | ||||
|                 'currency_decimal_places' => $currency->decimal_places, | ||||
|                 'value_parsed'            => app('amount')->formatAnything($currency, $leftToSpend, false), | ||||
|                 'local_icon'              => 'money', | ||||
|                 'sub_title'               => (string)trans('firefly.box_spend_per_day', ['amount' => app('amount')->formatAnything($currency, $perDay, false)]), | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getNetWorthInfo(Carbon $start, Carbon $end): array | ||||
|     { | ||||
|         /** @var User $user */ | ||||
|         $user = auth()->user(); | ||||
|         $date = Carbon::create()->startOfDay(); | ||||
|  | ||||
|  | ||||
|         // start and end in the future? use $end | ||||
|         if ($this->notInDateRange($date, $start, $end)) { | ||||
|             /** @var Carbon $date */ | ||||
|             $date = session('end', Carbon::now()->endOfMonth()); | ||||
|         } | ||||
|  | ||||
|         /** @var NetWorthInterface $netWorthHelper */ | ||||
|         $netWorthHelper = app(NetWorthInterface::class); | ||||
|         $netWorthHelper->setUser($user); | ||||
|         $allAccounts = $this->accountRepository->getActiveAccountsByType([AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE]); | ||||
|  | ||||
|         // filter list on preference of being included. | ||||
|         $filtered = $allAccounts->filter( | ||||
|             function (Account $account) { | ||||
|                 $includeNetWorth = $this->accountRepository->getMetaValue($account, 'include_net_worth'); | ||||
|  | ||||
|                 return null === $includeNetWorth ? true : '1' === $includeNetWorth; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         $netWorthSet = $netWorthHelper->getNetWorthByCurrency($filtered, $date); | ||||
|         $return      = []; | ||||
|         foreach ($netWorthSet as $index => $data) { | ||||
|             /** @var TransactionCurrency $currency */ | ||||
|             $currency = $data['currency']; | ||||
|             $amount   = round($data['balance'], $currency->decimal_places); | ||||
|             if (0.0 === $amount) { | ||||
|                 continue; | ||||
|             } | ||||
|             // return stuff | ||||
|             $return[] = [ | ||||
|                 'key'                     => sprintf('net-worth-in-%s', $currency->code), | ||||
|                 'title'                   => trans('firefly.box_net_worth_in_currency', ['currency' => $currency->symbol]), | ||||
|                 'monetary_value'          => $amount, | ||||
|                 'currency_id'             => $currency->id, | ||||
|                 'currency_code'           => $currency->code, | ||||
|                 'currency_symbol'         => $currency->symbol, | ||||
|                 'currency_decimal_places' => $currency->decimal_places, | ||||
|                 'value_parsed'            => app('amount')->formatAnything($currency, $data['balance'], false), | ||||
|                 'local_icon'              => 'line-chart', | ||||
|                 'sub_title'               => '', | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										298
									
								
								app/Api/V1/Controllers/TagController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										298
									
								
								app/Api/V1/Controllers/TagController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,298 @@ | ||||
| <?php | ||||
| /** | ||||
|  * TagController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Api\V1\Requests\TagRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Collector\TransactionCollectorInterface; | ||||
| use FireflyIII\Helpers\Filter\InternalTransferFilter; | ||||
| use FireflyIII\Models\Tag; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Repositories\Tag\TagRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Transformers\TagTransformer; | ||||
| use FireflyIII\Transformers\TransactionTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class TagController | ||||
|  */ | ||||
| class TagController extends Controller | ||||
| { | ||||
|     use TransactionFilter; | ||||
|  | ||||
|     /** @var TagRepositoryInterface The tag repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * RuleController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user = auth()->user(); | ||||
|  | ||||
|                 $this->repository = app(TagRepositoryInterface::class); | ||||
|                 $this->repository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function cloud(Request $request): JsonResponse | ||||
|     { | ||||
|         // parameters for cloud: | ||||
|         $start = (string)$request->get('start'); | ||||
|         $end   = (string)$request->get('end'); | ||||
|         if ('' === $start || '' === $end) { | ||||
|             throw new FireflyException('Start and end are mandatory parameters.'); | ||||
|         } | ||||
|         $start = Carbon::createFromFormat('Y-m-d', $start); | ||||
|         $end   = Carbon::createFromFormat('Y-m-d', $end); | ||||
|  | ||||
|         // get all tags: | ||||
|         $tags   = $this->repository->get(); | ||||
|         $min    = null; | ||||
|         $max    = 0; | ||||
|         $return = [ | ||||
|             'tags' => [], | ||||
|         ]; | ||||
|         /** @var Tag $tag */ | ||||
|         foreach ($tags as $tag) { | ||||
|             $earned = (float)$this->repository->earnedInPeriod($tag, $start, $end); | ||||
|             $spent  = (float)$this->repository->spentInPeriod($tag, $start, $end); | ||||
|             $size   = ($spent * -1) + $earned; | ||||
|             $min    = $min ?? $size; | ||||
|             if ($size > 0) { | ||||
|                 $max              = $size > $max ? $size : $max; | ||||
|                 $return['tags'][] = [ | ||||
|                     'tag'  => $tag->tag, | ||||
|                     'id'   => $tag->id, | ||||
|                     'size' => $size, | ||||
|                 ]; | ||||
|             } | ||||
|         } | ||||
|         foreach ($return['tags'] as $index => $info) { | ||||
|             $return['tags'][$index]['relative'] = $return['tags'][$index]['size'] / $max; | ||||
|         } | ||||
|         $return['min'] = $min; | ||||
|         $return['max'] = $max; | ||||
|  | ||||
|  | ||||
|         return response()->json($return); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Delete the resource. | ||||
|      * | ||||
|      * @param Tag $tag | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(Tag $tag): JsonResponse | ||||
|     { | ||||
|         $this->repository->destroy($tag); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List all of them. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse] | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of budgets. Count it and split it. | ||||
|         $collection = $this->repository->get(); | ||||
|         $count      = $collection->count(); | ||||
|         $rules      = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.tags.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var TagTransformer $transformer */ | ||||
|         $transformer = app(TagTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($rules, $transformer, 'tags'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List single resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * @param Tag     $tag | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, Tag $tag): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var TagTransformer $transformer */ | ||||
|         $transformer = app(TagTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($tag, $transformer, 'tags'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store new object. | ||||
|      * | ||||
|      * @param TagRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function store(TagRequest $request): JsonResponse | ||||
|     { | ||||
|         $rule    = $this->repository->store($request->getAll()); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var TagTransformer $transformer */ | ||||
|         $transformer = app(TagTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($rule, $transformer, 'tags'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show all transactions. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * @param Tag     $tag | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function transactions(Request $request, Tag $tag): JsonResponse | ||||
|     { | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $type     = $request->get('type') ?? 'default'; | ||||
|         $this->parameters->set('type', $type); | ||||
|  | ||||
|         $types   = $this->mapTransactionTypes($this->parameters->get('type')); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var User $admin */ | ||||
|         $admin = auth()->user(); | ||||
|         /** @var TransactionCollectorInterface $collector */ | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setUser($admin); | ||||
|         $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); | ||||
|         $collector->setAllAssetAccounts(); | ||||
|         $collector->setTag($tag); | ||||
|  | ||||
|         if (\in_array(TransactionType::TRANSFER, $types, true)) { | ||||
|             $collector->removeFilter(InternalTransferFilter::class); | ||||
|         } | ||||
|  | ||||
|         if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) { | ||||
|             $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); | ||||
|         } | ||||
|         $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); | ||||
|         $collector->setTypes($types); | ||||
|         $paginator = $collector->getPaginatedTransactions(); | ||||
|         $paginator->setPath(route('api.v1.transactions.index') . $this->buildParams()); | ||||
|         $transactions = $paginator->getCollection(); | ||||
|  | ||||
|         /** @var TransactionTransformer $transformer */ | ||||
|         $transformer = app(TransactionTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($transactions, $transformer, 'transactions'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update a rule. | ||||
|      * | ||||
|      * @param TagRequest $request | ||||
|      * @param Tag        $tag | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(TagRequest $request, Tag $tag): JsonResponse | ||||
|     { | ||||
|         $rule    = $this->repository->update($tag, $request->getAll()); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         /** @var TagTransformer $transformer */ | ||||
|         $transformer = app(TagTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($rule, $transformer, 'tags'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										331
									
								
								app/Api/V1/Controllers/TransactionController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										331
									
								
								app/Api/V1/Controllers/TransactionController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,331 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * TransactionController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\TransactionRequest; | ||||
| use FireflyIII\Events\StoredTransactionJournal; | ||||
| use FireflyIII\Events\UpdatedTransactionJournal; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Collector\TransactionCollectorInterface; | ||||
| use FireflyIII\Helpers\Filter\InternalTransferFilter; | ||||
| use FireflyIII\Helpers\Filter\NegativeAmountFilter; | ||||
| use FireflyIII\Helpers\Filter\PositiveAmountFilter; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Repositories\Journal\JournalRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Transformers\AttachmentTransformer; | ||||
| use FireflyIII\Transformers\PiggyBankEventTransformer; | ||||
| use FireflyIII\Transformers\TransactionTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Collection; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class TransactionController | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class TransactionController extends Controller | ||||
| { | ||||
|     use TransactionFilter; | ||||
|  | ||||
|     /** @var JournalRepositoryInterface The journal repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * TransactionController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $admin */ | ||||
|                 $admin = auth()->user(); | ||||
|  | ||||
|                 /** @var JournalRepositoryInterface repository */ | ||||
|                 $this->repository = app(JournalRepositoryInterface::class); | ||||
|                 $this->repository->setUser($admin); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Request     $request | ||||
|      * @param Transaction $transaction | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function attachments(Request $request, Transaction $transaction): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $attachments = $this->repository->getAttachmentsByTr($transaction); | ||||
|  | ||||
|         /** @var AttachmentTransformer $transformer */ | ||||
|         $transformer = app(AttachmentTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($attachments, $transformer, 'attachments'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  \FireflyIII\Models\Transaction $transaction | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(Transaction $transaction): JsonResponse | ||||
|     { | ||||
|         $journal = $transaction->transactionJournal; | ||||
|         $this->repository->destroy($journal); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show all transactions. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $type     = $request->get('type') ?? 'default'; | ||||
|         $this->parameters->set('type', $type); | ||||
|  | ||||
|         $types   = $this->mapTransactionTypes($this->parameters->get('type')); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var User $admin */ | ||||
|         $admin = auth()->user(); | ||||
|         /** @var TransactionCollectorInterface $collector */ | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setUser($admin); | ||||
|         $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); | ||||
|         $collector->setAllAssetAccounts(); | ||||
|  | ||||
|         if (\in_array(TransactionType::TRANSFER, $types, true)) { | ||||
|             $collector->removeFilter(InternalTransferFilter::class); | ||||
|         } | ||||
|  | ||||
|         if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) { | ||||
|             $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); | ||||
|         } | ||||
|         $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); | ||||
|         $collector->setTypes($types); | ||||
|         $paginator = $collector->getPaginatedTransactions(); | ||||
|         $paginator->setPath(route('api.v1.transactions.index') . $this->buildParams()); | ||||
|         $transactions = $paginator->getCollection(); | ||||
|  | ||||
|         /** @var TransactionTransformer $transformer */ | ||||
|         $transformer = app(TransactionTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($transactions, $transformer, 'transactions'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Request     $request | ||||
|      * @param Transaction $transaction | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function piggyBankEvents(Request $request, Transaction $transaction): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $events = $this->repository->getPiggyBankEventsbyTr($transaction); | ||||
|  | ||||
|         /** @var PiggyBankEventTransformer $transformer */ | ||||
|         $transformer = app(PiggyBankEventTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($events, $transformer, 'piggy_bank_events'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show a single transaction. | ||||
|      * | ||||
|      * @param Request     $request | ||||
|      * @param Transaction $transaction | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, Transaction $transaction): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         // collect transactions using the journal collector | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setUser(auth()->user()); | ||||
|         $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); | ||||
|         // filter on specific journals. | ||||
|         $collector->setJournals(new Collection([$transaction->transactionJournal])); | ||||
|  | ||||
|         // add filter to remove transactions: | ||||
|         $transactionType = $transaction->transactionJournal->transactionType->type; | ||||
|         if ($transactionType === TransactionType::WITHDRAWAL) { | ||||
|             $collector->addFilter(PositiveAmountFilter::class); | ||||
|         } | ||||
|         if (!($transactionType === TransactionType::WITHDRAWAL)) { | ||||
|             $collector->addFilter(NegativeAmountFilter::class); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         $transactions = $collector->getTransactions(); | ||||
|         /** @var TransactionTransformer $transformer */ | ||||
|         $transformer = app(TransactionTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|         $resource = new FractalCollection($transactions, $transformer, 'transactions'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a new transaction. | ||||
|      * | ||||
|      * @param TransactionRequest         $request | ||||
|      * | ||||
|      * @param JournalRepositoryInterface $repository | ||||
|      * | ||||
|      * @throws FireflyException | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function store(TransactionRequest $request, JournalRepositoryInterface $repository): JsonResponse | ||||
|     { | ||||
|         $data         = $request->getAll(); | ||||
|         $data['user'] = auth()->user()->id; | ||||
|         $journal      = $repository->store($data); | ||||
|  | ||||
|         event(new StoredTransactionJournal($journal)); | ||||
|  | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         // collect transactions using the journal collector | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setUser(auth()->user()); | ||||
|         $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); | ||||
|         // filter on specific journals. | ||||
|         $collector->setJournals(new Collection([$journal])); | ||||
|  | ||||
|         // add filter to remove transactions: | ||||
|         $transactionType = $journal->transactionType->type; | ||||
|         if ($transactionType === TransactionType::WITHDRAWAL) { | ||||
|             $collector->addFilter(PositiveAmountFilter::class); | ||||
|         } | ||||
|         if (!($transactionType === TransactionType::WITHDRAWAL)) { | ||||
|             $collector->addFilter(NegativeAmountFilter::class); | ||||
|         } | ||||
|  | ||||
|         $transactions = $collector->getTransactions(); | ||||
|  | ||||
|         /** @var TransactionTransformer $transformer */ | ||||
|         $transformer = app(TransactionTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($transactions, $transformer, 'transactions'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Update a transaction. | ||||
|      * | ||||
|      * @param TransactionRequest         $request | ||||
|      * @param JournalRepositoryInterface $repository | ||||
|      * @param Transaction                $transaction | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(TransactionRequest $request, JournalRepositoryInterface $repository, Transaction $transaction): JsonResponse | ||||
|     { | ||||
|         $data         = $request->getAll(); | ||||
|         $data['user'] = auth()->user()->id; | ||||
|         $journal      = $repository->update($transaction->transactionJournal, $data); | ||||
|         $manager      = new Manager(); | ||||
|         $baseUrl      = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         event(new UpdatedTransactionJournal($journal)); | ||||
|  | ||||
|         // needs a lot of extra data to match the journal collector. Or just expand that one. | ||||
|         // collect transactions using the journal collector | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setUser(auth()->user()); | ||||
|         $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); | ||||
|         // filter on specific journals. | ||||
|         $collector->setJournals(new Collection([$journal])); | ||||
|  | ||||
|         // add filter to remove transactions: | ||||
|         $transactionType = $journal->transactionType->type; | ||||
|         if ($transactionType === TransactionType::WITHDRAWAL) { | ||||
|             $collector->addFilter(PositiveAmountFilter::class); | ||||
|         } | ||||
|         if (!($transactionType === TransactionType::WITHDRAWAL)) { | ||||
|             $collector->addFilter(NegativeAmountFilter::class); | ||||
|         } | ||||
|  | ||||
|         $transactions = $collector->getTransactions(); | ||||
|  | ||||
|         /** @var TransactionTransformer $transformer */ | ||||
|         $transformer = app(TransactionTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($transactions, $transformer, 'transactions'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										219
									
								
								app/Api/V1/Controllers/TransactionLinkController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										219
									
								
								app/Api/V1/Controllers/TransactionLinkController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,219 @@ | ||||
| <?php | ||||
| /** | ||||
|  * TransactionLinkController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\TransactionLinkRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\TransactionJournalLink; | ||||
| use FireflyIII\Repositories\Journal\JournalRepositoryInterface; | ||||
| use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Transformers\TransactionLinkTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class TransactionLinkController | ||||
|  */ | ||||
| class TransactionLinkController extends Controller | ||||
| { | ||||
|     use TransactionFilter; | ||||
|  | ||||
|     /** @var JournalRepositoryInterface The journal repository */ | ||||
|     private $journalRepository; | ||||
|     /** @var LinkTypeRepositoryInterface The link type repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * JournalLinkController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user = auth()->user(); | ||||
|  | ||||
|                 $this->repository        = app(LinkTypeRepositoryInterface::class); | ||||
|                 $this->journalRepository = app(JournalRepositoryInterface::class); | ||||
|  | ||||
|                 $this->repository->setUser($user); | ||||
|                 $this->journalRepository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Delete the resource. | ||||
|      * | ||||
|      * @param TransactionJournalLink $link | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(TransactionJournalLink $link): JsonResponse | ||||
|     { | ||||
|         $this->repository->destroyLink($link); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List all of them. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse] | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // read type from URI | ||||
|         $name = $request->get('name') ?? null; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $linkType = $this->repository->findByName($name); | ||||
|  | ||||
|         // get list of transaction links. Count it and split it. | ||||
|         $collection   = $this->repository->getJournalLinks($linkType); | ||||
|         $count        = $collection->count(); | ||||
|         $journalLinks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($journalLinks, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.transaction_links.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var TransactionLinkTransformer $transformer */ | ||||
|         $transformer = app(TransactionLinkTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($journalLinks, $transformer, 'transaction_links'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List single resource. | ||||
|      * | ||||
|      * @param Request                $request | ||||
|      * @param TransactionJournalLink $journalLink | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, TransactionJournalLink $journalLink): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var TransactionLinkTransformer $transformer */ | ||||
|         $transformer = app(TransactionLinkTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($journalLink, $transformer, 'transaction_links'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store new object. | ||||
|      * | ||||
|      * @param TransactionLinkRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(TransactionLinkRequest $request): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager; | ||||
|         $data    = $request->getAll(); | ||||
|         $inward  = $this->journalRepository->findNull($data['inward_id'] ?? 0); | ||||
|         $outward = $this->journalRepository->findNull($data['outward_id'] ?? 0); | ||||
|         if (null === $inward || null === $outward) { | ||||
|             throw new FireflyException('Source or destination is NULL.'); | ||||
|         } | ||||
|         $data['direction'] = 'inward'; | ||||
|  | ||||
|         $journalLink = $this->repository->storeLink($data, $inward, $outward); | ||||
|  | ||||
|         /** @var TransactionLinkTransformer $transformer */ | ||||
|         $transformer = app(TransactionLinkTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($journalLink, $transformer, 'transaction_links'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update object. | ||||
|      * | ||||
|      * @param TransactionLinkRequest $request | ||||
|      * @param TransactionJournalLink $journalLink | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function update(TransactionLinkRequest $request, TransactionJournalLink $journalLink): JsonResponse | ||||
|     { | ||||
|         $manager         = new Manager; | ||||
|         $data            = $request->getAll(); | ||||
|         $data['inward']  = $this->journalRepository->findNull($data['inward_id'] ?? 0); | ||||
|         $data['outward'] = $this->journalRepository->findNull($data['outward_id'] ?? 0); | ||||
|         if (null === $data['inward'] || null === $data['outward']) { | ||||
|             throw new FireflyException('Source or destination is NULL.'); | ||||
|         } | ||||
|         $data['direction'] = 'inward'; | ||||
|         $journalLink       = $this->repository->updateLink($journalLink, $data); | ||||
|  | ||||
|         /** @var TransactionLinkTransformer $transformer */ | ||||
|         $transformer = app(TransactionLinkTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($journalLink, $transformer, 'transaction_links'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										208
									
								
								app/Api/V1/Controllers/UserController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								app/Api/V1/Controllers/UserController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,208 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * UserController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\UserRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Repositories\User\UserRepositoryInterface; | ||||
| use FireflyIII\Transformers\UserTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class UserController. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class UserController extends Controller | ||||
| { | ||||
|  | ||||
|     /** @var UserRepositoryInterface The user repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * UserController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var UserRepositoryInterface repository */ | ||||
|                 $this->repository = app(UserRepositoryInterface::class); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  \FireflyIII\User $user | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function delete(User $user): JsonResponse | ||||
|     { | ||||
|         /** @var User $admin */ | ||||
|         $admin = auth()->user(); | ||||
|         if ($admin->id !== $user->id && $this->repository->hasRole($admin, 'owner')) { | ||||
|             $this->repository->destroy($user); | ||||
|  | ||||
|             return response()->json([], 204); | ||||
|         } | ||||
|         throw new FireflyException('No access to method.'); // @codeCoverageIgnore | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // user preferences | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // make manager | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         // build collection | ||||
|         $collection = $this->repository->all(); | ||||
|         $count      = $collection->count(); | ||||
|         $users      = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($users, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.users.index') . $this->buildParams()); | ||||
|  | ||||
|         // make resource | ||||
|         /** @var UserTransformer $transformer */ | ||||
|         $transformer = app(UserTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($users, $transformer, 'users'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show a single user. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * @param User    $user | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, User $user): JsonResponse | ||||
|     { | ||||
|         // make manager | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         // make resource | ||||
|         /** @var UserTransformer $transformer */ | ||||
|         $transformer = app(UserTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($user, $transformer, 'users'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a new user. | ||||
|      * | ||||
|      * @param UserRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function store(UserRequest $request): JsonResponse | ||||
|     { | ||||
|         $data = $request->getAll(); | ||||
|         $user = $this->repository->store($data); | ||||
|  | ||||
|         // make manager | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         // make resource | ||||
|  | ||||
|         /** @var UserTransformer $transformer */ | ||||
|         $transformer = app(UserTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($user, $transformer, 'users'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update a user. | ||||
|      * | ||||
|      * @param UserRequest $request | ||||
|      * @param User        $user | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(UserRequest $request, User $user): JsonResponse | ||||
|     { | ||||
|         $data = $request->getAll(); | ||||
|         $user = $this->repository->update($user, $data); | ||||
|  | ||||
|         // make manager | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         // make resource | ||||
|         /** @var UserTransformer $transformer */ | ||||
|         $transformer = app(UserTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new Item($user, $transformer, 'users'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										141
									
								
								app/Api/V1/Requests/AccountRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								app/Api/V1/Requests/AccountRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,141 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * AccountRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
|  | ||||
| /** | ||||
|  * Class AccountRequest | ||||
|  */ | ||||
| class AccountRequest extends Request | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         $active          = true; | ||||
|         $includeNetWorth = true; | ||||
|         if (null !== $this->get('active')) { | ||||
|             $active = $this->boolean('active'); | ||||
|         } | ||||
|         if (null !== $this->get('include_net_worth')) { | ||||
|             $includeNetWorth = $this->boolean('include_net_worth'); | ||||
|         } | ||||
|  | ||||
|         $data = [ | ||||
|             'name'                 => $this->string('name'), | ||||
|             'active'               => $active, | ||||
|             'include_net_worth'    => $includeNetWorth, | ||||
|             'accountType'          => $this->string('type'), | ||||
|             'account_type_id'      => null, | ||||
|             'currency_id'          => $this->integer('currency_id'), | ||||
|             'currency_code'        => $this->string('currency_code'), | ||||
|             'virtualBalance'       => $this->string('virtual_balance'), | ||||
|             'iban'                 => $this->string('iban'), | ||||
|             'BIC'                  => $this->string('bic'), | ||||
|             'accountNumber'        => $this->string('account_number'), | ||||
|             'accountRole'          => $this->string('account_role'), | ||||
|             'openingBalance'       => $this->string('opening_balance'), | ||||
|             'openingBalanceDate'   => $this->date('opening_balance_date'), | ||||
|             'ccType'               => $this->string('credit_card_type'), | ||||
|             'ccMonthlyPaymentDate' => $this->string('monthly_payment_date'), | ||||
|             'notes'                => $this->string('notes'), | ||||
|             'interest'             => $this->string('interest'), | ||||
|             'interest_period'      => $this->string('interest_period'), | ||||
|         ]; | ||||
|  | ||||
|         if ('liability' === $data['accountType']) { | ||||
|             $data['openingBalance']     = bcmul($this->string('liability_amount'), '-1'); | ||||
|             $data['openingBalanceDate'] = $this->date('liability_start_date'); | ||||
|             $data['accountType']        = $this->string('liability_type'); | ||||
|             $data['account_type_id']    = null; | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $accountRoles   = implode(',', config('firefly.accountRoles')); | ||||
|         $types          = implode(',', array_keys(config('firefly.subTitlesByIdentifier'))); | ||||
|         $ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes'))); | ||||
|         $rules          = [ | ||||
|             'name'                 => 'required|min:1|uniqueAccountForUser', | ||||
|             'type'                 => 'required|in:' . $types, | ||||
|             'iban'                 => 'iban|nullable', | ||||
|             'bic'                  => 'bic|nullable', | ||||
|             'account_number'       => 'between:1,255|nullable|uniqueAccountNumberForUser', | ||||
|             'opening_balance'      => 'numeric|required_with:opening_balance_date|nullable', | ||||
|             'opening_balance_date' => 'date|required_with:opening_balance|nullable', | ||||
|             'virtual_balance'      => 'numeric|nullable', | ||||
|             'currency_id'          => 'numeric|exists:transaction_currencies,id', | ||||
|             'currency_code'        => 'min:3|max:3|exists:transaction_currencies,code', | ||||
|             'active'               => [new IsBoolean], | ||||
|             'include_net_worth'    => [new IsBoolean], | ||||
|             'account_role'         => 'in:' . $accountRoles . '|required_if:type,asset', | ||||
|             'credit_card_type'     => 'in:' . $ccPaymentTypes . '|required_if:account_role,ccAsset', | ||||
|             'monthly_payment_date' => 'date' . '|required_if:account_role,ccAsset|required_if:credit_card_type,monthlyFull', | ||||
|             'liability_type'       => 'required_if:type,liability|in:loan,debt,mortgage', | ||||
|             'liability_amount'     => 'required_if:type,liability|min:0|numeric', | ||||
|             'liability_start_date' => 'required_if:type,liability|date', | ||||
|             'interest'             => 'required_if:type,liability|between:0,100|numeric', | ||||
|             'interest_period'      => 'required_if:type,liability|in:daily,monthly,yearly', | ||||
|             'notes'                => 'min:0|max:65536', | ||||
|         ]; | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 $account                 = $this->route()->parameter('account'); | ||||
|                 $rules['name']           .= ':' . $account->id; | ||||
|                 $rules['account_number'] .= ':' . $account->id; | ||||
|                 $rules['type']           = 'in:' . $types; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										99
									
								
								app/Api/V1/Requests/AttachmentRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								app/Api/V1/Requests/AttachmentRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | ||||
| <?php | ||||
| /** | ||||
|  * AttachmentRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\ImportJob; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Rules\IsValidAttachmentModel; | ||||
|  | ||||
| /** | ||||
|  * Class AttachmentRequest | ||||
|  */ | ||||
| class AttachmentRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         return [ | ||||
|             'filename' => $this->string('filename'), | ||||
|             'title'    => $this->string('title'), | ||||
|             'notes'    => $this->string('notes'), | ||||
|             'model'    => $this->string('model'), | ||||
|             'model_id' => $this->integer('model_id'), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $models = implode( | ||||
|             ',', [ | ||||
|                    str_replace('FireflyIII\\Models\\', '', Bill::class), | ||||
|                    str_replace('FireflyIII\\Models\\', '', ImportJob::class), | ||||
|                    str_replace('FireflyIII\\Models\\', '', TransactionJournal::class), | ||||
|                    str_replace('FireflyIII\\Models\\', '', Transaction::class), | ||||
|                ] | ||||
|         ); | ||||
|         $model  = $this->string('model'); | ||||
|         $rules  = [ | ||||
|             'filename' => 'required|between:1,255', | ||||
|             'title'    => 'between:1,255', | ||||
|             'notes'    => 'between:1,65000', | ||||
|             'model'    => sprintf('required|in:%s', $models), | ||||
|             'model_id' => ['required', 'numeric', new IsValidAttachmentModel($model)], | ||||
|         ]; | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 unset($rules['model'], $rules['model_id']); | ||||
|                 $rules['filename'] = 'between:1,255'; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										77
									
								
								app/Api/V1/Requests/AvailableBudgetRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								app/Api/V1/Requests/AvailableBudgetRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| <?php | ||||
| /** | ||||
|  * AvailableBudgetRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| /** | ||||
|  * Class AvailableBudgetRequest | ||||
|  */ | ||||
| class AvailableBudgetRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         return [ | ||||
|             'currency_id'   => $this->integer('currency_id'), | ||||
|             'currency_code' => $this->string('currency_code'), | ||||
|             'amount'        => $this->string('amount'), | ||||
|             'start'         => $this->date('start'), | ||||
|             'end'           => $this->date('end'), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             'currency_id'   => 'numeric|exists:transaction_currencies,id', | ||||
|             'currency_code' => 'min:3|max:3|exists:transaction_currencies,code', | ||||
|             'amount'        => 'required|numeric|more:0', | ||||
|             'start'         => 'required|date|before:end', | ||||
|             'end'           => 'required|date|after:start', | ||||
|         ]; | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										128
									
								
								app/Api/V1/Requests/BillRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								app/Api/V1/Requests/BillRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,128 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * BillRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
| use Illuminate\Validation\Validator; | ||||
|  | ||||
| /** | ||||
|  * Class BillRequest | ||||
|  */ | ||||
| class BillRequest extends Request | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         $active = true; | ||||
|         if (null !== $this->get('active')) { | ||||
|             $active = $this->boolean('active'); | ||||
|         } | ||||
|  | ||||
|         $data = [ | ||||
|             'name'          => $this->string('name'), | ||||
|             'amount_min'    => $this->string('amount_min'), | ||||
|             'amount_max'    => $this->string('amount_max'), | ||||
|             'currency_id'   => $this->integer('currency_id'), | ||||
|             'currency_code' => $this->string('currency_code'), | ||||
|             'date'          => $this->date('date'), | ||||
|             'repeat_freq'   => $this->string('repeat_freq'), | ||||
|             'skip'          => $this->integer('skip'), | ||||
|             'active'        => $active, | ||||
|             'notes'         => $this->string('notes'), | ||||
|         ]; | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             'name'          => 'required|between:1,255|uniqueObjectForUser:bills,name', | ||||
|             'amount_min'    => 'required|numeric|more:0', | ||||
|             'amount_max'    => 'required|numeric|more:0', | ||||
|             'currency_id'   => 'numeric|exists:transaction_currencies,id', | ||||
|             'currency_code' => 'min:3|max:3|exists:transaction_currencies,code', | ||||
|             'date'          => 'required|date', | ||||
|             'repeat_freq'   => 'required|in:weekly,monthly,quarterly,half-year,yearly', | ||||
|             'skip'          => 'between:0,31', | ||||
|             'automatch'     => [new IsBoolean], | ||||
|             'active'        => [new IsBoolean], | ||||
|             'notes'         => 'between:1,65536', | ||||
|         ]; | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 $bill          = $this->route()->parameter('bill'); | ||||
|                 $rules['name'] .= ',' . $bill->id; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Configure the validator instance. | ||||
|      * | ||||
|      * @param  Validator $validator | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function withValidator(Validator $validator): void | ||||
|     { | ||||
|         $validator->after( | ||||
|             function (Validator $validator) { | ||||
|                 $data = $validator->getData(); | ||||
|                 $min  = (float)($data['amount_min'] ?? 0); | ||||
|                 $max  = (float)($data['amount_max'] ?? 0); | ||||
|                 if ($min > $max) { | ||||
|                     $validator->errors()->add('amount_min', (string)trans('validation.amount_min_over_max')); | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										93
									
								
								app/Api/V1/Requests/BudgetLimitRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								app/Api/V1/Requests/BudgetLimitRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,93 @@ | ||||
| <?php | ||||
| /** | ||||
|  * BudgetLimitRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class BudgetLimitRequest | ||||
|  */ | ||||
| class BudgetLimitRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         return [ | ||||
|             'budget_id'     => $this->integer('budget_id'), | ||||
|             'start'         => $this->date('start'), | ||||
|             'end'           => $this->date('end'), | ||||
|             'amount'        => $this->string('amount'), | ||||
|             'currency_id'   => $this->integer('currency_id'), | ||||
|             'currency_code' => $this->string('currency_code'), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             'budget_id'     => 'required|exists:budgets,id|belongsToUser:budgets,id', | ||||
|             'start'         => 'required|before:end|date', | ||||
|             'end'           => 'required|after:start|date', | ||||
|             'amount'        => 'required|more:0', | ||||
|             'currency_id'   => 'numeric|exists:transaction_currencies,id', | ||||
|             'currency_code' => 'min:3|max:3|exists:transaction_currencies,code', | ||||
|         ]; | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 $rules['budget_id'] = 'required|exists:budgets,id|belongsToUser:budgets,id'; | ||||
|                 break; | ||||
|         } | ||||
|         // if request has a budget already, drop the rule. | ||||
|         $budget = $this->route()->parameter('budget'); | ||||
|         if (null !== $budget) { | ||||
|             unset($rules['budget_id']); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										88
									
								
								app/Api/V1/Requests/BudgetRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								app/Api/V1/Requests/BudgetRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | ||||
| <?php | ||||
| /** | ||||
|  * BudgetRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
|  | ||||
| /** | ||||
|  * Class BudgetRequest | ||||
|  */ | ||||
| class BudgetRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         $active = true; | ||||
|         if (null !== $this->get('active')) { | ||||
|             $active = $this->boolean('active'); | ||||
|         } | ||||
|  | ||||
|         return [ | ||||
|             'name'   => $this->string('name'), | ||||
|             'active' => $active, | ||||
|             'order'  => 0, | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             'name'   => 'required|between:1,100|uniqueObjectForUser:budgets,name', | ||||
|             'active' => [new IsBoolean], | ||||
|         ]; | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 /** @var Budget $budget */ | ||||
|                 $budget        = $this->route()->parameter('budget'); | ||||
|                 $rules['name'] = sprintf('required|between:1,100|uniqueObjectForUser:budgets,name,%d', $budget->id); | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										79
									
								
								app/Api/V1/Requests/CategoryRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								app/Api/V1/Requests/CategoryRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| <?php | ||||
| /** | ||||
|  * CategoryRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Models\Category; | ||||
|  | ||||
| /** | ||||
|  * Class CategoryRequest | ||||
|  */ | ||||
| class CategoryRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         return [ | ||||
|             'name' => $this->string('name'), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             'name' => 'required|between:1,100|uniqueObjectForUser:categories,name', | ||||
|         ]; | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 /** @var Category $category */ | ||||
|                 $category      = $this->route()->parameter('category'); | ||||
|                 $rules['name'] = sprintf('required|between:1,100|uniqueObjectForUser:categories,name,%d', $category->id); | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										83
									
								
								app/Api/V1/Requests/ConfigurationRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								app/Api/V1/Requests/ConfigurationRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * ConfigurationRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
|  | ||||
| /** | ||||
|  * Class ConfigurationRequest | ||||
|  */ | ||||
| class ConfigurationRequest extends Request | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         $name = $this->route()->parameter('configName'); | ||||
|         switch ($name) { | ||||
|             case 'is_demo_site': | ||||
|             case 'single_user_mode': | ||||
|                 return ['value' => $this->boolean('value')]; | ||||
|             case 'permission_update_check': | ||||
|                 return ['value' => $this->integer('value')]; | ||||
|         } | ||||
|  | ||||
|         return ['value' => $this->string('value')]; // @codeCoverageIgnore | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $name = $this->route()->parameter('configName'); | ||||
|         switch ($name) { | ||||
|             case 'is_demo_site': | ||||
|             case 'single_user_mode': | ||||
|                 return ['value' => ['required', new IsBoolean]]; | ||||
|             case 'permission_update_check': | ||||
|                 return ['value' => 'required|numeric|between:-1,1']; | ||||
|         } | ||||
|  | ||||
|         return ['value' => 'required']; // @codeCoverageIgnore | ||||
|     } | ||||
| } | ||||
							
								
								
									
										103
									
								
								app/Api/V1/Requests/CurrencyRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								app/Api/V1/Requests/CurrencyRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,103 @@ | ||||
| <?php | ||||
| /** | ||||
|  * CurrencyRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class CurrencyRequest | ||||
|  */ | ||||
| class CurrencyRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         $enabled = true; | ||||
|         $default = false; | ||||
|         if (null !== $this->get('enabled')) { | ||||
|             $enabled = $this->boolean('enabled'); | ||||
|         } | ||||
|         if (null !== $this->get('default')) { | ||||
|             $default = $this->boolean('default'); | ||||
|         } | ||||
|  | ||||
|         return [ | ||||
|             'name'           => $this->string('name'), | ||||
|             'code'           => $this->string('code'), | ||||
|             'symbol'         => $this->string('symbol'), | ||||
|             'decimal_places' => $this->integer('decimal_places'), | ||||
|             'default'        => $default, | ||||
|             'enabled'        => $enabled, | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             'name'           => 'required|between:1,255|unique:transaction_currencies,name', | ||||
|             'code'           => 'required|between:3,3|unique:transaction_currencies,code', | ||||
|             'symbol'         => 'required|between:1,5|unique:transaction_currencies,symbol', | ||||
|             'decimal_places' => 'between:0,20|numeric|min:0|max:20', | ||||
|             'enabled'        => [new IsBoolean()], | ||||
|             'default'        => [new IsBoolean()], | ||||
|  | ||||
|         ]; | ||||
|  | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 $currency        = $this->route()->parameter('currency_code'); | ||||
|                 $rules['name']   = 'required|between:1,255|unique:transaction_currencies,name,' . $currency->id; | ||||
|                 $rules['code']   = 'required|between:1,255|unique:transaction_currencies,code,' . $currency->id; | ||||
|                 $rules['symbol'] = 'required|between:1,255|unique:transaction_currencies,symbol,' . $currency->id; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										91
									
								
								app/Api/V1/Requests/LinkTypeRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								app/Api/V1/Requests/LinkTypeRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | ||||
| <?php | ||||
| /** | ||||
|  * LinkTypeRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Models\LinkType; | ||||
| use Illuminate\Validation\Rule; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * Class LinkTypeRequest | ||||
|  */ | ||||
| class LinkTypeRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         return [ | ||||
|             'name'    => $this->string('name'), | ||||
|             'outward' => $this->string('outward'), | ||||
|             'inward'  => $this->string('inward'), | ||||
|         ]; | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             'name'    => 'required|unique:link_types,name|min:1', | ||||
|             'outward' => 'required|unique:link_types,outward|min:1|different:inward', | ||||
|             'inward'  => 'required|unique:link_types,inward|min:1|different:outward', | ||||
|         ]; | ||||
|  | ||||
|  | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 /** @var LinkType $linkType */ | ||||
|                 $linkType         = $this->route()->parameter('linkType'); | ||||
|                 $rules['name']    = ['required', Rule::unique('link_types', 'name')->ignore($linkType->id), 'min:1']; | ||||
|                 $rules['outward'] = ['required', 'different:inward', Rule::unique('link_types', 'outward')->ignore($linkType->id), 'min:1']; | ||||
|                 $rules['inward']  = ['required', 'different:outward', Rule::unique('link_types', 'inward')->ignore($linkType->id), 'min:1']; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										99
									
								
								app/Api/V1/Requests/PiggyBankRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								app/Api/V1/Requests/PiggyBankRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | ||||
| <?php | ||||
| /** | ||||
|  * PiggyBankRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Rules\IsAssetAccountId; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * Class PiggyBankRequest | ||||
|  */ | ||||
| class PiggyBankRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         $current = $this->string('current_amount'); | ||||
|         $current = '' === $current ? '0' : $current; | ||||
|  | ||||
|         return [ | ||||
|             'name'           => $this->string('name'), | ||||
|             'account_id'     => $this->integer('account_id'), | ||||
|             'targetamount'   => $this->string('target_amount'), | ||||
|             'current_amount' => $current, | ||||
|             'startdate'      => $this->date('start_date'), | ||||
|             'targetdate'     => $this->date('target_date'), | ||||
|             'notes'          => $this->string('notes'), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             'name'           => 'required|between:1,255|uniquePiggyBankForUser', | ||||
|             'account_id'     => ['required', 'belongsToUser:accounts', new IsAssetAccountId], | ||||
|             'target_amount'  => 'required|numeric|more:0', | ||||
|             'current_amount' => 'numeric|more:0|lte:target_amount', | ||||
|             'start_date'     => 'date|nullable', | ||||
|             'target_date'    => 'date|nullable|after:start_date', | ||||
|             'notes'          => 'max:65000', | ||||
|         ]; | ||||
|  | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 /** @var PiggyBank $piggyBank */ | ||||
|                 $piggyBank     = $this->route()->parameter('piggyBank'); | ||||
|                 $rules['name'] = 'required|between:1,255|uniquePiggyBankForUser:' . $piggyBank->id; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										69
									
								
								app/Api/V1/Requests/PreferenceRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								app/Api/V1/Requests/PreferenceRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| <?php | ||||
| /** | ||||
|  * PreferenceRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * Class PreferenceRequest | ||||
|  */ | ||||
| class PreferenceRequest extends Request | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         return [ | ||||
|             'data' => $this->get('data'), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         return [ | ||||
|             'data' => 'required|between:1,65000', | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										214
									
								
								app/Api/V1/Requests/RecurrenceRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										214
									
								
								app/Api/V1/Requests/RecurrenceRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,214 @@ | ||||
| <?php | ||||
| /** | ||||
|  * RecurrenceRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Rules\BelongsUser; | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
| use FireflyIII\Validation\RecurrenceValidation; | ||||
| use FireflyIII\Validation\TransactionValidation; | ||||
| use Illuminate\Validation\Validator; | ||||
|  | ||||
| /** | ||||
|  * Class RecurrenceRequest | ||||
|  */ | ||||
| class RecurrenceRequest extends Request | ||||
| { | ||||
|     use RecurrenceValidation, TransactionValidation; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         $active     = true; | ||||
|         $applyRules = true; | ||||
|         if (null !== $this->get('active')) { | ||||
|             $active = $this->boolean('active'); | ||||
|         } | ||||
|         if (null !== $this->get('apply_rules')) { | ||||
|             $applyRules = $this->boolean('apply_rules'); | ||||
|         } | ||||
|         $return = [ | ||||
|             'recurrence'   => [ | ||||
|                 'type'         => $this->string('type'), | ||||
|                 'title'        => $this->string('title'), | ||||
|                 'description'  => $this->string('description'), | ||||
|                 'first_date'   => $this->date('first_date'), | ||||
|                 'repeat_until' => $this->date('repeat_until'), | ||||
|                 'repetitions'  => $this->integer('nr_of_repetitions'), | ||||
|                 'apply_rules'  => $applyRules, | ||||
|                 'active'       => $active, | ||||
|             ], | ||||
|             'meta'         => [ | ||||
|                 'piggy_bank_id'   => $this->integer('piggy_bank_id'), | ||||
|                 'piggy_bank_name' => $this->string('piggy_bank_name'), | ||||
|                 'tags'            => explode(',', $this->string('tags')), | ||||
|             ], | ||||
|             'transactions' => $this->getTransactionData(), | ||||
|             'repetitions'  => $this->getRepetitionData(), | ||||
|         ]; | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $today = Carbon::now()->addDay(); | ||||
|  | ||||
|         return [ | ||||
|             'type'                                 => 'required|in:withdrawal,transfer,deposit', | ||||
|             'title'                                => 'required|between:1,255|uniqueObjectForUser:recurrences,title', | ||||
|             'description'                          => 'between:1,65000', | ||||
|             'first_date'                           => sprintf('required|date|after:%s', $today->format('Y-m-d')), | ||||
|             'apply_rules'                          => [new IsBoolean], | ||||
|             'active'                               => [new IsBoolean], | ||||
|             'repeat_until'                         => sprintf('date|after:%s', $today->format('Y-m-d')), | ||||
|             'nr_of_repetitions'                    => 'numeric|between:1,31', | ||||
|             'tags'                                 => 'between:1,64000', | ||||
|             'piggy_bank_id'                        => 'numeric', | ||||
|             'repetitions.*.type'                   => 'required|in:daily,weekly,ndom,monthly,yearly', | ||||
|             'repetitions.*.moment'                 => 'between:0,10', | ||||
|             'repetitions.*.skip'                   => 'required|numeric|between:0,31', | ||||
|             'repetitions.*.weekend'                => 'required|numeric|min:1|max:4', | ||||
|             'transactions.*.description'           => 'required|between:1,255', | ||||
|             'transactions.*.amount'                => 'required|numeric|more:0', | ||||
|             'transactions.*.foreign_amount'        => 'numeric|more:0', | ||||
|             'transactions.*.currency_id'           => 'numeric|exists:transaction_currencies,id', | ||||
|             'transactions.*.currency_code'         => 'min:3|max:3|exists:transaction_currencies,code', | ||||
|             'transactions.*.foreign_currency_id'   => 'numeric|exists:transaction_currencies,id', | ||||
|             'transactions.*.foreign_currency_code' => 'min:3|max:3|exists:transaction_currencies,code', | ||||
|             'transactions.*.budget_id'             => ['mustExist:budgets,id', new BelongsUser], | ||||
|             'transactions.*.category_name'         => 'between:1,255|nullable', | ||||
|             'transactions.*.source_id'             => ['numeric', 'nullable', new BelongsUser], | ||||
|             'transactions.*.source_name'           => 'between:1,255|nullable', | ||||
|             'transactions.*.destination_id'        => ['numeric', 'nullable', new BelongsUser], | ||||
|             'transactions.*.destination_name'      => 'between:1,255|nullable', | ||||
|  | ||||
|  | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Configure the validator instance. | ||||
|      * | ||||
|      * @param  Validator $validator | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function withValidator(Validator $validator): void | ||||
|     { | ||||
|         $validator->after( | ||||
|             function (Validator $validator) { | ||||
|                 $this->validateOneTransaction($validator); | ||||
|                 $this->validateOneRepetition($validator); | ||||
|                 $this->validateRecurrenceRepetition($validator); | ||||
|                 $this->validateRepetitionMoment($validator); | ||||
|                 $this->validateForeignCurrencyInformation($validator); | ||||
|                 $this->validateAccountInformation($validator); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Returns the repetition data as it is found in the submitted data. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getRepetitionData(): array | ||||
|     { | ||||
|         $return = []; | ||||
|         // repetition data: | ||||
|         /** @var array $repetitions */ | ||||
|         $repetitions = $this->get('repetitions'); | ||||
|         /** @var array $repetition */ | ||||
|         foreach ($repetitions as $repetition) { | ||||
|             $return[] = [ | ||||
|                 'type'    => $repetition['type'], | ||||
|                 'moment'  => $repetition['moment'], | ||||
|                 'skip'    => (int)$repetition['skip'], | ||||
|                 'weekend' => (int)$repetition['weekend'], | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the transaction data as it is found in the submitted data. It's a complex method according to code | ||||
|      * standards but it just has a lot of ??-statements because of the fields that may or may not exist. | ||||
|      * | ||||
|      * @return array | ||||
|      * @SuppressWarnings(PHPMD.NPathComplexity) | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      */ | ||||
|     private function getTransactionData(): array | ||||
|     { | ||||
|         $return = []; | ||||
|         // transaction data: | ||||
|         /** @var array $transactions */ | ||||
|         $transactions = $this->get('transactions'); | ||||
|         /** @var array $transaction */ | ||||
|         foreach ($transactions as $transaction) { | ||||
|             $return[] = [ | ||||
|                 'amount'                => $transaction['amount'], | ||||
|                 'currency_id'           => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null, | ||||
|                 'currency_code'         => $transaction['currency_code'] ?? null, | ||||
|                 'foreign_amount'        => $transaction['foreign_amount'] ?? null, | ||||
|                 'foreign_currency_id'   => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null, | ||||
|                 'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null, | ||||
|                 'budget_id'             => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null, | ||||
|                 'budget_name'           => $transaction['budget_name'] ?? null, | ||||
|                 'category_id'           => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null, | ||||
|                 'category_name'         => $transaction['category_name'] ?? null, | ||||
|                 'source_id'             => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null, | ||||
|                 'source_name'           => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null, | ||||
|                 'destination_id'        => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null, | ||||
|                 'destination_name'      => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null, | ||||
|                 'description'           => $transaction['description'], | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										39
									
								
								app/Api/V1/Requests/Request.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								app/Api/V1/Requests/Request.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * Request.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Http\Requests\Request as FireflyIIIRequest; | ||||
|  | ||||
| /** | ||||
|  * Class Request. | ||||
|  * | ||||
|  * Technically speaking this class does not have to be extended like this but who knows what the future brings. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.NumberOfChildren) | ||||
|  */ | ||||
| class Request extends FireflyIIIRequest | ||||
| { | ||||
|  | ||||
| } | ||||
							
								
								
									
										92
									
								
								app/Api/V1/Requests/RuleGroupRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								app/Api/V1/Requests/RuleGroupRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| <?php | ||||
| /** | ||||
|  * RuleGroupRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Models\RuleGroup; | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * Class RuleGroupRequest | ||||
|  */ | ||||
| class RuleGroupRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         $active = true; | ||||
|  | ||||
|         if (null !== $this->get('active')) { | ||||
|             $active = $this->boolean('active'); | ||||
|         } | ||||
|  | ||||
|         return [ | ||||
|             'title'       => $this->string('title'), | ||||
|             'description' => $this->string('description'), | ||||
|             'active'      => $active, | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             'title'       => 'required|between:1,100|uniqueObjectForUser:rule_groups,title', | ||||
|             'description' => 'between:1,5000|nullable', | ||||
|             'active'      => [new IsBoolean], | ||||
|         ]; | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 /** @var RuleGroup $ruleGroup */ | ||||
|                 $ruleGroup      = $this->route()->parameter('ruleGroup'); | ||||
|                 $rules['title'] = 'required|between:1,100|uniqueObjectForUser:rule_groups,title,' . $ruleGroup->id; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										205
									
								
								app/Api/V1/Requests/RuleRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										205
									
								
								app/Api/V1/Requests/RuleRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,205 @@ | ||||
| <?php | ||||
| /** | ||||
|  * RuleRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
| use Illuminate\Validation\Validator; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class RuleRequest | ||||
|  */ | ||||
| class RuleRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         $strict         = true; | ||||
|         $active         = true; | ||||
|         $stopProcessing = false; | ||||
|         if (null !== $this->get('active')) { | ||||
|             $active = $this->boolean('active'); | ||||
|         } | ||||
|         if (null !== $this->get('strict')) { | ||||
|             $strict = $this->boolean('strict'); | ||||
|         } | ||||
|         if (null !== $this->get('stop_processing')) { | ||||
|             $stopProcessing = $this->boolean('stop_processing'); | ||||
|         } | ||||
|  | ||||
|         $data = [ | ||||
|             'title'            => $this->string('title'), | ||||
|             'description'      => $this->string('description'), | ||||
|             'rule_group_id'    => $this->integer('rule_group_id'), | ||||
|             'rule_group_title' => $this->string('rule_group_title'), | ||||
|             'trigger'          => $this->string('trigger'), | ||||
|             'strict'           => $strict, | ||||
|             'stop_processing'  => $stopProcessing, | ||||
|             'active'           => $active, | ||||
|             'triggers'         => $this->getRuleTriggers(), | ||||
|             'actions'          => $this->getRuleActions(), | ||||
|         ]; | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $validTriggers = array_keys(config('firefly.rule-triggers')); | ||||
|         $validActions  = array_keys(config('firefly.rule-actions')); | ||||
|  | ||||
|         // some triggers and actions require text: | ||||
|         $contextTriggers = implode(',', config('firefly.context-rule-triggers')); | ||||
|         $contextActions  = implode(',', config('firefly.context-rule-actions')); | ||||
|         $rules           = [ | ||||
|             'title'                      => 'required|between:1,100|uniqueObjectForUser:rules,title', | ||||
|             'description'                => 'between:1,5000|nullable', | ||||
|             'rule_group_id'              => 'required|belongsToUser:rule_groups|required_without:rule_group_title', | ||||
|             'rule_group_title'           => 'nullable|between:1,255|required_without:rule_group_id|belongsToUser:rule_groups,title', | ||||
|             'trigger'                    => 'required|in:store-journal,update-journal', | ||||
|             'triggers.*.type'            => 'required|in:' . implode(',', $validTriggers), | ||||
|             'triggers.*.value'           => 'required_if:actions.*.type,' . $contextTriggers . '|min:1|ruleTriggerValue', | ||||
|             'triggers.*.stop_processing' => [new IsBoolean], | ||||
|             'triggers.*.active'          => [new IsBoolean], | ||||
|             'actions.*.type'             => 'required|in:' . implode(',', $validActions), | ||||
|             'actions.*.value'            => 'required_if:actions.*.type,' . $contextActions . '|ruleActionValue', | ||||
|             'actions.*.stop_processing'  => [new IsBoolean], | ||||
|             'actions.*.active'           => [new IsBoolean], | ||||
|             'strict'                     => [new IsBoolean], | ||||
|             'stop_processing'            => [new IsBoolean], | ||||
|             'active'                     => [new IsBoolean], | ||||
|         ]; | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Configure the validator instance. | ||||
|      * | ||||
|      * @param  Validator $validator | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function withValidator(Validator $validator): void | ||||
|     { | ||||
|         $validator->after( | ||||
|             function (Validator $validator) { | ||||
|                 $this->atLeastOneTrigger($validator); | ||||
|                 $this->atLeastOneAction($validator); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Adds an error to the validator when there are no repetitions in the array of data. | ||||
|      * | ||||
|      * @param Validator $validator | ||||
|      */ | ||||
|     protected function atLeastOneAction(Validator $validator): void | ||||
|     { | ||||
|         $data    = $validator->getData(); | ||||
|         $actions = $data['actions'] ?? []; | ||||
|         // need at least one trigger | ||||
|         if (0 === \count($actions)) { | ||||
|             $validator->errors()->add('title', (string)trans('validation.at_least_one_action')); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Adds an error to the validator when there are no repetitions in the array of data. | ||||
|      * | ||||
|      * @param Validator $validator | ||||
|      */ | ||||
|     protected function atLeastOneTrigger(Validator $validator): void | ||||
|     { | ||||
|         $data     = $validator->getData(); | ||||
|         $triggers = $data['triggers'] ?? []; | ||||
|         // need at least one trugger | ||||
|         if (0 === \count($triggers)) { | ||||
|             $validator->errors()->add('title', (string)trans('validation.at_least_one_trigger')); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getRuleActions(): array | ||||
|     { | ||||
|         $actions = $this->get('actions'); | ||||
|         $return  = []; | ||||
|         if (\is_array($actions)) { | ||||
|             foreach ($actions as $action) { | ||||
|                 $return[] = [ | ||||
|                     'type'            => $action['type'], | ||||
|                     'value'           => $action['value'], | ||||
|                     'active'          => $this->convertBoolean((string)($action['active'] ?? 'false')), | ||||
|                     'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')), | ||||
|                 ]; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getRuleTriggers(): array | ||||
|     { | ||||
|         $triggers = $this->get('triggers'); | ||||
|         $return   = []; | ||||
|         if (\is_array($triggers)) { | ||||
|             foreach ($triggers as $trigger) { | ||||
|                 $return[] = [ | ||||
|                     'type'            => $trigger['type'], | ||||
|                     'value'           => $trigger['value'], | ||||
|                     'active'          => $this->convertBoolean((string)($trigger['active'] ?? 'false')), | ||||
|                     'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')), | ||||
|                 ]; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										93
									
								
								app/Api/V1/Requests/TagRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								app/Api/V1/Requests/TagRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,93 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * TagRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Models\Tag; | ||||
|  | ||||
| /** | ||||
|  * Class TagRequest | ||||
|  */ | ||||
| class TagRequest extends Request | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         $data = [ | ||||
|             'tag'         => $this->string('tag'), | ||||
|             'date'        => $this->date('date'), | ||||
|             'description' => $this->string('description'), | ||||
|             'latitude'    => '' === $this->string('latitude') ? null : $this->string('latitude'), | ||||
|             'longitude'   => '' === $this->string('longitude') ? null : $this->string('longitude'), | ||||
|             'zoom_level'  => $this->integer('zoom_level'), | ||||
|         ]; | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             'tag'         => 'required|min:1|uniqueObjectForUser:tags,tag', | ||||
|             'description' => 'min:1|nullable', | ||||
|             'date'        => 'date|nullable', | ||||
|             'latitude'    => 'numeric|min:-90|max:90|nullable|required_with:longitude', | ||||
|             'longitude'   => 'numeric|min:-180|max:180|nullable|required_with:latitude', | ||||
|             'zoom_level'  => 'numeric|min:0|max:80|nullable', | ||||
|         ]; | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 /** @var Tag $tag */ | ||||
|                 $tag          = $this->route()->parameter('tagOrId'); | ||||
|                 $rules['tag'] = 'required|min:1|uniqueObjectForUser:tags,tag,' . $tag->id; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										138
									
								
								app/Api/V1/Requests/TransactionLinkRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								app/Api/V1/Requests/TransactionLinkRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,138 @@ | ||||
| <?php | ||||
| /** | ||||
|  * TransactionLinkRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Repositories\Journal\JournalRepositoryInterface; | ||||
| use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Validation\Validator; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * Class TransactionLinkRequest | ||||
|  */ | ||||
| class TransactionLinkRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         return [ | ||||
|             'link_type_id'   => $this->integer('link_type_id'), | ||||
|             'link_type_name' => $this->string('link_type_name'), | ||||
|             'inward_id'      => $this->integer('inward_id'), | ||||
|             'outward_id'     => $this->integer('outward_id'), | ||||
|             'notes'          => $this->string('notes'), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         return [ | ||||
|             'link_type_id'   => 'exists:link_types,id|required_without:link_type_name', | ||||
|             'link_type_name' => 'exists:link_types,name|required_without:link_type_id', | ||||
|             'inward_id'      => 'required|belongsToUser:transaction_journals,id|different:outward_id', | ||||
|             'outward_id'     => 'required|belongsToUser:transaction_journals,id|different:inward_id', | ||||
|             'notes'          => 'between:0,65000', | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Configure the validator instance. | ||||
|      * | ||||
|      * @param  Validator $validator | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function withValidator(Validator $validator): void | ||||
|     { | ||||
|         $validator->after( | ||||
|             function (Validator $validator) { | ||||
|                 $this->validateExistingLink($validator); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Validator $validator | ||||
|      */ | ||||
|     private function validateExistingLink(Validator $validator): void | ||||
|     { | ||||
|         /** @var User $user */ | ||||
|         $user = auth()->user(); | ||||
|         /** @var LinkTypeRepositoryInterface $repository */ | ||||
|         $repository = app(LinkTypeRepositoryInterface::class); | ||||
|         $repository->setUser($user); | ||||
|  | ||||
|         /** @var JournalRepositoryInterface $journalRepos */ | ||||
|         $journalRepos = app(JournalRepositoryInterface::class); | ||||
|         $journalRepos->setUser($user); | ||||
|  | ||||
|         $data      = $validator->getData(); | ||||
|         $inwardId  = (int)($data['inward_id'] ?? 0); | ||||
|         $outwardId = (int)($data['outward_id'] ?? 0); | ||||
|         $inward    = $journalRepos->findNull($inwardId); | ||||
|         $outward   = $journalRepos->findNull($outwardId); | ||||
|  | ||||
|         if (null === $inward) { | ||||
|             $validator->errors()->add('inward_id', 'Invalid inward ID.'); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|         if (null === $outward) { | ||||
|             $validator->errors()->add('outward_id', 'Invalid outward ID.'); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if ($repository->findLink($inward, $outward)) { | ||||
|             // only if not updating: | ||||
|             $link = $this->route()->parameter('journalLink'); | ||||
|             if (null === $link) { | ||||
|                 $validator->errors()->add('outward_id', 'Already have a link between inward and outward.'); | ||||
|                 $validator->errors()->add('inward_id', 'Already have a link between inward and outward.'); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										222
									
								
								app/Api/V1/Requests/TransactionRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										222
									
								
								app/Api/V1/Requests/TransactionRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,222 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * TransactionRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Rules\BelongsUser; | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
| use FireflyIII\Rules\IsDateOrTime; | ||||
| use FireflyIII\Validation\TransactionValidation; | ||||
| use Illuminate\Validation\Validator; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class TransactionRequest | ||||
|  */ | ||||
| class TransactionRequest extends Request | ||||
| { | ||||
|     use TransactionValidation; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data. Is pretty complex because of all the ??-statements. | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * @SuppressWarnings(PHPMD.NPathComplexity) | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         $data = [ | ||||
|             'type'               => $this->string('type'), | ||||
|             'date'               => $this->dateTime('date'), | ||||
|             'description'        => $this->string('description'), | ||||
|             'piggy_bank_id'      => $this->integer('piggy_bank_id'), | ||||
|             'piggy_bank_name'    => $this->string('piggy_bank_name'), | ||||
|             'bill_id'            => $this->integer('bill_id'), | ||||
|             'bill_name'          => $this->string('bill_name'), | ||||
|             'tags'               => explode(',', $this->string('tags')), | ||||
|             'notes'              => $this->string('notes'), | ||||
|             'sepa-cc'            => $this->string('sepa_cc'), | ||||
|             'sepa-ct-op'         => $this->string('sepa_ct_op'), | ||||
|             'sepa-ct-id'         => $this->string('sepa_ct_id'), | ||||
|             'sepa-db'            => $this->string('sepa_db'), | ||||
|             'sepa-country'       => $this->string('sepa_country'), | ||||
|             'sepa-ep'            => $this->string('sepa_ep'), | ||||
|             'sepa-ci'            => $this->string('sepa_ci'), | ||||
|             'sepa-batch-id'      => $this->string('sepa_batch_id'), | ||||
|             'interest_date'      => $this->date('interest_date'), | ||||
|             'book_date'          => $this->date('book_date'), | ||||
|             'process_date'       => $this->date('process_date'), | ||||
|             'due_date'           => $this->date('due_date'), | ||||
|             'payment_date'       => $this->date('payment_date'), | ||||
|             'invoice_date'       => $this->date('invoice_date'), | ||||
|             'internal_reference' => $this->string('internal_reference'), | ||||
|             'bunq_payment_id'    => $this->string('bunq_payment_id'), | ||||
|             'external_id'        => $this->string('external_id'), | ||||
|             'original-source'    => sprintf('ff3-v%s|api-v%s', config('firefly.version'), config('firefly.api_version')), | ||||
|             'transactions'       => $this->getTransactionData(), | ||||
|         ]; | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             // basic fields for journal: | ||||
|             'type'                                 => 'required|in:withdrawal,deposit,transfer,opening-balance,reconciliation', | ||||
|             'description'                          => 'between:1,255', | ||||
|             'date'                                 => ['required', new IsDateOrTime], | ||||
|             'piggy_bank_id'                        => ['numeric', 'nullable', 'mustExist:piggy_banks,id', new BelongsUser], | ||||
|             'piggy_bank_name'                      => ['between:1,255', 'nullable', new BelongsUser], | ||||
|             'bill_id'                              => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser], | ||||
|             'bill_name'                            => ['between:1,255', 'nullable', new BelongsUser], | ||||
|             'tags'                                 => 'between:1,255', | ||||
|  | ||||
|             // then, custom fields for journal | ||||
|             'notes'                                => 'min:1,max:50000|nullable', | ||||
|  | ||||
|             // SEPA fields: | ||||
|             'sepa_cc'                              => 'min:1,max:255|nullable', | ||||
|             'sepa_ct_op'                           => 'min:1,max:255|nullable', | ||||
|             'sepa_ct_id'                           => 'min:1,max:255|nullable', | ||||
|             'sepa_db'                              => 'min:1,max:255|nullable', | ||||
|             'sepa_country'                         => 'min:1,max:255|nullable', | ||||
|             'sepa_ep'                              => 'min:1,max:255|nullable', | ||||
|             'sepa_ci'                              => 'min:1,max:255|nullable', | ||||
|             'sepa_batch_id'                        => 'min:1,max:255|nullable', | ||||
|  | ||||
|             // dates | ||||
|             'interest_date'                        => 'date|nullable', | ||||
|             'book_date'                            => 'date|nullable', | ||||
|             'process_date'                         => 'date|nullable', | ||||
|             'due_date'                             => 'date|nullable', | ||||
|             'payment_date'                         => 'date|nullable', | ||||
|             'invoice_date'                         => 'date|nullable', | ||||
|             'internal_reference'                   => 'min:1,max:255|nullable', | ||||
|             'bunq_payment_id'                      => 'min:1,max:255|nullable', | ||||
|             'external_id'                          => 'min:1,max:255|nullable', | ||||
|  | ||||
|             // transaction rules (in array for splits): | ||||
|             'transactions.*.amount'                => 'required|numeric|more:0', | ||||
|             'transactions.*.description'           => 'nullable|between:1,255', | ||||
|             'transactions.*.currency_id'           => 'numeric|exists:transaction_currencies,id', | ||||
|             'transactions.*.currency_code'         => 'min:3|max:3|exists:transaction_currencies,code', | ||||
|             'transactions.*.foreign_amount'        => 'numeric|more:0', | ||||
|             'transactions.*.foreign_currency_id'   => 'numeric|exists:transaction_currencies,id', | ||||
|             'transactions.*.foreign_currency_code' => 'min:3|max:3|exists:transaction_currencies,code', | ||||
|             'transactions.*.budget_id'             => ['mustExist:budgets,id', new BelongsUser], | ||||
|             'transactions.*.budget_name'           => ['between:1,255', 'nullable', new BelongsUser], | ||||
|             'transactions.*.category_id'           => ['mustExist:categories,id', new BelongsUser], | ||||
|             'transactions.*.category_name'         => 'between:1,255|nullable', | ||||
|             'transactions.*.reconciled'            => [new IsBoolean], | ||||
|             'transactions.*.source_id'             => ['numeric', 'nullable', new BelongsUser], | ||||
|             'transactions.*.source_name'           => 'between:1,255|nullable', | ||||
|             'transactions.*.destination_id'        => ['numeric', 'nullable', new BelongsUser], | ||||
|             'transactions.*.destination_name'      => 'between:1,255|nullable', | ||||
|         ]; | ||||
|  | ||||
|         if ('PUT' === $this->method()) { | ||||
|             unset($rules['type'], $rules['piggy_bank_id'], $rules['piggy_bank_name']); | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Configure the validator instance. | ||||
|      * | ||||
|      * @param  Validator $validator | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function withValidator(Validator $validator): void | ||||
|     { | ||||
|         $validator->after( | ||||
|             function (Validator $validator) { | ||||
|                 $this->validateOneTransaction($validator); | ||||
|                 $this->validateDescriptions($validator); | ||||
|                 $this->validateJournalDescription($validator); | ||||
|                 $this->validateSplitDescriptions($validator); | ||||
|                 $this->validateForeignCurrencyInformation($validator); | ||||
|                 $this->validateAccountInformation($validator); | ||||
|                 $this->validateSplitAccounts($validator); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get transaction data. | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * @SuppressWarnings(PHPMD.NPathComplexity) | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getTransactionData(): array | ||||
|     { | ||||
|         $return = []; | ||||
|         foreach ($this->get('transactions') as $index => $transaction) { | ||||
|             $return[] = [ | ||||
|                 'amount'                => $transaction['amount'], | ||||
|                 'description'           => $transaction['description'] ?? null, | ||||
|                 'currency_id'           => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null, | ||||
|                 'currency_code'         => $transaction['currency_code'] ?? null, | ||||
|                 'foreign_amount'        => $transaction['foreign_amount'] ?? null, | ||||
|                 'foreign_currency_id'   => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null, | ||||
|                 'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null, | ||||
|                 'budget_id'             => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null, | ||||
|                 'budget_name'           => $transaction['budget_name'] ?? null, | ||||
|                 'category_id'           => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null, | ||||
|                 'category_name'         => $transaction['category_name'] ?? null, | ||||
|                 'source_id'             => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null, | ||||
|                 'source_name'           => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null, | ||||
|                 'destination_id'        => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null, | ||||
|                 'destination_name'      => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null, | ||||
|                 'reconciled'            => $this->convertBoolean((string)($transaction['reconciled'] ?? 'false')), | ||||
|                 'identifier'            => $index, | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										108
									
								
								app/Api/V1/Requests/UserRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								app/Api/V1/Requests/UserRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * UserRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Repositories\User\UserRepositoryInterface; | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
| use FireflyIII\User; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class UserRequest | ||||
|  */ | ||||
| class UserRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         $result = false; | ||||
|         // Only allow authenticated users | ||||
|         if (auth()->check()) { | ||||
|             /** @var User $user */ | ||||
|             $user = auth()->user(); | ||||
|  | ||||
|             /** @var UserRepositoryInterface $repository */ | ||||
|             $repository = app(UserRepositoryInterface::class); | ||||
|  | ||||
|             if ($repository->hasRole($user, 'owner')) { | ||||
|                 $result = true; // @codeCoverageIgnore | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         $blocked = false; | ||||
|         if (null === $this->get('blocked')) { | ||||
|             $blocked = $this->boolean('blocked'); | ||||
|         } | ||||
|         $data = [ | ||||
|             'email'        => $this->string('email'), | ||||
|             'blocked'      => $blocked, | ||||
|             'blocked_code' => $this->string('blocked_code'), | ||||
|             'role'         => $this->string('role'), | ||||
|         ]; | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             'email'        => 'required|email|unique:users,email,', | ||||
|             'blocked'      => [new IsBoolean], | ||||
|             'blocked_code' => 'in:email_changed', | ||||
|             'role'         => 'in:owner,demo', | ||||
|         ]; | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 $user           = $this->route()->parameter('user'); | ||||
|                 $rules['email'] = 'required|email|unique:users,email,' . $user->id; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
|  | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user