mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-31 10:47:00 +00:00 
			
		
		
		
	Compare commits
	
		
			710 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | ca3e4e978d | ||
|  | 0dbfeed639 | ||
|  | ca235e2287 | ||
|  | 9d826519e3 | ||
|  | 3979e12043 | ||
|  | b3f1737495 | ||
|  | 179a710c5b | ||
|  | 08f347cd57 | ||
|  | c910cbe5da | ||
|  | 34a2ab31df | ||
|  | 229a3b4284 | ||
|  | dbc878950c | ||
|  | ab4bcd3703 | ||
|  | 048e5eeb31 | ||
|  | a526559a0e | ||
|  | 8dbd785ab8 | ||
|  | 0845e1cb7d | ||
|  | 20598d877d | ||
|  | cf540bf173 | ||
|  | a8fcde1459 | ||
|  | bcdc562bf7 | ||
|  | 171f8c5848 | ||
|  | 58bb5eaeae | ||
|  | fd629d6574 | ||
|  | 9bafd067f6 | ||
|  | bc06afe17e | ||
|  | 250aa989c4 | ||
|  | 2e3317b95f | ||
|  | c8be714d16 | ||
|  | 2f885d65cc | ||
|  | f07c1f7164 | ||
|  | ed86c26a18 | ||
|  | ec787de5e0 | ||
|  | 0d5c09af84 | ||
|  | ff32f96295 | ||
|  | 590591f6bd | ||
|  | 30f708ba7a | ||
|  | 2e3af087e8 | ||
|  | 6ce922e983 | ||
|  | f63cff91bf | ||
|  | b422ba6547 | ||
|  | 114d53befd | ||
|  | 076010c058 | ||
|  | 56a7793bf1 | ||
|  | 00c610045d | ||
|  | 4b0b2f46ef | ||
|  | 5a53cea90b | ||
|  | 07a3ff01b0 | ||
|  | 03875d7e41 | ||
|  | 0e340288e6 | ||
|  | 1183c40114 | ||
|  | 06ab9df6fc | ||
|  | b871dab5fe | ||
|  | 054eecf541 | ||
|  | 348452ec7d | ||
|  | 1f5934d6e2 | ||
|  | 60fa6c775b | ||
|  | ed98c01ba0 | ||
|  | 198c79c048 | ||
|  | 3cd331062d | ||
|  | 22f1e4db31 | ||
|  | 68693f20bb | ||
|  | 54a4c25152 | ||
|  | 21c615818c | ||
|  | 204d7e57bd | ||
|  | cd151da240 | ||
|  | 687a62fe26 | ||
|  | 0bf0b762b8 | ||
|  | 53a6af7779 | ||
|  | 4c10f2b960 | ||
|  | 2630732b8a | ||
|  | b8774a7af3 | ||
|  | 7a89df749d | ||
|  | 937c11e83c | ||
|  | a79f7e3b59 | ||
|  | c1b52524b1 | ||
|  | 04d451be8d | ||
|  | e5109d6a0f | ||
|  | c404354890 | ||
|  | 01fbe89295 | ||
|  | 388da769bb | ||
|  | 0d4f203fae | ||
|  | 96dbd633bf | ||
|  | 4b1f4ae319 | ||
|  | 13e15d0476 | ||
|  | 7c962c617a | ||
|  | 4e51f0abc4 | ||
|  | 3bd5ac21c9 | ||
|  | d7b872eeaa | ||
|  | c868a6374d | ||
|  | e61720754a | ||
|  | f9f0eaefbe | ||
|  | 5712739df1 | ||
|  | 6e7152a200 | ||
|  | f2b8aab1d2 | ||
|  | 59f2e9cf72 | ||
|  | 3a0793b26a | ||
|  | 659df750d8 | ||
|  | b5983f7e99 | ||
|  | 86d0d18b00 | ||
|  | 28f71963f1 | ||
|  | 27f91365b4 | ||
|  | 8d11fecfeb | ||
|  | c10a955928 | ||
|  | d5a12d56a6 | ||
|  | f869ebbb30 | ||
|  | 3471c964d0 | ||
|  | 94b1934877 | ||
|  | adfd3ab3ac | ||
|  | a42008dd7b | ||
|  | acfc976f6d | ||
|  | 76cfdef27d | ||
|  | d75f33558d | ||
|  | 7345a558ce | ||
|  | 5ba93dda9f | ||
|  | a94195ae45 | ||
|  | 0b8415e82b | ||
|  | a5c37f1e4a | ||
|  | 7bd0b09711 | ||
|  | 64370229d8 | ||
|  | 6671c6d45c | ||
|  | a2eedb3742 | ||
|  | 3bae5e236b | ||
|  | 9f4e950a70 | ||
|  | 4d2d9d4d6e | ||
|  | 61ffc8ada6 | ||
|  | b8e36b0398 | ||
|  | d89e4ec143 | ||
|  | 712b8d6e0c | ||
|  | 50cfb54a3d | ||
|  | dcb1866e81 | ||
|  | f2550a7861 | ||
|  | 5ed3d52e9a | ||
|  | aadcb2cc5b | ||
|  | 96028e91be | ||
|  | f92780d3da | ||
|  | 8c7e3b3731 | ||
|  | 8eb6b5a364 | ||
|  | d03ca0ec36 | ||
|  | c25f5598f1 | ||
|  | d32611b2d5 | ||
|  | 9ab034c1ad | ||
|  | b3edbecde2 | ||
|  | 3ce949f0aa | ||
|  | df8c6abd5c | ||
|  | b94561223e | ||
|  | f633769f7b | ||
|  | 8767bad61e | ||
|  | c01345468d | ||
|  | 8046d14d2d | ||
|  | f957d8aeb5 | ||
|  | 564a387505 | ||
|  | 116fc0c70f | ||
|  | f82e35a8a8 | ||
|  | ea76647b29 | ||
|  | 26dc70c8fd | ||
|  | 85113d50be | ||
|  | 9e41cc27af | ||
|  | 89d8c11b52 | ||
|  | 70d16c31ad | ||
|  | e07f243344 | ||
|  | ba4a43b4aa | ||
|  | 860bf22503 | ||
|  | 4a1f009458 | ||
|  | 4830b3b2c1 | ||
|  | e2bf13b5ca | ||
|  | c36a4f64d4 | ||
|  | 39abea0290 | ||
|  | abec47f6c3 | ||
|  | 4f0100b7a9 | ||
|  | 8c576953ad | ||
|  | e8f9d2b608 | ||
|  | 2347267518 | ||
|  | 602f5b6646 | ||
|  | b1b2e0ff09 | ||
|  | ab38bfe4d2 | ||
|  | dcb3f23078 | ||
|  | c0f363cf86 | ||
|  | 46ebf3c07c | ||
|  | ed7977a105 | ||
|  | f093dbb30b | ||
|  | 620b69f234 | ||
|  | a346b6ee29 | ||
|  | ccb511936e | ||
|  | 9f98289952 | ||
|  | e549b74c97 | ||
|  | f73af50eb0 | ||
|  | 5f5346ed71 | ||
|  | fc157b2944 | ||
|  | cc1a537ecb | ||
|  | 1e5df66c62 | ||
|  | e5ea82663e | ||
|  | 2d6e6f3ec9 | ||
|  | a822c9f833 | ||
|  | 0b8b9cb280 | ||
|  | 29b8cf936e | ||
|  | b288d6b0eb | ||
|  | 8a2d5b12c3 | ||
|  | a7dc9e201f | ||
|  | c686f16a93 | ||
|  | 58245d85b3 | ||
|  | f564ef5195 | ||
|  | 18c24a7251 | ||
|  | d97fd73ce5 | ||
|  | 1624abd9ed | ||
|  | 14f22009ed | ||
|  | 86cd3c0c38 | ||
|  | 855fe1235a | ||
|  | 198a0f7011 | ||
|  | 2b16d73e65 | ||
|  | 03f68426e5 | ||
|  | 229479b7ed | ||
|  | 0f742aa040 | ||
|  | e5ac6a3a1d | ||
|  | d05fb4472c | ||
|  | 5161971373 | ||
|  | 2a5841c631 | ||
|  | 766abd3336 | ||
|  | b58cde5431 | ||
|  | 9964cf11a4 | ||
|  | 7f9c8fa133 | ||
|  | 10057f05a5 | ||
|  | fc61b20f6d | ||
|  | 40e7f019dd | ||
|  | 2f32ddce6b | ||
|  | 459015c01e | ||
|  | b669f96036 | ||
|  | 4524d1cfe3 | ||
|  | 651029e284 | ||
|  | cbeb2675fd | ||
|  | 7a80caf26b | ||
|  | f3eaf1dd4c | ||
|  | af88e91a48 | ||
|  | 706cb47065 | ||
|  | 0d72aa9673 | ||
|  | 039e654ef1 | ||
|  | 1c3fe93d59 | ||
|  | 5ef45fd4a3 | ||
|  | db700d6b80 | ||
|  | 7032bdc169 | ||
|  | 1dde09c738 | ||
|  | a54ca0141a | ||
|  | a553bfd142 | ||
|  | ed01551ad4 | ||
|  | 91473332b4 | ||
|  | 890de05394 | ||
|  | 29445e4ffb | ||
|  | 098eac8bab | ||
|  | e2ad5c60c6 | ||
|  | 34e2595a3d | ||
|  | 284222c2ee | ||
|  | 0b308cb5f2 | ||
|  | 22dc03f32c | ||
|  | c2ff26b515 | ||
|  | 402351a6b7 | ||
|  | 562be457ec | ||
|  | 600e98cf47 | ||
|  | bded065d42 | ||
|  | a526007957 | ||
|  | c0af49f336 | ||
|  | ff6c0c26e0 | ||
|  | a7af8d2195 | ||
|  | f5871898bd | ||
|  | df8f23cba3 | ||
|  | d9bc23725b | ||
|  | a68ab28f00 | ||
|  | 676c282f11 | ||
|  | f99731e90b | ||
|  | 302ece8ffc | ||
|  | 47100a8e51 | ||
|  | 7e59d8cb75 | ||
|  | 7eaa00a5ad | ||
|  | 0713cc55b6 | ||
|  | 8329d68b22 | ||
|  | 3e05cf7306 | ||
|  | 8c116e1bc5 | ||
|  | 7d61986025 | ||
|  | abff2a0a8f | ||
|  | 65499bb9ff | ||
|  | 6f219d1932 | ||
|  | 9d35048fb9 | ||
|  | af58c30249 | ||
|  | 366744ed69 | ||
|  | d809b77154 | ||
|  | 03cec69af3 | ||
|  | 9ae41b1645 | ||
|  | b0f18a0419 | ||
|  | 5648a9197d | ||
|  | f0fe8bf5c7 | ||
|  | 8a690afc46 | ||
|  | 2bb6c48278 | ||
|  | 6eb661df19 | ||
|  | 8e578e1058 | ||
|  | 4f7683b1fd | ||
|  | 656456b9d9 | ||
|  | 8c1daa9eed | ||
|  | f146205208 | ||
|  | dce3c333da | ||
|  | b0d67f1637 | ||
|  | bc913d0e9c | ||
|  | 415ef57458 | ||
|  | 278ddf27bd | ||
|  | 3566305c27 | ||
|  | b41b03e8f0 | ||
|  | e5642b59d7 | ||
|  | e159de9a6a | ||
|  | 2a02e8a790 | ||
|  | 798c73394d | ||
|  | 7f48043505 | ||
|  | 82b49a9e51 | ||
|  | 56ea680e46 | ||
|  | 70f3d13626 | ||
|  | 093f34b7a8 | ||
|  | 63794cab07 | ||
|  | ed17600f79 | ||
|  | 778af9f4e2 | ||
|  | 8c97754b64 | ||
|  | 2393344978 | ||
|  | 4c81a46af6 | ||
|  | 7df084dd3c | ||
|  | 08aa61a2bf | ||
|  | a16ac479d5 | ||
|  | 483e7256f7 | ||
|  | 412b169e3a | ||
|  | bfcd743efa | ||
|  | f123c28540 | ||
|  | 56f9ce333c | ||
|  | cd156d6991 | ||
|  | c985683ee3 | ||
|  | 59ab0c9f0d | ||
|  | a24b6711d1 | ||
|  | 7f7d7be646 | ||
|  | 2f2a02834b | ||
|  | e2a3aa12a8 | ||
|  | a4f70794a2 | ||
|  | 0ee3941b43 | ||
|  | 4e05ce4c35 | ||
|  | c5fa48ca46 | ||
|  | 20e39b2e12 | ||
|  | d28394c5d9 | ||
|  | 86fff1b61c | ||
|  | 71ef5abea5 | ||
|  | 6b83313ce8 | ||
|  | 2fe93656ee | ||
|  | ec8003245f | ||
|  | 8f632cb57b | ||
|  | d7b9129c33 | ||
|  | 82efe530ea | ||
|  | b3805585a7 | ||
|  | 04b84fd0dc | ||
|  | 2ac405b2d0 | ||
|  | eb8571a508 | ||
|  | f7e75e9b8a | ||
|  | 0fd7dabbc1 | ||
|  | 9123454545 | ||
|  | 3141ec0406 | ||
|  | 4bf86500bd | ||
|  | bee54146bf | ||
|  | 28698cc769 | ||
|  | 41f2339c8c | ||
|  | ce34e097a2 | ||
|  | fecc9f7659 | ||
|  | 139b3ffab4 | ||
|  | febe60b3d1 | ||
|  | fc519c41bc | ||
|  | 6e074d9b8b | ||
|  | d89a4d8a54 | ||
|  | a504617425 | ||
|  | 0c0fef6e84 | ||
|  | 1dfda62125 | ||
|  | 5e0c0e25f2 | ||
|  | 07220eb167 | ||
|  | 216a0a186c | ||
|  | 14df37712c | ||
|  | ab5a146277 | ||
|  | 24a373abf4 | ||
|  | ffca935ced | ||
|  | d69934ca8f | ||
|  | 3081911eae | ||
|  | 67806cacdb | ||
|  | 8ee2f12217 | ||
|  | c63721a15f | ||
|  | 9f80d729a2 | ||
|  | d78d2f25eb | ||
|  | 229d4bfe6b | ||
|  | 8e638d1cff | ||
|  | 1b17d53d65 | ||
|  | 77d3410b4e | ||
|  | 6b279398b3 | ||
|  | c34a00b3f3 | ||
|  | ce3c1cccc3 | ||
|  | 00683ff1bc | ||
|  | c2852e30bf | ||
|  | 44680a38b0 | ||
|  | 80a674baab | ||
|  | ff85654cb9 | ||
|  | 56a122705d | ||
|  | a48df9ac83 | ||
|  | d4029775ec | ||
|  | 3dc1050929 | ||
|  | c9a444b079 | ||
|  | 831267b2ab | ||
|  | d8b807df50 | ||
|  | 879e24e7b1 | ||
|  | a1e454d693 | ||
|  | 39f8f14aa1 | ||
|  | d7fd1e333e | ||
|  | 76cd77cc73 | ||
|  | ee3ef4b8cc | ||
|  | 5f9ba78d94 | ||
|  | 93628f4d36 | ||
|  | ac2824dfdd | ||
|  | 9dd6a4430e | ||
|  | f840de0b93 | ||
|  | 6b5e4d34d5 | ||
|  | 94f0b9f331 | ||
|  | 67b5a6c096 | ||
|  | 644796e466 | ||
|  | d244ab1af9 | ||
|  | f2683ae011 | ||
|  | 8844583807 | ||
|  | c7bf6fc866 | ||
|  | 55c4465e5d | ||
|  | f63054823b | ||
|  | 83f441340c | ||
|  | e81865fce3 | ||
|  | bceffbc874 | ||
|  | c6e8a63f7c | ||
|  | 10c9118f49 | ||
|  | cdf42e2a37 | ||
|  | d4c26820fc | ||
|  | 87c134322d | ||
|  | 6d627be679 | ||
|  | 1191ec00db | ||
|  | 027c212546 | ||
|  | be0f2f0b9f | ||
|  | 73c1452aa9 | ||
|  | 7a7f1e7d97 | ||
|  | f60bacba85 | ||
|  | d078764ae4 | ||
|  | 1558a41397 | ||
|  | 9fca946821 | ||
|  | 4f35b9f327 | ||
|  | 74d7183a10 | ||
|  | 3990f4b7af | ||
|  | 99342d615e | ||
|  | 0ad9380226 | ||
|  | 0453493a9e | ||
|  | eb256fced6 | ||
|  | ed0f04d644 | ||
|  | 1a17d5be39 | ||
|  | 0f33e9d48f | ||
|  | 5be8c8e2a7 | ||
|  | 66c1b881ef | ||
|  | 520206ad52 | ||
|  | db00e22063 | ||
|  | 342626684b | ||
|  | 8df6356abf | ||
|  | dfa60ec703 | ||
|  | 1e3fb073e0 | ||
|  | cbf44a9069 | ||
|  | 54e6b5aa83 | ||
|  | bd20500d39 | ||
|  | d26331bd36 | ||
|  | 9d6d15635f | ||
|  | 3e372bb1d9 | ||
|  | 8f22b97905 | ||
|  | 6ecbaf554b | ||
|  | 74b9b0db10 | ||
|  | 4623ff9955 | ||
|  | 2a3651013c | ||
|  | 3fa5694bb8 | ||
|  | 839ba9d109 | ||
|  | 8dd315d7d6 | ||
|  | 9a4a2708c0 | ||
|  | e93521f3ac | ||
|  | 71ce9eb004 | ||
|  | 1338dab5e7 | ||
|  | 7208f8ae35 | ||
|  | 490740721e | ||
|  | 9d9d1325bd | ||
|  | a22e757502 | ||
|  | 6db2b3d434 | ||
|  | e74bce197f | ||
|  | bb6f4843b9 | ||
|  | 61dc1b6f33 | ||
|  | 700579e06a | ||
|  | bff6c81ed2 | ||
|  | c741d56b32 | ||
|  | 0219069766 | ||
|  | d0a01d73c4 | ||
|  | e7e21348eb | ||
|  | e29b2066c2 | ||
|  | fb0d31226a | ||
|  | 30d7d5d90e | ||
|  | 386c067e93 | ||
|  | 384854b353 | ||
|  | 5d63f54fe2 | ||
|  | 9db79c3142 | ||
|  | f4b6a63514 | ||
|  | 1947d81c58 | ||
|  | 1169c5c5e2 | ||
|  | ae7cd76d87 | ||
|  | 7b7076116e | ||
|  | 1b8ebe498a | ||
|  | dc53bedff7 | ||
|  | b9b8c1168f | ||
|  | 35d30fea9c | ||
|  | f3b116cfce | ||
|  | 3bf6891e1c | ||
|  | 723d1cffe2 | ||
|  | 977c78412f | ||
|  | a6a83286b9 | ||
|  | 43fc4c5f52 | ||
|  | c26de3bdd2 | ||
|  | 65f54ed8f3 | ||
|  | c2fc759b68 | ||
|  | c41d766604 | ||
|  | f76fd06055 | ||
|  | 3d5230228e | ||
|  | 07b93037b3 | ||
|  | 8cebd03298 | ||
|  | a502594545 | ||
|  | 57cb325639 | ||
|  | e0b71c316b | ||
|  | ad76afe4f6 | ||
|  | 895762ff18 | ||
|  | 214dcc7e4c | ||
|  | 49b855f7fd | ||
|  | 62494e7943 | ||
|  | d2fd858d18 | ||
|  | 749236bc8d | ||
|  | d3daf8d61e | ||
|  | d3051cb229 | ||
|  | bb89c59b51 | ||
|  | fbd46c683e | ||
|  | d45a5e6c93 | ||
|  | fbb8a0e543 | ||
|  | 4d5a50c026 | ||
|  | b25d046528 | ||
|  | 142b7b9c0e | ||
|  | e46958c23e | ||
|  | c3d8d70b34 | ||
|  | b302775c37 | ||
|  | 4b96558433 | ||
|  | c3110a43da | ||
|  | 22b1bfd189 | ||
|  | c0b7ef878a | ||
|  | 9234636422 | ||
|  | 886e9459a5 | ||
|  | 9d6979e3dd | ||
|  | cea3f860f2 | ||
|  | bc27ce8c56 | ||
|  | c78c1bea7d | ||
|  | 7dcc76f217 | ||
|  | 4c38c7c67b | ||
|  | fcf6863aaf | ||
|  | e57251abf4 | ||
|  | 6e6dd60b46 | ||
|  | 8a91618f8d | ||
|  | cd19e86141 | ||
|  | 1e2829ed8e | ||
|  | 981960fcb4 | ||
|  | 77658d19dd | ||
|  | 0264184442 | ||
|  | eabda85b1e | ||
|  | 93856a3c57 | ||
|  | 7351d98590 | ||
|  | 7ad1458ad7 | ||
|  | 2cb61ea501 | ||
|  | 7c2ae7a91e | ||
|  | 5ae786516a | ||
|  | a590cfd881 | ||
|  | 3b03fb7e8b | ||
|  | d6564f7b7b | ||
|  | fcdeaf3510 | ||
|  | b3761c7088 | ||
|  | 2486faebe9 | ||
|  | 0c7a38a1ad | ||
|  | bdfce234b0 | ||
|  | c5e0ced4bd | ||
|  | 2aed0651b5 | ||
|  | 15089217f0 | ||
|  | 9dff2cca2b | ||
|  | 6eb401247e | ||
|  | dc66163edd | ||
|  | 8d7972ed07 | ||
|  | a40bbb34b3 | ||
|  | ab2602b5d6 | ||
|  | 9123222830 | ||
|  | b8994a7755 | ||
|  | 089bb9e076 | ||
|  | 5b3bb0fa80 | ||
|  | fafee5f527 | ||
|  | 21d7eadee2 | ||
|  | fe7a30c238 | ||
|  | e769a10a95 | ||
|  | 24b5a3787e | ||
|  | f227f19d9f | ||
|  | 8f95e4c55d | ||
|  | da309a3d03 | ||
|  | c2650df224 | ||
|  | 8bbbaab9bb | ||
|  | 67482858b9 | ||
|  | a29487abcd | ||
|  | b910a249cb | ||
|  | 20498efd2e | ||
|  | 4feddb61c5 | ||
|  | 012420c47d | ||
|  | ff9d8865d1 | ||
|  | 3cda3b27e2 | ||
|  | 8363efd1f9 | ||
|  | 36b0167eac | ||
|  | 66b5523310 | ||
|  | 8f568d41ca | ||
|  | 1c07feb446 | ||
|  | 261156588f | ||
|  | 294cda7f33 | ||
|  | 995c43d832 | ||
|  | d49743031f | ||
|  | 7017d33b87 | ||
|  | fade9ae6f9 | ||
|  | c5489a7c55 | ||
|  | 9c14bc24e2 | ||
|  | fe66be673a | ||
|  | fdea25051c | ||
|  | c86673f3ec | ||
|  | 94c31ad747 | ||
|  | 633bc043da | ||
|  | 453709a117 | ||
|  | 83467ef2f2 | ||
|  | 9d409a7412 | ||
|  | 4b16d7c53d | ||
|  | 5e1306282a | ||
|  | 02ad8273eb | ||
|  | 74247c292f | ||
|  | 1286694efd | ||
|  | 69d63bc3ba | ||
|  | bc4b841baa | ||
|  | ba488b71eb | ||
|  | 117affb1d4 | ||
|  | 50ee1a11f6 | ||
|  | 74eddfa1fa | ||
|  | 758e1ff2ad | ||
|  | e1f4cd7565 | ||
|  | 93a0338678 | ||
|  | 3d6bf713ee | ||
|  | b63e8d60bb | ||
|  | 162e791dfd | ||
|  | 0f840ad082 | ||
|  | 6a158a173d | ||
|  | f777abdeb1 | ||
|  | bb841e66c7 | ||
|  | 74ed80aaef | ||
|  | 723696b971 | ||
|  | 858158d886 | ||
|  | 62fd701808 | ||
|  | b207100074 | ||
|  | 5ad7439241 | ||
|  | debbe89187 | ||
|  | a654158bd4 | ||
|  | 0bb59f5505 | ||
|  | 6881d4479e | ||
|  | 7f3168cc55 | ||
|  | 14dd185717 | ||
|  | edf6ece7cb | ||
|  | 3619427f60 | ||
|  | bd779c8156 | ||
|  | cf977a2bfa | ||
|  | 8a4999406b | ||
|  | fd6f1fbbf0 | ||
|  | 9cf99314d1 | ||
|  | fc7d8bb810 | ||
|  | c1f0dedd09 | ||
|  | 3653469dda | ||
|  | 1e313f80a4 | ||
|  | 73f1f8aea0 | ||
|  | 78107b1212 | ||
|  | 3b56f4271e | ||
|  | f3a55e6cee | ||
|  | 2f70ea074e | ||
|  | 88172dbc7c | ||
|  | 34eda509c2 | ||
|  | c7eab7873e | ||
|  | 58c1880219 | ||
|  | d73195ec36 | ||
|  | 427bcaa522 | ||
|  | d55cc03edf | ||
|  | 1282009257 | ||
|  | 106f097b45 | ||
|  | fafb7f5e49 | ||
|  | e54c08e2d3 | ||
|  | 03a63d0119 | ||
|  | e2b698f166 | ||
|  | f14ac5928f | ||
|  | cd65d4d4c5 | ||
|  | 7aa3cd5ba4 | ||
|  | 0fe17d5458 | ||
|  | aaa3cc3d19 | ||
|  | c80d1d3402 | ||
|  | 254b004587 | ||
|  | d813d0b7c2 | ||
|  | 53909fdd8a | ||
|  | 0ba03be9a3 | ||
|  | 7aac446cf2 | ||
|  | f2dcb108e8 | ||
|  | c0e5d6dd68 | ||
|  | 0b966ed541 | ||
|  | 8219b51e47 | ||
|  | 9b102d1cf4 | 
							
								
								
									
										326
									
								
								.ci/.env.ci
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										326
									
								
								.ci/.env.ci
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,326 @@ | ||||
| # 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 | ||||
|  | ||||
| # This should be your email address. | ||||
| # If you use Docker or similar, you can set this variable from a file by using SITE_OWNER_FILE | ||||
| SITE_OWNER=mail@example.com | ||||
|  | ||||
| # The encryption key for your sessions. Keep this very secure. | ||||
| # If you generate a new one all existing attachments must be considered LOST. | ||||
| # Change it to a string of exactly 32 chars or use something like `php artisan key:generate` to generate it. | ||||
| # If you use Docker or similar, you can set this variable from a file by using APP_KEY_FILE | ||||
| APP_KEY=SomeRandomStringOf32CharsExactly | ||||
|  | ||||
| # | ||||
| # Firefly III will launch using this language (for new users and unauthenticated visitors) | ||||
| # For a list of available languages: https://github.com/firefly-iii/firefly-iii/tree/main/resources/lang | ||||
| # | ||||
| # If text is still in English, remember that not everything may have been translated. | ||||
| DEFAULT_LANGUAGE=en_US | ||||
|  | ||||
| # The locale defines how numbers are formatted. | ||||
| # by default this value is the same as whatever the language is. | ||||
| DEFAULT_LOCALE=equal | ||||
|  | ||||
| # Change this value to your preferred time zone. | ||||
| # Example: Europe/Amsterdam | ||||
| # For a list of supported time zones, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones | ||||
| TZ=Europe/Amsterdam | ||||
|  | ||||
| # TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy. | ||||
| # Set it to ** and reverse proxies work just fine. | ||||
| TRUSTED_PROXIES= | ||||
|  | ||||
| # The log channel defines where your log entries go to. | ||||
| # 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. | ||||
| # A rotating log option is 'daily', creates 5 files that (surprise) rotate. | ||||
| # Default setting 'stack' will log to 'daily' and to 'stdout' at the same time. | ||||
|  | ||||
| # - Docker + versions <= 4.8.1.8 and before: use "stdout" | ||||
| # - Docker + versions >  4.8.1.8           : use "docker_out" | ||||
| # - Docker + versions >=  5.1.1            : use "stack" | ||||
| # - For everything else (als not Docker)   : use 'stack' | ||||
|  | ||||
| LOG_CHANNEL=single | ||||
|  | ||||
| # 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=info | ||||
|  | ||||
| # Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III | ||||
| # For other database types, please see the FAQ: https://docs.firefly-iii.org/support/faq | ||||
| # If you use Docker or similar, you can set these variables from a file by appending them with _FILE | ||||
| # Use "pgsql" for PostgreSQL | ||||
| # Use "mysql" for MySQL and MariaDB. | ||||
| # Use "sqlite" for SQLite. | ||||
| DB_CONNECTION=sqlite_test | ||||
|  | ||||
| # MySQL supports SSL. You can configure it here. | ||||
| # If you use Docker or similar, you can set these variables from a file by appending them with _FILE | ||||
| MYSQL_USE_SSL=false | ||||
| MYSQL_SSL_VERIFY_SERVER_CERT=true | ||||
| # You need to set at least of these options | ||||
| MYSQL_SSL_CAPATH=/etc/ssl/certs/ | ||||
| MYSQL_SSL_CA= | ||||
| MYSQL_SSL_CERT= | ||||
| MYSQL_SSL_KEY= | ||||
| MYSQL_SSL_CIPHER= | ||||
|  | ||||
| # PostgreSQL supports SSL. You can configure it here. | ||||
| # If you use Docker or similar, you can set these variables from a file by appending them with _FILE | ||||
| PGSQL_SSL_MODE=prefer | ||||
| PGSQL_SSL_ROOT_CERT=null | ||||
| PGSQL_SSL_CERT=null | ||||
| PGSQL_SSL_KEY=null | ||||
| PGSQL_SSL_CRL_FILE=null | ||||
|  | ||||
| # If you're looking for performance improvements, you could install memcached. | ||||
| CACHE_DRIVER=array | ||||
| SESSION_DRIVER=array | ||||
|  | ||||
| # If you set either of these to 'redis', you might want to update these settings too | ||||
| # If you use Docker or similar, you can set REDIS_HOST_FILE, REDIS_PASSWORD_FILE or | ||||
| # REDIS_PORT_FILE to set the value from a file instead of from an environment variable | ||||
|  | ||||
| # can be tcp, unix or http | ||||
| REDIS_SCHEME=tcp | ||||
|  | ||||
| # use only when using 'unix' for REDIS_SCHEME. Leave empty otherwise. | ||||
| REDIS_PATH= | ||||
|  | ||||
| # use only when using 'tcp' or 'http' for REDIS_SCHEME. Leave empty otherwise. | ||||
| REDIS_HOST=127.0.0.1 | ||||
| REDIS_PORT=6379 | ||||
|  | ||||
| REDIS_PASSWORD=null | ||||
| # always use quotes and make sure redis db "0" and "1" exists. Otherwise change accordingly. | ||||
| REDIS_DB="0" | ||||
| REDIS_CACHE_DB="1" | ||||
|  | ||||
| # Cookie settings. Should not be necessary to change these. | ||||
| # If you use Docker or similar, you can set COOKIE_DOMAIN_FILE to set | ||||
| # the value from a file instead of from an environment variable | ||||
| COOKIE_PATH="/" | ||||
| COOKIE_DOMAIN= | ||||
| COOKIE_SECURE=false | ||||
|  | ||||
| # If you want Firefly III to mail you, update these settings | ||||
| # For instructions, see: https://docs.firefly-iii.org/advanced-installation/email | ||||
| # If you use Docker or similar, you can set these variables from a file by appending them with _FILE | ||||
| MAIL_MAILER=log | ||||
| MAIL_HOST=null | ||||
| MAIL_PORT=2525 | ||||
| MAIL_FROM=changeme@example.com | ||||
| MAIL_USERNAME=null | ||||
| MAIL_PASSWORD=null | ||||
| MAIL_ENCRYPTION=null | ||||
|  | ||||
| # Other mail drivers: | ||||
| # If you use Docker or similar, you can set these variables from a file by appending them with _FILE | ||||
| MAILGUN_DOMAIN= | ||||
| MAILGUN_SECRET= | ||||
|  | ||||
|  | ||||
| # If you are on EU region in mailgun, use api.eu.mailgun.net, otherwise use api.mailgun.net | ||||
| # If you use Docker or similar, you can set this variable from a file by appending it with _FILE | ||||
| MAILGUN_ENDPOINT=api.mailgun.net | ||||
|  | ||||
| # If you use Docker or similar, you can set these variables from a file by appending them with _FILE | ||||
| 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. | ||||
| # If you use Docker or similar, you can set this variable from a file by appending it with _FILE | ||||
| MAPBOX_API_KEY= | ||||
|  | ||||
| # The map will default to this location: | ||||
| MAP_DEFAULT_LAT=51.983333 | ||||
| MAP_DEFAULT_LONG=5.916667 | ||||
| MAP_DEFAULT_ZOOM=6 | ||||
|  | ||||
| # Firefly III currently supports two provider for live Currency Exchange Rates: | ||||
| # "fixer", and "ratesapi". | ||||
| # 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 doesn't require API key. | ||||
| CER_PROVIDER=ratesapi | ||||
|  | ||||
| # 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. | ||||
| # If you use Docker or similar, you can set this variable from a file by appending it with _FILE | ||||
| FIXER_API_KEY= | ||||
|  | ||||
| # 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://docs.firefly-iii.org/advanced-installation/authentication | ||||
| # If you use Docker or similar, you can set this variable from a file by appending it with _FILE | ||||
| LOGIN_PROVIDER=eloquent | ||||
|  | ||||
| # | ||||
| # It's also possible to change the way users are authenticated. You could use Authelia for example. | ||||
| # Authentication via the REMOTE_USER header is supported. Change the value below to "remote_user_guard". | ||||
| # | ||||
| # If you do this please read the documentation for instructions and warnings: | ||||
| # https://docs.firefly-iii.org/advanced-installation/authentication | ||||
| # | ||||
| # This function is available in Firefly III v5.3.0 and higher. | ||||
| AUTHENTICATION_GUARD=web | ||||
|  | ||||
| # | ||||
| # Likewise, it's impossible to log out users who's authentication is handled by an external system. | ||||
| # Enter a custom URL here that will force a logout (your authentication provider can tell you). | ||||
| # Setting this variable only works when AUTHENTICATION_GUARD != web | ||||
| # | ||||
| CUSTOM_LOGOUT_URI= | ||||
|  | ||||
| # LDAP connection configuration | ||||
| # OpenLDAP, FreeIPA or ActiveDirectory | ||||
| # # If you use Docker or similar, you can set this variable from a file by appending it with _FILE | ||||
| ADLDAP_CONNECTION_SCHEME=OpenLDAP | ||||
| ADLDAP_AUTO_CONNECT=true | ||||
|  | ||||
| # LDAP connection settings | ||||
| # You can set the following variables from a file by appending them with _FILE: | ||||
| # ADLDAP_CONTROLLERS, ADLDAP_PORT, ADLDAP_BASEDN | ||||
| ADLDAP_CONTROLLERS= | ||||
| ADLDAP_PORT=389 | ||||
| ADLDAP_TIMEOUT=5 | ||||
| ADLDAP_BASEDN="" | ||||
| ADLDAP_FOLLOW_REFFERALS=false | ||||
|  | ||||
| # SSL/TLS settings | ||||
| ADLDAP_USE_SSL=false | ||||
| ADLDAP_USE_TLS=false | ||||
| ADLDAP_SSL_CACERTDIR= | ||||
| ADLDAP_SSL_CACERTFILE= | ||||
| ADLDAP_SSL_CERTFILE= | ||||
| ADLDAP_SSL_KEYFILE= | ||||
| ADLDAP_SSL_CIPHER_SUITE= | ||||
| ADLDAP_SSL_REQUIRE_CERT= | ||||
|  | ||||
| # You can set the following variables from a file by appending them with _FILE: | ||||
| ADLDAP_ADMIN_USERNAME= | ||||
| ADLDAP_ADMIN_PASSWORD= | ||||
|  | ||||
| # You can set the following variables from a file by appending them with _FILE: | ||||
| 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. | ||||
| # You can set the following variables from a file by appending them with _FILE: | ||||
| WINDOWS_SSO_ENABLED=false | ||||
| WINDOWS_SSO_DISCOVER=samaccountname | ||||
| WINDOWS_SSO_KEY=AUTH_USER | ||||
|  | ||||
| # field to sync as local username. | ||||
| # You can set the following variable from a file by appending it with _FILE: | ||||
| ADLDAP_SYNC_FIELD=userprincipalname | ||||
|  | ||||
| # You can disable the X-Frame-Options header if it interferes with tools like | ||||
| # Organizr. This is at your own risk. Applications running in frames run the risk | ||||
| # of leaking information to their parent frame. | ||||
| DISABLE_FRAME_HEADER=false | ||||
|  | ||||
| # You can disable the Content Security Policy header when you're using an ancient browser | ||||
| # or any version of Microsoft Edge / Internet Explorer (which amounts to the same thing really) | ||||
| # This leaves you with the risk of not being able to stop XSS bugs should they ever surface. | ||||
| # This is at your own risk. | ||||
| DISABLE_CSP_HEADER=false | ||||
|  | ||||
| # If you wish to track your own behavior over Firefly III, set valid analytics tracker information here. | ||||
| # Nobody uses this except for me on the demo site. But hey, feel free to use this if you want to. | ||||
| # Do not prepend the TRACKER_URL with http:// or https:// | ||||
| # The only tracker supported is Matomo. | ||||
| # You can set the following variables from a file by appending them with _FILE: | ||||
| TRACKER_SITE_ID= | ||||
| TRACKER_URL= | ||||
|  | ||||
| # | ||||
| # Firefly III can collect telemetry on how you use Firefly III. This is opt-in. | ||||
| # In order to allow this, change the following variable to true. | ||||
| # To read more about this feature, go to this page: https://docs.firefly-iii.org/support/telemetry | ||||
| SEND_TELEMETRY=false | ||||
|  | ||||
| # You can fine tune the start-up of a Docker container by editing these environment variables. | ||||
| # Use this at your own risk. Disabling certain checks and features may result in lost of inconsistent data. | ||||
| # However if you know what you're doing you can significantly speed up container start times. | ||||
| # Set each value to true to enable, or false to disable. | ||||
|  | ||||
| # Check if the SQLite database exists. Can be skipped if you're not using SQLite. | ||||
| # Won't significantly speed up things. | ||||
| DKR_CHECK_SQLITE=true | ||||
|  | ||||
| # Run database creation and migration commands. Disable this only if you're 100% sure the DB exists | ||||
| # and is up to date. | ||||
| DKR_RUN_MIGRATION=true | ||||
|  | ||||
| # Run database upgrade commands. Disable this only when you're 100% sure your DB is up-to-date | ||||
| # with the latest fixes (outside of migrations!) | ||||
| DKR_RUN_UPGRADE=true | ||||
|  | ||||
| # Verify database integrity. Includes all data checks and verifications. | ||||
| # Disabling this makes Firefly III assume your DB is intact. | ||||
| DKR_RUN_VERIFY=true | ||||
|  | ||||
| # Run database reporting commands. When disabled, Firefly III won't go over your data to report current state. | ||||
| # Disabling this should have no impact on data integrity or safety but it won't warn you of possible issues. | ||||
| DKR_RUN_REPORT=true | ||||
|  | ||||
| # Generate OAuth2 keys. | ||||
| # When disabled, Firefly III won't attempt to generate OAuth2 Passport keys. This won't be an issue, IFF (if and only if) | ||||
| # you had previously generated keys already and they're stored in your database for restoration. | ||||
| DKR_RUN_PASSPORT_INSTALL=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 | ||||
| CACHE_PREFIX=firefly | ||||
| SEARCH_RESULT_LIMIT=50 | ||||
| PUSHER_KEY= | ||||
| PUSHER_SECRET= | ||||
| PUSHER_ID= | ||||
| DEMO_USERNAME= | ||||
| DEMO_PASSWORD= | ||||
| USE_ENCRYPTION=false | ||||
| IS_HEROKU=false | ||||
| FIREFLY_III_LAYOUT=v1 | ||||
|  | ||||
| # | ||||
| # If you have trouble configuring your Firefly III installation, DON'T BOTHER setting this variable. | ||||
| # It won't work. It doesn't do ANYTHING. Don't believe the lies you read online. I'm not joking. | ||||
| # This configuration value WILL NOT HELP. | ||||
| # | ||||
| # This variable is ONLY used in some of the emails Firefly III sends around. Nowhere else. | ||||
| # So when configuring anything WEB related this variable doesn't do anything. Nothing | ||||
| # | ||||
| # If you're stuck I understand you get desperate but look SOMEWHERE ELSE. | ||||
| # | ||||
| APP_URL=http://localhost | ||||
							
								
								
									
										250
									
								
								.ci/firefly-iii-standard.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								.ci/firefly-iii-standard.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,250 @@ | ||||
| parameters: | ||||
|     indentation: spaces | ||||
|  | ||||
|     file_extensions: | ||||
|         - php | ||||
|  | ||||
|     exclude_files: | ||||
|         - fixtures/* | ||||
|         - fixtures*/* | ||||
|         - temp/* | ||||
|         - tmp/* | ||||
|  | ||||
| services: | ||||
|     # Checkers bellow aim on 1:1 copy of https://nette.org/en/coding-standard | ||||
|  | ||||
|     # General rules - https://nette.org/en/coding-standard#toc-general-rules | ||||
|  | ||||
|     # use tabs over spaces | ||||
|     # PHP_CodeSniffer\Standards\Generic\Sniffs\WhiteSpace\DisallowSpaceIndentSniff: ~ | ||||
|     # PHP code must use only UTF-8 without BOM | ||||
|     PhpCsFixer\Fixer\Basic\EncodingFixer: ~ | ||||
|     # <?php opening tag | ||||
|     PhpCsFixer\Fixer\PhpTag\FullOpeningTagFixer: ~ | ||||
|     # Ensure there is no code on the same line as the PHP open tag. | ||||
|     PhpCsFixer\Fixer\PhpTag\LinebreakAfterOpeningTagFixer: ~ | ||||
|     # The closing ?> tag must be omitted from files containing only PHP. | ||||
|     PhpCsFixer\Fixer\PhpTag\NoClosingTagFixer: ~ | ||||
|     # There must not be trailing whitespace at the end of lines. | ||||
|     PhpCsFixer\Fixer\Whitespace\NoTrailingWhitespaceFixer: ~ | ||||
|     # ...and at the end of blank lines. | ||||
|     PhpCsFixer\Fixer\Whitespace\NoWhitespaceInBlankLineFixer: ~ | ||||
|     # All files must end with a single blank line. | ||||
|     PhpCsFixer\Fixer\Whitespace\SingleBlankLineAtEofFixer: ~ | ||||
|     # File name should match class name if possible. | ||||
|     PhpCsFixer\Fixer\Basic\Psr4Fixer: ~ | ||||
|     # Enforces using shorthand scalar typehint variants in phpDocs: `int` instead of `integer` and `bool` instead of `boolean` | ||||
|     SlevomatCodingStandard\Sniffs\TypeHints\LongTypeHintsSniff: ~ | ||||
|  | ||||
|     # File Header - https://nette.org/en/coding-standard#toc-file-header | ||||
|  | ||||
|     # empty line before namespace | ||||
|     PhpCsFixer\Fixer\NamespaceNotation\SingleBlankLineBeforeNamespaceFixer: ~ | ||||
|     # 1 Use statement per line | ||||
|     PhpCsFixer\Fixer\Import\SingleImportPerStatementFixer: ~ | ||||
|     # Use statements are alphabetically ordered | ||||
|     PhpCsFixer\Fixer\Import\OrderedImportsFixer: ~ | ||||
|     # disallow group use declarations use FooLibrary\Bar\Baz\{ ClassA, ClassB, ClassC, ClassD as Fizbo } | ||||
|     SlevomatCodingStandard\Sniffs\Namespaces\DisallowGroupUseSniff: ~ | ||||
|     # Disallows leading backslash in use statement: use \Foo\Bar; | ||||
|     SlevomatCodingStandard\Sniffs\Namespaces\UseDoesNotStartWithBackslashSniff: ~ | ||||
|     # Looks for unused imports from other namespaces. | ||||
|     Nette\CodingStandard\Sniffs\Namespaces\UnusedUsesSniff: | ||||
|         searchAnnotations: yes | ||||
|         ignoredAnnotationNames: ['@testCase'] | ||||
|         ignoredAnnotations: ['@internal'] | ||||
|  | ||||
|     # Language Construct (should be placed before some other fixers) | ||||
|  | ||||
|     # Functions should be used with `$strict` param set to `true` | ||||
|     PhpCsFixer\Fixer\Strict\StrictParamFixer: ~ | ||||
|     # replaces is_null(parameter) expression with `null === parameter`. | ||||
|     PhpCsFixer\Fixer\LanguageConstruct\IsNullFixer: | ||||
|         use_yoda_style: true | ||||
|     # Calling `unset` on multiple items should be done in one call. | ||||
|     PhpCsFixer\Fixer\LanguageConstruct\CombineConsecutiveUnsetsFixer: ~ | ||||
|     # Replace all `<>` with `!=`. | ||||
|     PhpCsFixer\Fixer\Operator\StandardizeNotEqualsFixer: ~ | ||||
|     # Include/Require and file path should be divided with a single space. File path should not be placed under brackets. | ||||
|     PhpCsFixer\Fixer\ControlStructure\IncludeFixer: ~ | ||||
|     # Requires short ternary operator ?: when possible | ||||
|     SlevomatCodingStandard\Sniffs\ControlStructures\RequireShortTernaryOperatorSniff: ~ | ||||
|  | ||||
|     # Arrays - https://nette.org/en/coding-standard#toc-arrays | ||||
|  | ||||
|     # use short array fixes | ||||
|     PhpCsFixer\Fixer\ArrayNotation\ArraySyntaxFixer: | ||||
|         syntax: short | ||||
|     # use trailing command in last array element | ||||
|     PhpCsFixer\Fixer\ArrayNotation\TrailingCommaInMultilineArrayFixer: ~ | ||||
|     # PHP single-line arrays should not have trailing comma. | ||||
|     # PhpCsFixer\Fixer\ArrayNotation\NoTrailingCommaInSinglelineArrayFixer: ~ | ||||
|     # In array declaration, there MUST NOT be a whitespace before each comma. | ||||
|     PhpCsFixer\Fixer\ArrayNotation\NoWhitespaceBeforeCommaInArrayFixer: ~ | ||||
|     # Arrays should be formatted like function/method arguments, without leading or trailing single line space. | ||||
|     PhpCsFixer\Fixer\ArrayNotation\TrimArraySpacesFixer: ~ | ||||
|     # In array declaration, there MUST be a whitespace after each comma. | ||||
|     PhpCsFixer\Fixer\ArrayNotation\WhitespaceAfterCommaInArrayFixer: ~ | ||||
|  | ||||
|     # Strings | ||||
|  | ||||
|     # Convert `heredoc` to `nowdoc` where possible. | ||||
|     PhpCsFixer\Fixer\StringNotation\HeredocToNowdocFixer: ~ | ||||
|     # Convert double quotes to single quotes for simple strings. | ||||
|     PhpCsFixer\Fixer\StringNotation\SingleQuoteFixer: ~ | ||||
|  | ||||
|     # Keywords and True/False/Null - https://nette.org/en/coding-standard#toc-keywords-and-true-false-null | ||||
|  | ||||
|     # PHP keywords must be in lower case | ||||
|     PhpCsFixer\Fixer\Casing\LowercaseKeywordsFixer: ~ | ||||
|     # The PHP constants `true`, `false`, and `null` MUST be in lower case | ||||
|     PhpCsFixer\Fixer\Casing\LowercaseConstantsFixer: ~ | ||||
|  | ||||
|     # Method and Functions Calls - https://nette.org/en/coding-standard#toc-method-and-function-calls | ||||
|  | ||||
|     # Function defined by PHP should be called using the correct casing | ||||
|     PhpCsFixer\Fixer\Casing\NativeFunctionCasingFixer: ~ | ||||
|     # In the argument list, there must be one space after each comma, and there must no be a space before each comma | ||||
|     PhpCsFixer\Fixer\FunctionNotation\MethodArgumentSpaceFixer: ~ | ||||
|     # This sniff checks that there are two blank lines between functions declarations and single between signatures. | ||||
|     #Nette\CodingStandard\Sniffs\WhiteSpace\FunctionSpacingSniff: ~ | ||||
|  | ||||
|     # Classes - https://nette.org/en/coding-standard#toc-classes | ||||
|  | ||||
|     # Inside a classy element "self" should be preferred to the class name itself. | ||||
|     PhpCsFixer\Fixer\ClassNotation\SelfAccessorFixer: ~ | ||||
|     # class element order: constants, properties, from public to private | ||||
|     PhpCsFixer\Fixer\ClassNotation\OrderedClassElementsFixer: | ||||
|         order: | ||||
|             - use_trait | ||||
|             - constant | ||||
|             - constant_public | ||||
|             - constant_protected | ||||
|             - constant_private | ||||
|             - property_public | ||||
|             - property_protected | ||||
|             - property_private | ||||
|  | ||||
|     # Constants - https://nette.org/en/coding-standard#toc-constants | ||||
|  | ||||
|     # constant names are CAPITALIZED (manuall fixing only :() | ||||
|     PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\UpperCaseConstantNameSniff: ~ | ||||
|  | ||||
|     # Class Properties - https://nette.org/en/coding-standard#toc-class-properties | ||||
|  | ||||
|     # There MUST NOT be more than one property declared per statement. | ||||
|     PhpCsFixer\Fixer\ClassNotation\SingleClassElementPerStatementFixer: | ||||
|         elements: ['property'] | ||||
|  | ||||
|     # Methods - https://nette.org/en/coding-standard#toc-methods | ||||
|  | ||||
|     # They must be declared in camelCase. | ||||
|     PHP_CodeSniffer\Standards\PSR1\Sniffs\Methods\CamelCapsMethodNameSniff: ~ | ||||
|     # Checks that there's a single space between a typehint and a parameter name and no whitespace between a nullability symbol and a typehint | ||||
|     SlevomatCodingStandard\Sniffs\TypeHints\ParameterTypeHintSpacingSniff: ~ | ||||
|     # Spaces should be properly placed in a function declaration. | ||||
|     PhpCsFixer\Fixer\FunctionNotation\FunctionDeclarationFixer: ~ | ||||
|     # In function arguments there must not be arguments with default values before non-default ones. | ||||
|     PhpCsFixer\Fixer\FunctionNotation\NoUnreachableDefaultArgumentValueFixer: ~ | ||||
|  | ||||
|     # Constans, Class Properties, Methods | ||||
|  | ||||
|     # Constants and Properties should be separated by 1 blank line | ||||
|     #PhpCsFixer\Fixer\ClassNotation\ClassAttributesSeparationFixer: | ||||
|     #    elements: [const, property] | ||||
|  | ||||
|     # Last property and 1st method should be separated by 2 spaces | ||||
|     Nette\CodingStandard\Fixer\ClassNotation\LastPropertyAndFirstMethodSeparationFixer: | ||||
|         space_count: 2 | ||||
|  | ||||
|     # Control Statements - https://nette.org/en/coding-standard#toc-control-statements | ||||
|  | ||||
|     # The keyword `elseif` should be used instead of `else if` so that all control keywords look like single words. | ||||
|     PhpCsFixer\Fixer\ControlStructure\ElseifFixer: ~ | ||||
|     # Remove useless semicolon statements. | ||||
|     PhpCsFixer\Fixer\Semicolon\NoEmptyStatementFixer: ~ | ||||
|     # Remove trailing commas in list() calls. | ||||
|     PhpCsFixer\Fixer\ControlStructure\NoTrailingCommaInListCallFixer: ~ | ||||
|     # Removes unneeded parentheses around control statements. | ||||
|     PhpCsFixer\Fixer\ControlStructure\NoUnneededControlParenthesesFixer: ~ | ||||
|     # A case should be followed by a colon and not a semicolon. | ||||
|     PhpCsFixer\Fixer\ControlStructure\SwitchCaseSemicolonToColonFixer: ~ | ||||
|     # The structure body must be indented once. | ||||
|     # The closing brace must be on the next line after the body. | ||||
|     # There should not be more than one statement per line. | ||||
|     #Nette\CodingStandard\Fixer\Basic\BracesFixer: | ||||
|     #    allow_single_line_closure: true | ||||
|     # changes if (1 === $cond) to if ($cond === 1) | ||||
|     #SlevomatCodingStandard\Sniffs\ControlStructures\DisallowYodaComparisonSniff: ~ | ||||
|     # finds unreachable catch blocks: | ||||
|     SlevomatCodingStandard\Sniffs\Exceptions\DeadCatchSniff: ~ | ||||
|  | ||||
|     # Casting | ||||
|  | ||||
|     # A single space or none should be between cast and variable (int) $val | ||||
|     PhpCsFixer\Fixer\CastNotation\CastSpacesFixer: ~ | ||||
|     # Cast should be written in lower case. | ||||
|     PhpCsFixer\Fixer\CastNotation\LowercaseCastFixer: ~ | ||||
|     # Replaces `intval`, `floatval`, `doubleval`, `strval` and `boolval` function calls with according type casting operator | ||||
|     PhpCsFixer\Fixer\CastNotation\ModernizeTypesCastingFixer: ~ | ||||
|     # Short cast `bool` using double exclamation mark should not be used | ||||
|     PhpCsFixer\Fixer\CastNotation\NoShortBoolCastFixer: ~ | ||||
|     # Cast `(boolean)` and `(integer)` should be written as `(bool)` and `(int)`, `(double)` and `(real)` as `(float)` | ||||
|     PhpCsFixer\Fixer\CastNotation\ShortScalarCastFixer: ~ | ||||
|  | ||||
|     # Language Whitespace | ||||
|  | ||||
|     # Binary operators should be surrounded by at least one space. DO NOT USE | ||||
|     #PhpCsFixer\Fixer\Operator\BinaryOperatorSpacesFixer: ~ | ||||
|     # Unary operators should be placed adjacent to their operands. | ||||
|     PhpCsFixer\Fixer\Operator\UnaryOperatorSpacesFixer: ~ | ||||
|     # No space after the opening parenthesis and before the closing parenthesis | ||||
|     PhpCsFixer\Fixer\Whitespace\NoSpacesInsideParenthesisFixer: ~ | ||||
|     # There MUST NOT be spaces around offset braces $a[0] | ||||
|     PhpCsFixer\Fixer\Whitespace\NoSpacesAroundOffsetFixer: ~ | ||||
|     # There should not be space before or after object `T_OBJECT_OPERATOR` `->`. | ||||
|     PhpCsFixer\Fixer\Operator\ObjectOperatorWithoutWhitespaceFixer: ~ | ||||
|     # Standardize spaces around ternary operator. | ||||
|     PhpCsFixer\Fixer\Operator\TernaryOperatorSpacesFixer: ~ | ||||
|     # Concatenation $a . $b should be spaced according configuration | ||||
|     PhpCsFixer\Fixer\Operator\ConcatSpaceFixer: | ||||
|         spacing: one | ||||
|     # Removes extra spaces between colon and case value. | ||||
|     PhpCsFixer\Fixer\ControlStructure\SwitchCaseSpaceFixer: ~ | ||||
|  | ||||
|     # Comments | ||||
|  | ||||
|     # Docblocks should have the same indentation as the documented subject. | ||||
|     PhpCsFixer\Fixer\Phpdoc\PhpdocIndentFixer: ~ | ||||
|     # There should not be any empty comments. | ||||
|     PhpCsFixer\Fixer\Comment\NoEmptyCommentFixer: ~ | ||||
|     # There should not be empty PHPDoc blocks. | ||||
|     #PhpCsFixer\Fixer\Phpdoc\NoEmptyPhpdocFixer: ~ | ||||
|     # Phpdocs should start and end with content, excluding the very first and last line of the docblocks. | ||||
|     PhpCsFixer\Fixer\Phpdoc\PhpdocTrimFixer: ~ | ||||
|     # Single-line comments comments with only one line of actual content should use the `//` syntax. | ||||
|     PhpCsFixer\Fixer\Comment\SingleLineCommentStyleFixer: | ||||
|         comment_types: ['hash'] | ||||
|     # Require comments with single-line content to be written as one-liners | ||||
|     SlevomatCodingStandard\Sniffs\Commenting\RequireOneLinePropertyDocCommentSniff: ~ | ||||
|  | ||||
|  | ||||
|     # Properties MUST not be explicitly initialized with `null`. | ||||
|     #PhpCsFixer\Fixer\ClassNotation\NoNullPropertyInitializationFixer: ~ | ||||
|  | ||||
|     PhpCsFixer\Fixer\ControlStructure\NoBreakCommentFixer: | ||||
|         comment_text: 'break omitted' | ||||
|  | ||||
|     # declare(strict_types=1); | ||||
|     PhpCsFixer\Fixer\Strict\DeclareStrictTypesFixer: ~ | ||||
|     # Enforces consistent formatting of return typehints: function foo(): ?int | ||||
|     SlevomatCodingStandard\Sniffs\TypeHints\ReturnTypeHintSpacingSniff: ~ | ||||
|     # Use `null` coalescing operator `??` where possible. | ||||
|     PhpCsFixer\Fixer\Operator\TernaryToNullCoalescingFixer: ~ | ||||
|  | ||||
|     Nette\CodingStandard\Fixer\ClassNotation\ClassAndTraitVisibilityRequiredFixer: | ||||
|         elements: ['const', 'property', 'method'] | ||||
|  | ||||
|     # short list() syntax [] | ||||
|     PhpCsFixer\Fixer\ListNotation\ListSyntaxFixer: | ||||
|         syntax: short | ||||
							
								
								
									
										20
									
								
								.ci/phpstan.neon
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								.ci/phpstan.neon
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| includes: | ||||
|   - ../vendor/nunomaduro/larastan/extension.neon | ||||
|   - ../vendor/ergebnis/phpstan-rules/rules.neon | ||||
|   - ../vendor/phpstan/phpstan-deprecation-rules/rules.neon | ||||
|   - ../vendor/thecodingmachine/phpstan-strict-rules/phpstan-strict-rules.neon | ||||
|  | ||||
| parameters: | ||||
|   ignoreErrors: | ||||
|     - '#is not allowed to extend#' | ||||
|     - '#is neither abstract nor final#' | ||||
|     - '#Control structures using switch should not be used\.#' | ||||
|     - '#has a nullable return type declaration#' | ||||
|   paths: | ||||
|     - ../app | ||||
|     - ../database | ||||
|     - ../routes | ||||
|     - ../bootstrap/app.php | ||||
|  | ||||
|   # The level 8 is the highest level. original was 5 | ||||
|   level: 5 | ||||
							
								
								
									
										12
									
								
								.ci/phpstan.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										12
									
								
								.ci/phpstan.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| # Install composer packages | ||||
| composer install --no-suggest --no-scripts --no-ansi | ||||
|  | ||||
| # enable test .env file. | ||||
| cp .ci/.env.ci .env | ||||
|  | ||||
| # Do static code analysis. | ||||
| ./vendor/bin/phpstan analyse -c .ci/phpstan.neon --no-progress | ||||
|  | ||||
| exit 0 | ||||
							
								
								
									
										12
									
								
								.ci/phpunit.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										12
									
								
								.ci/phpunit.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| # enable test .env file. | ||||
| cp .ci/.env.ci ../.env | ||||
|  | ||||
| # download test database | ||||
| wget --quiet https://raw.githubusercontent.com/firefly-iii/test-data/main/test_db.sqlite -o storage/database/test_db.sqlite | ||||
|  | ||||
| # run phpunit | ||||
| ./vendor/bin/phpunit --configuration phpunit.coverage.xml | ||||
|  | ||||
| exit 0 | ||||
| @@ -5,77 +5,118 @@ 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 | ||||
| # This should be your email address. | ||||
| # If you use Docker or similar, you can set this variable from a file by using SITE_OWNER_FILE | ||||
| 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 | ||||
| # The encryption key for your sessions. Keep this very secure. | ||||
| # If you generate a new one all existing attachments must be considered LOST. | ||||
| # Change it to a string of exactly 32 chars or use something like `php artisan key:generate` to generate it. | ||||
| # If you use Docker or similar, you can set this variable from a file by using APP_KEY_FILE | ||||
| APP_KEY=7ahyYVPVsmxjdhsweWCauGeJfwc92NP2 | ||||
|  | ||||
| # | ||||
| # Firefly III will launch using this language (for new users and unauthenticated visitors) | ||||
| # For a list of available languages: https://github.com/firefly-iii/firefly-iii/tree/main/resources/lang | ||||
| # | ||||
| # If text is still in English, remember that not everything may have been translated. | ||||
| DEFAULT_LANGUAGE=en_US | ||||
|  | ||||
| # The locale defines how numbers are formatted. | ||||
| # by default this value is the same as whatever the language is. | ||||
| DEFAULT_LOCALE=equal | ||||
|  | ||||
| # Change this value to your preferred time zone. | ||||
| # Example: Europe/Amsterdam | ||||
| # For a list of supported time zones, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones | ||||
| 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. | ||||
| # Set it to ** and reverse proxies work just fine. | ||||
| 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. | ||||
| # A rotating log option is 'daily', creates 5 files that (surprise) rotate. | ||||
| # Default setting 'stack' will log to 'daily' and to 'stdout' at the same time. | ||||
|  | ||||
| # - Docker + versions <= 4.8.1.8 and before: use "stdout" | ||||
| # - Docker + versions >  4.8.1.8           : use "docker_out" | ||||
| # - Docker + versions >=  5.1.1            : use "stack" | ||||
| # - For everything else (als not Docker)   : use 'stack' | ||||
|  | ||||
| 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 | ||||
| APP_LOG_LEVEL=notice | ||||
|  | ||||
| # 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. | ||||
| # For other database types, please see the FAQ: https://docs.firefly-iii.org/support/faq | ||||
| # If you use Docker or similar, you can set these variables from a file by appending them with _FILE | ||||
| # Use "pgsql" for PostgreSQL | ||||
| # Use "mysql" for MySQL and MariaDB. | ||||
| # Use "sqlite" for SQLite. | ||||
| DB_CONNECTION=pgsql | ||||
|  | ||||
|  | ||||
| # MySQL supports SSL. You can configure it here. | ||||
| # If you use Docker or similar, you can set these variables from a file by appending them with _FILE | ||||
| MYSQL_USE_SSL=false | ||||
| MYSQL_SSL_VERIFY_SERVER_CERT=true | ||||
| # You need to set at least of these options | ||||
| MYSQL_SSL_CAPATH=/etc/ssl/certs/ | ||||
| MYSQL_SSL_CA= | ||||
| MYSQL_SSL_CERT= | ||||
| MYSQL_SSL_KEY= | ||||
| MYSQL_SSL_CIPHER= | ||||
|  | ||||
| # PostgreSQL supports SSL. You can configure it here. | ||||
| # If you use Docker or similar, you can set these variables from a file by appending them with _FILE | ||||
| PGSQL_SSL_MODE=prefer | ||||
| PGSQL_SSL_ROOT_CERT=null | ||||
| PGSQL_SSL_CERT=null | ||||
| PGSQL_SSL_KEY=null | ||||
| PGSQL_SSL_CRL_FILE=null | ||||
|  | ||||
|  | ||||
| # 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= | ||||
| # If you set either of these to 'redis', you might want to update these settings too | ||||
| # If you use Docker or similar, you can set REDIS_HOST_FILE, REDIS_PASSWORD_FILE or | ||||
| # REDIS_PORT_FILE to set the value from a file instead of from an environment variable | ||||
|  | ||||
| # SFTP uses either the username/password combination or the private key to authenticate. | ||||
| SFTP_USERNAME= | ||||
| SFTP_PASSWORD= | ||||
| SFTP_PRIV_KEY= | ||||
| # can be tcp, unix or http | ||||
| REDIS_SCHEME=tcp | ||||
|  | ||||
| # use only when using 'unix' for REDIS_SCHEME. Leave empty otherwise. | ||||
| REDIS_PATH= | ||||
|  | ||||
| # use only when using 'tcp' or 'http' for REDIS_SCHEME. Leave empty otherwise. | ||||
| REDIS_HOST=127.0.0.1 | ||||
| REDIS_PORT=6379 | ||||
|  | ||||
| REDIS_PASSWORD=null | ||||
| # always use quotes and make sure redis db "0" and "1" exists. Otherwise change accordingly. | ||||
| REDIS_DB="0" | ||||
| REDIS_CACHE_DB="1" | ||||
|  | ||||
| # Cookie settings. Should not be necessary to change these. | ||||
| # If you use Docker or similar, you can set COOKIE_DOMAIN_FILE to set | ||||
| # the value from a file instead of from an environment variable | ||||
| 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 | ||||
| # For instructions, see: https://docs.firefly-iii.org/advanced-installation/email | ||||
| # If you use Docker or similar, you can set these variables from a file by appending them with _FILE | ||||
| MAIL_MAILER=log | ||||
| MAIL_HOST=null | ||||
| MAIL_PORT=2525 | ||||
| MAIL_FROM=changeme@example.com | ||||
| MAIL_USERNAME=null | ||||
| @@ -83,11 +124,20 @@ MAIL_PASSWORD=null | ||||
| MAIL_ENCRYPTION=null | ||||
|  | ||||
| # Other mail drivers: | ||||
| # If you use Docker or similar, you can set these variables from a file by appending them with _FILE | ||||
| MAILGUN_DOMAIN= | ||||
| MAILGUN_SECRET= | ||||
|  | ||||
|  | ||||
| # If you are on EU region in mailgun, use api.eu.mailgun.net, otherwise use api.mailgun.net | ||||
| # If you use Docker or similar, you can set this variable from a file by appending it with _FILE | ||||
| MAILGUN_ENDPOINT=api.mailgun.net | ||||
|  | ||||
| # If you use Docker or similar, you can set these variables from a file by appending them with _FILE | ||||
| MANDRILL_SECRET= | ||||
| SPARKPOST_SECRET= | ||||
|  | ||||
|  | ||||
| # Firefly III can send you the following messages | ||||
| SEND_REGISTRATION_MAIL=true | ||||
| SEND_ERROR_MESSAGE=true | ||||
| @@ -96,53 +146,85 @@ SEND_ERROR_MESSAGE=true | ||||
| SEND_REPORT_JOURNALS=true | ||||
|  | ||||
| # Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places. | ||||
| # If you use Docker or similar, you can set this variable from a file by appending it with _FILE | ||||
| MAPBOX_API_KEY= | ||||
|  | ||||
| # The map will default to this location: | ||||
| MAP_DEFAULT_LAT=51.983333 | ||||
| MAP_DEFAULT_LONG=5.916667 | ||||
| MAP_DEFAULT_ZOOM=6 | ||||
|  | ||||
| # Firefly III currently supports two provider for live Currency Exchange Rates: | ||||
| # "fixer" is the default (for backward compatibility), and "ratesapi" is the new one. | ||||
| # "fixer", and "ratesapi". | ||||
| # 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 | ||||
| # built compatible with Fixer.IO, based on data published by European Central Bank, and doesn't require API key. | ||||
| CER_PROVIDER=ratesapi | ||||
|  | ||||
| # 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. | ||||
| # If you use Docker or similar, you can set this variable from a file by appending it with _FILE | ||||
| FIXER_API_KEY= | ||||
|  | ||||
| # If you wish to track your own behavior over Firefly III, set a valid analytics tracker ID here. | ||||
| TRACKER_SITE_ID= | ||||
| TRACKER_URL= | ||||
|  | ||||
| # 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 | ||||
| # https://docs.firefly-iii.org/advanced-installation/authentication | ||||
| # If you use Docker or similar, you can set this variable from a file by appending it with _FILE | ||||
| LOGIN_PROVIDER=eloquent | ||||
|  | ||||
| # | ||||
| # It's also possible to change the way users are authenticated. You could use Authelia for example. | ||||
| # Authentication via the REMOTE_USER header is supported. Change the value below to "remote_user_guard". | ||||
| # | ||||
| # If you do this please read the documentation for instructions and warnings: | ||||
| # https://docs.firefly-iii.org/advanced-installation/authentication | ||||
| # | ||||
| # This function is available in Firefly III v5.3.0 and higher. | ||||
| AUTHENTICATION_GUARD=web | ||||
|  | ||||
| # | ||||
| # Likewise, it's impossible to log out users who's authentication is handled by an external system. | ||||
| # Enter a custom URL here that will force a logout (your authentication provider can tell you). | ||||
| # Setting this variable only works when AUTHENTICATION_GUARD != web | ||||
| # | ||||
| CUSTOM_LOGOUT_URI= | ||||
|  | ||||
| # LDAP connection configuration | ||||
| # OpenLDAP, FreeIPA or ActiveDirectory | ||||
| # # If you use Docker or similar, you can set this variable from a file by appending it with _FILE | ||||
| ADLDAP_CONNECTION_SCHEME=OpenLDAP | ||||
| ADLDAP_AUTO_CONNECT=true | ||||
|  | ||||
| # LDAP connection settings | ||||
| # You can set the following variables from a file by appending them with _FILE: | ||||
| # ADLDAP_CONTROLLERS, ADLDAP_PORT, ADLDAP_BASEDN | ||||
| ADLDAP_CONTROLLERS= | ||||
| ADLDAP_PORT=389 | ||||
| ADLDAP_TIMEOUT=5 | ||||
| ADLDAP_BASEDN="" | ||||
| ADLDAP_FOLLOW_REFFERALS=false | ||||
|  | ||||
| # SSL/TLS settings | ||||
| ADLDAP_USE_SSL=false | ||||
| ADLDAP_USE_TLS=false | ||||
| ADLDAP_SSL_CACERTDIR= | ||||
| ADLDAP_SSL_CACERTFILE= | ||||
| ADLDAP_SSL_CERTFILE= | ||||
| ADLDAP_SSL_KEYFILE= | ||||
| ADLDAP_SSL_CIPHER_SUITE= | ||||
| ADLDAP_SSL_REQUIRE_CERT= | ||||
|  | ||||
| # You can set the following variables from a file by appending them with _FILE: | ||||
| ADLDAP_ADMIN_USERNAME= | ||||
| ADLDAP_ADMIN_PASSWORD= | ||||
|  | ||||
| # You can set the following variables from a file by appending them with _FILE: | ||||
| ADLDAP_ACCOUNT_PREFIX= | ||||
| ADLDAP_ACCOUNT_SUFFIX= | ||||
|  | ||||
|  | ||||
| # LDAP authentication settings. | ||||
| ADLDAP_PASSWORD_SYNC=false | ||||
| ADLDAP_LOGIN_FALLBACK=false | ||||
| @@ -151,25 +233,76 @@ ADLDAP_DISCOVER_FIELD=distinguishedname | ||||
| ADLDAP_AUTH_FIELD=distinguishedname | ||||
|  | ||||
| # Will allow SSO if your server provides an AUTH_USER field. | ||||
| # You can set the following variables from a file by appending them with _FILE: | ||||
| WINDOWS_SSO_ENABLED=false | ||||
| WINDOWS_SSO_DISCOVER=samaccountname | ||||
| WINDOWS_SSO_KEY=AUTH_USER | ||||
|  | ||||
| # field to sync as local username. | ||||
| # You can set the following variable from a file by appending it with _FILE: | ||||
| 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. | ||||
| # You can disable the X-Frame-Options header if it interferes with tools like | ||||
| # Organizr. This is at your own risk. Applications running in frames run the risk | ||||
| # of leaking information to their parent frame. | ||||
| DISABLE_FRAME_HEADER=false | ||||
|  | ||||
| # You can disable the Content Security Policy header when you're using an ancient browser | ||||
| # or any version of Microsoft Edge / Internet Explorer (which amounts to the same thing really) | ||||
| # This leaves you with the risk of not being able to stop XSS bugs should they ever surface. | ||||
| # This is at your own risk. | ||||
| DISABLE_CSP_HEADER=false | ||||
|  | ||||
| # If you wish to track your own behavior over Firefly III, set valid analytics tracker information here. | ||||
| # Nobody uses this except for me on the demo site. But hey, feel free to use this if you want to. | ||||
| # Do not prepend the TRACKER_URL with http:// or https:// | ||||
| # The only tracker supported is Matomo. | ||||
| # You can set the following variables from a file by appending them with _FILE: | ||||
| TRACKER_SITE_ID= | ||||
| TRACKER_URL= | ||||
|  | ||||
| # | ||||
| # Firefly III can collect telemetry on how you use Firefly III. This is opt-in. | ||||
| # In order to allow this, change the following variable to true. | ||||
| # To read more about this feature, go to this page: https://docs.firefly-iii.org/support/telemetry | ||||
| SEND_TELEMETRY=false | ||||
|  | ||||
| # You can fine tune the start-up of a Docker container by editing these environment variables. | ||||
| # Use this at your own risk. Disabling certain checks and features may result in lost of inconsistent data. | ||||
| # However if you know what you're doing you can significantly speed up container start times. | ||||
| # Set each value to true to enable, or false to disable. | ||||
|  | ||||
| # Check if the SQLite database exists. Can be skipped if you're not using SQLite. | ||||
| # Won't significantly speed up things. | ||||
| DKR_CHECK_SQLITE=true | ||||
|  | ||||
| # Run database creation and migration commands. Disable this only if you're 100% sure the DB exists | ||||
| # and is up to date. | ||||
| DKR_RUN_MIGRATION=true | ||||
|  | ||||
| # Run database upgrade commands. Disable this only when you're 100% sure your DB is up-to-date | ||||
| # with the latest fixes (outside of migrations!) | ||||
| DKR_RUN_UPGRADE=true | ||||
|  | ||||
| # Verify database integrity. Includes all data checks and verifications. | ||||
| # Disabling this makes Firefly III assume your DB is intact. | ||||
| DKR_RUN_VERIFY=true | ||||
|  | ||||
| # Run database reporting commands. When disabled, Firefly III won't go over your data to report current state. | ||||
| # Disabling this should have no impact on data integrity or safety but it won't warn you of possible issues. | ||||
| DKR_RUN_REPORT=true | ||||
|  | ||||
| # Generate OAuth2 keys. | ||||
| # When disabled, Firefly III won't attempt to generate OAuth2 Passport keys. This won't be an issue, IFF (if and only if) | ||||
| # you had previously generated keys already and they're stored in your database for restoration. | ||||
| DKR_RUN_PASSPORT_INSTALL=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= | ||||
| @@ -177,7 +310,18 @@ PUSHER_SECRET= | ||||
| PUSHER_ID= | ||||
| DEMO_USERNAME= | ||||
| DEMO_PASSWORD= | ||||
| IS_SANDSTORM=false | ||||
| IS_HEROKU=true | ||||
| BUNQ_USE_SANDBOX=false | ||||
| FFIII_LAYOUT=v1 | ||||
| USE_ENCRYPTION=false | ||||
| IS_HEROKU=false | ||||
| FIREFLY_III_LAYOUT=v1 | ||||
|  | ||||
| # | ||||
| # If you have trouble configuring your Firefly III installation, DON'T BOTHER setting this variable. | ||||
| # It won't work. It doesn't do ANYTHING. Don't believe the lies you read online. I'm not joking. | ||||
| # This configuration value WILL NOT HELP. | ||||
| # | ||||
| # This variable is ONLY used in some of the emails Firefly III sends around. Nowhere else. | ||||
| # So when configuring anything WEB related this variable doesn't do anything. Nothing | ||||
| # | ||||
| # If you're stuck I understand you get desperate but look SOMEWHERE ELSE. | ||||
| # | ||||
| APP_URL=http://localhost | ||||
|   | ||||
| @@ -1,8 +1,13 @@ | ||||
| en_US | ||||
| bg_BG | ||||
| cs_CZ | ||||
| es_ES | ||||
| de_DE | ||||
| el_GR | ||||
| en_GB | ||||
| en_US | ||||
| es_ES | ||||
| fi_FI | ||||
| fr_FR | ||||
| hu_HU | ||||
| it_IT | ||||
| nb_NO | ||||
| nl_NL | ||||
| @@ -10,10 +15,8 @@ pl_PL | ||||
| pt_BR | ||||
| ro_RO | ||||
| ru_RU | ||||
| hu_HU | ||||
| el_GR | ||||
| sk_SK | ||||
| sv_SE | ||||
| vi_VN | ||||
| zh-hans_CN | ||||
| zh-hant_CN | ||||
| fi_FI | ||||
| vi_VN | ||||
|   | ||||
							
								
								
									
										62
									
								
								.env.example
									
									
									
									
									
								
							
							
						
						
									
										62
									
								
								.env.example
									
									
									
									
									
								
							| @@ -10,12 +10,10 @@ APP_DEBUG=false | ||||
| SITE_OWNER=mail@example.com | ||||
|  | ||||
| # The encryption key for your sessions. Keep this very secure. | ||||
| # If you generate a new one all existing attachments must be considered LOST. | ||||
| # Change it to a string of exactly 32 chars or use something like `php artisan key:generate` to generate it. | ||||
| # If you use Docker or similar, you can set this variable from a file by using APP_KEY_FILE | ||||
| APP_KEY=SomeRandomStringOf32CharsExactly | ||||
|  | ||||
| # | ||||
| # Firefly III will launch using this language (for new users and unauthenticated visitors) | ||||
| # For a list of available languages: https://github.com/firefly-iii/firefly-iii/tree/main/resources/lang | ||||
| # | ||||
| @@ -93,9 +91,18 @@ SESSION_DRIVER=file | ||||
| # If you set either of these to 'redis', you might want to update these settings too | ||||
| # If you use Docker or similar, you can set REDIS_HOST_FILE, REDIS_PASSWORD_FILE or | ||||
| # REDIS_PORT_FILE to set the value from a file instead of from an environment variable | ||||
|  | ||||
| # can be tcp, unix or http | ||||
| REDIS_SCHEME=tcp | ||||
|  | ||||
| # use only when using 'unix' for REDIS_SCHEME. Leave empty otherwise. | ||||
| REDIS_PATH= | ||||
|  | ||||
| # use only when using 'tcp' or 'http' for REDIS_SCHEME. Leave empty otherwise. | ||||
| REDIS_HOST=127.0.0.1 | ||||
| REDIS_PASSWORD=null | ||||
| REDIS_PORT=6379 | ||||
|  | ||||
| REDIS_PASSWORD=null | ||||
| # always use quotes and make sure redis db "0" and "1" exists. Otherwise change accordingly. | ||||
| REDIS_DB="0" | ||||
| REDIS_CACHE_DB="1" | ||||
| @@ -132,10 +139,10 @@ MAILGUN_ENDPOINT=api.mailgun.net | ||||
| MANDRILL_SECRET= | ||||
| SPARKPOST_SECRET= | ||||
|  | ||||
|  | ||||
| # Firefly III can send you the following messages | ||||
| SEND_REGISTRATION_MAIL=true | ||||
| SEND_ERROR_MESSAGE=true | ||||
| SEND_LOGIN_NEW_IP_WARNING=true | ||||
|  | ||||
| # These messages contain (sensitive) transaction information: | ||||
| SEND_REPORT_JOURNALS=true | ||||
| @@ -149,19 +156,6 @@ MAP_DEFAULT_LAT=51.983333 | ||||
| MAP_DEFAULT_LONG=5.916667 | ||||
| MAP_DEFAULT_ZOOM=6 | ||||
|  | ||||
| # Firefly III currently supports two provider for live Currency Exchange Rates: | ||||
| # "fixer", and "ratesapi". | ||||
| # 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 doesn't require API key. | ||||
| CER_PROVIDER=ratesapi | ||||
|  | ||||
| # 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. | ||||
| # If you use Docker or similar, you can set this variable from a file by appending it with _FILE | ||||
| FIXER_API_KEY= | ||||
|  | ||||
| # 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: | ||||
| @@ -169,18 +163,38 @@ FIXER_API_KEY= | ||||
| # If you use Docker or similar, you can set this variable from a file by appending it with _FILE | ||||
| LOGIN_PROVIDER=eloquent | ||||
|  | ||||
| # | ||||
| # It's also possible to change the way users are authenticated. You could use Authelia for example. | ||||
| # Authentication via the REMOTE_USER header is supported. Change the value below to "remote_user_guard". | ||||
| # | ||||
| # This will also allow Windows SSO. | ||||
| # | ||||
| # If you do this please read the documentation for instructions and warnings: | ||||
| # https://docs.firefly-iii.org/advanced-installation/authentication | ||||
| # | ||||
| # This function is available in Firefly III v5.3.0 and higher. | ||||
| AUTHENTICATION_GUARD=web | ||||
|  | ||||
| # If the guard is changed, Firefly III uses the 'REMOTE_USER' header as per RFC 3875. | ||||
| # You can also use another header, like AUTH_USER when using Windows SSO. | ||||
| # Some systems use X-Auth headers. In that case, use HTTP_X_AUTH_USERNAME or HTTP_X_AUTH_EMAIL | ||||
| # Depending on your system, REMOTE_USER may need to be changed to HTTP_REMOTE_USER | ||||
| # | ||||
| # Likewise, it's impossible to log out users who's authentication is handled by an external system. | ||||
| AUTHENTICATION_GUARD_HEADER=REMOTE_USER | ||||
|  | ||||
| # | ||||
| # Firefly III uses email addresses as user identifiers. When you're using an external authentication guard | ||||
| # that doesn't do this, Firefly III is incapable of emailing you. Messages sent to "Bill Gates" always fail. | ||||
| # | ||||
| # However, if you set this value, Firefly III will store the value from this header as the user's backup | ||||
| # email address and use it to communicate. So user "Bill Gates" could still have | ||||
| # the email address "bill@microsoft.com". | ||||
| # | ||||
| # Example value: AUTHENTICATION_GUARD_EMAIL=HTTP_X_AUTH_EMAIL | ||||
| # | ||||
| AUTHENTICATION_GUARD_EMAIL= | ||||
|  | ||||
|  | ||||
| # It's impossible to log out users who's authentication is handled by an external system. | ||||
| # Enter a custom URL here that will force a logout (your authentication provider can tell you). | ||||
| # Setting this variable only works when AUTHENTICATION_GUARD != web | ||||
| # | ||||
| @@ -219,7 +233,6 @@ ADLDAP_ADMIN_PASSWORD= | ||||
| ADLDAP_ACCOUNT_PREFIX= | ||||
| ADLDAP_ACCOUNT_SUFFIX= | ||||
|  | ||||
|  | ||||
| # LDAP authentication settings. | ||||
| ADLDAP_PASSWORD_SYNC=false | ||||
| ADLDAP_LOGIN_FALLBACK=false | ||||
| @@ -227,12 +240,6 @@ ADLDAP_LOGIN_FALLBACK=false | ||||
| ADLDAP_DISCOVER_FIELD=distinguishedname | ||||
| ADLDAP_AUTH_FIELD=distinguishedname | ||||
|  | ||||
| # Will allow SSO if your server provides an AUTH_USER field. | ||||
| # You can set the following variables from a file by appending them with _FILE: | ||||
| WINDOWS_SSO_ENABLED=false | ||||
| WINDOWS_SSO_DISCOVER=samaccountname | ||||
| WINDOWS_SSO_KEY=AUTH_USER | ||||
|  | ||||
| # field to sync as local username. | ||||
| # You can set the following variable from a file by appending it with _FILE: | ||||
| ADLDAP_SYNC_FIELD=userprincipalname | ||||
| @@ -256,7 +263,6 @@ DISABLE_CSP_HEADER=false | ||||
| TRACKER_SITE_ID= | ||||
| TRACKER_URL= | ||||
|  | ||||
| # | ||||
| # Firefly III can collect telemetry on how you use Firefly III. This is opt-in. | ||||
| # In order to allow this, change the following variable to true. | ||||
| # To read more about this feature, go to this page: https://docs.firefly-iii.org/support/telemetry | ||||
| @@ -299,13 +305,11 @@ ADLDAP_CONNECTION=default | ||||
| BROADCAST_DRIVER=log | ||||
| QUEUE_DRIVER=sync | ||||
| CACHE_PREFIX=firefly | ||||
| SEARCH_RESULT_LIMIT=50 | ||||
| PUSHER_KEY= | ||||
| PUSHER_SECRET= | ||||
| PUSHER_ID= | ||||
| DEMO_USERNAME= | ||||
| DEMO_PASSWORD= | ||||
| USE_ENCRYPTION=false | ||||
| IS_HEROKU=false | ||||
| FIREFLY_III_LAYOUT=v1 | ||||
|  | ||||
|   | ||||
							
								
								
									
										3
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							| @@ -3,3 +3,6 @@ | ||||
| *.scss linguist-vendored | ||||
| *.js linguist-vendored | ||||
| CHANGELOG.md export-ignore | ||||
| /tests       export-ignore | ||||
| /phpunit.xml export-ignore | ||||
| /.ci export-ignore | ||||
|   | ||||
							
								
								
									
										7
									
								
								.github/.mergify.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								.github/.mergify.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| pull_request_rules: | ||||
|   - name: PR on main is never approved. | ||||
|     conditions: | ||||
|       - base=main | ||||
|     actions: | ||||
|       close: | ||||
|         message: Please reopen this PR on the `develop` branch. Thank you. | ||||
							
								
								
									
										26
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| version: 2 | ||||
| updates: | ||||
|  | ||||
|   # composer updates | ||||
|   - package-ecosystem: "composer" | ||||
|     directory: "/" # Location of package manifests | ||||
|     target-branch: develop | ||||
|     labels: ["bug"] | ||||
|     schedule: | ||||
|       interval: "weekly" | ||||
|  | ||||
|   # yarn / JS updates | ||||
|   - package-ecosystem: "npm" | ||||
|     directory: "/" | ||||
|     target-branch: develop | ||||
|     labels: ["bug"] | ||||
|     schedule: | ||||
|       interval: "weekly" | ||||
|  | ||||
|   # yarn / JS updates for new frontend | ||||
|   - package-ecosystem: "npm" | ||||
|     directory: "/frontend" | ||||
|     target-branch: develop | ||||
|     labels: ["bug"] | ||||
|     schedule: | ||||
|       interval: "weekly" | ||||
							
								
								
									
										1
									
								
								.github/funding.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/funding.yml
									
									
									
									
										vendored
									
									
								
							| @@ -2,4 +2,3 @@ | ||||
|  | ||||
| github: jc5 | ||||
| patreon: JC5 | ||||
| custom: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=44UKUT455HUFA | ||||
|   | ||||
							
								
								
									
										146
									
								
								.github/workflows/laravel.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								.github/workflows/laravel.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,146 @@ | ||||
| name: Firefly III | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches-ignore: | ||||
|       - '**' | ||||
|  | ||||
| jobs: | ||||
|   prepare: | ||||
|  | ||||
|     runs-on: ubuntu-latest | ||||
|  | ||||
|     steps: | ||||
|       - uses: actions/checkout@v2 | ||||
|       - name: Copy .env | ||||
|         run: test -f .env || cp .ci/.env.ci .env | ||||
|       - name: Prepare dependencies | ||||
|         run: | | ||||
|           set -euxo pipefail | ||||
|           export PATH=$PATH:$HOME/.composer/vendor/bin/ | ||||
|           composer global require hirak/prestissimo --no-plugins --no-scripts | ||||
|           composer install --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist --no-suggest | ||||
|  | ||||
|           touch ./storage/database/database.sqlite | ||||
|       - name: Prepare Firefly III | ||||
|         run: | | ||||
|           chmod -R 777 storage bootstrap/cache | ||||
|           php artisan migrate --seed | ||||
|           php artisan firefly-iii:upgrade-database | ||||
|       - name: Upload database | ||||
|         uses: actions/upload-artifact@v2 | ||||
|         with: | ||||
|           name: database | ||||
|           path: storage/database/database.sqlite | ||||
|       - name: Upload cache | ||||
|         uses: actions/upload-artifact@v2 | ||||
|         with: | ||||
|           name: cache | ||||
|           path: bootstrap/cache/ | ||||
|       - name: Upload composer cache | ||||
|         uses: actions/upload-artifact@v2 | ||||
|         with: | ||||
|           name: composer | ||||
|           path: ~/.composer | ||||
|  | ||||
|   laravel-tests: | ||||
|  | ||||
|     runs-on: ubuntu-latest | ||||
|  | ||||
|     needs: | ||||
|       - prepare | ||||
|  | ||||
|     steps: | ||||
|       - uses: actions/checkout@v2 | ||||
|       - name: Copy .env | ||||
|         run: test -f .env || cp .ci/.env.ci .env | ||||
|       - name: Download database | ||||
|         uses: actions/download-artifact@v2 | ||||
|         with: | ||||
|           name: database | ||||
|           path: storage/database/database.sqlite | ||||
|       - name: Download cache | ||||
|         uses: actions/download-artifact@v2 | ||||
|         with: | ||||
|           name: cache | ||||
|           path: bootstrap/cache/ | ||||
|       - name: Download vendor | ||||
|         uses: actions/download-artifact@v2 | ||||
|         with: | ||||
|           name: composer | ||||
|           path: ~/.composer | ||||
|       - name: Install composer | ||||
|         run: composer install --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist --no-suggest | ||||
|  | ||||
|       - name: PHPUnit tests | ||||
|         uses: php-actions/phpunit@v1 | ||||
|         with: | ||||
|           config: phpunit.xml | ||||
|           memory: 512M | ||||
|  | ||||
|   coding-standards: | ||||
|  | ||||
|     runs-on: ubuntu-latest | ||||
|  | ||||
|     needs: | ||||
|       - prepare | ||||
|  | ||||
|     steps: | ||||
|       - uses: actions/checkout@v2 | ||||
|       - name: Copy .env | ||||
|         run: test -f .env || cp .ci/.env.ci .env | ||||
|       - name: Download database | ||||
|         uses: actions/download-artifact@v2 | ||||
|         with: | ||||
|           name: database | ||||
|           path: storage/database/database.sqlite | ||||
|       - name: Download cache | ||||
|         uses: actions/download-artifact@v2 | ||||
|         with: | ||||
|           name: cache | ||||
|           path: bootstrap/cache/ | ||||
|       - name: Download vendor | ||||
|         uses: actions/download-artifact@v2 | ||||
|         with: | ||||
|           name: composer | ||||
|           path: ~/.composer | ||||
|       - name: install depenencies | ||||
|         run: | | ||||
|           composer global require nette/coding-standard | ||||
|           composer install --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist --no-suggest | ||||
|  | ||||
|       - name: Execute code standard | ||||
|         run: /home/runner/.composer/vendor/bin/ecs check app tests --config ./.ci/firefly-iii-standard.yml | ||||
|  | ||||
|   phpstan: | ||||
|  | ||||
|     runs-on: ubuntu-latest | ||||
|  | ||||
|     needs: | ||||
|       - prepare | ||||
|  | ||||
|     steps: | ||||
|       - uses: actions/checkout@v2 | ||||
|       - name: Copy .env | ||||
|         run: test -f .env || cp .ci/.env.ci .env | ||||
|       - name: Download database | ||||
|         uses: actions/download-artifact@v2 | ||||
|         with: | ||||
|           name: database | ||||
|           path: storage/database/database.sqlite | ||||
|       - name: Download cache | ||||
|         uses: actions/download-artifact@v2 | ||||
|         with: | ||||
|           name: cache | ||||
|           path: bootstrap/cache/ | ||||
|       - name: Download vendor | ||||
|         uses: actions/download-artifact@v2 | ||||
|         with: | ||||
|           name: composer | ||||
|           path: ~/.composer | ||||
|       - name: Install depenencies | ||||
|         run: | | ||||
|           composer install --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist --no-suggest | ||||
|  | ||||
|       - name: Execute PHPStan | ||||
|         run: vendor/bin/phpstan analyse -c .ci/phpstan.neon | ||||
							
								
								
									
										21
									
								
								.travis.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								.travis.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| language: php | ||||
| php: | ||||
| - '7.4' | ||||
| dist: xenial | ||||
| os: linux | ||||
| cache: | ||||
|   directories: | ||||
|   - "/home/travis/.config" | ||||
|   - "/home/travis/build/firefly-iii/firefly-iii/vendor" | ||||
|  | ||||
| branches: | ||||
|   only: | ||||
|   - develop | ||||
|  | ||||
| before_script: | ||||
| - phpenv config-rm xdebug.ini || return 0 | ||||
| - composer global require hirak/prestissimo --no-plugins --no-scripts | ||||
|  | ||||
| script: | ||||
| - "./.ci/phpstan.sh" | ||||
| - "./.ci/phpunit.sh" | ||||
| @@ -60,7 +60,7 @@ class AboutController extends Controller | ||||
|             'driver'      => $currentDriver, | ||||
|         ]; | ||||
|  | ||||
|         return response()->json(['data' => $data])->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json(['data' => $data])->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -78,6 +78,6 @@ class AboutController extends Controller | ||||
|  | ||||
|         $resource = new Item(auth()->user(), $transformer, 'users'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -45,15 +45,16 @@ use League\Fractal\Resource\Item; | ||||
|  | ||||
| /** | ||||
|  * Class AccountController. | ||||
|  * | ||||
|  */ | ||||
| class AccountController extends Controller | ||||
| { | ||||
|     use AccountFilter, TransactionFilter; | ||||
|  | ||||
|     private AccountRepositoryInterface $repository; | ||||
|     public const RESOURCE_KEY = 'accounts'; | ||||
|  | ||||
|     private AccountRepositoryInterface $repository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * AccountController constructor. | ||||
|      * | ||||
| @@ -101,7 +102,7 @@ class AccountController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -154,7 +155,7 @@ class AccountController extends Controller | ||||
|         $resource = new FractalCollection($accounts, $transformer, self::RESOURCE_KEY); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|  | ||||
| @@ -165,7 +166,6 @@ class AccountController extends Controller | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      */ | ||||
|     public function piggyBanks(Account $account): JsonResponse | ||||
|     { | ||||
| @@ -191,7 +191,7 @@ class AccountController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -211,7 +211,7 @@ class AccountController extends Controller | ||||
|         $transformer->setParameters($this->parameters); | ||||
|         $resource = new Item($account, $transformer, self::RESOURCE_KEY); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -233,7 +233,7 @@ class AccountController extends Controller | ||||
|  | ||||
|         $resource = new Item($account, $transformer, self::RESOURCE_KEY); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -245,7 +245,6 @@ class AccountController extends Controller | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * | ||||
|      */ | ||||
|     public function transactions(Request $request, Account $account): JsonResponse | ||||
|     { | ||||
| @@ -284,7 +283,7 @@ class AccountController extends Controller | ||||
|         $resource = new FractalCollection($groups, $transformer, 'transactions'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -307,6 +306,6 @@ class AccountController extends Controller | ||||
|         $transformer->setParameters($this->parameters); | ||||
|         $resource = new Item($account, $transformer, self::RESOURCE_KEY); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -28,7 +28,6 @@ use FireflyIII\Api\V1\Requests\AttachmentStoreRequest; | ||||
| use FireflyIII\Api\V1\Requests\AttachmentUpdateRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Attachments\AttachmentHelperInterface; | ||||
| use FireflyIII\Http\Middleware\IsDemoUser; | ||||
| use FireflyIII\Models\Attachment; | ||||
| use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface; | ||||
| use FireflyIII\Transformers\AttachmentTransformer; | ||||
| @@ -45,13 +44,13 @@ use function strlen; | ||||
|  | ||||
| /** | ||||
|  * Class AttachmentController. | ||||
|  * | ||||
|  */ | ||||
| class AttachmentController extends Controller | ||||
| { | ||||
|     /** @var AttachmentRepositoryInterface The attachment repository */ | ||||
|     private $repository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * AccountController constructor. | ||||
|      * | ||||
| @@ -96,8 +95,8 @@ class AttachmentController extends Controller | ||||
|      * @param Attachment $attachment | ||||
|      * | ||||
|      * @codeCoverageIgnore | ||||
|      * @throws   FireflyException | ||||
|      * @return LaravelResponse | ||||
|      * @throws   FireflyException | ||||
|      */ | ||||
|     public function download(Attachment $attachment): LaravelResponse | ||||
|     { | ||||
| @@ -161,7 +160,7 @@ class AttachmentController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -180,7 +179,7 @@ class AttachmentController extends Controller | ||||
|  | ||||
|         $resource = new Item($attachment, $transformer, 'attachments'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -188,8 +187,8 @@ class AttachmentController extends Controller | ||||
|      * | ||||
|      * @param AttachmentStoreRequest $request | ||||
|      * | ||||
|      * @throws FireflyException | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(AttachmentStoreRequest $request): JsonResponse | ||||
|     { | ||||
| @@ -203,7 +202,7 @@ class AttachmentController extends Controller | ||||
|  | ||||
|         $resource = new Item($attachment, $transformer, 'attachments'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -226,7 +225,7 @@ class AttachmentController extends Controller | ||||
|  | ||||
|         $resource = new Item($attachment, $transformer, 'attachments'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
							
								
								
									
										116
									
								
								app/Api/V1/Controllers/Autocomplete/AccountController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								app/Api/V1/Controllers/Autocomplete/AccountController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,116 @@ | ||||
| <?php | ||||
| /** | ||||
|  * AccountController.php | ||||
|  * Copyright (c) 2020 james@firefly-iii.org | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program 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 Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers\Autocomplete; | ||||
|  | ||||
|  | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Api\AccountFilter; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
|  | ||||
| /** | ||||
|  * Class AccountController | ||||
|  */ | ||||
| class AccountController extends Controller | ||||
| { | ||||
|     use AccountFilter; | ||||
|  | ||||
|     private array                      $balanceTypes; | ||||
|     private AccountRepositoryInterface $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); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|         $this->balanceTypes = [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE,]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AutocompleteRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function accounts(AutocompleteRequest $request): JsonResponse | ||||
|     { | ||||
|         $data  = $request->getData(); | ||||
|         $types = $data['types']; | ||||
|         $query = $data['query']; | ||||
|         $date  = $data['date'] ?? today(config('app.timezone')); | ||||
|  | ||||
|         $return          = []; | ||||
|         $result          = $this->repository->searchAccount((string) $query, $types, $data['limit']); | ||||
|         $defaultCurrency = app('amount')->getDefaultCurrency(); | ||||
|  | ||||
|         /** @var Account $account */ | ||||
|         foreach ($result as $account) { | ||||
|             $nameWithBalance = $account->name; | ||||
|             $currency        = $this->repository->getAccountCurrency($account) ?? $defaultCurrency; | ||||
|  | ||||
|             if (in_array($account->accountType->type, $this->balanceTypes, true)) { | ||||
|                 $balance         = app('steam')->balance($account, $date); | ||||
|                 $nameWithBalance = sprintf('%s (%s)', $account->name, app('amount')->formatAnything($currency, $balance, false)); | ||||
|             } | ||||
|  | ||||
|             $return[] = [ | ||||
|                 'id'                      => $account->id, | ||||
|                 'name'                    => $account->name, | ||||
|                 'name_with_balance'       => $nameWithBalance, | ||||
|                 'type'                    => $account->accountType->type, | ||||
|                 'currency_id'             => $currency->id, | ||||
|                 'currency_name'           => $currency->name, | ||||
|                 'currency_code'           => $currency->code, | ||||
|                 'currency_decimal_places' => $currency->decimal_places, | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         // custom order. | ||||
|         $order = [AccountType::ASSET, AccountType::REVENUE, AccountType::EXPENSE]; | ||||
|  | ||||
|  | ||||
|         usort($return, function ($a, $b) use ($order) { | ||||
|             $pos_a = array_search($a['type'], $order); | ||||
|             $pos_b = array_search($b['type'], $order); | ||||
|             return $pos_a - $pos_b; | ||||
|         }); | ||||
|  | ||||
|         return response()->json($return); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										83
									
								
								app/Api/V1/Controllers/Autocomplete/BillController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								app/Api/V1/Controllers/Autocomplete/BillController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| <?php | ||||
| /** | ||||
|  * BillController.php | ||||
|  * Copyright (c) 2020 james@firefly-iii.org | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program 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 Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers\Autocomplete; | ||||
|  | ||||
|  | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Repositories\Bill\BillRepositoryInterface; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
|  | ||||
| /** | ||||
|  * Class BillController | ||||
|  */ | ||||
| class BillController extends Controller | ||||
| { | ||||
|     private BillRepositoryInterface $repository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * BillController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user             = auth()->user(); | ||||
|                 $this->repository = app(BillRepositoryInterface::class); | ||||
|                 $this->repository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * TODO add limit | ||||
|      * @param AutocompleteRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function bills(AutocompleteRequest $request): JsonResponse | ||||
|     { | ||||
|         $data     = $request->getData(); | ||||
|         $result   = $this->repository->searchBill($data['query'], $data['limit']); | ||||
|         $filtered = $result->map( | ||||
|             static function (Bill $item) { | ||||
|                 return [ | ||||
|                     'id'   => $item->id, | ||||
|                     'name' => $item->name, | ||||
|                 ]; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|  | ||||
|         return response()->json($filtered->toArray()); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										81
									
								
								app/Api/V1/Controllers/Autocomplete/BudgetController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								app/Api/V1/Controllers/Autocomplete/BudgetController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| <?php | ||||
| /** | ||||
|  * BudgetController.php | ||||
|  * Copyright (c) 2020 james@firefly-iii.org | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program 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 Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers\Autocomplete; | ||||
|  | ||||
|  | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
|  | ||||
| /** | ||||
|  * Class BudgetController | ||||
|  */ | ||||
| class BudgetController extends Controller | ||||
| { | ||||
|     private BudgetRepositoryInterface $repository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * BudgetController 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); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * TODO add limit | ||||
|      * @param AutocompleteRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function budgets(AutocompleteRequest $request): JsonResponse | ||||
|     { | ||||
|         $data     = $request->getData(); | ||||
|         $result   = $this->repository->searchBudget($data['query'], $data['limit']); | ||||
|         $filtered = $result->map( | ||||
|             static function (Budget $item) { | ||||
|                 return [ | ||||
|                     'id'   => $item->id, | ||||
|                     'name' => $item->name, | ||||
|                 ]; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return response()->json($filtered); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										79
									
								
								app/Api/V1/Controllers/Autocomplete/CategoryController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								app/Api/V1/Controllers/Autocomplete/CategoryController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| <?php | ||||
| /** | ||||
|  * CategoryController.php | ||||
|  * Copyright (c) 2020 james@firefly-iii.org | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program 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 Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers\Autocomplete; | ||||
|  | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; | ||||
| use FireflyIII\Models\Category; | ||||
| use FireflyIII\Repositories\Category\CategoryRepositoryInterface; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
|  | ||||
| /** | ||||
|  * Class CategoryController | ||||
|  */ | ||||
| class CategoryController extends Controller | ||||
| { | ||||
|     private CategoryRepositoryInterface $repository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * CategoryController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user             = auth()->user(); | ||||
|                 $this->repository = app(CategoryRepositoryInterface::class); | ||||
|                 $this->repository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AutocompleteRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function categories(AutocompleteRequest $request): JsonResponse | ||||
|     { | ||||
|         $data     = $request->getData(); | ||||
|         $result   = $this->repository->searchCategory($data['query'], $data['limit']); | ||||
|         $filtered = $result->map( | ||||
|             static function (Category $item) { | ||||
|                 return [ | ||||
|                     'id'   => $item->id, | ||||
|                     'name' => $item->name, | ||||
|                 ]; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return response()->json($filtered); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										109
									
								
								app/Api/V1/Controllers/Autocomplete/CurrencyController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								app/Api/V1/Controllers/Autocomplete/CurrencyController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,109 @@ | ||||
| <?php | ||||
| /** | ||||
|  * CurrencyController.php | ||||
|  * Copyright (c) 2020 james@firefly-iii.org | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program 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 Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers\Autocomplete; | ||||
|  | ||||
|  | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
|  | ||||
| /** | ||||
|  * Class CurrencyController | ||||
|  */ | ||||
| class CurrencyController extends Controller | ||||
| { | ||||
|     private CurrencyRepositoryInterface $repository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * CurrencyController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user             = auth()->user(); | ||||
|                 $this->repository = app(CurrencyRepositoryInterface::class); | ||||
|                 $this->repository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AutocompleteRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function currenciesWithCode(AutocompleteRequest $request): JsonResponse | ||||
|     { | ||||
|         $data       = $request->getData(); | ||||
|         $collection = $this->repository->searchCurrency($data['query'], $data['limit']); | ||||
|         $result     = []; | ||||
|  | ||||
|         /** @var TransactionCurrency $currency */ | ||||
|         foreach ($collection as $currency) { | ||||
|             $result[] = [ | ||||
|                 'id'             => $currency->id, | ||||
|                 'name'           => sprintf('%s (%s)', $currency->name, $currency->code), | ||||
|                 'code'           => $currency->code, | ||||
|                 'symbol'         => $currency->symbol, | ||||
|                 'decimal_places' => $currency->decimal_places, | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return response()->json($result); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AutocompleteRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function currencies(AutocompleteRequest $request): JsonResponse | ||||
|     { | ||||
|         $data       = $request->getData(); | ||||
|         $collection = $this->repository->searchCurrency($data['query'], $data['limit']); | ||||
|         $result     = []; | ||||
|  | ||||
|         /** @var TransactionCurrency $currency */ | ||||
|         foreach ($collection as $currency) { | ||||
|             $result[] = [ | ||||
|                 'id'             => $currency->id, | ||||
|                 'name'           => $currency->name, | ||||
|                 'code'           => $currency->code, | ||||
|                 'symbol'         => $currency->symbol, | ||||
|                 'decimal_places' => $currency->decimal_places, | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return response()->json($result); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,83 @@ | ||||
| <?php | ||||
| /** | ||||
|  * ObjectGroupController.php | ||||
|  * Copyright (c) 2020 james@firefly-iii.org | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program 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 Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers\Autocomplete; | ||||
|  | ||||
|  | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; | ||||
| use FireflyIII\Models\ObjectGroup; | ||||
| use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
|  | ||||
| /** | ||||
|  * Class ObjectGroupController | ||||
|  */ | ||||
| class ObjectGroupController extends Controller | ||||
| { | ||||
|     private ObjectGroupRepositoryInterface $repository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * CurrencyController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user             = auth()->user(); | ||||
|                 $this->repository = app(ObjectGroupRepositoryInterface::class); | ||||
|                 $this->repository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AutocompleteRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function objectGroups(AutocompleteRequest $request): JsonResponse | ||||
|     { | ||||
|         $data   = $request->getData(); | ||||
|         $return = []; | ||||
|         $result = $this->repository->search($data['query'], $data['limit']); | ||||
|  | ||||
|         /** @var ObjectGroup $account */ | ||||
|         foreach ($result as $objectGroup) { | ||||
|             $return[] = [ | ||||
|                 'id'    => $objectGroup->id, | ||||
|                 'name'  => $objectGroup->title, | ||||
|                 'title' => $objectGroup->title, | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return response()->json($return); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										125
									
								
								app/Api/V1/Controllers/Autocomplete/PiggyBankController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								app/Api/V1/Controllers/Autocomplete/PiggyBankController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,125 @@ | ||||
| <?php | ||||
| /** | ||||
|  * PiggyBankController.php | ||||
|  * Copyright (c) 2020 james@firefly-iii.org | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program 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 Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers\Autocomplete; | ||||
|  | ||||
|  | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
|  | ||||
| /** | ||||
|  * Class PiggyBankController | ||||
|  */ | ||||
| class PiggyBankController extends Controller | ||||
| { | ||||
|     private PiggyBankRepositoryInterface $piggyRepository; | ||||
|  | ||||
|     private AccountRepositoryInterface   $accountRepository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * PiggyBankController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user                    = auth()->user(); | ||||
|                 $this->piggyRepository   = app(PiggyBankRepositoryInterface::class); | ||||
|                 $this->accountRepository = app(AccountRepositoryInterface::class); | ||||
|                 $this->piggyRepository->setUser($user); | ||||
|                 $this->accountRepository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AutocompleteRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function piggyBanks(AutocompleteRequest $request): JsonResponse | ||||
|     { | ||||
|         $data            = $request->getData(); | ||||
|         $piggies         = $this->piggyRepository->searchPiggyBank($data['query'], $data['limit']); | ||||
|         $defaultCurrency = app('amount')->getDefaultCurrency(); | ||||
|         $response        = []; | ||||
|  | ||||
|         /** @var PiggyBank $piggy */ | ||||
|         foreach ($piggies as $piggy) { | ||||
|             $currency   = $this->accountRepository->getAccountCurrency($piggy->account) ?? $defaultCurrency; | ||||
|             $response[] = [ | ||||
|                 'id'                      => $piggy->id, | ||||
|                 'name'                    => $piggy->name, | ||||
|                 'currency_id'             => $currency->id, | ||||
|                 'currency_name'           => $currency->name, | ||||
|                 'currency_code'           => $currency->code, | ||||
|                 'currency_decimal_places' => $currency->decimal_places, | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return response()->json($response); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AutocompleteRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function piggyBanksWithBalance(AutocompleteRequest $request): JsonResponse | ||||
|     { | ||||
|         $data            = $request->getData(); | ||||
|         $piggies         = $this->piggyRepository->searchPiggyBank($data['query'], $data['limit']); | ||||
|         $defaultCurrency = app('amount')->getDefaultCurrency(); | ||||
|         $response        = []; | ||||
|         /** @var PiggyBank $piggy */ | ||||
|         foreach ($piggies as $piggy) { | ||||
|             $currency      = $this->accountRepository->getAccountCurrency($piggy->account) ?? $defaultCurrency; | ||||
|             $currentAmount = $this->piggyRepository->getRepetition($piggy)->currentamount ?? '0'; | ||||
|             $response[]    = [ | ||||
|                 'id'                      => $piggy->id, | ||||
|                 'name'                    => $piggy->name, | ||||
|                 'name_with_balance'       => sprintf( | ||||
|                     '%s (%s / %s)', $piggy->name, app('amount')->formatAnything($currency, $currentAmount, false), | ||||
|                     app('amount')->formatAnything($currency, $piggy->targetamount, false), | ||||
|                 ), | ||||
|                 'currency_id'             => $currency->id, | ||||
|                 'currency_name'           => $currency->name, | ||||
|                 'currency_code'           => $currency->code, | ||||
|                 'currency_decimal_places' => $currency->decimal_places, | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return response()->json($response); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										35
									
								
								app/Api/V1/Controllers/Autocomplete/RecurrenceController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								app/Api/V1/Controllers/Autocomplete/RecurrenceController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| <?php | ||||
| /** | ||||
|  * RecurrenceController.php | ||||
|  * Copyright (c) 2020 james@firefly-iii.org | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program 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 Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers\Autocomplete; | ||||
|  | ||||
|  | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
|  | ||||
| /** | ||||
|  * Class RecurrenceController | ||||
|  */ | ||||
| class RecurrenceController extends Controller | ||||
| { | ||||
|  | ||||
| } | ||||
							
								
								
									
										35
									
								
								app/Api/V1/Controllers/Autocomplete/RuleController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								app/Api/V1/Controllers/Autocomplete/RuleController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| <?php | ||||
| /** | ||||
|  * RuleController.php | ||||
|  * Copyright (c) 2020 james@firefly-iii.org | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program 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 Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers\Autocomplete; | ||||
|  | ||||
|  | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
|  | ||||
| /** | ||||
|  * Class RuleController | ||||
|  */ | ||||
| class RuleController extends Controller | ||||
| { | ||||
|  | ||||
| } | ||||
							
								
								
									
										35
									
								
								app/Api/V1/Controllers/Autocomplete/RuleGroupController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								app/Api/V1/Controllers/Autocomplete/RuleGroupController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| <?php | ||||
| /** | ||||
|  * RuleGroupController.php | ||||
|  * Copyright (c) 2020 james@firefly-iii.org | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program 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 Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers\Autocomplete; | ||||
|  | ||||
|  | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
|  | ||||
| /** | ||||
|  * Class RuleGroupController | ||||
|  */ | ||||
| class RuleGroupController extends Controller | ||||
| { | ||||
|  | ||||
| } | ||||
							
								
								
									
										82
									
								
								app/Api/V1/Controllers/Autocomplete/TagController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								app/Api/V1/Controllers/Autocomplete/TagController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | ||||
| <?php | ||||
| /** | ||||
|  * TagController.php | ||||
|  * Copyright (c) 2020 james@firefly-iii.org | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program 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 Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers\Autocomplete; | ||||
|  | ||||
|  | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; | ||||
| use FireflyIII\Models\Tag; | ||||
| use FireflyIII\Repositories\Tag\TagRepositoryInterface; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
|  | ||||
| /** | ||||
|  * Class TagController | ||||
|  */ | ||||
| class TagController extends Controller | ||||
| { | ||||
|     private TagRepositoryInterface $repository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * TagController 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 AutocompleteRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function tags(AutocompleteRequest $request): JsonResponse | ||||
|     { | ||||
|         $data = $request->getData(); | ||||
|  | ||||
|         $result = $this->repository->searchTags($data['query'], $data['limit']); | ||||
|         $array  = []; | ||||
|         /** @var Tag $tag */ | ||||
|         foreach ($result as $tag) { | ||||
|             $array[] = [ | ||||
|                 'id'   => $tag->id, | ||||
|                 'name' => $tag->tag, | ||||
|                 'tag'  => $tag->tag, | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return response()->json($array); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										132
									
								
								app/Api/V1/Controllers/Autocomplete/TransactionController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								app/Api/V1/Controllers/Autocomplete/TransactionController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,132 @@ | ||||
| <?php | ||||
| /** | ||||
|  * TransactionController.php | ||||
|  * Copyright (c) 2020 james@firefly-iii.org | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program 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 Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers\Autocomplete; | ||||
|  | ||||
|  | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Repositories\Journal\JournalRepositoryInterface; | ||||
| use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class TransactionController | ||||
|  */ | ||||
| class TransactionController extends Controller | ||||
| { | ||||
|     private JournalRepositoryInterface          $repository; | ||||
|  | ||||
|     private TransactionGroupRepositoryInterface $groupRepository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * TransactionController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user                  = auth()->user(); | ||||
|                 $this->repository      = app(JournalRepositoryInterface::class); | ||||
|                 $this->groupRepository = app(TransactionGroupRepositoryInterface::class); | ||||
|                 $this->repository->setUser($user); | ||||
|                 $this->groupRepository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param AutocompleteRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function transactions(AutocompleteRequest $request): JsonResponse | ||||
|     { | ||||
|         $data   = $request->getData(); | ||||
|         $result = $this->repository->searchJournalDescriptions($data['query'], $data['limit']); | ||||
|  | ||||
|         // limit and unique | ||||
|         $filtered = $result->unique('description'); | ||||
|         $array    = []; | ||||
|  | ||||
|         /** @var TransactionJournal $journal */ | ||||
|         foreach ($filtered as $journal) { | ||||
|             $array[] = [ | ||||
|                 'id'                   => $journal->id, | ||||
|                 'transaction_group_id' => $journal->transaction_group_id, | ||||
|                 'name'                 => $journal->description, | ||||
|                 'description'          => $journal->description, | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return response()->json($array); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AutocompleteRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function transactionsWithID(AutocompleteRequest $request): JsonResponse | ||||
|     { | ||||
|         $data   = $request->getData(); | ||||
|         $result = new Collection; | ||||
|         if (is_numeric($data['query'])) { | ||||
|             // search for group, not journal. | ||||
|             $firstResult = $this->groupRepository->find((int) $data['query']); | ||||
|             if (null !== $firstResult) { | ||||
|                 // group may contain multiple journals, each a result: | ||||
|                 foreach ($firstResult->transactionJournals as $journal) { | ||||
|                     $result->push($journal); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         if (!is_numeric($data['query'])) { | ||||
|             $result = $this->repository->searchJournalDescriptions($data['query'], $data['limit']); | ||||
|         } | ||||
|  | ||||
|         // limit and unique | ||||
|         $array = []; | ||||
|  | ||||
|         /** @var TransactionJournal $journal */ | ||||
|         foreach ($result as $journal) { | ||||
|             $array[] = [ | ||||
|                 'id'                   => $journal->id, | ||||
|                 'transaction_group_id' => $journal->transaction_group_id, | ||||
|                 'name'                 => sprintf('#%d: %s', $journal->transaction_group_id, $journal->description), | ||||
|                 'description'          => sprintf('#%d: %s', $journal->transaction_group_id, $journal->description), | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return response()->json($array); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,80 @@ | ||||
| <?php | ||||
| /** | ||||
|  * TransactionTypeController.php | ||||
|  * Copyright (c) 2020 james@firefly-iii.org | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program 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 Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers\Autocomplete; | ||||
|  | ||||
|  | ||||
| use FireflyIII\Api\V1\Controllers\Controller; | ||||
| use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Repositories\TransactionType\TransactionTypeRepositoryInterface; | ||||
| use Illuminate\Http\JsonResponse; | ||||
|  | ||||
| /** | ||||
|  * Class TransactionTypeController | ||||
|  */ | ||||
| class TransactionTypeController extends Controller | ||||
| { | ||||
|     private TransactionTypeRepositoryInterface $repository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * TransactionTypeController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 $this->repository = app(TransactionTypeRepositoryInterface::class); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AutocompleteRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @codeCoverageIgnore | ||||
|      */ | ||||
|     public function transactionTypes(AutocompleteRequest $request): JsonResponse | ||||
|     { | ||||
|         $data  = $request->getData(); | ||||
|         $types = $this->repository->searchTypes($data['query'], $data['limit']); | ||||
|         $array = []; | ||||
|  | ||||
|         /** @var TransactionType $type */ | ||||
|         foreach ($types as $type) { | ||||
|             // different key for consistency. | ||||
|             $array[] = [ | ||||
|                 'id'   => $type->id, | ||||
|                 'name' => $type->type, | ||||
|                 'type' => $type->type, | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return response()->json($array); | ||||
|     } | ||||
| } | ||||
| @@ -38,12 +38,10 @@ use League\Fractal\Resource\Item; | ||||
|  | ||||
| /** | ||||
|  * Class AvailableBudgetController. | ||||
|  * | ||||
|  */ | ||||
| class AvailableBudgetController extends Controller | ||||
| { | ||||
|     /** @var AvailableBudgetRepositoryInterface */ | ||||
|     private $abRepository; | ||||
|     private AvailableBudgetRepositoryInterface $abRepository; | ||||
|  | ||||
|     /** | ||||
|      * AvailableBudgetController constructor. | ||||
| @@ -113,7 +111,7 @@ class AvailableBudgetController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -134,7 +132,7 @@ class AvailableBudgetController extends Controller | ||||
|  | ||||
|         $resource = new Item($availableBudget, $transformer, 'available_budgets'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -147,6 +145,9 @@ class AvailableBudgetController extends Controller | ||||
|     public function store(AvailableBudgetRequest $request): JsonResponse | ||||
|     { | ||||
|         $data = $request->getAll(); | ||||
|         $data['start']->startOfDay(); | ||||
|         $data['end']->endOfDay(); | ||||
|  | ||||
|         /** @var TransactionCurrencyFactory $factory */ | ||||
|         $factory  = app(TransactionCurrencyFactory::class); | ||||
|         $currency = $factory->find($data['currency_id'], $data['currency_code']); | ||||
| @@ -164,7 +165,7 @@ class AvailableBudgetController extends Controller | ||||
|  | ||||
|         $resource = new Item($availableBudget, $transformer, 'available_budgets'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|  | ||||
| @@ -204,7 +205,7 @@ class AvailableBudgetController extends Controller | ||||
|  | ||||
|         $resource = new Item($availableBudget, $transformer, 'available_budgets'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -44,14 +44,15 @@ use League\Fractal\Resource\Item; | ||||
|  | ||||
| /** | ||||
|  * Class BillController. | ||||
|  * | ||||
|  */ | ||||
| class BillController extends Controller | ||||
| { | ||||
|     use TransactionFilter; | ||||
|  | ||||
|     /** @var BillRepositoryInterface The bill repository */ | ||||
|     private $repository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * BillController constructor. | ||||
|      * | ||||
| @@ -102,7 +103,7 @@ class BillController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -142,7 +143,7 @@ class BillController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -177,7 +178,7 @@ class BillController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -198,7 +199,7 @@ class BillController extends Controller | ||||
|  | ||||
|         $resource = new Item($bill, $transformer, 'bills'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -206,8 +207,8 @@ class BillController extends Controller | ||||
|      * | ||||
|      * @param BillRequest $request | ||||
|      * | ||||
|      * @throws FireflyException | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(BillRequest $request): JsonResponse | ||||
|     { | ||||
| @@ -220,7 +221,7 @@ class BillController extends Controller | ||||
|  | ||||
|         $resource = new Item($bill, $transformer, 'bills'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -278,7 +279,7 @@ class BillController extends Controller | ||||
|         $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 response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -301,7 +302,7 @@ class BillController extends Controller | ||||
|  | ||||
|         $resource = new Item($bill, $transformer, 'bills'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -23,8 +23,6 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use Exception; | ||||
| use FireflyIII\Api\V1\Requests\BudgetLimitRequest; | ||||
| use FireflyIII\Api\V1\Requests\BudgetStoreRequest; | ||||
| use FireflyIII\Api\V1\Requests\BudgetUpdateRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| @@ -47,16 +45,18 @@ use League\Fractal\Resource\Item; | ||||
|  | ||||
| /** | ||||
|  * Class BudgetController. | ||||
|  * | ||||
|  */ | ||||
| class BudgetController extends Controller | ||||
| { | ||||
|     use TransactionFilter; | ||||
|  | ||||
|     /** @var BudgetLimitRepositoryInterface */ | ||||
|     private $blRepository; | ||||
|  | ||||
|     /** @var BudgetRepositoryInterface The budget repository */ | ||||
|     private $repository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * BudgetController constructor. | ||||
|      * | ||||
| @@ -107,7 +107,7 @@ class BudgetController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -136,7 +136,7 @@ class BudgetController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -183,7 +183,7 @@ class BudgetController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -204,7 +204,7 @@ class BudgetController extends Controller | ||||
|  | ||||
|         $resource = new Item($budget, $transformer, 'budgets'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -212,9 +212,9 @@ class BudgetController extends Controller | ||||
|      * | ||||
|      * @param BudgetStoreRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function store(BudgetStoreRequest $request): JsonResponse | ||||
|     { | ||||
| @@ -227,32 +227,7 @@ class BudgetController extends Controller | ||||
|  | ||||
|         $resource = new Item($budget, $transformer, 'budgets'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param BudgetLimitRequest $request | ||||
|      * @param Budget             $budget | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function storeBudgetLimit(BudgetLimitRequest $request, Budget $budget): JsonResponse | ||||
|     { | ||||
|         $data           = $request->getAll(); | ||||
|         $data['budget'] = $budget; | ||||
|         $budgetLimit    = $this->blRepository->storeBudgetLimit($data); | ||||
|         $manager        = $this->getManager(); | ||||
|  | ||||
|         /** @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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -316,7 +291,7 @@ class BudgetController extends Controller | ||||
|         $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 response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -339,7 +314,7 @@ class BudgetController extends Controller | ||||
|  | ||||
|         $resource = new Item($budget, $transformer, 'budgets'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -44,16 +44,18 @@ use League\Fractal\Resource\Item; | ||||
|  | ||||
| /** | ||||
|  * Class BudgetLimitController. | ||||
|  * | ||||
|  */ | ||||
| class BudgetLimitController extends Controller | ||||
| { | ||||
|     use TransactionFilter; | ||||
|  | ||||
|     /** @var BudgetLimitRepositoryInterface */ | ||||
|     private $blRepository; | ||||
|  | ||||
|     /** @var BudgetRepositoryInterface The budget repository */ | ||||
|     private $repository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * BudgetLimitController constructor. | ||||
|      * | ||||
| @@ -127,7 +129,7 @@ class BudgetLimitController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -148,7 +150,7 @@ class BudgetLimitController extends Controller | ||||
|  | ||||
|         $resource = new Item($budgetLimit, $transformer, 'budget_limits'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -156,20 +158,19 @@ class BudgetLimitController extends Controller | ||||
|      * | ||||
|      * @param BudgetLimitRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function store(BudgetLimitRequest $request): JsonResponse | ||||
|     { | ||||
|         $data   = $request->getAll(); | ||||
|         $budget = $this->repository->findNull($data['budget_id']); | ||||
|         if (null === $budget) { | ||||
|             throw new FireflyException('200004: Budget does not exist.'); // @codeCoverageIgnore | ||||
|         } | ||||
|         $data['budget'] = $budget; | ||||
|         $budgetLimit    = $this->blRepository->storeBudgetLimit($data); | ||||
|         $manager        = $this->getManager(); | ||||
|         $data               = $request->getAll(); | ||||
|         $data['start_date'] = $data['start']; | ||||
|         $data['end_date']   = $data['end']; | ||||
|  | ||||
|         $budgetLimit = $this->blRepository->store($data); | ||||
|         $manager     = $this->getManager(); | ||||
|  | ||||
|  | ||||
|         /** @var BudgetLimitTransformer $transformer */ | ||||
|         $transformer = app(BudgetLimitTransformer::class); | ||||
| @@ -177,7 +178,7 @@ class BudgetLimitController extends Controller | ||||
|  | ||||
|         $resource = new Item($budgetLimit, $transformer, 'budget_limits'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -230,7 +231,7 @@ class BudgetLimitController extends Controller | ||||
|         $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 response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -243,10 +244,9 @@ class BudgetLimitController extends Controller | ||||
|      */ | ||||
|     public function update(BudgetLimitRequest $request, BudgetLimit $budgetLimit): JsonResponse | ||||
|     { | ||||
|         $data           = $request->getAll(); | ||||
|         $data['budget'] = $budgetLimit->budget; | ||||
|         $budgetLimit    = $this->blRepository->updateBudgetLimit($budgetLimit, $data); | ||||
|         $manager        = $this->getManager(); | ||||
|         $data        = $request->getAll(); | ||||
|         $budgetLimit = $this->blRepository->update($budgetLimit, $data); | ||||
|         $manager     = $this->getManager(); | ||||
|  | ||||
|         /** @var BudgetLimitTransformer $transformer */ | ||||
|         $transformer = app(BudgetLimitTransformer::class); | ||||
| @@ -254,7 +254,7 @@ class BudgetLimitController extends Controller | ||||
|  | ||||
|         $resource = new Item($budgetLimit, $transformer, 'budget_limits'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -42,14 +42,15 @@ use League\Fractal\Resource\Item; | ||||
|  | ||||
| /** | ||||
|  * Class CategoryController. | ||||
|  * | ||||
|  */ | ||||
| class CategoryController extends Controller | ||||
| { | ||||
|     use TransactionFilter; | ||||
|  | ||||
|     /** @var CategoryRepositoryInterface The category repository */ | ||||
|     private $repository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * CategoryController constructor. | ||||
|      * | ||||
| @@ -98,7 +99,7 @@ class CategoryController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -146,7 +147,7 @@ class CategoryController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|  | ||||
| @@ -168,7 +169,7 @@ class CategoryController extends Controller | ||||
|  | ||||
|         $resource = new Item($category, $transformer, 'categories'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -176,8 +177,8 @@ class CategoryController extends Controller | ||||
|      * | ||||
|      * @param CategoryRequest $request | ||||
|      * | ||||
|      * @throws FireflyException | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(CategoryRequest $request): JsonResponse | ||||
|     { | ||||
| @@ -190,7 +191,7 @@ class CategoryController extends Controller | ||||
|  | ||||
|         $resource = new Item($category, $transformer, 'categories'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -246,7 +247,7 @@ class CategoryController extends Controller | ||||
|         $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 response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -269,7 +270,7 @@ class CategoryController extends Controller | ||||
|  | ||||
|         $resource = new Item($category, $transformer, 'categories'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -42,9 +42,12 @@ use Illuminate\Http\JsonResponse; | ||||
| class AccountController extends Controller | ||||
| { | ||||
|     use ApiSupport; | ||||
|  | ||||
|     private CurrencyRepositoryInterface $currencyRepository; | ||||
|  | ||||
|     private AccountRepositoryInterface $repository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * AccountController constructor. | ||||
|      * | ||||
| @@ -207,7 +210,7 @@ class AccountController extends Controller | ||||
|             while ($currentStart <= $end) { | ||||
|                 $format   = $currentStart->format('Y-m-d'); | ||||
|                 $label    = $currentStart->format('Y-m-d'); | ||||
|                 $balance  = isset($range[$format]) ? round($range[$format], 12) : $previous; | ||||
|                 $balance  = array_key_exists($format, $range) ? round($range[$format], 12) : $previous; | ||||
|                 $previous = $balance; | ||||
|                 $currentStart->addDay(); | ||||
|                 $currentSet['entries'][$label] = $balance; | ||||
|   | ||||
| @@ -31,17 +31,14 @@ use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| use FireflyIII\Repositories\Budget\OperationsRepositoryInterface; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class AvailableBudgetController | ||||
|  */ | ||||
| class AvailableBudgetController extends Controller | ||||
| { | ||||
|     /** @var OperationsRepositoryInterface */ | ||||
|     private $opsRepository; | ||||
|     /** @var BudgetRepositoryInterface */ | ||||
|     private $repository; | ||||
|     private OperationsRepositoryInterface $opsRepository; | ||||
|     private BudgetRepositoryInterface     $repository; | ||||
|  | ||||
|     /** | ||||
|      * AvailableBudgetController constructor. | ||||
| @@ -72,18 +69,18 @@ class AvailableBudgetController extends Controller | ||||
|      */ | ||||
|     public function overview(AvailableBudget $availableBudget): JsonResponse | ||||
|     { | ||||
|         $currency          = $availableBudget->transactionCurrency; | ||||
|         $budgets           = $this->repository->getActiveBudgets(); | ||||
|         $budgetInformation = $this->opsRepository->spentInPeriodMc($budgets, new Collection, $availableBudget->start_date, $availableBudget->end_date); | ||||
|         $spent             = 0.0; | ||||
|         $currency             = $availableBudget->transactionCurrency; | ||||
|         $budgets              = $this->repository->getActiveBudgets(); | ||||
|         $newBudgetInformation = $this->opsRepository->sumExpenses($availableBudget->start_date, $availableBudget->end_date, null, $budgets); | ||||
|         $spent                = '0'; | ||||
|  | ||||
|         // get for current currency | ||||
|         foreach ($budgetInformation as $spentInfo) { | ||||
|             if ($spentInfo['currency_id'] === $availableBudget->transaction_currency_id) { | ||||
|                 $spent = $spentInfo['amount']; | ||||
|         foreach ($newBudgetInformation as $currencyId => $info) { | ||||
|             if ($currencyId === (int) $availableBudget->transaction_currency_id) { | ||||
|                 $spent = $info['sum']; | ||||
|             } | ||||
|         } | ||||
|         $left = bcadd($availableBudget->amount, (string) $spent); | ||||
|  | ||||
|         $left = bcadd($availableBudget->amount, $spent); | ||||
|         // left less than zero? Set to zero. | ||||
|         if (-1 === bccomp($left, '0')) { | ||||
|             $left = '0'; | ||||
|   | ||||
| @@ -41,9 +41,12 @@ use Illuminate\Support\Collection; | ||||
| class BudgetController extends Controller | ||||
| { | ||||
|     private BudgetLimitRepositoryInterface $blRepository; | ||||
|  | ||||
|     private OperationsRepositoryInterface  $opsRepository; | ||||
|  | ||||
|     private BudgetRepositoryInterface      $repository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * BudgetController constructor. | ||||
|      * | ||||
| @@ -55,13 +58,10 @@ class BudgetController extends Controller | ||||
|  | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 //$this->generator     = app(GeneratorInterface::class); | ||||
|                 $this->repository    = app(BudgetRepositoryInterface::class); | ||||
|                 $this->opsRepository = app(OperationsRepositoryInterface::class); | ||||
|                 $this->blRepository  = app(BudgetLimitRepositoryInterface::class); | ||||
|  | ||||
|                 //$this->nbRepository  = app(NoBudgetRepositoryInterface::class); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
| @@ -131,6 +131,100 @@ class BudgetController extends Controller | ||||
|         return $arr; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getExpenseInRange(Budget $budget, Carbon $start, Carbon $end): array | ||||
|     { | ||||
|         $spent  = $this->opsRepository->sumExpenses($start, $end, null, new Collection([$budget]), null); | ||||
|         $return = []; | ||||
|         /** @var array $set */ | ||||
|         foreach ($spent as $set) { | ||||
|             $current                            = [ | ||||
|                 'label'                   => sprintf('%s (%s)', $budget->name, $set['currency_name']), | ||||
|                 'budget_name'             => $budget->name, | ||||
|                 'start_date'              => $start->format('Y-m-d'), | ||||
|                 'end_date'                => $end->format('Y-m-d'), | ||||
|                 'currency_id'             => (int) $set['currency_id'], | ||||
|                 'currency_code'           => $set['currency_code'], | ||||
|                 'currency_name'           => $set['currency_name'], | ||||
|                 'currency_symbol'         => $set['currency_symbol'], | ||||
|                 'currency_decimal_places' => (int) $set['currency_decimal_places'], | ||||
|                 'type'                    => 'bar', // line, area or bar, | ||||
|                 'entries'                 => [], | ||||
|             ]; | ||||
|             $sumSpent                           = bcmul($set['sum'], '-1'); // spent | ||||
|             $current['entries']['spent']        = $sumSpent; | ||||
|             $current['entries']['amount']       = '0'; | ||||
|             $current['entries']['spent_capped'] = $sumSpent; | ||||
|             $current['entries']['left']         = '0'; | ||||
|             $current['entries']['overspent']    = '0'; | ||||
|             $return[]                           = $current; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BudgetLimit $limit | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getExpensesForLimit(BudgetLimit $limit): array | ||||
|     { | ||||
|         $budget   = $limit->budget; | ||||
|         $spent    = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, null, new Collection([$budget]), $limit->transactionCurrency); | ||||
|         $currency = $limit->transactionCurrency; | ||||
|         // when limited to a currency, the count is always one. Or it's empty. | ||||
|         $set = array_shift($spent); | ||||
|         if (null === $set) { | ||||
|             return []; | ||||
|         } | ||||
|         $return                            = [ | ||||
|             'label'                   => sprintf('%s (%s)', $budget->name, $set['currency_name']), | ||||
|             'budget_name'             => $budget->name, | ||||
|             'start_date'              => $limit->start_date->format('Y-m-d'), | ||||
|             'end_date'                => $limit->end_date->format('Y-m-d'), | ||||
|             'currency_id'             => (int) $currency->id, | ||||
|             'currency_code'           => $currency->code, | ||||
|             'currency_name'           => $currency->name, | ||||
|             'currency_symbol'         => $currency->symbol, | ||||
|             'currency_decimal_places' => (int) $currency->decimal_places, | ||||
|             'type'                    => 'bar', // line, area or bar, | ||||
|             'entries'                 => [], | ||||
|         ]; | ||||
|         $sumSpent                          = bcmul($set['sum'], '-1'); // spent | ||||
|         $return['entries']['spent']        = $sumSpent; | ||||
|         $return['entries']['amount']       = $limit->amount; | ||||
|         $return['entries']['spent_capped'] = 1 === bccomp($sumSpent, $limit->amount) ? $limit->amount : $sumSpent; | ||||
|         $return['entries']['left']         = 1 === bccomp($limit->amount, $sumSpent) ? bcadd($set['sum'], $limit->amount) : '0';              // left | ||||
|         $return['entries']['overspent']    = 1 === bccomp($limit->amount, $sumSpent) ? '0' : bcmul(bcadd($set['sum'], $limit->amount), '-1'); // overspent | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $expenses | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function filterNulls(array $expenses): array | ||||
|     { | ||||
|         $return = []; | ||||
|         /** @var array|null $arr */ | ||||
|         foreach ($expenses as $arr) { | ||||
|             if ([] !== $arr) { | ||||
|                 $return[] = $arr; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $budgetNames | ||||
|      * @param array $currencyNames | ||||
| @@ -192,7 +286,6 @@ class BudgetController extends Controller | ||||
|     { | ||||
|         foreach ($sets as $set) { | ||||
|             $label                                    = $set['label']; | ||||
|             //$basic['spent']['entries'][$label]        = $set['entries']['spent']; | ||||
|             $basic['spent_capped']['entries'][$label] = $set['entries']['spent_capped']; | ||||
|             $basic['left']['entries'][$label]         = $set['entries']['left']; | ||||
|             $basic['overspent']['entries'][$label]    = $set['entries']['overspent']; | ||||
| @@ -201,98 +294,4 @@ class BudgetController extends Controller | ||||
|         return $basic; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $expenses | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function filterNulls(array $expenses): array | ||||
|     { | ||||
|         $return = []; | ||||
|         /** @var array|null $arr */ | ||||
|         foreach ($expenses as $arr) { | ||||
|             if (null !== $arr) { | ||||
|                 $return[] = $arr; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getExpenseInRange(Budget $budget, Carbon $start, Carbon $end): array | ||||
|     { | ||||
|         $spent  = $this->opsRepository->sumExpenses($start, $end, null, new Collection([$budget]), null); | ||||
|         $return = []; | ||||
|         /** @var array $set */ | ||||
|         foreach ($spent as $set) { | ||||
|             $current                            = [ | ||||
|                 'label'                   => sprintf('%s (%s)', $budget->name, $set['currency_name']), | ||||
|                 'budget_name'             => $budget->name, | ||||
|                 'start_date'              => $start->format('Y-m-d'), | ||||
|                 'end_date'                => $end->format('Y-m-d'), | ||||
|                 'currency_id'             => (int) $set['currency_id'], | ||||
|                 'currency_code'           => $set['currency_code'], | ||||
|                 'currency_name'           => $set['currency_name'], | ||||
|                 'currency_symbol'         => $set['currency_symbol'], | ||||
|                 'currency_decimal_places' => (int) $set['currency_decimal_places'], | ||||
|                 'type'                    => 'bar', // line, area or bar, | ||||
|                 'entries'                 => [], | ||||
|             ]; | ||||
|             $sumSpent                           = bcmul($set['sum'], '-1'); // spent | ||||
|             $current['entries']['spent']        = $sumSpent; | ||||
|             $current['entries']['amount']       = '0'; | ||||
|             $current['entries']['spent_capped'] = $sumSpent; | ||||
|             $current['entries']['left']         = '0'; | ||||
|             $current['entries']['overspent']    = '0'; | ||||
|             $return[]                           = $current; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BudgetLimit $limit | ||||
|      * | ||||
|      * @return array|null | ||||
|      */ | ||||
|     private function getExpensesForLimit(BudgetLimit $limit): ?array | ||||
|     { | ||||
|         $budget   = $limit->budget; | ||||
|         $spent    = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, null, new Collection([$budget]), $limit->transactionCurrency); | ||||
|         $currency = $limit->transactionCurrency; | ||||
|         // when limited to a currency, the count is always one. Or it's empty. | ||||
|         $set = array_shift($spent); | ||||
|         if (null === $set) { | ||||
|             return null; | ||||
|         } | ||||
|         $return                            = [ | ||||
|             'label'                   => sprintf('%s (%s)', $budget->name, $set['currency_name']), | ||||
|             'budget_name'             => $budget->name, | ||||
|             'start_date'              => $limit->start_date->format('Y-m-d'), | ||||
|             'end_date'                => $limit->end_date->format('Y-m-d'), | ||||
|             'currency_id'             => (int) $currency->id, | ||||
|             'currency_code'           => $currency->code, | ||||
|             'currency_name'           => $currency->name, | ||||
|             'currency_symbol'         => $currency->symbol, | ||||
|             'currency_decimal_places' => (int) $currency->decimal_places, | ||||
|             'type'                    => 'bar', // line, area or bar, | ||||
|             'entries'                 => [], | ||||
|         ]; | ||||
|         $sumSpent                          = bcmul($set['sum'], '-1'); // spent | ||||
|         $return['entries']['spent']        = $sumSpent; | ||||
|         $return['entries']['amount']       = $limit->amount; | ||||
|         $return['entries']['spent_capped'] = 1 === bccomp($sumSpent, $limit->amount) ? $limit->amount : $sumSpent; | ||||
|         $return['entries']['left']         = 1 === bccomp($limit->amount, $sumSpent) ? bcadd($set['sum'], $limit->amount) : '0'; // left | ||||
|         $return['entries']['overspent']    = 1 === bccomp($limit->amount, $sumSpent) ? '0' : bcmul(bcadd($set['sum'], $limit->amount), '-1'); // overspent | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -40,11 +40,14 @@ class CategoryController extends Controller | ||||
| { | ||||
|     /** @var CategoryRepositoryInterface */ | ||||
|     private $categoryRepository; | ||||
|  | ||||
|     /** @var NoCategoryRepositoryInterface */ | ||||
|     private $noCatRepository; | ||||
|  | ||||
|     /** @var OperationsRepositoryInterface */ | ||||
|     private $opsRepository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * AccountController constructor. | ||||
|      * | ||||
| @@ -85,17 +88,17 @@ class CategoryController extends Controller | ||||
|         $end = $dates['end']; | ||||
|  | ||||
|  | ||||
|         $tempData      = []; | ||||
|         $spentWith     = $this->opsRepository->listExpenses($start, $end); | ||||
|         $spentWithout  = $this->noCatRepository->listExpenses($start, $end); | ||||
|         $categories    = []; | ||||
|         $tempData     = []; | ||||
|         $spentWith    = $this->opsRepository->listExpenses($start, $end); | ||||
|         $spentWithout = $this->noCatRepository->listExpenses($start, $end); | ||||
|         $categories   = []; | ||||
|  | ||||
|  | ||||
|         foreach ([$spentWith, $spentWithout,] as $set) { | ||||
|             foreach ($set as $currency) { | ||||
|                 foreach ($currency['categories'] as $category) { | ||||
|                     $categories[] = $category['name']; | ||||
|                     $outKey       = sprintf('%d-e', $currency['currency_id']); | ||||
|                     $categories[]      = $category['name']; | ||||
|                     $outKey            = sprintf('%d-e', $currency['currency_id']); | ||||
|                     $tempData[$outKey] = $tempData[$outKey] ?? [ | ||||
|                             'currency_id'             => $currency['currency_id'], | ||||
|                             'label'                   => (string) trans('firefly.box_spent_in_currency', ['currency' => $currency['currency_name']]), | ||||
|   | ||||
| @@ -37,14 +37,12 @@ use Illuminate\Http\JsonResponse; | ||||
|  */ | ||||
| class ConfigurationController extends Controller | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** @var UserRepositoryInterface The user repository */ | ||||
|     private $repository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * ConfigurationController constructor. | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
| @@ -73,24 +71,7 @@ class ConfigurationController extends Controller | ||||
|     { | ||||
|         $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 | ||||
|      */ | ||||
|     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'); | ||||
|         return response()->json(['data' => $configData])->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -116,4 +97,21 @@ class ConfigurationController extends Controller | ||||
|             'single_user_mode'        => null === $singleUser ? null : $singleUser->data, | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the configuration. | ||||
|      * | ||||
|      * @param ConfigurationRequest $request | ||||
|      * @param string               $name | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     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', self::CONTENT_TYPE); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -39,61 +39,32 @@ use Symfony\Component\HttpFoundation\ParameterBag; | ||||
|  * Class Controller. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  */ | ||||
| class Controller extends BaseController | ||||
| abstract class Controller extends BaseController | ||||
| { | ||||
|     use AuthorizesRequests, DispatchesJobs, ValidatesRequests; | ||||
|  | ||||
|     /** @var ParameterBag Parameters from the URI are stored here. */ | ||||
|     protected $parameters; | ||||
|     protected const CONTENT_TYPE = 'application/vnd.api+json'; | ||||
|     protected ParameterBag $parameters; | ||||
|  | ||||
|     /** | ||||
|      * Controller constructor. | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         // get global parameters | ||||
|         $this->parameters = $this->getParameters(); | ||||
|     } | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 if (auth()->check()) { | ||||
|                     $language = app('steam')->getLanguage(); | ||||
|                     app()->setLocale($language); | ||||
|                 } | ||||
|  | ||||
|     /** | ||||
|      * Method to help build URI's. | ||||
|      * | ||||
|      * @return string | ||||
|      * | ||||
|      */ | ||||
|     protected function buildParams(): string | ||||
|     { | ||||
|         $return = '?'; | ||||
|         $params = []; | ||||
|         foreach ($this->parameters as $key => $value) { | ||||
|             if ('page' === $key) { | ||||
|                 continue; | ||||
|                 return $next($request); | ||||
|             } | ||||
|             if ($value instanceof Carbon) { | ||||
|                 $params[$key] = $value->format('Y-m-d'); | ||||
|                 continue; | ||||
|             } | ||||
|             $params[$key] = $value; | ||||
|         } | ||||
|         $return .= http_build_query($params); | ||||
|         ); | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Manager | ||||
|      */ | ||||
|     protected function getManager(): Manager | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = request()->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         return $manager; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -104,7 +75,7 @@ class Controller extends BaseController | ||||
|     private function getParameters(): ParameterBag | ||||
|     { | ||||
|         $bag  = new ParameterBag; | ||||
|         $page = (int) request()->get('page'); | ||||
|         $page = (int)request()->get('page'); | ||||
|         if (0 === $page) { | ||||
|             $page = 1; | ||||
|         } | ||||
| @@ -131,11 +102,47 @@ class Controller extends BaseController | ||||
|         foreach ($integers as $integer) { | ||||
|             $value = request()->query->get($integer); | ||||
|             if (null !== $value) { | ||||
|                 $bag->set($integer, (int) $value); | ||||
|                 $bag->set($integer, (int)$value); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $bag; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Method to help build URI's. | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     final 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 $return . http_build_query($params); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Manager | ||||
|      */ | ||||
|     final protected function getManager(): Manager | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = request()->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         return $manager; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -21,7 +21,6 @@ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\CurrencyRequest; | ||||
| @@ -38,7 +37,6 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Bill\BillRepositoryInterface; | ||||
| use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface; | ||||
| use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface; | ||||
| use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; | ||||
| use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; | ||||
| use FireflyIII\Repositories\Rule\RuleRepositoryInterface; | ||||
| @@ -64,15 +62,14 @@ use League\Fractal\Resource\Item; | ||||
|  | ||||
| /** | ||||
|  * Class CurrencyController. | ||||
|  * | ||||
|  */ | ||||
| class CurrencyController extends Controller | ||||
| { | ||||
|     use AccountFilter, TransactionFilter; | ||||
|     /** @var CurrencyRepositoryInterface The currency repository */ | ||||
|     private $repository; | ||||
|     /** @var UserRepositoryInterface The user repository */ | ||||
|     private $userRepository; | ||||
|  | ||||
|     private CurrencyRepositoryInterface $repository; | ||||
|     private UserRepositoryInterface     $userRepository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * CurrencyRepository constructor. | ||||
| @@ -147,7 +144,7 @@ class CurrencyController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -160,22 +157,14 @@ class CurrencyController extends Controller | ||||
|      */ | ||||
|     public function availableBudgets(TransactionCurrency $currency): JsonResponse | ||||
|     { | ||||
|         /** @var User $admin */ | ||||
|         $admin = auth()->user(); | ||||
|  | ||||
|         $manager = $this->getManager(); | ||||
|         // 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); | ||||
|  | ||||
|         /** @var AvailableBudgetRepositoryInterface $abRepository */ | ||||
|         $abRepository = app(AvailableBudgetRepositoryInterface::class); | ||||
|  | ||||
|         $repository->setUser($admin); | ||||
|         $collection       = $abRepository->getAvailableBudgetsByCurrency($currency); | ||||
|         $count            = $collection->count(); | ||||
|         $availableBudgets = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
| @@ -192,7 +181,7 @@ class CurrencyController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -207,10 +196,10 @@ class CurrencyController extends Controller | ||||
|     { | ||||
|         $manager = $this->getManager(); | ||||
|  | ||||
|         /** @var BillRepositoryInterface $repository */ | ||||
|         $repository = app(BillRepositoryInterface::class); | ||||
|         /** @var BillRepositoryInterface $billRepos */ | ||||
|         $billRepos  = app(BillRepositoryInterface::class); | ||||
|         $pageSize   = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $unfiltered = $repository->getBills(); | ||||
|         $unfiltered = $billRepos->getBills(); | ||||
|  | ||||
|         // filter and paginate list: | ||||
|         $collection = $unfiltered->filter( | ||||
| @@ -232,7 +221,7 @@ class CurrencyController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -263,7 +252,7 @@ class CurrencyController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -294,7 +283,7 @@ class CurrencyController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -302,9 +291,9 @@ class CurrencyController extends Controller | ||||
|      * | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      * @codeCoverageIgnore | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(TransactionCurrency $currency): JsonResponse | ||||
|     { | ||||
| @@ -353,7 +342,7 @@ class CurrencyController extends Controller | ||||
|  | ||||
|         $resource = new Item($currency, $transformer, 'currencies'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -379,7 +368,7 @@ class CurrencyController extends Controller | ||||
|  | ||||
|         $resource = new Item($currency, $transformer, 'currencies'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -411,7 +400,7 @@ class CurrencyController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -439,7 +428,7 @@ class CurrencyController extends Controller | ||||
|  | ||||
|         $resource = new Item($currency, $transformer, 'currencies'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -458,9 +447,9 @@ class CurrencyController extends Controller | ||||
|         $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(); | ||||
|         /** @var RecurringRepositoryInterface $recurringRepos */ | ||||
|         $recurringRepos = app(RecurringRepositoryInterface::class); | ||||
|         $unfiltered     = $recurringRepos->getAll(); | ||||
|  | ||||
|         // filter selection | ||||
|         $collection = $unfiltered->filter( | ||||
| @@ -491,7 +480,7 @@ class CurrencyController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -509,9 +498,9 @@ class CurrencyController extends Controller | ||||
|         $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(); | ||||
|         /** @var RuleRepositoryInterface $ruleRepos */ | ||||
|         $ruleRepos  = app(RuleRepositoryInterface::class); | ||||
|         $unfiltered = $ruleRepos->getAll(); | ||||
|  | ||||
|         $collection = $unfiltered->filter( | ||||
|             static function (Rule $rule) use ($currency) { | ||||
| @@ -540,7 +529,7 @@ class CurrencyController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -564,7 +553,7 @@ class CurrencyController extends Controller | ||||
|  | ||||
|         $resource = new Item($currency, $transformer, 'currencies'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -578,14 +567,14 @@ class CurrencyController extends Controller | ||||
|         $manager  = $this->getManager(); | ||||
|         $currency = app('amount')->getDefaultCurrencyByUser(auth()->user()); | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -593,8 +582,8 @@ class CurrencyController extends Controller | ||||
|      * | ||||
|      * @param CurrencyRequest $request | ||||
|      * | ||||
|      * @throws FireflyException | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(CurrencyRequest $request): JsonResponse | ||||
|     { | ||||
| @@ -613,7 +602,7 @@ class CurrencyController extends Controller | ||||
|  | ||||
|         $resource = new Item($currency, $transformer, 'currencies'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -669,7 +658,7 @@ class CurrencyController extends Controller | ||||
|         $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 response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -701,7 +690,7 @@ class CurrencyController extends Controller | ||||
|  | ||||
|         $resource = new Item($currency, $transformer, 'currencies'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -43,9 +43,9 @@ class CurrencyExchangeRateController extends Controller | ||||
|     /** @var CurrencyRepositoryInterface The currency repository */ | ||||
|     private $repository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * CurrencyExchangeRateController constructor. | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
| @@ -69,8 +69,8 @@ class CurrencyExchangeRateController extends Controller | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @throws FireflyException | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
| @@ -107,6 +107,6 @@ class CurrencyExchangeRateController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -160,31 +160,6 @@ class DestroyController extends Controller | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $types | ||||
|      */ | ||||
|     private function destroyAccounts(array $types): void | ||||
|     { | ||||
|         /** @var AccountRepositoryInterface $repository */ | ||||
|         $repository = app(AccountRepositoryInterface::class); | ||||
|         $collection = $repository->getAccountsByType($types); | ||||
|         $service    = app(AccountDestroyService::class); | ||||
|         /** @var Account $account */ | ||||
|         foreach ($collection as $account) { | ||||
|             $service->destroy($account, null); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     private function destroyBills(): void | ||||
|     { | ||||
|         /** @var BillRepositoryInterface $repository */ | ||||
|         $repository = app(BillRepositoryInterface::class); | ||||
|         $repository->destroyAll(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
| @@ -206,18 +181,11 @@ class DestroyController extends Controller | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     private function destroyCategories(): void | ||||
|     private function destroyBills(): void | ||||
|     { | ||||
|         /** @var CategoryRepositoryInterface $categoryRepos */ | ||||
|         $categoryRepos = app(CategoryRepositoryInterface::class); | ||||
|         $categoryRepos->destroyAll(); | ||||
|     } | ||||
|  | ||||
|     private function destroyObjectGroups(): void | ||||
|     { | ||||
|         /** @var ObjectGroupRepositoryInterface $repository */ | ||||
|         $repository = app(ObjectGroupRepositoryInterface::class); | ||||
|         $repository->deleteAll(); | ||||
|         /** @var BillRepositoryInterface $repository */ | ||||
|         $repository = app(BillRepositoryInterface::class); | ||||
|         $repository->destroyAll(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -230,16 +198,6 @@ class DestroyController extends Controller | ||||
|         $repository->destroyAll(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     private function destroyRecurringTransactions(): void | ||||
|     { | ||||
|         /** @var RecurringRepositoryInterface $repository */ | ||||
|         $repository = app(RecurringRepositoryInterface::class); | ||||
|         $repository->destroyAll(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
| @@ -250,6 +208,26 @@ class DestroyController extends Controller | ||||
|         $repository->destroyAll(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     private function destroyRecurringTransactions(): void | ||||
|     { | ||||
|         /** @var RecurringRepositoryInterface $repository */ | ||||
|         $repository = app(RecurringRepositoryInterface::class); | ||||
|         $repository->destroyAll(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     private function destroyCategories(): void | ||||
|     { | ||||
|         /** @var CategoryRepositoryInterface $categoryRepos */ | ||||
|         $categoryRepos = app(CategoryRepositoryInterface::class); | ||||
|         $categoryRepos->destroyAll(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
| @@ -260,6 +238,28 @@ class DestroyController extends Controller | ||||
|         $tagRepository->destroyAll(); | ||||
|     } | ||||
|  | ||||
|     private function destroyObjectGroups(): void | ||||
|     { | ||||
|         /** @var ObjectGroupRepositoryInterface $repository */ | ||||
|         $repository = app(ObjectGroupRepositoryInterface::class); | ||||
|         $repository->deleteAll(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $types | ||||
|      */ | ||||
|     private function destroyAccounts(array $types): void | ||||
|     { | ||||
|         /** @var AccountRepositoryInterface $repository */ | ||||
|         $repository = app(AccountRepositoryInterface::class); | ||||
|         $collection = $repository->getAccountsByType($types); | ||||
|         $service    = app(AccountDestroyService::class); | ||||
|         /** @var Account $account */ | ||||
|         foreach ($collection as $account) { | ||||
|             $service->destroy($account, null); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $types | ||||
|      */ | ||||
| @@ -267,10 +267,10 @@ class DestroyController extends Controller | ||||
|     { | ||||
|         /** @var JournalRepositoryInterface $repository */ | ||||
|         $repository = app(JournalRepositoryInterface::class); | ||||
|         $journals = $repository->findByType($types); | ||||
|         $service = app(JournalDestroyService::class); | ||||
|         $journals   = $repository->findByType($types); | ||||
|         $service    = app(JournalDestroyService::class); | ||||
|         /** @var TransactionJournal $journal */ | ||||
|         foreach($journals as $journal) { | ||||
|         foreach ($journals as $journal) { | ||||
|             $service->destroy($journal); | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -42,17 +42,18 @@ use League\Fractal\Resource\Item; | ||||
|  | ||||
| /** | ||||
|  * Class LinkTypeController. | ||||
|  * | ||||
|  */ | ||||
| class LinkTypeController extends Controller | ||||
| { | ||||
|     use TransactionFilter; | ||||
|  | ||||
|     /** @var LinkTypeRepositoryInterface The link type repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** @var UserRepositoryInterface The user repository */ | ||||
|     private $userRepository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * LinkTypeController constructor. | ||||
|      * | ||||
| @@ -79,9 +80,9 @@ class LinkTypeController extends Controller | ||||
|      * | ||||
|      * @param LinkType $linkType | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      * @codeCoverageIgnore | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(LinkType $linkType): JsonResponse | ||||
|     { | ||||
| @@ -121,7 +122,7 @@ class LinkTypeController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -142,7 +143,7 @@ class LinkTypeController extends Controller | ||||
|  | ||||
|         $resource = new Item($linkType, $transformer, 'link_types'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -151,8 +152,8 @@ class LinkTypeController extends Controller | ||||
|      * | ||||
|      * @param LinkTypeRequest $request | ||||
|      * | ||||
|      * @throws FireflyException | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(LinkTypeRequest $request): JsonResponse | ||||
|     { | ||||
| @@ -172,7 +173,7 @@ class LinkTypeController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -231,7 +232,7 @@ class LinkTypeController extends Controller | ||||
|         $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 response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|  | ||||
| @@ -241,8 +242,8 @@ class LinkTypeController extends Controller | ||||
|      * @param LinkTypeRequest $request | ||||
|      * @param LinkType        $linkType | ||||
|      * | ||||
|      * @throws FireflyException | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function update(LinkTypeRequest $request, LinkType $linkType): JsonResponse | ||||
|     { | ||||
| @@ -266,7 +267,7 @@ class LinkTypeController extends Controller | ||||
|  | ||||
|         $resource = new Item($linkType, $transformer, 'link_types'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -39,12 +39,12 @@ use League\Fractal\Resource\Item; | ||||
|  | ||||
| /** | ||||
|  * Class GroupController. | ||||
|  * | ||||
|  */ | ||||
| class ObjectGroupController extends Controller | ||||
| { | ||||
|     private ObjectGroupRepositoryInterface $repository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * ObjectGroupController constructor. | ||||
|      * | ||||
| @@ -111,7 +111,7 @@ class ObjectGroupController extends Controller | ||||
|         $resource = new FractalCollection($objectGroups, $transformer, 'object_groups'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|  | ||||
| @@ -122,7 +122,6 @@ class ObjectGroupController extends Controller | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      */ | ||||
|     public function piggyBanks(ObjectGroup $objectGroup): JsonResponse | ||||
|     { | ||||
| @@ -148,7 +147,7 @@ class ObjectGroupController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -168,7 +167,7 @@ class ObjectGroupController extends Controller | ||||
|         $transformer->setParameters($this->parameters); | ||||
|         $resource = new Item($objectGroup, $transformer, 'object_groups'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -191,6 +190,6 @@ class ObjectGroupController extends Controller | ||||
|         $transformer->setParameters($this->parameters); | ||||
|         $resource = new Item($objectGroup, $transformer, 'object_groups'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -40,13 +40,10 @@ use League\Fractal\Resource\Item; | ||||
|  | ||||
| /** | ||||
|  * Class PiggyBankController. | ||||
|  * | ||||
|  */ | ||||
| class PiggyBankController extends Controller | ||||
| { | ||||
|  | ||||
|     /** @var PiggyBankRepositoryInterface The piggy bank repository */ | ||||
|     private $repository; | ||||
|     private PiggyBankRepositoryInterface $repository; | ||||
|  | ||||
|     /** | ||||
|      * PiggyBankController constructor. | ||||
| @@ -112,7 +109,7 @@ class PiggyBankController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -143,7 +140,7 @@ class PiggyBankController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -176,7 +173,7 @@ class PiggyBankController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -198,7 +195,7 @@ class PiggyBankController extends Controller | ||||
|  | ||||
|         $resource = new Item($piggyBank, $transformer, 'piggy_banks'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -207,8 +204,8 @@ class PiggyBankController extends Controller | ||||
|      * | ||||
|      * @param PiggyBankStoreRequest $request | ||||
|      * | ||||
|      * @throws FireflyException | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(PiggyBankStoreRequest $request): JsonResponse | ||||
|     { | ||||
| @@ -221,7 +218,7 @@ class PiggyBankController extends Controller | ||||
|  | ||||
|         $resource = new Item($piggyBank, $transformer, 'piggy_banks'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -248,7 +245,7 @@ class PiggyBankController extends Controller | ||||
|  | ||||
|         $resource = new Item($piggyBank, $transformer, 'piggy_banks'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -35,7 +35,6 @@ use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * Class PreferenceController | ||||
|  */ | ||||
| class PreferenceController extends Controller | ||||
| @@ -102,7 +101,7 @@ class PreferenceController extends Controller | ||||
|  | ||||
|         $resource = new FractalCollection($preferences, $transformer, 'preferences'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -123,7 +122,7 @@ class PreferenceController extends Controller | ||||
|  | ||||
|         $resource = new Item($preference, $transformer, 'preferences'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -162,7 +161,7 @@ class PreferenceController extends Controller | ||||
|  | ||||
|         $resource = new Item($result, $transformer, 'preferences'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -48,9 +48,11 @@ use Log; | ||||
| class RecurrenceController extends Controller | ||||
| { | ||||
|     use TransactionFilter; | ||||
|  | ||||
|     /** @var RecurringRepositoryInterface The recurring transaction repository */ | ||||
|     private $repository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * RecurrenceController constructor. | ||||
|      * | ||||
| @@ -117,7 +119,7 @@ class RecurrenceController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -139,7 +141,7 @@ class RecurrenceController extends Controller | ||||
|  | ||||
|         $resource = new Item($recurrence, $transformer, 'recurrences'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|  | ||||
|     } | ||||
| @@ -149,8 +151,8 @@ class RecurrenceController extends Controller | ||||
|      * | ||||
|      * @param RecurrenceStoreRequest $request | ||||
|      * | ||||
|      * @throws FireflyException | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(RecurrenceStoreRequest $request): JsonResponse | ||||
|     { | ||||
| @@ -164,7 +166,7 @@ class RecurrenceController extends Controller | ||||
|  | ||||
|         $resource = new Item($recurrence, $transformer, 'recurrences'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -220,13 +222,13 @@ class RecurrenceController extends Controller | ||||
|         $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 response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      * @codeCoverageIgnore | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function trigger(): JsonResponse | ||||
|     { | ||||
| @@ -236,7 +238,7 @@ class RecurrenceController extends Controller | ||||
|             $result = $recurring->fire(); | ||||
|         } catch (FireflyException $e) { | ||||
|             Log::error($e->getMessage()); | ||||
|             throw new FireflyException('200022: Error in cron job.'); | ||||
|             throw new FireflyException('200022: Error in cron job.', 0, $e); | ||||
|         } | ||||
|         if (false === $result) { | ||||
|             return response()->json([], 204); | ||||
| @@ -268,7 +270,7 @@ class RecurrenceController extends Controller | ||||
|  | ||||
|         $resource = new Item($category, $transformer, 'recurrences'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -28,33 +28,32 @@ use FireflyIII\Api\V1\Requests\RuleTestRequest; | ||||
| use FireflyIII\Api\V1\Requests\RuleTriggerRequest; | ||||
| use FireflyIII\Api\V1\Requests\RuleUpdateRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Models\Rule; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Rule\RuleRepositoryInterface; | ||||
| use FireflyIII\TransactionRules\Engine\RuleEngine; | ||||
| use FireflyIII\TransactionRules\TransactionMatcher; | ||||
| use FireflyIII\TransactionRules\Engine\RuleEngineInterface; | ||||
| use FireflyIII\Transformers\RuleTransformer; | ||||
| use FireflyIII\Transformers\TransactionGroupTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use Illuminate\Support\Collection; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class RuleController | ||||
|  * | ||||
|  */ | ||||
| class RuleController extends Controller | ||||
| { | ||||
|     /** @var AccountRepositoryInterface Account repository */ | ||||
|     private $accountRepository; | ||||
|  | ||||
|     /** @var RuleRepositoryInterface The rule repository */ | ||||
|     private $ruleRepository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * RuleController constructor. | ||||
|      * | ||||
| @@ -123,7 +122,7 @@ class RuleController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -144,7 +143,7 @@ class RuleController extends Controller | ||||
|  | ||||
|         $resource = new Item($rule, $transformer, 'rules'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -165,7 +164,7 @@ class RuleController extends Controller | ||||
|  | ||||
|         $resource = new Item($rule, $transformer, 'rules'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -186,7 +185,7 @@ class RuleController extends Controller | ||||
|  | ||||
|         $resource = new Item($rule, $transformer, 'rules'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -207,36 +206,44 @@ class RuleController extends Controller | ||||
|  | ||||
|         $resource = new Item($rule, $transformer, 'rules'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param RuleTestRequest $request | ||||
|      * @param Rule            $rule | ||||
|      * | ||||
|      * @throws FireflyException | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function testRule(RuleTestRequest $request, Rule $rule): JsonResponse | ||||
|     { | ||||
|         $pageSize   = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $parameters = $request->getTestParameters(); | ||||
|         /** @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($parameters['start_date']); | ||||
|         $matcher->setEndDate($parameters['end_date']); | ||||
|         $matcher->setSearchLimit($parameters['search_limit']); | ||||
|         $matcher->setTriggeredLimit($parameters['trigger_limit']); | ||||
|         $matcher->setAccounts($parameters['accounts']); | ||||
|  | ||||
|         $matchingTransactions = $matcher->findTransactionsByRule(); | ||||
|         $count                = count($matchingTransactions); | ||||
|         $transactions         = array_slice($matchingTransactions, ($parameters['page'] - 1) * $pageSize, $pageSize); | ||||
|         $paginator            = new LengthAwarePaginator($transactions, $count, $pageSize, $this->parameters->get('page')); | ||||
|         /** @var RuleEngineInterface $ruleEngine */ | ||||
|         $ruleEngine = app(RuleEngineInterface::class); | ||||
|         $ruleEngine->setRules(new Collection([$rule])); | ||||
|  | ||||
|  | ||||
|         // overrule the rule(s) if necessary. | ||||
|         if (array_key_exists('start', $parameters) && null !== $parameters['start']) { | ||||
|             // add a range: | ||||
|             $ruleEngine->addOperator(['type' => 'date_after', 'value' => $parameters['start']->format('Y-m-d')]); | ||||
|         } | ||||
|  | ||||
|         if (array_key_exists('end', $parameters) && null !== $parameters['end']) { | ||||
|             // add a range: | ||||
|             $ruleEngine->addOperator(['type' => 'date_before', 'value' => $parameters['end']->format('Y-m-d')]); | ||||
|         } | ||||
|         if (array_key_exists('accounts', $parameters) && '' !== $parameters['accounts']) { | ||||
|             $ruleEngine->addOperator(['type' => 'account_id', 'value' => $parameters['accounts']]); | ||||
|         } | ||||
|  | ||||
|         // file the rule(s) | ||||
|         $transactions = $ruleEngine->find(); | ||||
|         $count        = $transactions->count(); | ||||
|  | ||||
|         $paginator = new LengthAwarePaginator($transactions, $count, 31337, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.rules.test', [$rule->id]) . $this->buildParams()); | ||||
|  | ||||
|         // resulting list is presented as JSON thing. | ||||
| @@ -245,10 +252,10 @@ class RuleController extends Controller | ||||
|         $transformer = app(TransactionGroupTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($matchingTransactions, $transformer, 'transactions'); | ||||
|         $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 response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -264,28 +271,27 @@ class RuleController extends Controller | ||||
|         // Get parameters specified by the user | ||||
|         $parameters = $request->getTriggerParameters(); | ||||
|  | ||||
|         /** @var RuleEngine $ruleEngine */ | ||||
|         $ruleEngine = app(RuleEngine::class); | ||||
|         $ruleEngine->setUser(auth()->user()); | ||||
|         /** @var RuleEngineInterface $ruleEngine */ | ||||
|         $ruleEngine = app(RuleEngineInterface::class); | ||||
|         $ruleEngine->setRules(new Collection([$rule])); | ||||
|  | ||||
|         $rules = [$rule->id]; | ||||
|  | ||||
|         $ruleEngine->setRulesToApply($rules); | ||||
|         $ruleEngine->setTriggerMode(RuleEngine::TRIGGER_STORE); | ||||
|  | ||||
|         /** @var GroupCollectorInterface $collector */ | ||||
|         $collector = app(GroupCollectorInterface::class); | ||||
|         $collector->setAccounts($parameters['accounts']); | ||||
|         $collector->setRange($parameters['start_date'], $parameters['end_date']); | ||||
|         $journals = $collector->getExtractedJournals(); | ||||
|  | ||||
|         /** @var array $journal */ | ||||
|         foreach ($journals as $journal) { | ||||
|             Log::debug('Start of new journal.'); | ||||
|             $ruleEngine->processJournalArray($journal); | ||||
|             Log::debug('Done with all rules for this group + done with journal.'); | ||||
|         // overrule the rule(s) if necessary. | ||||
|         if (array_key_exists('start', $parameters) && null !== $parameters['start']) { | ||||
|             // add a range: | ||||
|             $ruleEngine->addOperator(['type' => 'date_after', 'value' => $parameters['start']->format('Y-m-d')]); | ||||
|         } | ||||
|  | ||||
|         if (array_key_exists('end', $parameters) && null !== $parameters['end']) { | ||||
|             // add a range: | ||||
|             $ruleEngine->addOperator(['type' => 'date_before', 'value' => $parameters['end']->format('Y-m-d')]); | ||||
|         } | ||||
|         if (array_key_exists('accounts', $parameters) && '' !== $parameters['accounts']) { | ||||
|             $ruleEngine->addOperator(['type' => 'account_id', 'value' => $parameters['accounts']]); | ||||
|         } | ||||
|  | ||||
|         // file the rule(s) | ||||
|         $ruleEngine->fire(); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
| @@ -309,6 +315,6 @@ class RuleController extends Controller | ||||
|  | ||||
|         $resource = new Item($rule, $transformer, 'rules'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -28,13 +28,10 @@ use FireflyIII\Api\V1\Requests\RuleGroupRequest; | ||||
| use FireflyIII\Api\V1\Requests\RuleGroupTestRequest; | ||||
| use FireflyIII\Api\V1\Requests\RuleGroupTriggerRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| use FireflyIII\Models\Rule; | ||||
| use FireflyIII\Models\RuleGroup; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface; | ||||
| use FireflyIII\TransactionRules\Engine\RuleEngine; | ||||
| use FireflyIII\TransactionRules\TransactionMatcher; | ||||
| use FireflyIII\TransactionRules\Engine\RuleEngineInterface; | ||||
| use FireflyIII\Transformers\RuleGroupTransformer; | ||||
| use FireflyIII\Transformers\RuleTransformer; | ||||
| use FireflyIII\Transformers\TransactionGroupTransformer; | ||||
| @@ -45,7 +42,6 @@ use Illuminate\Support\Collection; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class RuleGroupController | ||||
| @@ -54,9 +50,11 @@ class RuleGroupController extends Controller | ||||
| { | ||||
|     /** @var AccountRepositoryInterface Account repository */ | ||||
|     private $accountRepository; | ||||
|  | ||||
|     /** @var RuleGroupRepositoryInterface The rule group repository */ | ||||
|     private $ruleGroupRepository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * RuleGroupController constructor. | ||||
|      * | ||||
| @@ -124,7 +122,7 @@ class RuleGroupController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -144,7 +142,7 @@ class RuleGroupController extends Controller | ||||
|  | ||||
|         $resource = new Item($ruleGroup, $transformer, 'rule_groups'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -164,7 +162,7 @@ class RuleGroupController extends Controller | ||||
|  | ||||
|         $resource = new Item($ruleGroup, $transformer, 'rule_groups'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -195,7 +193,7 @@ class RuleGroupController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -216,7 +214,7 @@ class RuleGroupController extends Controller | ||||
|  | ||||
|         $resource = new Item($ruleGroup, $transformer, 'rule_groups'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -238,7 +236,7 @@ class RuleGroupController extends Controller | ||||
|  | ||||
|         $resource = new Item($ruleGroup, $transformer, 'rule_groups'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -246,57 +244,54 @@ class RuleGroupController extends Controller | ||||
|      * @param RuleGroupTestRequest $request | ||||
|      * @param RuleGroup            $group | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function testGroup(RuleGroupTestRequest $request, RuleGroup $group): JsonResponse | ||||
|     { | ||||
|         $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         Log::debug('Now in testGroup()'); | ||||
|         /** @var Collection $rules */ | ||||
|         $rules = $this->ruleGroupRepository->getActiveRules($group); | ||||
|         if (0 === $rules->count()) { | ||||
|             throw new FireflyException('200023: No rules in this rule group.'); | ||||
|         } | ||||
|         $parameters           = $request->getTestParameters(); | ||||
|         $matchingTransactions = []; | ||||
|         $parameters = $request->getTestParameters(); | ||||
|  | ||||
|         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($parameters['accounts']); | ||||
|         /** @var RuleEngineInterface $ruleEngine */ | ||||
|         $ruleEngine = app(RuleEngineInterface::class); | ||||
|         $ruleEngine->setRules($rules); | ||||
|  | ||||
|             $result = $matcher->findTransactionsByRule(); | ||||
|             /** @noinspection AdditionOperationOnArraysInspection */ | ||||
|             $matchingTransactions = $result + $matchingTransactions; | ||||
|         // overrule the rule(s) if necessary. | ||||
|         if (array_key_exists('start', $parameters) && null !== $parameters['start']) { | ||||
|             // add a range: | ||||
|             $ruleEngine->addOperator(['type' => 'date_after', 'value' => $parameters['start']->format('Y-m-d')]); | ||||
|         } | ||||
|  | ||||
|         // make paginator out of results. | ||||
|         $count        = count($matchingTransactions); | ||||
|         $transactions = array_slice($matchingTransactions, ($parameters['page'] - 1) * $pageSize, $pageSize); | ||||
|         if (array_key_exists('end', $parameters) && null !== $parameters['end']) { | ||||
|             // add a range: | ||||
|             $ruleEngine->addOperator(['type' => 'date_before', 'value' => $parameters['end']->format('Y-m-d')]); | ||||
|         } | ||||
|         if (array_key_exists('accounts', $parameters) && '' !== $parameters['accounts']) { | ||||
|             $ruleEngine->addOperator(['type' => 'account_id', 'value' => $parameters['accounts']]); | ||||
|         } | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($transactions, $count, $pageSize, $parameters['page']); | ||||
|         // file the rule(s) | ||||
|         $transactions = $ruleEngine->find(); | ||||
|         $count        = $transactions->count(); | ||||
|  | ||||
|         $paginator = new LengthAwarePaginator($transactions, $count, 31337, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.rule_groups.test', [$group->id]) . $this->buildParams()); | ||||
|  | ||||
|         $manager     = $this->getManager(); | ||||
|         // resulting list is presented as JSON thing. | ||||
|         $manager = $this->getManager(); | ||||
|         /** @var TransactionGroupTransformer $transformer */ | ||||
|         $transformer = app(TransactionGroupTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($matchingTransactions, $transformer, 'transactions'); | ||||
|         $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 response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -305,40 +300,40 @@ class RuleGroupController extends Controller | ||||
|      * @param RuleGroupTriggerRequest $request | ||||
|      * @param RuleGroup               $group | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * @return JsonResponse | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function triggerGroup(RuleGroupTriggerRequest $request, RuleGroup $group): JsonResponse | ||||
|     { | ||||
|         /** @var Collection $rules */ | ||||
|         $rules = $this->ruleGroupRepository->getActiveRules($group); | ||||
|         if (0 === $rules->count()) { | ||||
|             throw new FireflyException('200023: No rules in this rule group.'); | ||||
|         } | ||||
|  | ||||
|         // Get parameters specified by the user | ||||
|         $parameters = $request->getTriggerParameters(); | ||||
|  | ||||
|         /** @var Collection $collection */ | ||||
|         $collection = $this->ruleGroupRepository->getActiveRules($group); | ||||
|         $rules      = []; | ||||
|         /** @var Rule $item */ | ||||
|         foreach ($collection as $item) { | ||||
|             $rules[] = $item->id; | ||||
|         /** @var RuleEngineInterface $ruleEngine */ | ||||
|         $ruleEngine = app(RuleEngineInterface::class); | ||||
|         $ruleEngine->setRules($rules); | ||||
|  | ||||
|         // overrule the rule(s) if necessary. | ||||
|         if (array_key_exists('start', $parameters) && null !== $parameters['start']) { | ||||
|             // add a range: | ||||
|             $ruleEngine->addOperator(['type' => 'date_after', 'value' => $parameters['start']->format('Y-m-d')]); | ||||
|         } | ||||
|  | ||||
|         // start looping. | ||||
|         /** @var RuleEngine $ruleEngine */ | ||||
|         $ruleEngine = app(RuleEngine::class); | ||||
|         $ruleEngine->setUser(auth()->user()); | ||||
|         $ruleEngine->setRulesToApply($rules); | ||||
|         $ruleEngine->setTriggerMode(RuleEngine::TRIGGER_STORE); | ||||
|  | ||||
|         /** @var GroupCollectorInterface $collector */ | ||||
|         $collector = app(GroupCollectorInterface::class); | ||||
|         $collector->setAccounts($parameters['accounts']); | ||||
|         $collector->setRange($parameters['start_date'], $parameters['end_date']); | ||||
|         $journals = $collector->getExtractedJournals(); | ||||
|  | ||||
|         /** @var array $journal */ | ||||
|         foreach ($journals as $journal) { | ||||
|             Log::debug('Start of new journal.'); | ||||
|             $ruleEngine->processJournalArray($journal); | ||||
|             Log::debug('Done with all rules for this group + done with journal.'); | ||||
|         if (array_key_exists('end', $parameters) && null !== $parameters['end']) { | ||||
|             // add a range: | ||||
|             $ruleEngine->addOperator(['type' => 'date_before', 'value' => $parameters['end']->format('Y-m-d')]); | ||||
|         } | ||||
|         if (array_key_exists('accounts', $parameters) && '' !== $parameters['accounts']) { | ||||
|             $ruleEngine->addOperator(['type' => 'account_id', 'value' => $parameters['accounts']]); | ||||
|         } | ||||
|  | ||||
|         // file the rule(s) | ||||
|         $ruleEngine->fire(); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
| @@ -362,6 +357,6 @@ class RuleGroupController extends Controller | ||||
|  | ||||
|         $resource = new Item($ruleGroup, $transformer, 'rule_groups'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -45,6 +45,7 @@ class AccountController extends Controller | ||||
|  | ||||
|     private array $validFields; | ||||
|  | ||||
|  | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
| @@ -96,6 +97,6 @@ class AccountController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -45,7 +45,7 @@ class TransactionController extends Controller | ||||
|      */ | ||||
|     public function search(Request $request, SearchInterface $searcher): JsonResponse | ||||
|     { | ||||
|         $manager = $this->getManager(); | ||||
|         $manager   = $this->getManager(); | ||||
|         $fullQuery = (string) $request->get('query'); | ||||
|         $page      = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page'); | ||||
|  | ||||
| @@ -65,6 +65,6 @@ class TransactionController extends Controller | ||||
|         $resource = new Collection($transactions, $transformer, 'transactions'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($groups)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -49,18 +49,23 @@ class SummaryController extends Controller | ||||
| { | ||||
|     /** @var AvailableBudgetRepositoryInterface */ | ||||
|     private $abRepository; | ||||
|  | ||||
|     /** @var AccountRepositoryInterface */ | ||||
|     private $accountRepository; | ||||
|  | ||||
|     /** @var BillRepositoryInterface */ | ||||
|     private $billRepository; | ||||
|  | ||||
|     /** @var BudgetRepositoryInterface */ | ||||
|     private $budgetRepository; | ||||
|  | ||||
|     /** @var CurrencyRepositoryInterface */ | ||||
|     private $currencyRepos; | ||||
|  | ||||
|     /** @var OperationsRepositoryInterface */ | ||||
|     private $opsRepository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * SummaryController constructor. | ||||
|      * | ||||
| @@ -96,8 +101,8 @@ class SummaryController extends Controller | ||||
|     /** | ||||
|      * @param DateRequest $request | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * @return JsonResponse | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function basic(DateRequest $request): JsonResponse | ||||
|     { | ||||
| @@ -125,30 +130,6 @@ class SummaryController extends Controller | ||||
|         return response()->json($return); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Check if date is outside session range. | ||||
|      * | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     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; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
| @@ -317,13 +298,13 @@ class SummaryController extends Controller | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @throws Exception | ||||
|      * @return array | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     private function getLeftToSpendInfo(Carbon $start, Carbon $end): array | ||||
|     { | ||||
|         $return    = []; | ||||
|         $today     = new Carbon; | ||||
|         $today     = today(config('app.timezone')); | ||||
|         $available = $this->abRepository->getAvailableBudgetWithCurrency($start, $end); | ||||
|         $budgets   = $this->budgetRepository->getActiveBudgets(); | ||||
|         $spent     = $this->opsRepository->sumExpenses($start, $end, null, $budgets); | ||||
| @@ -424,4 +405,28 @@ class SummaryController extends Controller | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Check if date is outside session range. | ||||
|      * | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     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; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -23,8 +23,6 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Api\V1\Requests\DateRequest; | ||||
| use FireflyIII\Api\V1\Requests\TagStoreRequest; | ||||
| use FireflyIII\Api\V1\Requests\TagUpdateRequest; | ||||
| use FireflyIII\Helpers\Collector\GroupCollectorInterface; | ||||
| @@ -38,7 +36,6 @@ use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use Illuminate\Support\Collection; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| @@ -53,6 +50,7 @@ class TagController extends Controller | ||||
|     /** @var TagRepositoryInterface The tag repository */ | ||||
|     private $repository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * TagController constructor. | ||||
|      * | ||||
| @@ -74,25 +72,6 @@ class TagController extends Controller | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param DateRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function cloud(DateRequest $request): JsonResponse | ||||
|     { | ||||
|         // parameters for boxes: | ||||
|         $dates = $request->getAll(); | ||||
|         $start = $dates['start']; | ||||
|         $end   = $dates['end']; | ||||
|  | ||||
|         // get all tags: | ||||
|         $tags  = $this->repository->get(); | ||||
|         $cloud = $this->getTagCloud($tags, $start, $end); | ||||
|  | ||||
|         return response()->json($cloud); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Delete the resource. | ||||
|      * | ||||
| @@ -136,7 +115,7 @@ class TagController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|  | ||||
| @@ -166,7 +145,7 @@ class TagController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -186,7 +165,7 @@ class TagController extends Controller | ||||
|  | ||||
|         $resource = new Item($tag, $transformer, 'tags'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -207,7 +186,7 @@ class TagController extends Controller | ||||
|  | ||||
|         $resource = new Item($rule, $transformer, 'tags'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -260,7 +239,7 @@ class TagController extends Controller | ||||
|         $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 response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -281,59 +260,7 @@ class TagController extends Controller | ||||
|  | ||||
|         $resource = new Item($rule, $transformer, 'tags'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $cloud | ||||
|      * @param float $min | ||||
|      * @param float $max | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function analyseTagCloud(array $cloud, float $min, float $max): array | ||||
|     { | ||||
|         foreach (array_keys($cloud['tags']) as $index) { | ||||
|             $cloud['tags'][$index]['relative'] = round($cloud['tags'][$index]['size'] / $max, 4); | ||||
|         } | ||||
|         $cloud['min'] = $min; | ||||
|         $cloud['max'] = $max; | ||||
|  | ||||
|         return $cloud; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $tags | ||||
|      * @param Carbon     $start | ||||
|      * @param Carbon     $end | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getTagCloud(Collection $tags, Carbon $start, Carbon $end): array | ||||
|     { | ||||
|         $min   = null; | ||||
|         $max   = 0; | ||||
|         $cloud = [ | ||||
|             '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; | ||||
|                 $cloud['tags'][] = [ | ||||
|                     'tag'  => $tag->tag, | ||||
|                     'id'   => $tag->id, | ||||
|                     'size' => $size, | ||||
|                 ]; | ||||
|             } | ||||
|         } | ||||
|         $cloud = $this->analyseTagCloud($cloud, $min, $max); | ||||
|  | ||||
|         return $cloud; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -40,6 +40,7 @@ use FireflyIII\Support\Http\Api\TransactionFilter; | ||||
| use FireflyIII\Transformers\AttachmentTransformer; | ||||
| use FireflyIII\Transformers\PiggyBankEventTransformer; | ||||
| use FireflyIII\Transformers\TransactionGroupTransformer; | ||||
| use FireflyIII\Transformers\TransactionLinkTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| @@ -57,12 +58,10 @@ class TransactionController extends Controller | ||||
| { | ||||
|     use TransactionFilter; | ||||
|  | ||||
|     /** @var TransactionGroupRepositoryInterface Group repository. */ | ||||
|     private $groupRepository; | ||||
|     /** @var JournalAPIRepositoryInterface Journal API repos */ | ||||
|     private $journalAPIRepository; | ||||
|     /** @var JournalRepositoryInterface The journal repository */ | ||||
|     private $repository; | ||||
|     private TransactionGroupRepositoryInterface $groupRepository; | ||||
|     private JournalAPIRepositoryInterface       $journalAPIRepository; | ||||
|     private JournalRepositoryInterface          $repository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * TransactionController constructor. | ||||
| @@ -109,7 +108,27 @@ class TransactionController extends Controller | ||||
|  | ||||
|         $resource = new FractalCollection($attachments, $transformer, 'attachments'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $transactionJournal | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @codeCoverageIgnore | ||||
|      */ | ||||
|     public function transactionLinks(TransactionJournal $transactionJournal): JsonResponse | ||||
|     { | ||||
|         $manager      = $this->getManager(); | ||||
|         $journalLinks = $this->journalAPIRepository->getJournalLinks($transactionJournal); | ||||
|  | ||||
|         /** @var TransactionLinkTransformer $transformer */ | ||||
|         $transformer = app(TransactionLinkTransformer::class); | ||||
|         $transformer->setParameters($this->parameters); | ||||
|  | ||||
|         $resource = new FractalCollection($journalLinks, $transformer, 'transaction_links'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -190,7 +209,7 @@ class TransactionController extends Controller | ||||
|         $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 response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -213,7 +232,20 @@ class TransactionController extends Controller | ||||
|  | ||||
|         $resource = new FractalCollection($events, $transformer, 'piggy_bank_events'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show a single transaction, by transaction journal. | ||||
|      * | ||||
|      * @param TransactionJournal $transactionJournal | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @codeCoverageIgnore | ||||
|      */ | ||||
|     public function showByJournal(TransactionJournal $transactionJournal): JsonResponse | ||||
|     { | ||||
|         return $this->show($transactionJournal->transactionGroup); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -248,20 +280,7 @@ class TransactionController extends Controller | ||||
|         $transformer->setParameters($this->parameters); | ||||
|         $resource = new Item($selectedGroup, $transformer, 'transactions'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show a single transaction, by transaction journal. | ||||
|      * | ||||
|      * @param TransactionJournal $transactionJournal | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @codeCoverageIgnore | ||||
|      */ | ||||
|     public function showByJournal(TransactionJournal $transactionJournal): JsonResponse | ||||
|     { | ||||
|         return $this->show($transactionJournal->transactionGroup); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -269,8 +288,8 @@ class TransactionController extends Controller | ||||
|      * | ||||
|      * @param TransactionStoreRequest $request | ||||
|      * | ||||
|      * @throws FireflyException | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(TransactionStoreRequest $request): JsonResponse | ||||
|     { | ||||
| @@ -334,7 +353,7 @@ class TransactionController extends Controller | ||||
|         $transformer->setParameters($this->parameters); | ||||
|         $resource = new Item($selectedGroup, $transformer, 'transactions'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|  | ||||
| @@ -377,6 +396,6 @@ class TransactionController extends Controller | ||||
|         $transformer->setParameters($this->parameters); | ||||
|         $resource = new Item($selectedGroup, $transformer, 'transactions'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -47,9 +47,11 @@ class TransactionLinkController extends Controller | ||||
|  | ||||
|     /** @var JournalRepositoryInterface The journal repository */ | ||||
|     private $journalRepository; | ||||
|  | ||||
|     /** @var LinkTypeRepositoryInterface The link type repository */ | ||||
|     private $repository; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * TransactionLinkController constructor. | ||||
|      * | ||||
| @@ -124,7 +126,7 @@ class TransactionLinkController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -146,7 +148,7 @@ class TransactionLinkController extends Controller | ||||
|  | ||||
|         $resource = new Item($journalLink, $transformer, 'transaction_links'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -155,8 +157,8 @@ class TransactionLinkController extends Controller | ||||
|      * | ||||
|      * @param TransactionLinkRequest $request | ||||
|      * | ||||
|      * @throws FireflyException | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(TransactionLinkRequest $request): JsonResponse | ||||
|     { | ||||
| @@ -177,7 +179,7 @@ class TransactionLinkController extends Controller | ||||
|  | ||||
|         $resource = new Item($journalLink, $transformer, 'transaction_links'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -186,8 +188,8 @@ class TransactionLinkController extends Controller | ||||
|      * @param TransactionLinkRequest $request | ||||
|      * @param TransactionJournalLink $journalLink | ||||
|      * | ||||
|      * @throws FireflyException | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function update(TransactionLinkRequest $request, TransactionJournalLink $journalLink): JsonResponse | ||||
|     { | ||||
| @@ -207,7 +209,7 @@ class TransactionLinkController extends Controller | ||||
|  | ||||
|         $resource = new Item($journalLink, $transformer, 'transaction_links'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -39,13 +39,11 @@ use League\Fractal\Resource\Item; | ||||
|  | ||||
| /** | ||||
|  * Class UserController. | ||||
|  * | ||||
|  */ | ||||
| class UserController extends Controller | ||||
| { | ||||
|     private UserRepositoryInterface $repository; | ||||
|  | ||||
|     /** @var UserRepositoryInterface The user repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * UserController constructor. | ||||
| @@ -70,9 +68,9 @@ class UserController extends Controller | ||||
|      * | ||||
|      * @param User $user | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      * @codeCoverageIgnore | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(User $user): JsonResponse | ||||
|     { | ||||
| @@ -115,7 +113,7 @@ class UserController extends Controller | ||||
|         $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'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -137,7 +135,7 @@ class UserController extends Controller | ||||
|  | ||||
|         $resource = new Item($user, $transformer, 'users'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -161,7 +159,7 @@ class UserController extends Controller | ||||
|  | ||||
|         $resource = new Item($user, $transformer, 'users'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -184,7 +182,7 @@ class UserController extends Controller | ||||
|  | ||||
|         $resource = new Item($user, $transformer, 'users'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); | ||||
|  | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -23,7 +23,6 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Api\V1\Middleware; | ||||
|  | ||||
| use Closure; | ||||
| use FireflyIII\Repositories\User\UserRepositoryInterface; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| @@ -48,12 +47,9 @@ class ApiDemoUser | ||||
|         if (null === $user) { | ||||
|             return $next($request); | ||||
|         } | ||||
|  | ||||
|         /** @var UserRepositoryInterface $repository */ | ||||
|         $repository = app(UserRepositoryInterface::class); | ||||
|  | ||||
|         if ($repository->hasRole($user, 'demo')) { | ||||
|         if ($user->hasRole('demo')) { | ||||
|             return response('', 403); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return $next($request); | ||||
|   | ||||
| @@ -26,14 +26,18 @@ namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Models\Location; | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
| use FireflyIII\Support\Request\AppendsLocationData; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
| /** | ||||
|  * Class AccountStoreRequest | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class AccountStoreRequest extends Request | ||||
| class AccountStoreRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes, AppendsLocationData; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
| @@ -66,6 +70,7 @@ class AccountStoreRequest extends Request | ||||
|             'account_type'            => $this->string('type'), | ||||
|             'account_type_id'         => null, | ||||
|             'currency_id'             => $this->integer('currency_id'), | ||||
|             'order'                   => $this->integer('order'), | ||||
|             'currency_code'           => $this->string('currency_code'), | ||||
|             'virtual_balance'         => $this->string('virtual_balance'), | ||||
|             'iban'                    => $this->string('iban'), | ||||
| @@ -75,7 +80,7 @@ class AccountStoreRequest extends Request | ||||
|             'opening_balance'         => $this->string('opening_balance'), | ||||
|             'opening_balance_date'    => $this->date('opening_balance_date'), | ||||
|             'cc_type'                 => $this->string('credit_card_type'), | ||||
|             'cc_Monthly_payment_date' => $this->string('monthly_payment_date'), | ||||
|             'cc_monthly_payment_date' => $this->string('monthly_payment_date'), | ||||
|             'notes'                   => $this->nlString('notes'), | ||||
|             'interest'                => $this->string('interest'), | ||||
|             'interest_period'         => $this->string('interest_period'), | ||||
| @@ -112,6 +117,7 @@ class AccountStoreRequest extends Request | ||||
|             'opening_balance'      => 'numeric|required_with:opening_balance_date|nullable', | ||||
|             'opening_balance_date' => 'date|required_with:opening_balance|nullable', | ||||
|             'virtual_balance'      => 'numeric|nullable', | ||||
|             'order'                => 'numeric|nullable', | ||||
|             'currency_id'          => 'numeric|exists:transaction_currencies,id', | ||||
|             'currency_code'        => 'min:3|max:3|exists:transaction_currencies,code', | ||||
|             'active'               => [new IsBoolean], | ||||
| @@ -126,8 +132,6 @@ class AccountStoreRequest extends Request | ||||
|             'interest_period'      => 'required_if:type,liability|in:daily,monthly,yearly', | ||||
|             'notes'                => 'min:0|max:65536', | ||||
|         ]; | ||||
|         $rules          = Location::requestRules($rules); | ||||
|  | ||||
|         return $rules; | ||||
|         return Location::requestRules($rules); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -26,14 +26,18 @@ namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Models\Location; | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
| use FireflyIII\Support\Request\AppendsLocationData; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
| /** | ||||
|  * Class AccountUpdateRequest | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class AccountUpdateRequest extends Request | ||||
| class AccountUpdateRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes, AppendsLocationData; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
| @@ -66,6 +70,7 @@ class AccountUpdateRequest extends Request | ||||
|             'account_type'            => $this->nullableString('type'), | ||||
|             'account_type_id'         => null, | ||||
|             'currency_id'             => $this->nullableInteger('currency_id'), | ||||
|             'order'                   => $this->integer('order'), | ||||
|             'currency_code'           => $this->nullableString('currency_code'), | ||||
|             'virtual_balance'         => $this->nullableString('virtual_balance'), | ||||
|             'iban'                    => $this->nullableString('iban'), | ||||
| @@ -75,7 +80,7 @@ class AccountUpdateRequest extends Request | ||||
|             'opening_balance'         => $this->nullableString('opening_balance'), | ||||
|             'opening_balance_date'    => $this->date('opening_balance_date'), | ||||
|             'cc_type'                 => $this->nullableString('credit_card_type'), | ||||
|             'cc_Monthly_payment_date' => $this->nullableString('monthly_payment_date'), | ||||
|             'cc_monthly_payment_date' => $this->nullableString('monthly_payment_date'), | ||||
|             'notes'                   => $this->nullableNlString('notes'), | ||||
|             'interest'                => $this->nullableString('interest'), | ||||
|             'interest_period'         => $this->nullableString('interest_period'), | ||||
| @@ -114,6 +119,7 @@ class AccountUpdateRequest extends Request | ||||
|             'opening_balance'      => 'numeric|required_with:opening_balance_date|nullable', | ||||
|             'opening_balance_date' => 'date|required_with:opening_balance|nullable', | ||||
|             'virtual_balance'      => 'numeric|nullable', | ||||
|             'order'                => 'numeric|nullable', | ||||
|             'currency_id'          => 'numeric|exists:transaction_currencies,id', | ||||
|             'currency_code'        => 'min:3|max:3|exists:transaction_currencies,code', | ||||
|             'active'               => [new IsBoolean], | ||||
| @@ -128,8 +134,6 @@ class AccountUpdateRequest extends Request | ||||
|             'interest_period'      => 'required_if:type,liability|in:daily,monthly,yearly', | ||||
|             'notes'                => 'min:0|max:65536', | ||||
|         ]; | ||||
|         $rules = Location::requestRules($rules); | ||||
|  | ||||
|         return $rules; | ||||
|         return Location::requestRules($rules); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -24,14 +24,18 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Rules\IsValidAttachmentModel; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
| /** | ||||
|  * Class AttachmentStoreRequest | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class AttachmentStoreRequest extends Request | ||||
| class AttachmentStoreRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|   | ||||
| @@ -23,13 +23,18 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
| /** | ||||
|  * ClassAttachmentUpdateRequest | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class AttachmentUpdateRequest extends Request | ||||
| class AttachmentUpdateRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| /** | ||||
|  * TransferRequest.php | ||||
|  * AutocompleteRequest.php | ||||
|  * Copyright (c) 2020 james@firefly-iii.org | ||||
|  * | ||||
|  * This file is part of Firefly III (https://github.com/firefly-iii). | ||||
| @@ -22,16 +21,20 @@ | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace FireflyIII\Api\V1\Requests\Search; | ||||
| namespace FireflyIII\Api\V1\Requests\Autocomplete; | ||||
| 
 | ||||
| use FireflyIII\Api\V1\Requests\Request; | ||||
| use FireflyIII\Rules\IsTransferAccount; | ||||
| 
 | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| 
 | ||||
| /** | ||||
|  * Class TransferRequest | ||||
|  * Class AutocompleteRequest | ||||
|  */ | ||||
| class TransferRequest extends Request | ||||
| class AutocompleteRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
| 
 | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
| @@ -43,17 +46,37 @@ class TransferRequest extends Request | ||||
|         return auth()->check(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getData(): array | ||||
|     { | ||||
|         $types = $this->string('types'); | ||||
|         $array = []; | ||||
|         if ('' !== $types) { | ||||
|             $array = explode(',', $types); | ||||
|         } | ||||
|         $limit = $this->integer('limit'); | ||||
|         $limit = 0 === $limit ? 10 : $limit; | ||||
| 
 | ||||
|         // remove 'initial balance' from allowed types. its internal
 | ||||
|         $array = array_diff($array, [AccountType::INITIAL_BALANCE]); | ||||
| 
 | ||||
|         return [ | ||||
|             'types' => $array, | ||||
|             'query' => $this->string('query'), | ||||
|             'date'  => $this->date('date'), | ||||
|             'limit' => $limit, | ||||
|         ]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         return [ | ||||
|             'source'      => ['required', new IsTransferAccount], | ||||
|             'destination' => ['required', new IsTransferAccount], | ||||
|             'amount'      => 'required|numeric|gt:0', | ||||
|             'description' => 'required|min:1', | ||||
|             'date'        => 'required|date', | ||||
|             'limit' => 'min:0|max:1337', | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| @@ -23,13 +23,18 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
| /** | ||||
|  * Class AvailableBudgetRequest | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class AvailableBudgetRequest extends Request | ||||
| class AvailableBudgetRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|   | ||||
| @@ -25,6 +25,8 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| use Illuminate\Validation\Validator; | ||||
|  | ||||
| /** | ||||
| @@ -34,8 +36,9 @@ use Illuminate\Validation\Validator; | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class BillRequest extends Request | ||||
| class BillRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
| @@ -79,7 +82,6 @@ class BillRequest extends Request | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      * | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|   | ||||
| @@ -23,14 +23,19 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
| /** | ||||
|  * Class BudgetLimitRequest | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * TODO AFTER 4.8,0: split this into two request classes. | ||||
|  */ | ||||
| class BudgetLimitRequest extends Request | ||||
| class BudgetLimitRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
| @@ -49,7 +54,7 @@ class BudgetLimitRequest extends Request | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         return [ | ||||
|         $data = [ | ||||
|             'budget_id'     => $this->integer('budget_id'), | ||||
|             'start'         => $this->date('start'), | ||||
|             'end'           => $this->date('end'), | ||||
| @@ -57,6 +62,12 @@ class BudgetLimitRequest extends Request | ||||
|             'currency_id'   => $this->integer('currency_id'), | ||||
|             'currency_code' => $this->string('currency_code'), | ||||
|         ]; | ||||
|         // if request has a budget already, drop the rule. | ||||
|         $budget = $this->route()->parameter('budget'); | ||||
|         if (null !== $budget) { | ||||
|             $data['budget_id'] = $budget->id; | ||||
|         } | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -24,6 +24,9 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use FireflyIII\Validation\AutoBudget\ValidatesAutoBudgetRequest; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| use Illuminate\Validation\Validator; | ||||
|  | ||||
| /** | ||||
| @@ -31,8 +34,10 @@ use Illuminate\Validation\Validator; | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class BudgetStoreRequest extends Request | ||||
| class BudgetStoreRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes, ValidatesAutoBudgetRequest; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|   | ||||
| @@ -24,6 +24,9 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use FireflyIII\Validation\AutoBudget\ValidatesAutoBudgetRequest; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| use Illuminate\Validation\Validator; | ||||
|  | ||||
| /** | ||||
| @@ -31,8 +34,10 @@ use Illuminate\Validation\Validator; | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class BudgetUpdateRequest extends Request | ||||
| class BudgetUpdateRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes, ValidatesAutoBudgetRequest; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|   | ||||
| @@ -24,6 +24,8 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Models\Category; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
| /** | ||||
|  * Class CategoryRequest | ||||
| @@ -31,8 +33,10 @@ use FireflyIII\Models\Category; | ||||
|  * @codeCoverageIgnore | ||||
|  * TODO AFTER 4.8,0: split this into two request classes. | ||||
|  */ | ||||
| class CategoryRequest extends Request | ||||
| class CategoryRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|   | ||||
| @@ -25,14 +25,17 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
| /** | ||||
|  * Class ConfigurationRequest | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class ConfigurationRequest extends Request | ||||
| class ConfigurationRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
| @@ -54,6 +57,8 @@ class ConfigurationRequest extends Request | ||||
|     { | ||||
|         $name = $this->route()->parameter('configName'); | ||||
|         switch ($name) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'is_demo_site': | ||||
|             case 'single_user_mode': | ||||
|                 return ['value' => $this->boolean('value')]; | ||||
| @@ -73,6 +78,8 @@ class ConfigurationRequest extends Request | ||||
|     { | ||||
|         $name = $this->route()->parameter('configName'); | ||||
|         switch ($name) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'is_demo_site': | ||||
|             case 'single_user_mode': | ||||
|                 return ['value' => ['required', new IsBoolean]]; | ||||
|   | ||||
| @@ -24,6 +24,8 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
|  | ||||
| /** | ||||
| @@ -32,8 +34,10 @@ use FireflyIII\Rules\IsBoolean; | ||||
|  * @codeCoverageIgnore | ||||
|  * TODO AFTER 4.8,0: split this into two request classes. | ||||
|  */ | ||||
| class CurrencyRequest extends Request | ||||
| class CurrencyRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|   | ||||
| @@ -23,11 +23,16 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
| /** | ||||
|  * Class DataDestroyRequest | ||||
|  */ | ||||
| class DataDestroyRequest extends Request | ||||
| class DataDestroyRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
| @@ -60,7 +65,7 @@ class DataDestroyRequest extends Request | ||||
|                  ',accounts,asset_accounts,expense_accounts,revenue_accounts,liabilities,transactions,withdrawals,deposits,transfers'; | ||||
|  | ||||
|         return [ | ||||
|             'objects' => sprintf('min:1|string|in:%s', $valid), | ||||
|             'objects' => sprintf('required|min:1|string|in:%s', $valid), | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -25,13 +25,18 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
|  | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
| /** | ||||
|  * Request class for end points that require date parameters. | ||||
|  * | ||||
|  * Class DateRequest | ||||
|  */ | ||||
| class DateRequest extends Request | ||||
| class DateRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|   | ||||
| @@ -24,17 +24,20 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Models\LinkType; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| use Illuminate\Validation\Rule; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * Class LinkTypeRequest | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * TODO AFTER 4.8,0: split this into two request classes. | ||||
|  */ | ||||
| class LinkTypeRequest extends Request | ||||
| class LinkTypeRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|   | ||||
| @@ -24,13 +24,17 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
| /** | ||||
|  * Class AccountObjectGroupUpdateRequestUpdateRequest | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class ObjectGroupUpdateRequest extends Request | ||||
| class ObjectGroupUpdateRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|   | ||||
| @@ -27,16 +27,19 @@ use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Rules\IsAssetAccountId; | ||||
| use FireflyIII\Rules\LessThanPiggyTarget; | ||||
| use FireflyIII\Rules\ZeroOrMore; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * Class PiggyBankRequest | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * TODO AFTER 4.8,0: split this into two request classes. | ||||
|  */ | ||||
| class PiggyBankRequest extends Request | ||||
| class PiggyBankRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|   | ||||
| @@ -24,15 +24,18 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Rules\ZeroOrMore; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * Class PiggyBankStoreRequest | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class PiggyBankStoreRequest extends Request | ||||
| class PiggyBankStoreRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|   | ||||
| @@ -23,15 +23,17 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * Class PreferenceRequest | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class PreferenceRequest extends Request | ||||
| class PreferenceRequest extends FormRequest | ||||
| { | ||||
|  | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|   | ||||
| @@ -26,17 +26,20 @@ namespace FireflyIII\Api\V1\Requests; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Rules\BelongsUser; | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use FireflyIII\Support\Request\GetRecurrenceData; | ||||
| use FireflyIII\Validation\CurrencyValidation; | ||||
| use FireflyIII\Validation\RecurrenceValidation; | ||||
| use FireflyIII\Validation\TransactionValidation; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| use Illuminate\Validation\Validator; | ||||
|  | ||||
| /** | ||||
|  * Class RecurrenceStoreRequest | ||||
|  */ | ||||
| class RecurrenceStoreRequest extends Request | ||||
| class RecurrenceStoreRequest extends FormRequest | ||||
| { | ||||
|     use RecurrenceValidation, TransactionValidation, CurrencyValidation; | ||||
|     use ConvertsDataTypes, RecurrenceValidation, TransactionValidation, CurrencyValidation, GetRecurrenceData; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
| @@ -81,6 +84,56 @@ class RecurrenceStoreRequest extends Request | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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 | ||||
|      */ | ||||
|     private function getTransactionData(): array | ||||
|     { | ||||
|         $return = []; | ||||
|         // transaction data: | ||||
|         /** @var array $transactions */ | ||||
|         $transactions = $this->get('transactions'); | ||||
|         if (null === $transactions) { | ||||
|             return []; | ||||
|         } | ||||
|         /** @var array $transaction */ | ||||
|         foreach ($transactions as $transaction) { | ||||
|             $return[] = $this->getSingleRecurrenceData($transaction); | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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'); | ||||
|         if (null === $repetitions) { | ||||
|             return []; | ||||
|         } | ||||
|         /** @var array $repetition */ | ||||
|         foreach ($repetitions as $repetition) { | ||||
|             $return[] = [ | ||||
|                 'type'    => $repetition['type'], | ||||
|                 'moment'  => $repetition['moment'], | ||||
|                 'skip'    => (int) $repetition['skip'], | ||||
|                 'weekend' => (int) $repetition['weekend'], | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
| @@ -148,54 +201,4 @@ class RecurrenceStoreRequest extends Request | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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'); | ||||
|         if (null === $repetitions) { | ||||
|             return []; | ||||
|         } | ||||
|         /** @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 | ||||
|      */ | ||||
|     private function getTransactionData(): array | ||||
|     { | ||||
|         $return = []; | ||||
|         // transaction data: | ||||
|         /** @var array $transactions */ | ||||
|         $transactions = $this->get('transactions'); | ||||
|         if (null === $transactions) { | ||||
|             return []; | ||||
|         } | ||||
|         /** @var array $transaction */ | ||||
|         foreach ($transactions as $transaction) { | ||||
|             $return[] = $this->getSingleRecurrenceData($transaction); | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -26,17 +26,20 @@ namespace FireflyIII\Api\V1\Requests; | ||||
| use FireflyIII\Models\Recurrence; | ||||
| use FireflyIII\Rules\BelongsUser; | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use FireflyIII\Support\Request\GetRecurrenceData; | ||||
| use FireflyIII\Validation\CurrencyValidation; | ||||
| use FireflyIII\Validation\RecurrenceValidation; | ||||
| use FireflyIII\Validation\TransactionValidation; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| use Illuminate\Validation\Validator; | ||||
|  | ||||
| /** | ||||
|  * Class RecurrenceUpdateRequest | ||||
|  */ | ||||
| class RecurrenceUpdateRequest extends Request | ||||
| class RecurrenceUpdateRequest extends FormRequest | ||||
| { | ||||
|     use RecurrenceValidation, TransactionValidation, CurrencyValidation; | ||||
|     use ConvertsDataTypes, RecurrenceValidation, TransactionValidation, CurrencyValidation, GetRecurrenceData; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
| @@ -82,6 +85,56 @@ class RecurrenceUpdateRequest extends Request | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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 | ||||
|      */ | ||||
|     private function getTransactionData(): array | ||||
|     { | ||||
|         $return = []; | ||||
|         // transaction data: | ||||
|         /** @var array $transactions */ | ||||
|         $transactions = $this->get('transactions'); | ||||
|         if (null === $transactions) { | ||||
|             return []; | ||||
|         } | ||||
|         /** @var array $transaction */ | ||||
|         foreach ($transactions as $transaction) { | ||||
|             $return[] = $this->getSingleRecurrenceData($transaction); | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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'); | ||||
|         if (null === $repetitions) { | ||||
|             return []; | ||||
|         } | ||||
|         /** @var array $repetition */ | ||||
|         foreach ($repetitions as $repetition) { | ||||
|             $return[] = [ | ||||
|                 'type'    => $repetition['type'], | ||||
|                 'moment'  => $repetition['moment'], | ||||
|                 'skip'    => (int) $repetition['skip'], | ||||
|                 'weekend' => (int) $repetition['weekend'], | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
| @@ -150,54 +203,4 @@ class RecurrenceUpdateRequest extends Request | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the repetition data as it is found in the submitted data. | ||||
|      * | ||||
|      * @return array|null | ||||
|      */ | ||||
|     private function getRepetitionData(): ?array | ||||
|     { | ||||
|         $return = []; | ||||
|         // repetition data: | ||||
|         /** @var array $repetitions */ | ||||
|         $repetitions = $this->get('repetitions'); | ||||
|         if (null === $repetitions) { | ||||
|             return null; | ||||
|         } | ||||
|         /** @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|null | ||||
|      */ | ||||
|     private function getTransactionData(): ?array | ||||
|     { | ||||
|         $return = []; | ||||
|         // transaction data: | ||||
|         /** @var array $transactions */ | ||||
|         $transactions = $this->get('transactions'); | ||||
|         if (null === $transactions) { | ||||
|             return null; | ||||
|         } | ||||
|         /** @var array $transaction */ | ||||
|         foreach ($transactions as $transaction) { | ||||
|             $return[] = $this->getSingleRecurrenceData($transaction); | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -25,6 +25,8 @@ namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Models\RuleGroup; | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
|  | ||||
| /** | ||||
| @@ -32,8 +34,10 @@ use FireflyIII\Rules\IsBoolean; | ||||
|  * Class RuleGroupRequest | ||||
|  * TODO AFTER 4.8,0: split this into two request classes. | ||||
|  */ | ||||
| class RuleGroupRequest extends Request | ||||
| class RuleGroupRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|   | ||||
| @@ -22,22 +22,21 @@ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class RuleGroupTestRequest | ||||
|  */ | ||||
| class RuleGroupTestRequest extends Request | ||||
| class RuleGroupTestRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
| @@ -55,47 +54,12 @@ class RuleGroupTestRequest extends Request | ||||
|     public function getTestParameters(): array | ||||
|     { | ||||
|         return [ | ||||
|             'page'          => $this->getPage(), | ||||
|             'start_date'    => $this->getDate('start_date'), | ||||
|             'end_date'      => $this->getDate('end_date'), | ||||
|             'search_limit'  => $this->getSearchLimit(), | ||||
|             'trigger_limit' => $this->getTriggerLimit(), | ||||
|             'accounts'      => $this->getAccounts(), | ||||
|             'start'    => $this->getDate('start'), | ||||
|             'end'      => $this->getDate('end'), | ||||
|             'accounts' => $this->getAccounts(), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     private function getAccounts(): Collection | ||||
|     { | ||||
|         $accountList = '' === (string) $this->query('accounts') ? [] : explode(',', $this->query('accounts')); | ||||
|         $accounts    = new Collection; | ||||
|  | ||||
|         /** @var AccountRepositoryInterface $accountRepository */ | ||||
|         $accountRepository = app(AccountRepositoryInterface::class); | ||||
|  | ||||
|         foreach ($accountList as $accountId) { | ||||
|             Log::debug(sprintf('Searching for asset account with id "%s"', $accountId)); | ||||
|             $account = $accountRepository->findNull((int) $accountId); | ||||
|             if ($this->validAccount($account)) { | ||||
|                 /** @noinspection NullPointerExceptionInspection */ | ||||
|                 Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name)); | ||||
|                 $accounts->push($account); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $accounts; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $field | ||||
|      * | ||||
| @@ -103,45 +67,28 @@ class RuleGroupTestRequest extends Request | ||||
|      */ | ||||
|     private function getDate(string $field): ?Carbon | ||||
|     { | ||||
|         /** @var Carbon $result */ | ||||
|         $result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field)); | ||||
|  | ||||
|         return $result; | ||||
|         return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return int | ||||
|      * @return Collection | ||||
|      */ | ||||
|     private function getPage(): int | ||||
|     private function getAccounts(): string | ||||
|     { | ||||
|         return 0 === (int) $this->query('page') ? 1 : (int) $this->query('page'); | ||||
|  | ||||
|         return (string) $this->query('accounts'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return int | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getSearchLimit(): int | ||||
|     public function rules(): array | ||||
|     { | ||||
|         return 0 === (int) $this->query('search_limit') ? (int) config('firefly.test-triggers.limit') : (int) $this->query('search_limit'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return int | ||||
|      */ | ||||
|     private function getTriggerLimit(): int | ||||
|     { | ||||
|         return 0 === (int) $this->query('triggered_limit') ? (int) config('firefly.test-triggers.range') : (int) $this->query('triggered_limit'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account|null $account | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     private function validAccount(?Account $account): bool | ||||
|     { | ||||
|         return null !== $account && AccountType::ASSET === $account->accountType->type; | ||||
|         return [ | ||||
|             'start'      => 'date', | ||||
|             'end'        => 'date|after:start', | ||||
|             'accounts'   => '', | ||||
|             'accounts.*' => 'exists:accounts,id|belongsToUser:accounts', | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -22,22 +22,20 @@ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
| /** | ||||
|  * Class RuleGroupTriggerRequest | ||||
|  */ | ||||
| class RuleGroupTriggerRequest extends Request | ||||
| class RuleGroupTriggerRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
| @@ -55,47 +53,12 @@ class RuleGroupTriggerRequest extends Request | ||||
|     public function getTriggerParameters(): array | ||||
|     { | ||||
|         return [ | ||||
|             'start_date' => $this->getDate('start_date'), | ||||
|             'end_date'   => $this->getDate('end_date'), | ||||
|             'accounts'   => $this->getAccounts(), | ||||
|             'start'    => $this->getDate('start'), | ||||
|             'end'      => $this->getDate('end'), | ||||
|             'accounts' => $this->getAccounts(), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         return [ | ||||
|             'start_date' => 'required|date', | ||||
|             'end_date'   => 'required|date|after:start_date', | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     private function getAccounts(): Collection | ||||
|     { | ||||
|         $accountList = '' === (string) $this->query('accounts') ? [] : explode(',', $this->query('accounts')); | ||||
|         $accounts    = new Collection; | ||||
|  | ||||
|         /** @var AccountRepositoryInterface $accountRepository */ | ||||
|         $accountRepository = app(AccountRepositoryInterface::class); | ||||
|  | ||||
|         foreach ($accountList as $accountId) { | ||||
|             Log::debug(sprintf('Searching for asset account with id "%s"', $accountId)); | ||||
|             $account = $accountRepository->findNull((int) $accountId); | ||||
|             if ($this->validAccount($account)) { | ||||
|                 /** @noinspection NullPointerExceptionInspection */ | ||||
|                 Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name)); | ||||
|                 $accounts->push($account); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $accounts; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $field | ||||
|      * | ||||
| @@ -103,20 +66,26 @@ class RuleGroupTriggerRequest extends Request | ||||
|      */ | ||||
|     private function getDate(string $field): ?Carbon | ||||
|     { | ||||
|         /** @var Carbon $result */ | ||||
|         $result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field)); | ||||
|  | ||||
|         return $result; | ||||
|         return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account|null $account | ||||
|      * | ||||
|      * @return bool | ||||
|      * @return string | ||||
|      */ | ||||
|     private function validAccount(?Account $account): bool | ||||
|     private function getAccounts(): string | ||||
|     { | ||||
|         return null !== $account && AccountType::ASSET === $account->accountType->type; | ||||
|         return (string) $this->query('accounts'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         return [ | ||||
|             'start' => 'date', | ||||
|             'end'   => 'date|after:start', | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -24,16 +24,20 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use FireflyIII\Support\Request\GetRuleConfiguration; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| use Illuminate\Validation\Validator; | ||||
| use function is_array; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class RuleStoreRequest | ||||
|  * | ||||
|  */ | ||||
| class RuleStoreRequest extends Request | ||||
| class RuleStoreRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes, GetRuleConfiguration; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
| @@ -79,6 +83,48 @@ class RuleStoreRequest extends Request | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @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; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @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; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
| @@ -86,11 +132,11 @@ class RuleStoreRequest extends Request | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $validTriggers = array_keys(config('firefly.rule-triggers')); | ||||
|         $validTriggers = $this->getTriggers(); | ||||
|         $validActions  = array_keys(config('firefly.rule-actions')); | ||||
|  | ||||
|         // some triggers and actions require text: | ||||
|         $contextTriggers = implode(',', config('firefly.context-rule-triggers')); | ||||
|         $contextTriggers = implode(',', $this->getTriggersWithContext()); | ||||
|         $contextActions  = implode(',', config('firefly.context-rule-actions')); | ||||
|  | ||||
|         return [ | ||||
| @@ -130,21 +176,6 @@ class RuleStoreRequest extends Request | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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. | ||||
|      * | ||||
| @@ -161,44 +192,17 @@ class RuleStoreRequest extends Request | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      * Adds an error to the validator when there are no repetitions in the array of data. | ||||
|      * | ||||
|      * @param Validator $validator | ||||
|      */ | ||||
|     private function getRuleActions(): array | ||||
|     protected function atLeastOneAction(Validator $validator): void | ||||
|     { | ||||
|         $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')), | ||||
|                 ]; | ||||
|             } | ||||
|         $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')); | ||||
|         } | ||||
|  | ||||
|         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; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -22,22 +22,20 @@ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
| /** | ||||
|  * Class RuleTestRequest | ||||
|  */ | ||||
| class RuleTestRequest extends Request | ||||
| class RuleTestRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
| @@ -55,60 +53,14 @@ class RuleTestRequest extends Request | ||||
|     public function getTestParameters(): array | ||||
|     { | ||||
|         return [ | ||||
|             'page'          => $this->getPage(), | ||||
|             'start_date'    => $this->getDate('start_date'), | ||||
|             'end_date'      => $this->getDate('end_date'), | ||||
|             'search_limit'  => $this->getSearchLimit(), | ||||
|             'trigger_limit' => $this->getTriggerLimit(), | ||||
|             'accounts'      => $this->getAccounts(), | ||||
|             'page'     => $this->getPage(), | ||||
|             'start'    => $this->getDate('start'), | ||||
|             'end'      => $this->getDate('end'), | ||||
|             'accounts' => $this->getAccounts(), | ||||
|  | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     private function getAccounts(): Collection | ||||
|     { | ||||
|         $accountList = '' === (string) $this->query('accounts') ? [] : explode(',', $this->query('accounts')); | ||||
|         $accounts    = new Collection; | ||||
|  | ||||
|         /** @var AccountRepositoryInterface $accountRepository */ | ||||
|         $accountRepository = app(AccountRepositoryInterface::class); | ||||
|  | ||||
|         foreach ($accountList as $accountId) { | ||||
|             Log::debug(sprintf('Searching for asset account with id "%s"', $accountId)); | ||||
|             $account = $accountRepository->findNull((int) $accountId); | ||||
|             if ($this->validAccount($account)) { | ||||
|                 /** @noinspection NullPointerExceptionInspection */ | ||||
|                 Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name)); | ||||
|                 $accounts->push($account); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $accounts; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $field | ||||
|      * | ||||
|      * @return Carbon|null | ||||
|      */ | ||||
|     private function getDate(string $field): ?Carbon | ||||
|     { | ||||
|         /** @var Carbon $result */ | ||||
|         $result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field)); | ||||
|  | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return int | ||||
|      */ | ||||
| @@ -119,29 +71,34 @@ class RuleTestRequest extends Request | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return int | ||||
|      */ | ||||
|     private function getSearchLimit(): int | ||||
|     { | ||||
|         return 0 === (int) $this->query('search_limit') ? (int) config('firefly.test-triggers.limit') : (int) $this->query('search_limit'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return int | ||||
|      */ | ||||
|     private function getTriggerLimit(): int | ||||
|     { | ||||
|         return 0 === (int) $this->query('triggered_limit') ? (int) config('firefly.test-triggers.range') : (int) $this->query('triggered_limit'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account|null $account | ||||
|      * @param string $field | ||||
|      * | ||||
|      * @return bool | ||||
|      * @return Carbon|null | ||||
|      */ | ||||
|     private function validAccount(?Account $account): bool | ||||
|     private function getDate(string $field): ?Carbon | ||||
|     { | ||||
|         return null !== $account && AccountType::ASSET === $account->accountType->type; | ||||
|         return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     private function getAccounts(): string | ||||
|     { | ||||
|         return (string) $this->query('accounts'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         return [ | ||||
|             'start'      => 'date', | ||||
|             'end'        => 'date|after:start', | ||||
|             'accounts'   => '', | ||||
|             'accounts.*' => 'required|exists:accounts,id|belongsToUser:accounts', | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -26,17 +26,16 @@ namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
| /** | ||||
|  * Class RuleTriggerRequest | ||||
|  */ | ||||
| class RuleTriggerRequest extends Request | ||||
| class RuleTriggerRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
| @@ -54,47 +53,12 @@ class RuleTriggerRequest extends Request | ||||
|     public function getTriggerParameters(): array | ||||
|     { | ||||
|         return [ | ||||
|             'start_date' => $this->getDate('start_date'), | ||||
|             'end_date'   => $this->getDate('end_date'), | ||||
|             'accounts'   => $this->getAccounts(), | ||||
|             'start'    => $this->getDate('start'), | ||||
|             'end'      => $this->getDate('end'), | ||||
|             'accounts' => $this->getAccounts(), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         return [ | ||||
|             'start_date' => 'required|date', | ||||
|             'end_date'   => 'required|date|after:start_date', | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     private function getAccounts(): Collection | ||||
|     { | ||||
|         $accountList = '' === (string) $this->query('accounts') ? [] : explode(',', $this->query('accounts')); | ||||
|         $accounts    = new Collection; | ||||
|  | ||||
|         /** @var AccountRepositoryInterface $accountRepository */ | ||||
|         $accountRepository = app(AccountRepositoryInterface::class); | ||||
|  | ||||
|         foreach ($accountList as $accountId) { | ||||
|             Log::debug(sprintf('Searching for asset account with id "%s"', $accountId)); | ||||
|             $account = $accountRepository->findNull((int) $accountId); | ||||
|             if ($this->validAccount($account)) { | ||||
|                 /** @noinspection NullPointerExceptionInspection */ | ||||
|                 Log::debug(sprintf('Found account #%d ("%s") and its an asset account', $account->id, $account->name)); | ||||
|                 $accounts->push($account); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $accounts; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $field | ||||
|      * | ||||
| @@ -102,20 +66,28 @@ class RuleTriggerRequest extends Request | ||||
|      */ | ||||
|     private function getDate(string $field): ?Carbon | ||||
|     { | ||||
|         /** @var Carbon $result */ | ||||
|         $result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field)); | ||||
|  | ||||
|         return $result; | ||||
|         return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', $this->query($field)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account|null $account | ||||
|      * | ||||
|      * @return bool | ||||
|      * @return string | ||||
|      */ | ||||
|     private function validAccount(?Account $account): bool | ||||
|     private function getAccounts(): string | ||||
|     { | ||||
|         return null !== $account && AccountType::ASSET === $account->accountType->type; | ||||
|         return (string) $this->query('accounts'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         return [ | ||||
|             'start'      => 'date', | ||||
|             'end'        => 'date|after:start', | ||||
|             'accounts'   => '', | ||||
|             'accounts.*' => 'exists:accounts,id|belongsToUser:accounts', | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -24,16 +24,20 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use FireflyIII\Support\Request\GetRuleConfiguration; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| use Illuminate\Validation\Validator; | ||||
| use function is_array; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class RuleUpdateRequest | ||||
|  * | ||||
|  */ | ||||
| class RuleUpdateRequest extends Request | ||||
| class RuleUpdateRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes, GetRuleConfiguration; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
| @@ -79,6 +83,54 @@ class RuleUpdateRequest extends Request | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array|null | ||||
|      */ | ||||
|     private function getRuleTriggers(): ?array | ||||
|     { | ||||
|         if (!$this->has('triggers')) { | ||||
|             return null; | ||||
|         } | ||||
|         $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; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array|null | ||||
|      */ | ||||
|     private function getRuleActions(): ?array | ||||
|     { | ||||
|         if (!$this->has('actions')) { | ||||
|             return null; | ||||
|         } | ||||
|         $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; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
| @@ -86,12 +138,12 @@ class RuleUpdateRequest extends Request | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $validTriggers = array_keys(config('firefly.rule-triggers')); | ||||
|         $validTriggers = $this->getTriggers(); | ||||
|         $validActions  = array_keys(config('firefly.rule-actions')); | ||||
|         $rule          = $this->route()->parameter('rule'); | ||||
|  | ||||
|         // some triggers and actions require text: | ||||
|         $contextTriggers = implode(',', config('firefly.context-rule-triggers')); | ||||
|         $contextTriggers = implode(',', $this->getTriggersWithContext()); | ||||
|         $contextActions  = implode(',', config('firefly.context-rule-actions')); | ||||
|  | ||||
|         return [ | ||||
| @@ -131,21 +183,6 @@ class RuleUpdateRequest extends Request | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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'] ?? null; | ||||
|         // need at least one action | ||||
|         if (is_array($actions) && 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. | ||||
|      * | ||||
| @@ -162,50 +199,17 @@ class RuleUpdateRequest extends Request | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array|null | ||||
|      * Adds an error to the validator when there are no repetitions in the array of data. | ||||
|      * | ||||
|      * @param Validator $validator | ||||
|      */ | ||||
|     private function getRuleActions(): ?array | ||||
|     protected function atLeastOneAction(Validator $validator): void | ||||
|     { | ||||
|         if (!$this->has('actions')) { | ||||
|             return null; | ||||
|         $data    = $validator->getData(); | ||||
|         $actions = $data['actions'] ?? null; | ||||
|         // need at least one action | ||||
|         if (is_array($actions) && 0 === count($actions)) { | ||||
|             $validator->errors()->add('title', (string) trans('validation.at_least_one_action')); | ||||
|         } | ||||
|         $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|null | ||||
|      */ | ||||
|     private function getRuleTriggers(): ?array | ||||
|     { | ||||
|         if (!$this->has('triggers')) { | ||||
|             return null; | ||||
|         } | ||||
|         $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; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -24,15 +24,17 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Models\Location; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
| /** | ||||
|  * Class TagStoreRequest | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  */ | ||||
| class TagStoreRequest extends Request | ||||
| class TagStoreRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|   | ||||
| @@ -25,15 +25,17 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Models\Location; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
| /** | ||||
|  * Class TagUpdateRequest | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  */ | ||||
| class TagUpdateRequest extends Request | ||||
| class TagUpdateRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|   | ||||
| @@ -25,15 +25,18 @@ namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Repositories\Journal\JournalRepositoryInterface; | ||||
| use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| use Illuminate\Validation\Validator; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * Class TransactionLinkRequest | ||||
|  */ | ||||
| class TransactionLinkRequest extends Request | ||||
| class TransactionLinkRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
| @@ -62,7 +65,6 @@ class TransactionLinkRequest extends Request | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|   | ||||
| @@ -28,18 +28,20 @@ use FireflyIII\Rules\BelongsUser; | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
| use FireflyIII\Rules\IsDateOrTime; | ||||
| use FireflyIII\Support\NullArrayObject; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use FireflyIII\Validation\CurrencyValidation; | ||||
| use FireflyIII\Validation\GroupValidation; | ||||
| use FireflyIII\Validation\TransactionValidation; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| use Illuminate\Validation\Validator; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class TransactionStoreRequest | ||||
|  */ | ||||
| class TransactionStoreRequest extends Request | ||||
| class TransactionStoreRequest extends FormRequest | ||||
| { | ||||
|     use TransactionValidation, GroupValidation, CurrencyValidation; | ||||
|     use TransactionValidation, GroupValidation, CurrencyValidation, ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
| @@ -71,132 +73,6 @@ class TransactionStoreRequest extends Request | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         Log::debug('Collect rules of TransactionStoreRequest'); | ||||
|  | ||||
|         return [ | ||||
|             // basic fields for group: | ||||
|             'group_title'                          => 'between:1,1000|nullable', | ||||
|             'error_if_duplicate_hash'              => [new IsBoolean], | ||||
|             'apply_rules'                          => [new IsBoolean], | ||||
|  | ||||
|             // transaction rules (in array for splits): | ||||
|             'transactions.*.type'                  => 'required|in:withdrawal,deposit,transfer,opening-balance,reconciliation', | ||||
|             'transactions.*.date'                  => ['required', new IsDateOrTime], | ||||
|             'transactions.*.order'                 => 'numeric|min:0', | ||||
|  | ||||
|             // currency info | ||||
|             'transactions.*.currency_id'           => 'numeric|exists:transaction_currencies,id|nullable', | ||||
|             'transactions.*.currency_code'         => 'min:3|max:3|exists:transaction_currencies,code|nullable', | ||||
|             'transactions.*.foreign_currency_id'   => 'numeric|exists:transaction_currencies,id|nullable', | ||||
|             'transactions.*.foreign_currency_code' => 'min:3|max:3|exists:transaction_currencies,code|nullable', | ||||
|  | ||||
|             // amount | ||||
|             'transactions.*.amount'                => 'required|numeric|gt:0', | ||||
|             'transactions.*.foreign_amount'        => 'numeric', | ||||
|  | ||||
|             // description | ||||
|             'transactions.*.description'           => 'nullable|between:1,1000', | ||||
|  | ||||
|             // source of transaction | ||||
|             'transactions.*.source_id'             => ['numeric', 'nullable', new BelongsUser], | ||||
|             'transactions.*.source_name'           => 'between:1,255|nullable', | ||||
|             'transactions.*.source_iban'           => 'between:1,255|nullable|iban', | ||||
|             'transactions.*.source_number'         => 'between:1,255|nullable', | ||||
|             'transactions.*.source_bic'            => 'between:1,255|nullable|bic', | ||||
|  | ||||
|             // destination of transaction | ||||
|             'transactions.*.destination_id'        => ['numeric', 'nullable', new BelongsUser], | ||||
|             'transactions.*.destination_name'      => 'between:1,255|nullable', | ||||
|             'transactions.*.destination_iban'      => 'between:1,255|nullable|iban', | ||||
|             'transactions.*.destination_number'    => 'between:1,255|nullable', | ||||
|             'transactions.*.destination_bic'       => 'between:1,255|nullable|bic', | ||||
|  | ||||
|             // budget, category, bill and piggy | ||||
|             '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.*.bill_id'               => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser], | ||||
|             'transactions.*.bill_name'             => ['between:1,255', 'nullable', new BelongsUser], | ||||
|             'transactions.*.piggy_bank_id'         => ['numeric', 'nullable', 'mustExist:piggy_banks,id', new BelongsUser], | ||||
|             'transactions.*.piggy_bank_name'       => ['between:1,255', 'nullable', new BelongsUser], | ||||
|  | ||||
|             // other interesting fields | ||||
|             'transactions.*.reconciled'            => [new IsBoolean], | ||||
|             'transactions.*.notes'                 => 'min:1,max:50000|nullable', | ||||
|             'transactions.*.tags'                  => 'between:0,255', | ||||
|  | ||||
|             // meta info fields | ||||
|             'transactions.*.internal_reference'    => 'min:1,max:255|nullable', | ||||
|             'transactions.*.external_id'           => 'min:1,max:255|nullable', | ||||
|             'transactions.*.recurrence_id'         => 'min:1,max:255|nullable', | ||||
|             'transactions.*.bunq_payment_id'       => 'min:1,max:255|nullable', | ||||
|  | ||||
|             // SEPA fields: | ||||
|             'transactions.*.sepa_cc'               => 'min:1,max:255|nullable', | ||||
|             'transactions.*.sepa_ct_op'            => 'min:1,max:255|nullable', | ||||
|             'transactions.*.sepa_ct_id'            => 'min:1,max:255|nullable', | ||||
|             'transactions.*.sepa_db'               => 'min:1,max:255|nullable', | ||||
|             'transactions.*.sepa_country'          => 'min:1,max:255|nullable', | ||||
|             'transactions.*.sepa_ep'               => 'min:1,max:255|nullable', | ||||
|             'transactions.*.sepa_ci'               => 'min:1,max:255|nullable', | ||||
|             'transactions.*.sepa_batch_id'         => 'min:1,max:255|nullable', | ||||
|  | ||||
|             // dates | ||||
|             'transactions.*.interest_date'         => 'date|nullable', | ||||
|             'transactions.*.book_date'             => 'date|nullable', | ||||
|             'transactions.*.process_date'          => 'date|nullable', | ||||
|             'transactions.*.due_date'              => 'date|nullable', | ||||
|             'transactions.*.payment_date'          => 'date|nullable', | ||||
|             'transactions.*.invoice_date'          => 'date|nullable', | ||||
|         ]; | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Configure the validator instance. | ||||
|      * | ||||
|      * @param Validator $validator | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function withValidator(Validator $validator): void | ||||
|     { | ||||
|         $validator->after( | ||||
|             function (Validator $validator) { | ||||
|                 // must submit at least one transaction. | ||||
|                 $this->validateOneTransaction($validator); | ||||
|  | ||||
|                 // all journals must have a description | ||||
|                 $this->validateDescriptions($validator); | ||||
|  | ||||
|                 // all transaction types must be equal: | ||||
|                 $this->validateTransactionTypes($validator); | ||||
|  | ||||
|                 // validate foreign currency info | ||||
|                 $this->validateForeignCurrencyInformation($validator); | ||||
|  | ||||
|                 // validate all account info | ||||
|                 $this->validateAccountInformation($validator); | ||||
|  | ||||
|                 // validate source/destination is equal, depending on the transaction journal type. | ||||
|                 $this->validateEqualAccounts($validator); | ||||
|  | ||||
|                 // the group must have a description if > 1 journal. | ||||
|                 $this->validateGroupDescription($validator); | ||||
|  | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get transaction data. | ||||
|      * | ||||
| @@ -271,6 +147,7 @@ class TransactionStoreRequest extends Request | ||||
|                 'original_source'       => sprintf('ff3-v%s|api-v%s', config('firefly.version'), config('firefly.api_version')), | ||||
|                 'recurrence_id'         => $this->integerFromValue($object['recurrence_id']), | ||||
|                 'bunq_payment_id'       => $this->stringFromValue((string) $object['bunq_payment_id']), | ||||
|                 'external_uri'          => $this->stringFromValue((string) $object['external_uri']), | ||||
|  | ||||
|                 'sepa_cc'       => $this->stringFromValue($object['sepa_cc']), | ||||
|                 'sepa_ct_op'    => $this->stringFromValue($object['sepa_ct_op']), | ||||
| @@ -295,4 +172,135 @@ class TransactionStoreRequest extends Request | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         Log::debug('Collect rules of TransactionStoreRequest'); | ||||
|  | ||||
|         return [ | ||||
|             // basic fields for group: | ||||
|             'group_title'                          => 'between:1,1000|nullable', | ||||
|             'error_if_duplicate_hash'              => [new IsBoolean], | ||||
|             'apply_rules'                          => [new IsBoolean], | ||||
|  | ||||
|             // transaction rules (in array for splits): | ||||
|             'transactions.*.type'                  => 'required|in:withdrawal,deposit,transfer,opening-balance,reconciliation', | ||||
|             'transactions.*.date'                  => ['required', new IsDateOrTime], | ||||
|             'transactions.*.order'                 => 'numeric|min:0', | ||||
|  | ||||
|             // currency info | ||||
|             'transactions.*.currency_id'           => 'numeric|exists:transaction_currencies,id|nullable', | ||||
|             'transactions.*.currency_code'         => 'min:3|max:3|exists:transaction_currencies,code|nullable', | ||||
|             'transactions.*.foreign_currency_id'   => 'numeric|exists:transaction_currencies,id|nullable', | ||||
|             'transactions.*.foreign_currency_code' => 'min:3|max:3|exists:transaction_currencies,code|nullable', | ||||
|  | ||||
|             // amount | ||||
|             'transactions.*.amount'                => 'required|numeric|gt:0', | ||||
|             'transactions.*.foreign_amount'        => 'numeric', | ||||
|  | ||||
|             // description | ||||
|             'transactions.*.description'           => 'nullable|between:1,1000', | ||||
|  | ||||
|             // source of transaction | ||||
|             'transactions.*.source_id'             => ['numeric', 'nullable', new BelongsUser], | ||||
|             'transactions.*.source_name'           => 'between:1,255|nullable', | ||||
|             'transactions.*.source_iban'           => 'between:1,255|nullable|iban', | ||||
|             'transactions.*.source_number'         => 'between:1,255|nullable', | ||||
|             'transactions.*.source_bic'            => 'between:1,255|nullable|bic', | ||||
|  | ||||
|             // destination of transaction | ||||
|             'transactions.*.destination_id'        => ['numeric', 'nullable', new BelongsUser], | ||||
|             'transactions.*.destination_name'      => 'between:1,255|nullable', | ||||
|             'transactions.*.destination_iban'      => 'between:1,255|nullable|iban', | ||||
|             'transactions.*.destination_number'    => 'between:1,255|nullable', | ||||
|             'transactions.*.destination_bic'       => 'between:1,255|nullable|bic', | ||||
|  | ||||
|             // budget, category, bill and piggy | ||||
|             '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.*.bill_id'               => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser], | ||||
|             'transactions.*.bill_name'             => ['between:1,255', 'nullable', new BelongsUser], | ||||
|             'transactions.*.piggy_bank_id'         => ['numeric', 'nullable', 'mustExist:piggy_banks,id', new BelongsUser], | ||||
|             'transactions.*.piggy_bank_name'       => ['between:1,255', 'nullable', new BelongsUser], | ||||
|  | ||||
|             // other interesting fields | ||||
|             'transactions.*.reconciled'            => [new IsBoolean], | ||||
|             'transactions.*.notes'                 => 'min:1,max:50000|nullable', | ||||
|             'transactions.*.tags'                  => 'between:0,255', | ||||
|  | ||||
|             // meta info fields | ||||
|             'transactions.*.internal_reference'    => 'min:1,max:255|nullable', | ||||
|             'transactions.*.external_id'           => 'min:1,max:255|nullable', | ||||
|             'transactions.*.recurrence_id'         => 'min:1,max:255|nullable', | ||||
|             'transactions.*.bunq_payment_id'       => 'min:1,max:255|nullable', | ||||
|             'transactions.*.external_uri'          => 'min:1,max:255|nullable|url', | ||||
|  | ||||
|             // SEPA fields: | ||||
|             'transactions.*.sepa_cc'               => 'min:1,max:255|nullable', | ||||
|             'transactions.*.sepa_ct_op'            => 'min:1,max:255|nullable', | ||||
|             'transactions.*.sepa_ct_id'            => 'min:1,max:255|nullable', | ||||
|             'transactions.*.sepa_db'               => 'min:1,max:255|nullable', | ||||
|             'transactions.*.sepa_country'          => 'min:1,max:255|nullable', | ||||
|             'transactions.*.sepa_ep'               => 'min:1,max:255|nullable', | ||||
|             'transactions.*.sepa_ci'               => 'min:1,max:255|nullable', | ||||
|             'transactions.*.sepa_batch_id'         => 'min:1,max:255|nullable', | ||||
|  | ||||
|             // dates | ||||
|             'transactions.*.interest_date'         => 'date|nullable', | ||||
|             'transactions.*.book_date'             => 'date|nullable', | ||||
|             'transactions.*.process_date'          => 'date|nullable', | ||||
|             'transactions.*.due_date'              => 'date|nullable', | ||||
|             'transactions.*.payment_date'          => 'date|nullable', | ||||
|             'transactions.*.invoice_date'          => 'date|nullable', | ||||
|         ]; | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Configure the validator instance. | ||||
|      * | ||||
|      * @param Validator $validator | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function withValidator(Validator $validator): void | ||||
|     { | ||||
|         $validator->after( | ||||
|             function (Validator $validator) { | ||||
|  | ||||
|                 // must be valid array. | ||||
|                 $this->validateTransactionArray($validator); | ||||
|  | ||||
|                 // must submit at least one transaction. | ||||
|                 $this->validateOneTransaction($validator); | ||||
|  | ||||
|                 // all journals must have a description | ||||
|                 $this->validateDescriptions($validator); | ||||
|  | ||||
|                 // all transaction types must be equal: | ||||
|                 $this->validateTransactionTypes($validator); | ||||
|  | ||||
|                 // validate foreign currency info | ||||
|                 $this->validateForeignCurrencyInformation($validator); | ||||
|  | ||||
|                 // validate all account info | ||||
|                 $this->validateAccountInformation($validator); | ||||
|  | ||||
|                 // validate source/destination is equal, depending on the transaction journal type. | ||||
|                 $this->validateEqualAccounts($validator); | ||||
|  | ||||
|                 // the group must have a description if > 1 journal. | ||||
|                 $this->validateGroupDescription($validator); | ||||
|  | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -28,30 +28,27 @@ use FireflyIII\Models\TransactionGroup; | ||||
| use FireflyIII\Rules\BelongsUser; | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
| use FireflyIII\Rules\IsDateOrTime; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use FireflyIII\Validation\GroupValidation; | ||||
| use FireflyIII\Validation\TransactionValidation; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
| use Illuminate\Validation\Validator; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class TransactionUpdateRequest | ||||
|  */ | ||||
| class TransactionUpdateRequest extends Request | ||||
| class TransactionUpdateRequest extends FormRequest | ||||
| { | ||||
|     use TransactionValidation, GroupValidation; | ||||
|     use TransactionValidation, GroupValidation, ConvertsDataTypes; | ||||
|  | ||||
|     private array $arrayFields; | ||||
|     private array $booleanFields; | ||||
|     private array $dateFields; | ||||
|     private array $integerFields; | ||||
|     private array $stringFields; | ||||
|     private array $textareaFields; | ||||
|  | ||||
|     /** @var array Array values. */ | ||||
|     private $arrayFields; | ||||
|     /** @var array Boolean values. */ | ||||
|     private $booleanFields; | ||||
|     /** @var array Fields that contain date values. */ | ||||
|     private $dateFields; | ||||
|     /** @var array Fields that contain integer values. */ | ||||
|     private $integerFields; | ||||
|     /** @var array Fields that contain string values. */ | ||||
|     private $stringFields; | ||||
|     /** @var array Fields that contain text (with newlines) */ | ||||
|     private $textareaFields; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
| @@ -127,6 +124,7 @@ class TransactionUpdateRequest extends Request | ||||
|             'sepa_ep', | ||||
|             'sepa_ci', | ||||
|             'sepa_batch_id', | ||||
|             'external_uri', | ||||
|         ]; | ||||
|         $this->booleanFields = [ | ||||
|             'reconciled', | ||||
| @@ -148,6 +146,139 @@ class TransactionUpdateRequest extends Request | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get transaction data. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getTransactionData(): array | ||||
|     { | ||||
|         Log::debug('Now in getTransactionData()'); | ||||
|         $return = []; | ||||
|         /** | ||||
|          * @var int   $index | ||||
|          * @var array $transaction | ||||
|          */ | ||||
|         foreach ($this->get('transactions') as $transaction) { | ||||
|             // default response is to update nothing in the transaction: | ||||
|             $current  = []; | ||||
|             $current  = $this->getIntegerData($current, $transaction); | ||||
|             $current  = $this->getStringData($current, $transaction); | ||||
|             $current  = $this->getNlStringData($current, $transaction); | ||||
|             $current  = $this->getDateData($current, $transaction); | ||||
|             $current  = $this->getBooleanData($current, $transaction); | ||||
|             $current  = $this->getArrayData($current, $transaction); | ||||
|             $return[] = $current; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * For each field, add it to the array if a reference is present in the request: | ||||
|      * | ||||
|      * @param array $current | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getIntegerData(array $current, array $transaction): array | ||||
|     { | ||||
|         foreach ($this->integerFields as $fieldName) { | ||||
|             if (array_key_exists($fieldName, $transaction)) { | ||||
|                 $current[$fieldName] = $this->integerFromValue((string) $transaction[$fieldName]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $current; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $current | ||||
|      * @param array $transaction | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getStringData(array $current, array $transaction): array | ||||
|     { | ||||
|         foreach ($this->stringFields as $fieldName) { | ||||
|             if (array_key_exists($fieldName, $transaction)) { | ||||
|                 $current[$fieldName] = $this->stringFromValue((string) $transaction[$fieldName]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $current; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $current | ||||
|      * @param array $transaction | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getNlStringData(array $current, array $transaction): array | ||||
|     { | ||||
|         foreach ($this->textareaFields as $fieldName) { | ||||
|             if (array_key_exists($fieldName, $transaction)) { | ||||
|                 $current[$fieldName] = $this->nlStringFromValue((string) $transaction[$fieldName]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $current; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $current | ||||
|      * @param array $transaction | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getDateData(array $current, array $transaction): array | ||||
|     { | ||||
|         foreach ($this->dateFields as $fieldName) { | ||||
|             Log::debug(sprintf('Now at date field %s', $fieldName)); | ||||
|             if (array_key_exists($fieldName, $transaction)) { | ||||
|                 Log::debug(sprintf('New value: "%s"', (string) $transaction[$fieldName])); | ||||
|                 $current[$fieldName] = $this->dateFromValue((string) $transaction[$fieldName]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $current; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $current | ||||
|      * @param array $transaction | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getBooleanData(array $current, array $transaction): array | ||||
|     { | ||||
|         foreach ($this->booleanFields as $fieldName) { | ||||
|             if (array_key_exists($fieldName, $transaction)) { | ||||
|                 $current[$fieldName] = $this->convertBoolean((string) $transaction[$fieldName]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $current; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $current | ||||
|      * @param array $transaction | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getArrayData(array $current, array $transaction): array | ||||
|     { | ||||
|         foreach ($this->arrayFields as $fieldName) { | ||||
|             if (array_key_exists($fieldName, $transaction)) { | ||||
|                 $current[$fieldName] = $this->arrayFromValue($transaction[$fieldName]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $current; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
| @@ -168,12 +299,12 @@ class TransactionUpdateRequest extends Request | ||||
|             // currency info | ||||
|             '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.*.foreign_currency_id'   => 'nullable|numeric|exists:transaction_currencies,id', | ||||
|             'transactions.*.foreign_currency_code' => 'nullable|min:3|max:3|exists:transaction_currencies,code', | ||||
|  | ||||
|             // amount | ||||
|             'transactions.*.amount'                => 'numeric|gt:0|max:100000000000', | ||||
|             'transactions.*.foreign_amount'        => 'numeric|gte:0', | ||||
|             'transactions.*.foreign_amount'        => 'nullable|numeric|gte:0', | ||||
|  | ||||
|             // description | ||||
|             'transactions.*.description'           => 'nullable|between:1,1000', | ||||
| @@ -204,6 +335,7 @@ class TransactionUpdateRequest extends Request | ||||
|             'transactions.*.external_id'           => 'min:1,max:255|nullable', | ||||
|             'transactions.*.recurrence_id'         => 'min:1,max:255|nullable', | ||||
|             'transactions.*.bunq_payment_id'       => 'min:1,max:255|nullable', | ||||
|             'transactions.*.external_uri'          => 'min:1,max:255|nullable|url', | ||||
|  | ||||
|             // SEPA fields: | ||||
|             'transactions.*.sepa_cc'               => 'min:1,max:255|nullable', | ||||
| @@ -273,137 +405,4 @@ class TransactionUpdateRequest extends Request | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $current | ||||
|      * @param array $transaction | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getArrayData(array $current, array $transaction): array | ||||
|     { | ||||
|         foreach ($this->arrayFields as $fieldName) { | ||||
|             if (array_key_exists($fieldName, $transaction)) { | ||||
|                 $current[$fieldName] = $this->arrayFromValue($transaction[$fieldName]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $current; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $current | ||||
|      * @param array $transaction | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getBooleanData(array $current, array $transaction): array | ||||
|     { | ||||
|         foreach ($this->booleanFields as $fieldName) { | ||||
|             if (array_key_exists($fieldName, $transaction)) { | ||||
|                 $current[$fieldName] = $this->convertBoolean((string) $transaction[$fieldName]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $current; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $current | ||||
|      * @param array $transaction | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getDateData(array $current, array $transaction): array | ||||
|     { | ||||
|         foreach ($this->dateFields as $fieldName) { | ||||
|             Log::debug(sprintf('Now at date field %s', $fieldName)); | ||||
|             if (array_key_exists($fieldName, $transaction)) { | ||||
|                 $current[$fieldName] = $this->dateFromValue((string) $transaction[$fieldName]); | ||||
|                 Log::debug(sprintf('New value: "%s"', (string) $transaction[$fieldName])); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $current; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * For each field, add it to the array if a reference is present in the request: | ||||
|      * | ||||
|      * @param array $current | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getIntegerData(array $current, array $transaction): array | ||||
|     { | ||||
|         foreach ($this->integerFields as $fieldName) { | ||||
|             if (array_key_exists($fieldName, $transaction)) { | ||||
|                 $current[$fieldName] = $this->integerFromValue((string) $transaction[$fieldName]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $current; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $current | ||||
|      * @param array $transaction | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getNlStringData(array $current, array $transaction): array | ||||
|     { | ||||
|         foreach ($this->textareaFields as $fieldName) { | ||||
|             if (array_key_exists($fieldName, $transaction)) { | ||||
|                 $current[$fieldName] = $this->nlStringFromValue((string) $transaction[$fieldName]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $current; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $current | ||||
|      * @param array $transaction | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getStringData(array $current, array $transaction): array | ||||
|     { | ||||
|         foreach ($this->stringFields as $fieldName) { | ||||
|             if (array_key_exists($fieldName, $transaction)) { | ||||
|                 $current[$fieldName] = $this->stringFromValue((string) $transaction[$fieldName]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $current; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get transaction data. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getTransactionData(): array | ||||
|     { | ||||
|         Log::debug('Now in getTransactionData()'); | ||||
|         $return = []; | ||||
|         /** | ||||
|          * @var int   $index | ||||
|          * @var array $transaction | ||||
|          */ | ||||
|         foreach ($this->get('transactions') as $transaction) { | ||||
|             // default response is to update nothing in the transaction: | ||||
|             $current  = []; | ||||
|             $current  = $this->getIntegerData($current, $transaction); | ||||
|             $current  = $this->getStringData($current, $transaction); | ||||
|             $current  = $this->getNlStringData($current, $transaction); | ||||
|             $current  = $this->getDateData($current, $transaction); | ||||
|             $current  = $this->getBooleanData($current, $transaction); | ||||
|             $current  = $this->getArrayData($current, $transaction); | ||||
|             $return[] = $current; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -24,16 +24,18 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Repositories\User\UserRepositoryInterface; | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
| use FireflyIII\User; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class UserStoreRequest | ||||
|  */ | ||||
| class UserStoreRequest extends Request | ||||
| class UserStoreRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
| @@ -41,21 +43,7 @@ class UserStoreRequest extends Request | ||||
|      */ | ||||
|     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; | ||||
|         return auth()->check() && auth()->user()->hasRole('owner'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -24,16 +24,18 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Repositories\User\UserRepositoryInterface; | ||||
| use FireflyIII\Rules\IsBoolean; | ||||
| use FireflyIII\User; | ||||
| use FireflyIII\Support\Request\ConvertsDataTypes; | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class UserUpdateRequest | ||||
|  */ | ||||
| class UserUpdateRequest extends Request | ||||
| class UserUpdateRequest extends FormRequest | ||||
| { | ||||
|     use ConvertsDataTypes; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
| @@ -41,21 +43,7 @@ class UserUpdateRequest extends Request | ||||
|      */ | ||||
|     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; | ||||
|         return auth()->check() && auth()->user()->hasRole('owner'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -48,6 +48,7 @@ class CorrectDatabase extends Command | ||||
|      */ | ||||
|     protected $signature = 'firefly-iii:correct-database'; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Execute the console command. | ||||
|      */ | ||||
| @@ -70,11 +71,13 @@ class CorrectDatabase extends Command | ||||
|             'firefly-iii:delete-empty-journals', | ||||
|             'firefly-iii:delete-empty-groups', | ||||
|             'firefly-iii:fix-account-types', | ||||
|             'firefly-iii:fix-account-order', | ||||
|             'firefly-iii:rename-meta-fields', | ||||
|             'firefly-iii:fix-ob-currencies', | ||||
|             'firefly-iii:fix-long-descriptions', | ||||
|             'firefly-iii:fix-recurring-transactions', | ||||
|             'firefly-iii:restore-oauth-keys', | ||||
|             'firefly-iii:fix-transaction-types', | ||||
|         ]; | ||||
|         foreach ($commands as $command) { | ||||
|             $this->line(sprintf('Now executing %s', $command)); | ||||
|   | ||||
| @@ -32,6 +32,7 @@ use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use Illuminate\Console\Command; | ||||
| use JsonException; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
| @@ -52,6 +53,7 @@ class CorrectOpeningBalanceCurrencies extends Command | ||||
|      */ | ||||
|     protected $signature = 'firefly-iii:fix-ob-currencies'; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Execute the console command. | ||||
|      * | ||||
| @@ -59,6 +61,7 @@ class CorrectOpeningBalanceCurrencies extends Command | ||||
|      */ | ||||
|     public function handle(): int | ||||
|     { | ||||
|         Log::debug(sprintf('Now in %s', __METHOD__)); | ||||
|         // get all OB journals: | ||||
|         $set = TransactionJournal | ||||
|             ::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') | ||||
| @@ -69,16 +72,23 @@ class CorrectOpeningBalanceCurrencies extends Command | ||||
|         $count = 0; | ||||
|         /** @var TransactionJournal $journal */ | ||||
|         foreach ($set as $journal) { | ||||
|             Log::debug(sprintf('Going to fix journal #%d', $journal->id)); | ||||
|             $count += $this->correctJournal($journal); | ||||
|             Log::debug(sprintf('Done, count is now %d', $count)); | ||||
|         } | ||||
|  | ||||
|         if ($count > 0) { | ||||
|             $this->line(sprintf('Corrected %d opening balance transactions.', $count)); | ||||
|             $message = sprintf('Corrected %d opening balance transaction(s).', $count); | ||||
|             Log::debug($message); | ||||
|             $this->line($message); | ||||
|         } | ||||
|         if (0 === $count) { | ||||
|             $this->info('There was nothing to fix in the opening balance transactions.'); | ||||
|             $message = 'There was nothing to fix in the opening balance transactions.'; | ||||
|             Log::debug($message); | ||||
|             $this->info($message); | ||||
|         } | ||||
|  | ||||
|         Log::debug(sprintf('Done with %s', __METHOD__)); | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
| @@ -93,18 +103,18 @@ class CorrectOpeningBalanceCurrencies extends Command | ||||
|         // get the asset account for this opening balance: | ||||
|         $account = $this->getAccount($journal); | ||||
|         if (null === $account) { | ||||
|             $this->warn(sprintf('Transaction journal #%d has no valid account. Cant fix this line.', $journal->id)); | ||||
|             $message = sprintf('Transaction journal #%d has no valid account. Cant fix this line.', $journal->id); | ||||
|             Log::warning($message); | ||||
|             $this->warn($message); | ||||
|  | ||||
|             return 0; | ||||
|         } | ||||
|         Log::debug(sprintf('Found %s #%d "%s".', $account->accountType->type, $account->id, $account->name)); | ||||
|         Log::debug(sprintf('Found "%s" #%d "%s".', $account->accountType->type, $account->id, $account->name)); | ||||
|         $currency = $this->getCurrency($account); | ||||
|         Log::debug(sprintf('Found currency #%d (%s)', $currency->id, $currency->code)); | ||||
|  | ||||
|         // update journal and all transactions: | ||||
|         $this->setCurrency($journal, $currency); | ||||
|  | ||||
|         return 1; | ||||
|         return $this->setCurrency($journal, $currency); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -114,22 +124,27 @@ class CorrectOpeningBalanceCurrencies extends Command | ||||
|      */ | ||||
|     private function getAccount(TransactionJournal $journal): ?Account | ||||
|     { | ||||
|         $transactions = $journal->transactions()->with(['account', 'account.accountType'])->get(); | ||||
|         $transactions = $journal->transactions()->get(); | ||||
|         Log::debug(sprintf('Found %d transactions for journal #%d.', $transactions->count(), $journal->id)); | ||||
|         /** @var Transaction $transaction */ | ||||
|         foreach ($transactions as $transaction) { | ||||
|             $account = $transaction->account; | ||||
|             if ((null !== $account) && AccountType::INITIAL_BALANCE !== $account->accountType->type) { | ||||
|             Log::debug(sprintf('Testing transaction #%d', $transaction->id)); | ||||
|             /** @var Account $account */ | ||||
|             $account = $transaction->account()->first(); | ||||
|             if (null !== $account && AccountType::INITIAL_BALANCE !== $account->accountType()->first()->type) { | ||||
|                 Log::debug(sprintf('Account of transaction #%d is opposite of IB account (%s).', $transaction->id, $account->accountType()->first()->type)); | ||||
|                 return $account; | ||||
|             } | ||||
|         } | ||||
|         Log::debug('Found no IB account in transactions of journal.'); | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return TransactionCurrency | ||||
|      * @throws JsonException | ||||
|      */ | ||||
|     private function getCurrency(Account $account): TransactionCurrency | ||||
|     { | ||||
| @@ -143,16 +158,30 @@ class CorrectOpeningBalanceCurrencies extends Command | ||||
|     /** | ||||
|      * @param TransactionJournal  $journal | ||||
|      * @param TransactionCurrency $currency | ||||
|      * @return int | ||||
|      */ | ||||
|     private function setCurrency(TransactionJournal $journal, TransactionCurrency $currency): void | ||||
|     private function setCurrency(TransactionJournal $journal, TransactionCurrency $currency): int | ||||
|     { | ||||
|         $journal->transaction_currency_id = $currency->id; | ||||
|         $journal->save(); | ||||
|         Log::debug('Now in setCurrency'); | ||||
|         $count = 0; | ||||
|         if ((int) $journal->transaction_currency_id !== (int) $currency->id) { | ||||
|             Log::debug(sprintf('Currency ID of journal #%d was #%d, now set to #%d', $journal->id, $journal->transaction_currency_id, $currency->id)); | ||||
|             $journal->transaction_currency_id = $currency->id; | ||||
|             $journal->save(); | ||||
|             $count = 1; | ||||
|         } | ||||
|  | ||||
|         /** @var Transaction $transaction */ | ||||
|         foreach ($journal->transactions as $transaction) { | ||||
|             $transaction->transaction_currency_id = $currency->id; | ||||
|             $transaction->save(); | ||||
|             if ((int) $transaction->transaction_currency_id !== (int) $currency->id) { | ||||
|                 Log::debug(sprintf('Currency ID of transaction #%d was #%d, now set to #%d', $transaction->id, $transaction->transaction_currency_id, $currency->id)); | ||||
|                 $transaction->transaction_currency_id = $currency->id; | ||||
|                 $transaction->save(); | ||||
|                 $count = 1; | ||||
|             } | ||||
|         } | ||||
|         Log::debug(sprintf('Return %d', $count)); | ||||
|  | ||||
|         return $count; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -21,7 +21,6 @@ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
|  | ||||
| namespace FireflyIII\Console\Commands\Correction; | ||||
|  | ||||
| use Exception; | ||||
| @@ -47,6 +46,7 @@ class CreateAccessTokens extends Command | ||||
|      */ | ||||
|     protected $signature = 'firefly-iii:create-access-tokens'; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Execute the console command. | ||||
|      * | ||||
|   | ||||
| @@ -44,6 +44,7 @@ class CreateLinkTypes extends Command | ||||
|      */ | ||||
|     protected $signature = 'firefly-iii:create-link-types'; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Execute the console command. | ||||
|      * | ||||
|   | ||||
| @@ -46,6 +46,7 @@ class DeleteEmptyGroups extends Command | ||||
|      */ | ||||
|     protected $signature = 'firefly-iii:delete-empty-groups'; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Execute the console command. | ||||
|      * | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user